diff --git a/test/jstests/operators.py b/test/jstests/operators.py index c95a8baca..c70bac39b 100644 --- a/test/jstests/operators.py +++ b/test/jstests/operators.py @@ -39,5 +39,16 @@ tests = [ (Token.OP, _OPERATORS['>>'][1]) ]), None) ]))] + }, { + 'code': 'return -5 + +3;', + 'asserts': [{'value': -2}] + }, { + 'code': 'return -5 + ++a;', + 'globals': {'a': -3}, + 'asserts': [{'value': -7}] + }, { + 'code': 'function f() {return -5 + a++;}', + 'globals': {'a': -3}, + 'asserts': [{'value': -8, 'call': ('f',)}, {'value': -7, 'call': ('f',)}] } ] diff --git a/youtube_dl/jsinterp/jsinterp.py b/youtube_dl/jsinterp/jsinterp.py index 0232f8d20..0fbb734d5 100644 --- a/youtube_dl/jsinterp/jsinterp.py +++ b/youtube_dl/jsinterp/jsinterp.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import re from ..utils import ExtractorError -from .tstream import TokenStream, _UNARY_OPERATORS +from .tstream import TokenStream, convert_to_unary from .jsgrammar import Token, token_keys @@ -744,7 +744,7 @@ class JSInterpreter(object): if peek_id is Token.OP and peek_value[0] in (Token.ADD, Token.SUB): # any binary operators will be consumed later peek_id = Token.UOP - peek_value = {Token.ADD: _UNARY_OPERATORS['+'], Token.SUB: _UNARY_OPERATORS['-']}[peek_value[0]] + peek_value = convert_to_unary(peek_value) if peek_id is Token.UOP: name, op = peek_value had_inc = name in (Token.INC, Token.DEC) @@ -881,17 +881,18 @@ class JSInterpreter(object): elif name is Token.OPEXPR: stack = [] rpn = expr[1][:] + # FIXME support pre- and postfix operators while rpn: token = rpn.pop(0) - # XXX add unary operator 'delete', 'void', 'instanceof' # XXX relation 'in' 'instanceof' - if token[0] in (Token.OP, Token.AOP, Token.UOP, Token.LOP, Token.REL): + if token[0] in (Token.OP, Token.AOP, Token.LOP, Token.REL): right = stack.pop() left = stack.pop() stack.append(Reference(token[1](left.getvalue(), right.getvalue()))) + # XXX add unary operator 'delete', 'void', 'instanceof' elif token[0] is Token.UOP: right = stack.pop() - stack.append(token[1](right.getvalue())) + stack.append(Reference(token[1](right.getvalue()))) else: stack.append(self.interpret_expression(token)) result = stack.pop() diff --git a/youtube_dl/jsinterp/tstream.py b/youtube_dl/jsinterp/tstream.py index e4786b5ed..8a37b53c2 100644 --- a/youtube_dl/jsinterp/tstream.py +++ b/youtube_dl/jsinterp/tstream.py @@ -13,8 +13,7 @@ from .jsgrammar import ( RELATIONS_RE, ASSIGN_OPERATORS_RE, OPERATORS_RE, - Token, - token_keys + Token ) _PUNCTUATIONS = { @@ -40,7 +39,7 @@ _UNARY_OPERATORS = { '++': (Token.INC, lambda cur: cur + 1), '--': (Token.DEC, lambda cur: cur - 1), '!': (Token.NOT, operator.not_), - '~': (Token.BNOT, operator.invert), + '~': (Token.BNOT, operator.inv), # XXX define these operators 'delete': (Token.DEL, None), 'void': (Token.VOID, None), @@ -99,6 +98,10 @@ _input_element = re.compile(r'\s*(?:%(comment)s|%(token)s|%(lop)s|%(uop)s|%(aop) }) +def convert_to_unary(token_value): + return {Token.ADD: _UNARY_OPERATORS['+'], Token.SUB: _UNARY_OPERATORS['-']}[token_value[0]] + + class TokenStream(object): def __init__(self, code, start=0): self.code = code