mirror of
https://github.com/RGBCube/serenity
synced 2025-07-28 06:37:35 +00:00
LibJS: De-duplicate ClassFieldDefinition Records
This was defined twice, despite being the very same thing: - ClassElement::ClassFieldDefinition - ECMAScriptFunctionObject::InstanceField Move the former to a new header and use it everywhere. Also update the define_field() AO to take a single field instead of separate name and initializer arguments.
This commit is contained in:
parent
7a02d33cd5
commit
e815d3f9ce
9 changed files with 66 additions and 41 deletions
22
Userland/Libraries/LibJS/Runtime/ClassFieldDefinition.h
Normal file
22
Userland/Libraries/LibJS/Runtime/ClassFieldDefinition.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <LibJS/Forward.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
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]]
|
||||
};
|
||||
|
||||
}
|
|
@ -299,8 +299,6 @@ void ECMAScriptFunctionObject::visit_edges(Visitor& visitor)
|
|||
for (auto& field : m_fields) {
|
||||
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());
|
||||
|
||||
visitor.visit(field.initializer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -886,9 +884,4 @@ void ECMAScriptFunctionObject::set_name(FlyString const& name)
|
|||
VERIFY(success);
|
||||
}
|
||||
|
||||
void ECMAScriptFunctionObject::add_field(ClassElement::ClassElementName property_key, ECMAScriptFunctionObject* initializer)
|
||||
{
|
||||
m_fields.empend(property_key, initializer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -68,13 +68,8 @@ public:
|
|||
String const& source_text() const { return m_source_text; }
|
||||
void set_source_text(String source_text) { m_source_text = move(source_text); }
|
||||
|
||||
struct InstanceField {
|
||||
Variant<PropertyKey, PrivateName> name;
|
||||
ECMAScriptFunctionObject* initializer { nullptr };
|
||||
};
|
||||
|
||||
Vector<InstanceField> const& fields() const { return m_fields; }
|
||||
void add_field(Variant<PropertyKey, PrivateName> property_key, ECMAScriptFunctionObject* initializer);
|
||||
Vector<ClassFieldDefinition> const& fields() const { return m_fields; }
|
||||
void add_field(ClassFieldDefinition field) { m_fields.append(move(field)); }
|
||||
|
||||
Vector<PrivateElement> const& private_methods() const { return m_private_methods; }
|
||||
void add_private_method(PrivateElement method) { m_private_methods.append(move(method)); };
|
||||
|
@ -123,7 +118,7 @@ private:
|
|||
ScriptOrModule m_script_or_module; // [[ScriptOrModule]]
|
||||
Object* m_home_object { nullptr }; // [[HomeObject]]
|
||||
String m_source_text; // [[SourceText]]
|
||||
Vector<InstanceField> m_fields; // [[Fields]]
|
||||
Vector<ClassFieldDefinition> m_fields; // [[Fields]]
|
||||
Vector<PrivateElement> m_private_methods; // [[PrivateMethods]]
|
||||
Variant<PropertyKey, PrivateName, Empty> m_class_field_initializer_name; // [[ClassFieldInitializerName]]
|
||||
ConstructorKind m_constructor_kind : 1 { ConstructorKind::Base }; // [[ConstructorKind]]
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Accessor.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/ClassFieldDefinition.h>
|
||||
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
@ -556,17 +557,36 @@ ThrowCompletionOr<void> Object::private_set(PrivateName const& name, Value value
|
|||
}
|
||||
|
||||
// 7.3.32 DefineField ( receiver, fieldRecord ), https://tc39.es/ecma262/#sec-definefield
|
||||
ThrowCompletionOr<void> Object::define_field(Variant<PropertyKey, PrivateName> name, ECMAScriptFunctionObject* initializer)
|
||||
ThrowCompletionOr<void> Object::define_field(ClassFieldDefinition const& field)
|
||||
{
|
||||
Value init_value = js_undefined();
|
||||
if (initializer)
|
||||
init_value = TRY(call(global_object(), *initializer, this));
|
||||
// 1. Let fieldName be fieldRecord.[[Name]].
|
||||
auto const& field_name = field.name;
|
||||
|
||||
if (auto* property_key_ptr = name.get_pointer<PropertyKey>())
|
||||
TRY(create_data_property_or_throw(*property_key_ptr, init_value));
|
||||
else
|
||||
TRY(private_field_add(name.get<PrivateName>(), init_value));
|
||||
// 2. Let initializer be fieldRecord.[[Initializer]].
|
||||
auto const& initializer = field.initializer;
|
||||
|
||||
auto init_value = js_undefined();
|
||||
|
||||
// 3. If initializer is not empty, then
|
||||
if (!initializer.is_null()) {
|
||||
// a. Let initValue be ? Call(initializer, receiver).
|
||||
init_value = TRY(call(global_object(), initializer.cell(), this));
|
||||
}
|
||||
// 4. Else, let initValue be undefined.
|
||||
|
||||
// 5. If fieldName is a Private Name, then
|
||||
if (field_name.has<PrivateName>()) {
|
||||
// a. Perform ? PrivateFieldAdd(receiver, fieldName, initValue).
|
||||
TRY(private_field_add(field_name.get<PrivateName>(), init_value));
|
||||
}
|
||||
// 6. Else,
|
||||
else {
|
||||
// a. Assert: IsPropertyKey(fieldName) is true.
|
||||
// b. Perform ? CreateDataPropertyOrThrow(receiver, fieldName, initValue).
|
||||
TRY(create_data_property_or_throw(field_name.get<PropertyKey>(), init_value));
|
||||
}
|
||||
|
||||
// 7. Return unused.
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ public:
|
|||
ThrowCompletionOr<void> private_method_or_accessor_add(PrivateElement element);
|
||||
ThrowCompletionOr<Value> private_get(PrivateName const& name);
|
||||
ThrowCompletionOr<void> private_set(PrivateName const& name, Value value);
|
||||
ThrowCompletionOr<void> define_field(Variant<PropertyKey, PrivateName> name, ECMAScriptFunctionObject* initializer);
|
||||
ThrowCompletionOr<void> define_field(ClassFieldDefinition const&);
|
||||
|
||||
// 10.1 Ordinary Object Internal Methods and Internal Slots, https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
|
||||
|
||||
|
|
|
@ -600,7 +600,7 @@ ThrowCompletionOr<void> VM::initialize_instance_elements(Object& object, ECMAScr
|
|||
TRY(object.private_method_or_accessor_add(method));
|
||||
|
||||
for (auto& field : constructor.fields())
|
||||
TRY(object.define_field(field.name, field.initializer));
|
||||
TRY(object.define_field(field));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue