Browse Source

LibJS/Bytecode: Add support for new.target

Luke Wilde 3 years ago
parent
commit
eac5534ce4

+ 1 - 0
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<void> generate_bytecode(Bytecode::Generator&) const override;
 
 private:
     Type m_type;

+ 21 - 0
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -2031,4 +2031,25 @@ Bytecode::CodeGenerationErrorOr<void> 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<void> MetaProperty::generate_bytecode(Bytecode::Generator& generator) const
+{
+    // NewTarget : new . target
+    if (m_type == MetaProperty::Type::NewTarget) {
+        // 1. Return GetNewTarget().
+        generator.emit<Bytecode::Op::GetNewTarget>();
+        return {};
+    }
+
+    // ImportMeta : import . meta
+    if (m_type == MetaProperty::Type::ImportMeta) {
+        return Bytecode::CodeGenerationError {
+            this,
+            "Unimplemented meta property: import.meta"sv,
+        };
+    }
+
+    VERIFY_NOT_REACHED();
+}
+
 }

+ 1 - 0
Userland/Libraries/LibJS/Bytecode/Instruction.h

@@ -31,6 +31,7 @@
     O(GetById)                       \
     O(GetByValue)                    \
     O(GetIterator)                   \
+    O(GetNewTarget)                  \
     O(GetObjectPropertyIterator)     \
     O(GetVariable)                   \
     O(GreaterThan)                   \

+ 11 - 0
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -358,6 +358,12 @@ ThrowCompletionOr<void> ResolveThisBinding::execute_impl(Bytecode::Interpreter&
     return {};
 }
 
+ThrowCompletionOr<void> 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;
+}
+
 }

+ 12 - 0
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<void> execute_impl(Bytecode::Interpreter&) const;
+    String to_string_impl(Bytecode::Executable const&) const;
+    void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
+};
+
 }
 
 namespace JS::Bytecode {