LibJS: Don't leak class field initializers

We were storing these in Handle (strong GC roots) hanging off of
ECMAScriptFunctionObject which effectively turned into world leaks.

(cherry picked from commit 5aa1d7837fe37dd203763178df3325ff8b24abbd)
This commit is contained in:
Andreas Kling 2024-11-10 13:03:38 +01:00 committed by Nico Weber
parent 1b6c784b77
commit 3590a94fc4
4 changed files with 7 additions and 6 deletions

View file

@ -227,7 +227,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation
auto& realm = *vm.current_realm();
auto property_key_or_private_name = TRY(class_key_to_property_name(vm, *m_key, property_key));
Handle<ECMAScriptFunctionObject> initializer {};
GCPtr<ECMAScriptFunctionObject> initializer;
if (m_initializer) {
auto copy_initializer = m_initializer;
auto name = property_key_or_private_name.visit(
@ -370,7 +370,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
ConservativeVector<PrivateElement> static_private_methods(vm.heap());
ConservativeVector<PrivateElement> instance_private_methods(vm.heap());
Vector<ClassFieldDefinition> instance_fields;
ConservativeVector<ClassFieldDefinition> instance_fields(vm.heap());
Vector<StaticElement> static_elements;
for (size_t element_index = 0; element_index < m_elements.size(); element_index++) {

View file

@ -17,8 +17,8 @@ using ClassElementName = Variant<PropertyKey, PrivateName>;
// 6.2.10 The ClassFieldDefinition Record Specification Type, https://tc39.es/ecma262/#sec-classfielddefinition-record-specification-type
struct ClassFieldDefinition {
ClassElementName name; // [[Name]]
Handle<ECMAScriptFunctionObject> initializer; // [[Initializer]]
ClassElementName name; // [[Name]]
GCPtr<ECMAScriptFunctionObject> initializer; // [[Initializer]]
};
}

View file

@ -544,6 +544,7 @@ void ECMAScriptFunctionObject::visit_edges(Visitor& visitor)
visitor.visit(m_bytecode_executable);
for (auto& field : m_fields) {
visitor.visit(field.initializer);
if (auto* property_key_ptr = field.name.get_pointer<PropertyKey>(); property_key_ptr && property_key_ptr->is_symbol())
visitor.visit(property_key_ptr->as_symbol());
}

View file

@ -679,9 +679,9 @@ ThrowCompletionOr<void> Object::define_field(ClassFieldDefinition const& field)
auto init_value = js_undefined();
// 3. If initializer is not empty, then
if (!initializer.is_null()) {
if (initializer) {
// a. Let initValue be ? Call(initializer, receiver).
init_value = TRY(call(vm, initializer.cell(), this));
init_value = TRY(call(vm, initializer, this));
}
// 4. Else, let initValue be undefined.