diff --git a/test/jstests/morespace.py b/test/jstests/morespace.py index 1e238f419..327e46192 100644 --- a/test/jstests/morespace.py +++ b/test/jstests/morespace.py @@ -1,8 +1,6 @@ from youtube_dl.jsinterp.jsgrammar import Token from youtube_dl.jsinterp.tstream import _ASSIGN_OPERATORS -skip = {'i': 'Interpreting set field not yet implemented'} - tests = [ { 'code': 'x = 2 ; return x;', diff --git a/test/jstests/precedence.py b/test/jstests/precedence.py index 7b8bf9bcc..8008ff589 100644 --- a/test/jstests/precedence.py +++ b/test/jstests/precedence.py @@ -1,7 +1,7 @@ from youtube_dl.jsinterp.jsgrammar import Token from youtube_dl.jsinterp.tstream import _ASSIGN_OPERATORS, _OPERATORS -skip = {'i': 'Interpreting get field not yet implemented'} +skip = {'i': 'Interpreting built-in fields not yet implemented'} tests = [ { diff --git a/youtube_dl/jsinterp/jsinterp.py b/youtube_dl/jsinterp/jsinterp.py index 9aebe128f..312bfeba4 100644 --- a/youtube_dl/jsinterp/jsinterp.py +++ b/youtube_dl/jsinterp/jsinterp.py @@ -12,7 +12,7 @@ class Context(object): def __init__(self, variables=None, ended=False): self.ended = ended self.no_in = True - self.local_vars = {} + self.local_vars = {'this': {}} if variables is not None: for k, v in dict(variables).items(): # XXX validate identifiers @@ -58,6 +58,10 @@ class JSInterpreter(object): self._context = Context() self._context_stack = [] + @property + def this(self): + return self._context.local_vars['this'] + def statements(self, code=None, pos=0, stack_size=100): if code is None: code = self.code @@ -889,7 +893,22 @@ class JSInterpreter(object): ref = self.interpret_expression(left) else: # TODO handle undeclared variables (create propery) - leftref = self.interpret_expression(left) + try: + leftref = self.interpret_expression(left) + except KeyError: + lname = left[0] + key = None + if lname is Token.OPEXPR and len(left[1]) == 1: + lname = left[1][0][0] + if lname is Token.MEMBER: + lid, args, tail = left[1][0][1:] + if lid[0] is Token.ID and args is None and tail is None: + key = lid[1] + if key is not None: + u = Reference(self.undefined, (self.this, key)) + leftref = self.this[key] = u + else: + raise ExtractorError('''Invalid left-hand side in assignment''') leftvalue = leftref.getvalue() rightvalue = self.interpret_expression(right).getvalue() leftref.putvalue(op(leftvalue, rightvalue)) @@ -952,7 +971,7 @@ class JSInterpreter(object): elif name is Token.ID: # XXX error handling (unknown id) ref = (self._context.local_vars[expr[1]] if expr[1] in self._context.local_vars else - self.global_vars[expr[1]]) + self.this[expr[1]] if expr[1] in self.this else self.global_vars[expr[1]]) # literal elif name in token_keys: