diff --git a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index d741a3c4578..c35bdb5097f 100644 --- a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -649,21 +649,23 @@ void ECMAScriptFunctionObject::visit_edges(Visitor& visitor) visitor.visit(m_bytecode_executable); - for (auto& field : m_fields) { - field.initializer.visit( - [&visitor](GC::Ref& initializer) { - visitor.visit(initializer); - }, - [&visitor](Value initializer) { - visitor.visit(initializer); - }, - [](Empty) {}); - if (auto* property_key_ptr = field.name.get_pointer(); property_key_ptr && property_key_ptr->is_symbol()) - visitor.visit(property_key_ptr->as_symbol()); - } + if (m_class_data) { + for (auto& field : m_class_data->fields) { + field.initializer.visit( + [&visitor](GC::Ref& initializer) { + visitor.visit(initializer); + }, + [&visitor](Value initializer) { + visitor.visit(initializer); + }, + [](Empty) {}); + if (auto* property_key_ptr = field.name.get_pointer(); property_key_ptr && property_key_ptr->is_symbol()) + visitor.visit(property_key_ptr->as_symbol()); + } - for (auto& private_element : m_private_methods) - visitor.visit(private_element.value); + for (auto& private_element : m_class_data->private_methods) + visitor.visit(private_element.value); + } m_script_or_module.visit( [](Empty) {}, @@ -960,4 +962,12 @@ void ECMAScriptFunctionObject::set_name(FlyString const& name) m_name_string = PrimitiveString::create(vm, name); MUST(define_property_or_throw(vm.names.name, { .value = m_name_string, .writable = false, .enumerable = false, .configurable = true })); } + +ECMAScriptFunctionObject::ClassData& ECMAScriptFunctionObject::ensure_class_data() const +{ + if (!m_class_data) + m_class_data = make(); + return *m_class_data; +} + } diff --git a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h b/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h index e9ba2439f92..95b053996b1 100644 --- a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h +++ b/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h @@ -152,11 +152,13 @@ public: [[nodiscard]] ByteString const& source_text() const { return shared_data().m_source_text; } void set_source_text(ByteString source_text) { const_cast(shared_data()).m_source_text = move(source_text); } - Vector const& fields() const { return m_fields; } - void add_field(ClassFieldDefinition field) { m_fields.append(move(field)); } + Vector const& fields() const { return ensure_class_data().fields; } + void add_field(ClassFieldDefinition field) { ensure_class_data().fields.append(move(field)); } - Vector const& private_methods() const { return m_private_methods; } - void add_private_method(PrivateElement method) { m_private_methods.append(move(method)); } + Vector const& private_methods() const { return ensure_class_data().private_methods; } + void add_private_method(PrivateElement method) { ensure_class_data().private_methods.append(move(method)); } + + [[nodiscard]] bool has_class_data() const { return m_class_data; } // This is for IsSimpleParameterList (static semantics) bool has_simple_parameter_list() const { return shared_data().m_has_simple_parameter_list; } @@ -211,8 +213,12 @@ private: GC::Ptr m_realm; // [[Realm]] ScriptOrModule m_script_or_module; // [[ScriptOrModule]] GC::Ptr m_home_object; // [[HomeObject]] - Vector m_fields; // [[Fields]] - Vector m_private_methods; // [[PrivateMethods]] + struct ClassData { + Vector fields; // [[Fields]] + Vector private_methods; // [[PrivateMethods]] + }; + ClassData& ensure_class_data() const; + mutable OwnPtr m_class_data; }; template<> diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index 7812d3433f6..606bd0cba90 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -699,6 +699,10 @@ ThrowCompletionOr Object::define_field(ClassFieldDefinition const& field) // 7.3.34 InitializeInstanceElements ( O, constructor ), https://tc39.es/ecma262/#sec-initializeinstanceelements ThrowCompletionOr Object::initialize_instance_elements(ECMAScriptFunctionObject& constructor) { + // AD-HOC: Avoid lazy instantiation of ECMAScriptFunctionObject::ClassData. + if (!constructor.has_class_data()) + return {}; + // 1. Let methods be the value of constructor.[[PrivateMethods]]. // 2. For each PrivateElement method of methods, do for (auto const& method : constructor.private_methods()) {