diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index 4880b30766..ea9b283116 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -1866,6 +1866,7 @@ public: virtual Completion execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; + virtual Bytecode::CodeGenerationErrorOr generate_bytecode(Bytecode::Generator&) const override; private: Type m_type; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index cd68d08209..49001ab8de 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -2031,4 +2031,25 @@ Bytecode::CodeGenerationErrorOr ForOfStatement::generate_bytecode(Bytecode return for_in_of_body_evaluation(generator, *this, m_lhs, body(), head_result, loop_end, loop_update); } +// 13.3.12.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-meta-properties-runtime-semantics-evaluation +Bytecode::CodeGenerationErrorOr MetaProperty::generate_bytecode(Bytecode::Generator& generator) const +{ + // NewTarget : new . target + if (m_type == MetaProperty::Type::NewTarget) { + // 1. Return GetNewTarget(). + generator.emit(); + return {}; + } + + // ImportMeta : import . meta + if (m_type == MetaProperty::Type::ImportMeta) { + return Bytecode::CodeGenerationError { + this, + "Unimplemented meta property: import.meta"sv, + }; + } + + VERIFY_NOT_REACHED(); +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index cf28733751..f9c8dffa0c 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -31,6 +31,7 @@ O(GetById) \ O(GetByValue) \ O(GetIterator) \ + O(GetNewTarget) \ O(GetObjectPropertyIterator) \ O(GetVariable) \ O(GreaterThan) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 76d3e606bb..5e8d6183be 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -358,6 +358,12 @@ ThrowCompletionOr ResolveThisBinding::execute_impl(Bytecode::Interpreter& return {}; } +ThrowCompletionOr GetNewTarget::execute_impl(Bytecode::Interpreter& interpreter) const +{ + interpreter.accumulator() = interpreter.vm().get_new_target(); + return {}; +} + void Jump::replace_references_impl(BasicBlock const& from, BasicBlock const& to) { if (m_true_target.has_value() && &m_true_target->block() == &from) @@ -976,4 +982,9 @@ String ResolveThisBinding::to_string_impl(Bytecode::Executable const&) const return "ResolveThisBinding"sv; } +String GetNewTarget::to_string_impl(Bytecode::Executable const&) const +{ + return "GetNewTarget"sv; +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 0c6f4116a8..d3c5284af4 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -838,6 +838,18 @@ public: void replace_references_impl(BasicBlock const&, BasicBlock const&) { } }; +class GetNewTarget final : public Instruction { +public: + explicit GetNewTarget() + : Instruction(Type::GetNewTarget) + { + } + + ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; + String to_string_impl(Bytecode::Executable const&) const; + void replace_references_impl(BasicBlock const&, BasicBlock const&) { } +}; + } namespace JS::Bytecode {