summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibTest/JavaScriptTestRunner.h
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibTest/JavaScriptTestRunner.h')
-rw-r--r--Userland/Libraries/LibTest/JavaScriptTestRunner.h37
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())