diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index f1c3504429..8145727bb9 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -3492,7 +3492,6 @@ Completion MetaProperty::execute(Interpreter& interpreter) const { InterpreterNodeScope node_scope { interpreter, *this }; auto& vm = interpreter.vm(); - auto& realm = *vm.current_realm(); // NewTarget : new . target if (m_type == MetaProperty::Type::NewTarget) { @@ -3502,49 +3501,7 @@ Completion MetaProperty::execute(Interpreter& interpreter) const // ImportMeta : import . meta if (m_type == MetaProperty::Type::ImportMeta) { - // 1. Let module be GetActiveScriptOrModule(). - auto script_or_module = interpreter.vm().get_active_script_or_module(); - - // 2. Assert: module is a Source Text Module Record. - VERIFY(script_or_module.has>()); - VERIFY(script_or_module.get>()); - VERIFY(is(*script_or_module.get>())); - auto& module = static_cast(*script_or_module.get>()); - - // 3. Let importMeta be module.[[ImportMeta]]. - auto* import_meta = module.import_meta(); - - // 4. If importMeta is empty, then - if (import_meta == nullptr) { - // a. Set importMeta to OrdinaryObjectCreate(null). - import_meta = Object::create(realm, nullptr); - - // b. Let importMetaValues be HostGetImportMetaProperties(module). - auto import_meta_values = interpreter.vm().host_get_import_meta_properties(module); - - // c. For each Record { [[Key]], [[Value]] } p of importMetaValues, do - for (auto& entry : import_meta_values) { - // i. Perform ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]]). - MUST(import_meta->create_data_property_or_throw(entry.key, entry.value)); - } - - // d. Perform HostFinalizeImportMeta(importMeta, module). - interpreter.vm().host_finalize_import_meta(import_meta, module); - - // e. Set module.[[ImportMeta]] to importMeta. - module.set_import_meta({}, import_meta); - - // f. Return importMeta. - return Value { import_meta }; - } - // 5. Else, - else { - // a. Assert: Type(importMeta) is Object. - // Note: This is always true by the type. - - // b. Return importMeta. - return Value { import_meta }; - } + return Value(vm.get_import_meta()); } VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index cfe8583ee7..c2d4248464 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -2884,10 +2884,8 @@ Bytecode::CodeGenerationErrorOr MetaProperty::generate_bytecode(Bytecode:: // ImportMeta : import . meta if (m_type == MetaProperty::Type::ImportMeta) { - return Bytecode::CodeGenerationError { - this, - "Unimplemented meta property: import.meta"sv, - }; + generator.emit(); + return {}; } VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index 30cab2e458..b0e34fb794 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -42,6 +42,7 @@ O(GetIterator) \ O(GetMethod) \ O(GetNewTarget) \ + O(GetImportMeta) \ O(GetObjectPropertyIterator) \ O(GetPrivateById) \ O(GetVariable) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index e928721a30..1cf54287f6 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace JS::Bytecode { @@ -762,6 +763,12 @@ ThrowCompletionOr GetNewTarget::execute_impl(Bytecode::Interpreter& interp return {}; } +ThrowCompletionOr GetImportMeta::execute_impl(Bytecode::Interpreter& interpreter) const +{ + interpreter.accumulator() = interpreter.vm().get_import_meta(); + return {}; +} + void Jump::replace_references_impl(BasicBlock const& from, BasicBlock const& to) { if (m_true_target.has_value() && &m_true_target->block() == &from) @@ -1896,6 +1903,11 @@ DeprecatedString GetNewTarget::to_deprecated_string_impl(Bytecode::Executable co return "GetNewTarget"sv; } +DeprecatedString GetImportMeta::to_deprecated_string_impl(Bytecode::Executable const&) const +{ + return "GetImportMeta"sv; +} + DeprecatedString TypeofVariable::to_deprecated_string_impl(Bytecode::Executable const& executable) const { return DeprecatedString::formatted("TypeofVariable {} ({})", m_identifier, executable.identifier_table->get(m_identifier)); diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index ff1b1747a2..f466892e8d 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -1538,6 +1538,19 @@ public: void replace_references_impl(Register, Register) { } }; +class GetImportMeta final : public Instruction { +public: + explicit GetImportMeta() + : Instruction(Type::GetImportMeta) + { + } + + ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; + DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const; + void replace_references_impl(BasicBlock const&, BasicBlock const&) { } + void replace_references_impl(Register, Register) { } +}; + class TypeofVariable final : public Instruction { public: explicit TypeofVariable(IdentifierTableIndex identifier) diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 9e067071de..15a9dfab98 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -682,6 +682,52 @@ Value VM::get_new_target() return verify_cast(*env).new_target(); } +// 13.3.12.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-meta-properties-runtime-semantics-evaluation +// ImportMeta branch only +Object* VM::get_import_meta() +{ + // 1. Let module be GetActiveScriptOrModule(). + auto script_or_module = get_active_script_or_module(); + + // 2. Assert: module is a Source Text Module Record. + auto& module = verify_cast(*script_or_module.get>()); + + // 3. Let importMeta be module.[[ImportMeta]]. + auto* import_meta = module.import_meta(); + + // 4. If importMeta is empty, then + if (import_meta == nullptr) { + // a. Set importMeta to OrdinaryObjectCreate(null). + import_meta = Object::create(*current_realm(), nullptr); + + // b. Let importMetaValues be HostGetImportMetaProperties(module). + auto import_meta_values = host_get_import_meta_properties(module); + + // c. For each Record { [[Key]], [[Value]] } p of importMetaValues, do + for (auto& entry : import_meta_values) { + // i. Perform ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]]). + MUST(import_meta->create_data_property_or_throw(entry.key, entry.value)); + } + + // d. Perform HostFinalizeImportMeta(importMeta, module). + host_finalize_import_meta(import_meta, module); + + // e. Set module.[[ImportMeta]] to importMeta. + module.set_import_meta({}, import_meta); + + // f. Return importMeta. + return import_meta; + } + // 5. Else, + else { + // a. Assert: Type(importMeta) is Object. + // Note: This is always true by the type. + + // b. Return importMeta. + return import_meta; + } +} + // 9.4.5 GetGlobalObject ( ), https://tc39.es/ecma262/#sec-getglobalobject Object& VM::get_global_object() { diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index ec5dc552d2..015a5bfe45 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -219,6 +219,8 @@ public: Value get_new_target(); + Object* get_import_meta(); + Object& get_global_object(); CommonPropertyNames names; diff --git a/Userland/Libraries/LibJS/SourceTextModule.h b/Userland/Libraries/LibJS/SourceTextModule.h index c79f122bfa..5bef17696d 100644 --- a/Userland/Libraries/LibJS/SourceTextModule.h +++ b/Userland/Libraries/LibJS/SourceTextModule.h @@ -26,7 +26,7 @@ public: virtual ThrowCompletionOr resolve_export(VM& vm, DeprecatedFlyString const& export_name, Vector resolve_set = {}) override; Object* import_meta() { return m_import_meta; } - void set_import_meta(Badge, Object* import_meta) { m_import_meta = import_meta; } + void set_import_meta(Badge, Object* import_meta) { m_import_meta = import_meta; } protected: virtual ThrowCompletionOr initialize_environment(VM& vm) override;