mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-29 15:58:47 +00:00
LibJS: Remove {Bytecode::,}Interpreter::global_object()
The basic idea is that a global object cannot just come out of nowhere, it must be associated to a realm - so get it from there, if needed. This is to enforce the changes from all the previous commits by not handing out global objects unless you actually have an initialized realm (either stored somewhere, or the VM's current realm).
This commit is contained in:
parent
b345a0acca
commit
275dea9d98
Notes:
sideshowbarker
2024-07-17 07:52:44 +09:00
Author: https://github.com/linusg
Commit: 275dea9d98
Pull-request: https://github.com/SerenityOS/serenity/pull/14973
Reviewed-by: https://github.com/davidot ✅
10 changed files with 15 additions and 37 deletions
|
@ -20,7 +20,7 @@
|
||||||
\
|
\
|
||||||
auto script = script_or_error.release_value(); \
|
auto script = script_or_error.release_value(); \
|
||||||
auto const& program = script->parse_node(); \
|
auto const& program = script->parse_node(); \
|
||||||
JS::Bytecode::Interpreter bytecode_interpreter(ast_interpreter->global_object(), ast_interpreter->realm());
|
JS::Bytecode::Interpreter bytecode_interpreter(ast_interpreter->realm());
|
||||||
|
|
||||||
#define EXPECT_NO_EXCEPTION(executable) \
|
#define EXPECT_NO_EXCEPTION(executable) \
|
||||||
auto executable = MUST(JS::Bytecode::Generator::generate(program)); \
|
auto executable = MUST(JS::Bytecode::Generator::generate(program)); \
|
||||||
|
|
|
@ -43,7 +43,7 @@ Sheet::Sheet(Workbook& workbook)
|
||||||
, m_interpreter(JS::Interpreter::create<SheetGlobalObject>(m_workbook.vm(), *this))
|
, m_interpreter(JS::Interpreter::create<SheetGlobalObject>(m_workbook.vm(), *this))
|
||||||
{
|
{
|
||||||
JS::DeferGC defer_gc(m_workbook.vm().heap());
|
JS::DeferGC defer_gc(m_workbook.vm().heap());
|
||||||
m_global_object = static_cast<SheetGlobalObject*>(&m_interpreter->global_object());
|
m_global_object = static_cast<SheetGlobalObject*>(&m_interpreter->realm().global_object());
|
||||||
global_object().define_direct_property("workbook", m_workbook.workbook_object(), JS::default_attributes);
|
global_object().define_direct_property("workbook", m_workbook.workbook_object(), JS::default_attributes);
|
||||||
global_object().define_direct_property("thisSheet", &global_object(), JS::default_attributes); // Self-reference is unfortunate, but required.
|
global_object().define_direct_property("thisSheet", &global_object(), JS::default_attributes); // Self-reference is unfortunate, but required.
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,10 @@ Workbook::Workbook(NonnullRefPtrVector<Sheet>&& sheets, GUI::Window& parent_wind
|
||||||
, m_parent_window(parent_window)
|
, m_parent_window(parent_window)
|
||||||
{
|
{
|
||||||
m_workbook_object = m_vm->heap().allocate<WorkbookObject>(m_interpreter->realm(), m_interpreter->realm(), *this);
|
m_workbook_object = m_vm->heap().allocate<WorkbookObject>(m_interpreter->realm(), m_interpreter->realm(), *this);
|
||||||
m_interpreter->global_object().define_direct_property("workbook", workbook_object(), JS::default_attributes);
|
m_interpreter->realm().global_object().define_direct_property("workbook", workbook_object(), JS::default_attributes);
|
||||||
|
|
||||||
m_main_execution_context.current_node = nullptr;
|
m_main_execution_context.current_node = nullptr;
|
||||||
m_main_execution_context.this_value = &m_interpreter->global_object();
|
m_main_execution_context.this_value = &m_interpreter->realm().global_object();
|
||||||
m_main_execution_context.function_name = "(global execution context)"sv;
|
m_main_execution_context.function_name = "(global execution context)"sv;
|
||||||
m_main_execution_context.lexical_environment = &m_interpreter->realm().global_environment();
|
m_main_execution_context.lexical_environment = &m_interpreter->realm().global_environment();
|
||||||
m_main_execution_context.variable_environment = &m_interpreter->realm().global_environment();
|
m_main_execution_context.variable_environment = &m_interpreter->realm().global_environment();
|
||||||
|
|
|
@ -25,9 +25,8 @@ Interpreter* Interpreter::current()
|
||||||
return s_current;
|
return s_current;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interpreter::Interpreter(GlobalObject& global_object, Realm& realm)
|
Interpreter::Interpreter(Realm& realm)
|
||||||
: m_vm(global_object.vm())
|
: m_vm(realm.vm())
|
||||||
, m_global_object(global_object)
|
|
||||||
, m_realm(realm)
|
, m_realm(realm)
|
||||||
{
|
{
|
||||||
VERIFY(!s_current);
|
VERIFY(!s_current);
|
||||||
|
@ -51,7 +50,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
|
||||||
ExecutionContext execution_context(vm().heap());
|
ExecutionContext execution_context(vm().heap());
|
||||||
if (vm().execution_context_stack().is_empty() || !vm().running_execution_context().lexical_environment) {
|
if (vm().execution_context_stack().is_empty() || !vm().running_execution_context().lexical_environment) {
|
||||||
// The "normal" interpreter pushes an execution context without environment so in that case we also want to push one.
|
// The "normal" interpreter pushes an execution context without environment so in that case we also want to push one.
|
||||||
execution_context.this_value = &global_object();
|
execution_context.this_value = &m_realm.global_object();
|
||||||
static FlyString global_execution_context_name = "(*BC* global execution context)";
|
static FlyString global_execution_context_name = "(*BC* global execution context)";
|
||||||
execution_context.function_name = global_execution_context_name;
|
execution_context.function_name = global_execution_context_name;
|
||||||
execution_context.lexical_environment = &m_realm.global_environment();
|
execution_context.lexical_environment = &m_realm.global_environment();
|
||||||
|
@ -69,7 +68,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
|
||||||
m_register_windows.append(make<RegisterWindow>(MarkedVector<Value>(vm().heap()), MarkedVector<Environment*>(vm().heap()), MarkedVector<Environment*>(vm().heap())));
|
m_register_windows.append(make<RegisterWindow>(MarkedVector<Value>(vm().heap()), MarkedVector<Environment*>(vm().heap()), MarkedVector<Environment*>(vm().heap())));
|
||||||
|
|
||||||
registers().resize(executable.number_of_registers);
|
registers().resize(executable.number_of_registers);
|
||||||
registers()[Register::global_object_index] = Value(&global_object());
|
registers()[Register::global_object_index] = Value(&m_realm.global_object());
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Bytecode::InstructionStreamIterator pc(block->instruction_stream());
|
Bytecode::InstructionStreamIterator pc(block->instruction_stream());
|
||||||
|
|
|
@ -26,13 +26,12 @@ struct RegisterWindow {
|
||||||
|
|
||||||
class Interpreter {
|
class Interpreter {
|
||||||
public:
|
public:
|
||||||
Interpreter(GlobalObject&, Realm&);
|
explicit Interpreter(Realm&);
|
||||||
~Interpreter();
|
~Interpreter();
|
||||||
|
|
||||||
// FIXME: Remove this thing once we don't need it anymore!
|
// FIXME: Remove this thing once we don't need it anymore!
|
||||||
static Interpreter* current();
|
static Interpreter* current();
|
||||||
|
|
||||||
GlobalObject& global_object() { return m_global_object; }
|
|
||||||
Realm& realm() { return m_realm; }
|
Realm& realm() { return m_realm; }
|
||||||
VM& vm() { return m_vm; }
|
VM& vm() { return m_vm; }
|
||||||
|
|
||||||
|
@ -90,7 +89,6 @@ private:
|
||||||
static AK::Array<OwnPtr<PassManager>, static_cast<UnderlyingType<Interpreter::OptimizationLevel>>(Interpreter::OptimizationLevel::__Count)> s_optimization_pipelines;
|
static AK::Array<OwnPtr<PassManager>, static_cast<UnderlyingType<Interpreter::OptimizationLevel>>(Interpreter::OptimizationLevel::__Count)> s_optimization_pipelines;
|
||||||
|
|
||||||
VM& m_vm;
|
VM& m_vm;
|
||||||
GlobalObject& m_global_object;
|
|
||||||
Realm& m_realm;
|
Realm& m_realm;
|
||||||
Vector<Variant<NonnullOwnPtr<RegisterWindow>, RegisterWindow*>> m_register_windows;
|
Vector<Variant<NonnullOwnPtr<RegisterWindow>, RegisterWindow*>> m_register_windows;
|
||||||
Optional<BasicBlock const*> m_pending_jump;
|
Optional<BasicBlock const*> m_pending_jump;
|
||||||
|
|
|
@ -25,7 +25,6 @@ NonnullOwnPtr<Interpreter> Interpreter::create_with_existing_realm(Realm& realm)
|
||||||
auto& vm = realm.vm();
|
auto& vm = realm.vm();
|
||||||
DeferGC defer_gc(vm.heap());
|
DeferGC defer_gc(vm.heap());
|
||||||
auto interpreter = adopt_own(*new Interpreter(vm));
|
auto interpreter = adopt_own(*new Interpreter(vm));
|
||||||
interpreter->m_global_object = make_handle(&realm.global_object());
|
|
||||||
interpreter->m_realm = make_handle(&realm);
|
interpreter->m_realm = make_handle(&realm);
|
||||||
return interpreter;
|
return interpreter;
|
||||||
}
|
}
|
||||||
|
@ -140,16 +139,6 @@ ThrowCompletionOr<Value> Interpreter::run(SourceTextModule& module)
|
||||||
return js_undefined();
|
return js_undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalObject& Interpreter::global_object()
|
|
||||||
{
|
|
||||||
return static_cast<GlobalObject&>(*m_global_object.cell());
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalObject const& Interpreter::global_object() const
|
|
||||||
{
|
|
||||||
return static_cast<GlobalObject const&>(*m_global_object.cell());
|
|
||||||
}
|
|
||||||
|
|
||||||
Realm& Interpreter::realm()
|
Realm& Interpreter::realm()
|
||||||
{
|
{
|
||||||
return static_cast<Realm&>(*m_realm.cell());
|
return static_cast<Realm&>(*m_realm.cell());
|
||||||
|
|
|
@ -43,15 +43,13 @@ public:
|
||||||
auto interpreter = adopt_own(*new Interpreter(vm));
|
auto interpreter = adopt_own(*new Interpreter(vm));
|
||||||
VM::InterpreterExecutionScope scope(*interpreter);
|
VM::InterpreterExecutionScope scope(*interpreter);
|
||||||
|
|
||||||
GlobalObject* global_object { nullptr };
|
|
||||||
Realm* realm { nullptr };
|
Realm* realm { nullptr };
|
||||||
|
|
||||||
interpreter->m_global_execution_context = MUST(Realm::initialize_host_defined_realm(
|
interpreter->m_global_execution_context = MUST(Realm::initialize_host_defined_realm(
|
||||||
vm,
|
vm,
|
||||||
[&](Realm& realm_) -> GlobalObject* {
|
[&](Realm& realm_) -> GlobalObject* {
|
||||||
global_object = interpreter->heap().allocate_without_realm<GlobalObjectType>(realm_, forward<Args>(args)...);
|
|
||||||
realm = &realm_;
|
realm = &realm_;
|
||||||
return global_object;
|
return interpreter->heap().allocate_without_realm<GlobalObjectType>(realm_, forward<Args>(args)...);
|
||||||
},
|
},
|
||||||
nullptr));
|
nullptr));
|
||||||
|
|
||||||
|
@ -59,7 +57,6 @@ public:
|
||||||
static FlyString global_execution_context_name = "(global execution context)";
|
static FlyString global_execution_context_name = "(global execution context)";
|
||||||
interpreter->m_global_execution_context->function_name = global_execution_context_name;
|
interpreter->m_global_execution_context->function_name = global_execution_context_name;
|
||||||
|
|
||||||
interpreter->m_global_object = make_handle(global_object);
|
|
||||||
interpreter->m_realm = make_handle(realm);
|
interpreter->m_realm = make_handle(realm);
|
||||||
|
|
||||||
return interpreter;
|
return interpreter;
|
||||||
|
@ -72,9 +69,6 @@ public:
|
||||||
ThrowCompletionOr<Value> run(Script&);
|
ThrowCompletionOr<Value> run(Script&);
|
||||||
ThrowCompletionOr<Value> run(SourceTextModule&);
|
ThrowCompletionOr<Value> run(SourceTextModule&);
|
||||||
|
|
||||||
GlobalObject& global_object();
|
|
||||||
GlobalObject const& global_object() const;
|
|
||||||
|
|
||||||
Realm& realm();
|
Realm& realm();
|
||||||
Realm const& realm() const;
|
Realm const& realm() const;
|
||||||
|
|
||||||
|
@ -104,8 +98,6 @@ private:
|
||||||
ExecutingASTNodeChain* m_ast_node_chain { nullptr };
|
ExecutingASTNodeChain* m_ast_node_chain { nullptr };
|
||||||
|
|
||||||
NonnullRefPtr<VM> m_vm;
|
NonnullRefPtr<VM> m_vm;
|
||||||
|
|
||||||
Handle<GlobalObject> m_global_object;
|
|
||||||
Handle<Realm> m_realm;
|
Handle<Realm> m_realm;
|
||||||
|
|
||||||
// This is here to keep the global execution context alive for the entire lifespan of the Interpreter.
|
// This is here to keep the global execution context alive for the entire lifespan of the Interpreter.
|
||||||
|
|
|
@ -365,7 +365,7 @@ inline JSFileResult TestRunner::run_file_test(String const& test_path)
|
||||||
executable->name = test_path;
|
executable->name = test_path;
|
||||||
if (JS::Bytecode::g_dump_bytecode)
|
if (JS::Bytecode::g_dump_bytecode)
|
||||||
executable->dump();
|
executable->dump();
|
||||||
JS::Bytecode::Interpreter bytecode_interpreter(interpreter->global_object(), interpreter->realm());
|
JS::Bytecode::Interpreter bytecode_interpreter(interpreter->realm());
|
||||||
MUST(bytecode_interpreter.run(*executable));
|
MUST(bytecode_interpreter.run(*executable));
|
||||||
} else {
|
} else {
|
||||||
g_vm->push_execution_context(global_execution_context);
|
g_vm->push_execution_context(global_execution_context);
|
||||||
|
@ -383,7 +383,7 @@ inline JSFileResult TestRunner::run_file_test(String const& test_path)
|
||||||
executable->name = test_path;
|
executable->name = test_path;
|
||||||
if (JS::Bytecode::g_dump_bytecode)
|
if (JS::Bytecode::g_dump_bytecode)
|
||||||
executable->dump();
|
executable->dump();
|
||||||
JS::Bytecode::Interpreter bytecode_interpreter(interpreter->realm().global_object(), interpreter->realm());
|
JS::Bytecode::Interpreter bytecode_interpreter(interpreter->realm());
|
||||||
(void)bytecode_interpreter.run(*executable);
|
(void)bytecode_interpreter.run(*executable);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -390,8 +390,8 @@ void ConnectionFromClient::initialize_js_console(Badge<PageHost>)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_interpreter = interpreter;
|
m_interpreter = interpreter;
|
||||||
m_console_client = make<WebContentConsoleClient>(interpreter->global_object().console(), interpreter, *this);
|
m_console_client = make<WebContentConsoleClient>(interpreter->realm().global_object().console(), interpreter, *this);
|
||||||
interpreter->global_object().console().set_client(*m_console_client.ptr());
|
interpreter->realm().global_object().console().set_client(*m_console_client.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionFromClient::js_console_input(String const& js_source)
|
void ConnectionFromClient::js_console_input(String const& js_source)
|
||||||
|
|
|
@ -1170,7 +1170,7 @@ static bool parse_and_run(JS::Interpreter& interpreter, StringView source, Strin
|
||||||
executable->dump();
|
executable->dump();
|
||||||
|
|
||||||
if (s_run_bytecode) {
|
if (s_run_bytecode) {
|
||||||
JS::Bytecode::Interpreter bytecode_interpreter(interpreter.realm().global_object(), interpreter.realm());
|
JS::Bytecode::Interpreter bytecode_interpreter(interpreter.realm());
|
||||||
auto result_or_error = bytecode_interpreter.run_and_return_frame(*executable, nullptr);
|
auto result_or_error = bytecode_interpreter.run_and_return_frame(*executable, nullptr);
|
||||||
if (result_or_error.value.is_error())
|
if (result_or_error.value.is_error())
|
||||||
result = result_or_error.value.release_error();
|
result = result_or_error.value.release_error();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue