瀏覽代碼

LibJS: Move [[ConstructorKind]] to ECMAScriptFunctionObject

Linus Groh 3 年之前
父節點
當前提交
06726d41ac

+ 1 - 1
Userland/Libraries/LibJS/AST.cpp

@@ -886,7 +886,7 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
             interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ClassExtendsValueNotAConstructorOrNull, super_constructor.to_string_without_side_effects());
             interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ClassExtendsValueNotAConstructorOrNull, super_constructor.to_string_without_side_effects());
             return {};
             return {};
         }
         }
-        class_constructor->set_constructor_kind(FunctionObject::ConstructorKind::Derived);
+        class_constructor->set_constructor_kind(ECMAScriptFunctionObject::ConstructorKind::Derived);
 
 
         Object* super_constructor_prototype = nullptr;
         Object* super_constructor_prototype = nullptr;
         if (!super_constructor.is_null()) {
         if (!super_constructor.is_null()) {

+ 16 - 7
Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h

@@ -17,6 +17,11 @@ class ECMAScriptFunctionObject final : public FunctionObject {
     JS_OBJECT(ECMAScriptFunctionObject, FunctionObject);
     JS_OBJECT(ECMAScriptFunctionObject, FunctionObject);
 
 
 public:
 public:
+    enum class ConstructorKind : u8 {
+        Base,
+        Derived,
+    };
+
     enum class ThisMode : u8 {
     enum class ThisMode : u8 {
         Lexical,
         Lexical,
         Strict,
         Strict,
@@ -45,6 +50,9 @@ public:
     virtual Environment* environment() override { return m_environment; }
     virtual Environment* environment() override { return m_environment; }
     virtual Realm* realm() const override { return m_realm; }
     virtual Realm* realm() const override { return m_realm; }
 
 
+    ConstructorKind constructor_kind() const { return m_constructor_kind; };
+    void set_constructor_kind(ConstructorKind constructor_kind) { m_constructor_kind = constructor_kind; }
+
     ThisMode this_mode() const { return m_this_mode; }
     ThisMode this_mode() const { return m_this_mode; }
 
 
 protected:
 protected:
@@ -58,13 +66,14 @@ private:
     Value execute_function_body();
     Value execute_function_body();
 
 
     // Internal Slots of ECMAScript Function Objects, https://tc39.es/ecma262/#table-internal-slots-of-ecmascript-function-objects
     // Internal Slots of ECMAScript Function Objects, https://tc39.es/ecma262/#table-internal-slots-of-ecmascript-function-objects
-    Environment* m_environment { nullptr };                    // [[Environment]]
-    Vector<FunctionNode::Parameter> const m_formal_parameters; // [[FormalParameters]]
-    NonnullRefPtr<Statement> m_ecmascript_code;                // [[ECMAScriptCode]]
-    Realm* m_realm { nullptr };                                // [[Realm]]
-    ThisMode m_this_mode { ThisMode::Global };                 // [[ThisMode]]
-    bool m_strict { false };                                   // [[Strict]]
-    bool m_is_class_constructor { false };                     // [[IsClassConstructor]]
+    Environment* m_environment { nullptr };                       // [[Environment]]
+    Vector<FunctionNode::Parameter> const m_formal_parameters;    // [[FormalParameters]]
+    NonnullRefPtr<Statement> m_ecmascript_code;                   // [[ECMAScriptCode]]
+    ConstructorKind m_constructor_kind { ConstructorKind::Base }; // [[ConstructorKind]]
+    Realm* m_realm { nullptr };                                   // [[Realm]]
+    ThisMode m_this_mode { ThisMode::Global };                    // [[ThisMode]]
+    bool m_strict { false };                                      // [[Strict]]
+    bool m_is_class_constructor { false };                        // [[IsClassConstructor]]
 
 
     FlyString m_name;
     FlyString m_name;
     Optional<Bytecode::Executable> m_bytecode_executable;
     Optional<Bytecode::Executable> m_bytecode_executable;

+ 0 - 9
Userland/Libraries/LibJS/Runtime/FunctionObject.h

@@ -15,11 +15,6 @@ class FunctionObject : public Object {
     JS_OBJECT(Function, Object);
     JS_OBJECT(Function, Object);
 
 
 public:
 public:
-    enum class ConstructorKind {
-        Base,
-        Derived,
-    };
-
     virtual ~FunctionObject();
     virtual ~FunctionObject();
     virtual void initialize(GlobalObject&) override { }
     virtual void initialize(GlobalObject&) override { }
 
 
@@ -37,9 +32,6 @@ public:
     Object* home_object() const { return m_home_object; }
     Object* home_object() const { return m_home_object; }
     void set_home_object(Object* home_object) { m_home_object = home_object; }
     void set_home_object(Object* home_object) { m_home_object = home_object; }
 
 
-    ConstructorKind constructor_kind() const { return m_constructor_kind; };
-    void set_constructor_kind(ConstructorKind constructor_kind) { m_constructor_kind = constructor_kind; }
-
     virtual bool is_strict_mode() const { return false; }
     virtual bool is_strict_mode() const { return false; }
 
 
     // [[Environment]]
     // [[Environment]]
@@ -77,7 +69,6 @@ private:
     Value m_bound_this;
     Value m_bound_this;
     Vector<Value> m_bound_arguments;
     Vector<Value> m_bound_arguments;
     Object* m_home_object { nullptr };
     Object* m_home_object { nullptr };
-    ConstructorKind m_constructor_kind = ConstructorKind::Base;
     bool m_has_simple_parameter_list { false };
     bool m_has_simple_parameter_list { false };
     Vector<InstanceField> m_fields;
     Vector<InstanceField> m_fields;
 };
 };

+ 8 - 3
Userland/Libraries/LibJS/Runtime/VM.cpp

@@ -470,12 +470,14 @@ void VM::initialize_instance_elements(Object& object, FunctionObject& constructo
     }
     }
 }
 }
 
 
+// FIXME: This function should not exist as-is, most of it should be moved to the individual
+//        [[Construct]] implementations so that this becomes the Construct() AO (3 steps).
 Value VM::construct(FunctionObject& function, FunctionObject& new_target, Optional<MarkedValueList> arguments)
 Value VM::construct(FunctionObject& function, FunctionObject& new_target, Optional<MarkedValueList> arguments)
 {
 {
     auto& global_object = function.global_object();
     auto& global_object = function.global_object();
 
 
     Value this_argument;
     Value this_argument;
-    if (function.constructor_kind() == FunctionObject::ConstructorKind::Base)
+    if (!is<ECMAScriptFunctionObject>(function) || static_cast<ECMAScriptFunctionObject&>(function).constructor_kind() == ECMAScriptFunctionObject::ConstructorKind::Base)
         this_argument = TRY_OR_DISCARD(ordinary_create_from_constructor<Object>(global_object, new_target, &GlobalObject::object_prototype));
         this_argument = TRY_OR_DISCARD(ordinary_create_from_constructor<Object>(global_object, new_target, &GlobalObject::object_prototype));
 
 
     // FIXME: prepare_for_ordinary_call() is not supposed to receive a BoundFunction, ProxyObject, etc. - ever.
     // FIXME: prepare_for_ordinary_call() is not supposed to receive a BoundFunction, ProxyObject, etc. - ever.
@@ -507,7 +509,7 @@ Value VM::construct(FunctionObject& function, FunctionObject& new_target, Option
     // If we are a Derived constructor, |this| has not been constructed before super is called.
     // If we are a Derived constructor, |this| has not been constructed before super is called.
     callee_context.this_value = this_argument;
     callee_context.this_value = this_argument;
 
 
-    if (function.constructor_kind() == FunctionObject::ConstructorKind::Base) {
+    if (!is<ECMAScriptFunctionObject>(function) || static_cast<ECMAScriptFunctionObject&>(function).constructor_kind() == ECMAScriptFunctionObject::ConstructorKind::Base) {
         VERIFY(this_argument.is_object());
         VERIFY(this_argument.is_object());
         initialize_instance_elements(this_argument.as_object(), function);
         initialize_instance_elements(this_argument.as_object(), function);
         if (exception())
         if (exception())
@@ -521,7 +523,10 @@ Value VM::construct(FunctionObject& function, FunctionObject& new_target, Option
 
 
     // If we are constructing an instance of a derived class,
     // If we are constructing an instance of a derived class,
     // set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses).
     // set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses).
-    if (function.constructor_kind() == FunctionObject::ConstructorKind::Base && new_target.constructor_kind() == FunctionObject::ConstructorKind::Derived && result.is_object()) {
+
+    if ((!is<ECMAScriptFunctionObject>(function) || static_cast<ECMAScriptFunctionObject&>(function).constructor_kind() == ECMAScriptFunctionObject::ConstructorKind::Base)
+        && is<ECMAScriptFunctionObject>(new_target) && static_cast<ECMAScriptFunctionObject&>(new_target).constructor_kind() == ECMAScriptFunctionObject::ConstructorKind::Derived
+        && result.is_object()) {
         if (auto* environment = callee_context.lexical_environment)
         if (auto* environment = callee_context.lexical_environment)
             verify_cast<FunctionEnvironment>(environment)->replace_this_binding(result);
             verify_cast<FunctionEnvironment>(environment)->replace_this_binding(result);
         auto prototype = new_target.get(names.prototype);
         auto prototype = new_target.get(names.prototype);