diff options
Diffstat (limited to 'Userland/Libraries/LibTest/JavaScriptTestRunner.h')
-rw-r--r-- | Userland/Libraries/LibTest/JavaScriptTestRunner.h | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/Userland/Libraries/LibTest/JavaScriptTestRunner.h b/Userland/Libraries/LibTest/JavaScriptTestRunner.h index b1f4454d2b..b24f7b9b53 100644 --- a/Userland/Libraries/LibTest/JavaScriptTestRunner.h +++ b/Userland/Libraries/LibTest/JavaScriptTestRunner.h @@ -175,7 +175,6 @@ protected: void print_file_result(const JSFileResult& file_result) const; String m_common_path; - RefPtr<JS::Script> m_test_script; }; class TestRunnerGlobalObject final : public JS::GlobalObject { @@ -279,6 +278,14 @@ inline JSFileResult TestRunner::run_file_test(const String& test_path) double start_time = get_time_in_ms(); auto interpreter = JS::Interpreter::create<TestRunnerGlobalObject>(*g_vm); + // Since g_vm is reused for each new interpreter, Interpreter::create will end up pushing multiple + // global execution contexts onto the VM's execution context stack. To prevent this, we immediately + // pop the global execution context off the execution context stack and manually handle pushing + // and popping it. Since the global execution context should be the only thing on the stack + // at interpreter creation, let's assert there is only one. + VERIFY(g_vm->execution_context_stack().size() == 1); + auto& global_execution_context = *g_vm->execution_context_stack().take_first(); + // FIXME: This is a hack while we're refactoring Interpreter/VM stuff. JS::VM::InterpreterExecutionScope scope(*interpreter); @@ -323,26 +330,28 @@ inline JSFileResult TestRunner::run_file_test(const String& test_path) } } - if (!m_test_script) { - auto result = parse_script(m_common_path, interpreter->realm()); - if (result.is_error()) { - warnln("Unable to parse test-common.js"); - warnln("{}", result.error().error.to_string()); - warnln("{}", result.error().hint); - cleanup_and_exit(); - } - m_test_script = result.release_value(); + // FIXME: Since a new interpreter is created every time with a new realm, we no longer cache the test-common.js file as scripts are parsed for the current realm only. + // Find a way to cache this. + auto result = parse_script(m_common_path, interpreter->realm()); + if (result.is_error()) { + warnln("Unable to parse test-common.js"); + warnln("{}", result.error().error.to_string()); + warnln("{}", result.error().hint); + cleanup_and_exit(); } + auto test_script = result.release_value(); if (g_run_bytecode) { - auto executable = JS::Bytecode::Generator::generate(m_test_script->parse_node()); + auto executable = JS::Bytecode::Generator::generate(test_script->parse_node()); executable.name = test_path; if (JS::Bytecode::g_dump_bytecode) executable.dump(); JS::Bytecode::Interpreter bytecode_interpreter(interpreter->global_object(), interpreter->realm()); MUST(bytecode_interpreter.run(executable)); } else { - MUST(interpreter->run(interpreter->global_object(), m_test_script->parse_node())); + g_vm->push_execution_context(global_execution_context, interpreter->global_object()); + MUST(interpreter->run(*test_script)); + g_vm->pop_execution_context(); } auto file_script = parse_script(test_path, interpreter->realm()); @@ -356,7 +365,9 @@ inline JSFileResult TestRunner::run_file_test(const String& test_path) JS::Bytecode::Interpreter bytecode_interpreter(interpreter->global_object(), interpreter->realm()); (void)bytecode_interpreter.run(executable); } else { - (void)interpreter->run(interpreter->global_object(), file_script.value()->parse_node()); + g_vm->push_execution_context(global_execution_context, interpreter->global_object()); + (void)interpreter->run(file_script.value()); + g_vm->pop_execution_context(); } if (g_vm->exception()) |