def eval(self, expression, context=None): if context is None: context = js.ExecutionContext({}) if not isinstance(context, js.ExecutionContext): context = js.ExecutionContext(context) expression_ast = self.parser.parse(expression) return js.get_value(expression_ast.eval(context))
def eval(self, stmt, context=None): if context is None: context = js.ExecutionContext({}) if not isinstance(context, js.ExecutionContext): context = js.ExecutionContext(context) stmt_ast = self.parser.parse(stmt) return js.get_value(stmt_ast.eval(context))
def test_closure(self): program = """var fibgen = function () { var a = 0, b = 1; return function () { var old = a; a = b; b = b + old; return old; }; }; var fib = fibgen(); var f1 = fib(); var f2 = fib(); fib(); fib(); fib(); fib(); var f7 = fib(); fib(); fib(); fib(); fib(); var fib2 = fibgen(); fib2(); fib2(); fib2(); fib2(); var f5 = fib2(); fib(); // f12 """ context = js.ExecutionContext({}) self.assertEqual(self.eval(program, context), js.Completion(js.NORMAL, 89, js.EMPTY)) self.assertEqual(context['f1'], 0) self.assertEqual(context['f2'], 1) self.assertEqual(context['f5'], 3) self.assertEqual(context['f7'], 8)
def test_object_set_property(self): context = js.ExecutionContext( {'x': js.Object({ 'cheese': 7, 'ham': 3 })}) self.assertEqual(self.eval('x["cheese"] = 4', context), 4) self.assertEqual(context['x']['cheese'], 4)
def test_object_set_new_property(self): context = js.ExecutionContext( {'x': js.Object({ 'cheese': 7, 'ham': 3 })}) self.assertEqual(self.eval('x["spam"] = 2', context), 2) self.assertEqual(context['x']['spam'], 2)
def test_shadowing(self): program = """var x = 1; var shadow = function () { var x = 3; x += 1; return x; }; shadow();""" context = js.ExecutionContext({}) self.assertEqual(self.eval(program, context), js.Completion(js.NORMAL, 4, js.EMPTY)) self.assertEqual(context['x'], 1)
def test_console_object(self): program = """var i = 0; while (i < 10) { console.log(i); i++; } """ out = StringIO() context = js.ExecutionContext({'console': js.Console(out=out)}) self.assertEqual(self.eval(program, context), js.Completion(js.NORMAL, 9, js.EMPTY)) self.assertEqual(out.getvalue(), "0.0\n1.0\n2.0\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0\n9.0\n")
def test_break_statement(self): stmt = """while (x < 10) { ++x; if (x % 3 == 0) break; ++y; }""" context = js.ExecutionContext({'x': 0, 'y': 0}) self.assertEqual(self.eval(stmt, context), js.Completion(js.NORMAL, 2, js.EMPTY)) self.assertEqual(context['x'], 3) self.assertEqual(context['y'], 2)
def test_continue_statement(self): stmt = """while (x < 10) { ++x; if (x % 2 == 0) continue; ++y; }""" context = js.ExecutionContext({'x': 0, 'y': 0}) self.assertEqual(self.eval(stmt, context), js.Completion(js.NORMAL, 5, js.EMPTY)) self.assertEqual(context['x'], 10) self.assertEqual(context['y'], 5)
def eval(self, context): result_value = js.EMPTY cntx = js.ExecutionContext(dict(), parent=context) while True: condition_value = js.get_value(self.condition.eval(cntx)) if not condition_value: return js.Completion(js.NORMAL, result_value, js.EMPTY) stmt = self.statement.eval(cntx) if stmt.value is not js.EMPTY: result_value = stmt.value if stmt.type is js.BREAK: return js.Completion(js.NORMAL, result_value, js.EMPTY) elif js.is_abrupt(stmt) and stmt.type is not js.CONTINUE: return stmt
def test_postfix_op(self): context = js.ExecutionContext({'x': 3}) self.assertEqual(self.eval('x++', context), 3) self.assertEqual(context['x'], 4) self.assertEqual(self.eval('x--', context), 4) self.assertEqual(context['x'], 3)
def test_prefix_op(self): context = js.ExecutionContext({'x': 3}) self.assertEqual(self.eval('++x', context), 4) self.assertEqual(context['x'], 4) self.assertEqual(self.eval('--x', context), 3) self.assertEqual(context['x'], 3)
def test_while_statement(self): context = js.ExecutionContext({'x': 3}) self.assertEqual(self.eval('while (x < 5) ++x;', context), js.Completion(js.NORMAL, 5, js.EMPTY)) self.assertEqual(context['x'], 5)
def test_do_while_statement(self): context = js.ExecutionContext({'x': 3}) self.assertEqual(self.eval('do ++x; while (x < 3);', context), js.Completion(js.NORMAL, 4, js.EMPTY)) self.assertEqual(context['x'], 4)
def test_variable_declaration_list(self): context = js.ExecutionContext({}) self.assertEqual(self.eval('var x = 7, y = 5;', context), js.EMPTY_COMPLETION) self.assertEqual(context['x'], 7) self.assertEqual(context['y'], 5)
def test_compound_assignment(self): context = js.ExecutionContext({'x': 15}) self.assertEqual(self.eval('x /= 5 - 2', context), 5) self.assertEqual(context['x'], 5)
def test_array_set_index(self): context = js.ExecutionContext({'x': js.Array([9, 10, 'ala ma kota'])}) self.assertEqual(self.eval('x[2] = 11', context), 11) self.assertEqual(context['x'], js.Array([9, 10, 11]))