parent
195f22f679
commit
14ef89a8da
3 changed files with 54 additions and 3 deletions
|
@ -158,6 +158,38 @@ class TestJSInterpreter(unittest.TestCase):
|
||||||
self.assertEqual(jsi.call_function('z'), 5)
|
self.assertEqual(jsi.call_function('z'), 5)
|
||||||
self.assertEqual(jsi.call_function('y'), 2)
|
self.assertEqual(jsi.call_function('y'), 2)
|
||||||
|
|
||||||
|
def test_if(self):
|
||||||
|
jsi = JSInterpreter('''
|
||||||
|
function x() {
|
||||||
|
let a = 9;
|
||||||
|
if (0==0) {a++}
|
||||||
|
return a
|
||||||
|
}''')
|
||||||
|
self.assertEqual(jsi.call_function('x'), 10)
|
||||||
|
|
||||||
|
jsi = JSInterpreter('''
|
||||||
|
function x() {
|
||||||
|
if (0==0) {return 10}
|
||||||
|
}''')
|
||||||
|
self.assertEqual(jsi.call_function('x'), 10)
|
||||||
|
|
||||||
|
jsi = JSInterpreter('''
|
||||||
|
function x() {
|
||||||
|
if (0!=0) {return 1}
|
||||||
|
else {return 10}
|
||||||
|
}''')
|
||||||
|
self.assertEqual(jsi.call_function('x'), 10)
|
||||||
|
|
||||||
|
""" # Unsupported
|
||||||
|
jsi = JSInterpreter('''
|
||||||
|
function x() {
|
||||||
|
if (0!=0) {return 1}
|
||||||
|
else if (1==0) {return 2}
|
||||||
|
else {return 10}
|
||||||
|
}''')
|
||||||
|
self.assertEqual(jsi.call_function('x'), 10)
|
||||||
|
"""
|
||||||
|
|
||||||
def test_for_loop(self):
|
def test_for_loop(self):
|
||||||
# function x() { a=0; for (i=0; i-10; i++) {a++} a }
|
# function x() { a=0; for (i=0; i-10; i++) {a++} a }
|
||||||
jsi = JSInterpreter('''
|
jsi = JSInterpreter('''
|
||||||
|
|
|
@ -135,6 +135,10 @@ _NSIG_TESTS = [
|
||||||
'https://www.youtube.com/s/player/5a3b6271/player_ias.vflset/en_US/base.js',
|
'https://www.youtube.com/s/player/5a3b6271/player_ias.vflset/en_US/base.js',
|
||||||
'B2j7f_UPT4rfje85Lu_e', 'm5DmNymaGQ5RdQ',
|
'B2j7f_UPT4rfje85Lu_e', 'm5DmNymaGQ5RdQ',
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
'https://www.youtube.com/s/player/dac945fd/player_ias.vflset/en_US/base.js',
|
||||||
|
'o8BkRxXhuYsBCWi6RplPdP', '3Lx32v_hmzTm6A',
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ class JSInterpreter(object):
|
||||||
def __init__(self, msg, *args, **kwargs):
|
def __init__(self, msg, *args, **kwargs):
|
||||||
expr = kwargs.pop('expr', None)
|
expr = kwargs.pop('expr', None)
|
||||||
if expr is not None:
|
if expr is not None:
|
||||||
msg = '{0} in: {1!r:.100}'.format(msg.rstrip(), expr)
|
msg = '{0} in: {1!r}'.format(msg.rstrip(), expr[:100])
|
||||||
super(JSInterpreter.Exception, self).__init__(msg, *args, **kwargs)
|
super(JSInterpreter.Exception, self).__init__(msg, *args, **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -268,7 +268,7 @@ class JSInterpreter(object):
|
||||||
elif in_quote == '/' and char in '[]':
|
elif in_quote == '/' and char in '[]':
|
||||||
in_regex_char_group = char == '['
|
in_regex_char_group = char == '['
|
||||||
escaping = not escaping and in_quote and char == '\\'
|
escaping = not escaping and in_quote and char == '\\'
|
||||||
after_op = not in_quote and (char in cls.OP_CHARS or char == '[' or (char.isspace() and after_op))
|
after_op = not in_quote and (char in cls.OP_CHARS or (char.isspace() and after_op))
|
||||||
|
|
||||||
if char != delim[pos] or any(counters.values()) or in_quote:
|
if char != delim[pos] or any(counters.values()) or in_quote:
|
||||||
pos = skipping = 0
|
pos = skipping = 0
|
||||||
|
@ -301,7 +301,7 @@ class JSInterpreter(object):
|
||||||
separated = list(cls._separate(expr, delim, 1))
|
separated = list(cls._separate(expr, delim, 1))
|
||||||
|
|
||||||
if len(separated) < 2:
|
if len(separated) < 2:
|
||||||
raise cls.Exception('No terminating paren {delim} in {expr:.100}'.format(**locals()))
|
raise cls.Exception('No terminating paren {delim} in {expr}'.format(**locals()))
|
||||||
return separated[0][1:].strip(), separated[1].strip()
|
return separated[0][1:].strip(), separated[1].strip()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -428,10 +428,25 @@ class JSInterpreter(object):
|
||||||
|
|
||||||
m = re.match(r'''(?x)
|
m = re.match(r'''(?x)
|
||||||
(?P<try>try)\s*\{|
|
(?P<try>try)\s*\{|
|
||||||
|
(?P<if>if)\s*\(|
|
||||||
(?P<switch>switch)\s*\(|
|
(?P<switch>switch)\s*\(|
|
||||||
(?P<for>for)\s*\(
|
(?P<for>for)\s*\(
|
||||||
''', expr)
|
''', expr)
|
||||||
md = m.groupdict() if m else {}
|
md = m.groupdict() if m else {}
|
||||||
|
if md.get('if'):
|
||||||
|
cndn, expr = self._separate_at_paren(expr[m.end() - 1:])
|
||||||
|
if_expr, expr = self._separate_at_paren(expr.lstrip())
|
||||||
|
# TODO: "else if" is not handled
|
||||||
|
else_expr = None
|
||||||
|
m = re.match(r'else\s*{', expr)
|
||||||
|
if m:
|
||||||
|
else_expr, expr = self._separate_at_paren(expr[m.end() - 1:])
|
||||||
|
cndn = _js_ternary(self.interpret_expression(cndn, local_vars, allow_recursion))
|
||||||
|
ret, should_abort = self.interpret_statement(
|
||||||
|
if_expr if cndn else else_expr, local_vars, allow_recursion)
|
||||||
|
if should_abort:
|
||||||
|
return ret, True
|
||||||
|
|
||||||
if md.get('try'):
|
if md.get('try'):
|
||||||
try_expr, expr = self._separate_at_paren(expr[m.end() - 1:])
|
try_expr, expr = self._separate_at_paren(expr[m.end() - 1:])
|
||||||
err = None
|
err = None
|
||||||
|
|
Loading…
Reference in a new issue