[jsinterp] Adding interpreter support to get field

This commit is contained in:
sulyi 2016-12-16 00:11:59 +01:00
parent 5238ed11ac
commit 171680120d
2 changed files with 19 additions and 9 deletions

View File

@ -1,7 +1,5 @@
from youtube_dl.jsinterp.jsgrammar import Token from youtube_dl.jsinterp.jsgrammar import Token
skip = {'i': 'Interpreting get field not yet implemented'}
tests = [ tests = [
{ {
'code': 'return a.var;', 'code': 'return a.var;',

View File

@ -53,7 +53,7 @@ class JSInterpreter(object):
if variables is not None: if variables is not None:
for k, v in dict(variables).items(): for k, v in dict(variables).items():
# XXX validate identifiers # XXX validate identifiers
self.global_vars[k] = Reference(v, (self.global_vars, k)) self.global_vars[k] = self.create_reference(v, (self.global_vars, k))
self._context = Context() self._context = Context()
self._context_stack = [] self._context_stack = []
@ -65,6 +65,20 @@ class JSInterpreter(object):
yield self._statement(ts, stack_size) yield self._statement(ts, stack_size)
raise StopIteration raise StopIteration
def create_reference(self, value, parent_key):
if isinstance(value, dict):
o = {}
for k, v in value.items():
o[k] = self.create_reference(v, (o, k))
elif isinstance(value, list):
o = []
for k, v in enumerate(value):
o[k] = self.create_reference(v, (o, k))
else:
o = value
return Reference(o, parent_key)
def _statement(self, token_stream, stack_top): def _statement(self, token_stream, stack_top):
if stack_top < 0: if stack_top < 0:
raise ExtractorError('Recursion limit reached') raise ExtractorError('Recursion limit reached')
@ -923,10 +937,9 @@ class JSInterpreter(object):
while tail is not None: while tail is not None:
tail_name, tail_value, tail = tail tail_name, tail_value, tail = tail
if tail_name is Token.FIELD: if tail_name is Token.FIELD:
# TODO interpret field target = target.getvalue()[tail_value]
raise ExtractorError('''Can't interpret expression called %s''' % tail_name)
elif tail_name is Token.ELEM: elif tail_name is Token.ELEM:
index = self.interpret_statement(tail_value).getvalue() index = self.interpret_expression(tail_value).getvalue()
target = target.getvalue()[index] target = target.getvalue()[index]
elif tail_name is Token.CALL: elif tail_name is Token.CALL:
# TODO interpret call # TODO interpret call
@ -945,9 +958,8 @@ class JSInterpreter(object):
elif name is Token.ARRAY: elif name is Token.ARRAY:
array = [] array = []
for key, elem in enumerate(expr[1]): for key, elem in enumerate(expr[1]):
value = self.interpret_expression(elem) value = self.interpret_expression(elem).getvalue()
value._parent = array, key array.append(Reference(value, (array, key)))
array.append(value)
ref = Reference(array) ref = Reference(array)
else: else: