1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:07:45 +00:00

LibJS: Add spec comments to Object

This commit is contained in:
Linus Groh 2023-04-14 17:05:02 +02:00
parent 63624a3a67
commit f0dd425492

View file

@ -429,23 +429,43 @@ ThrowCompletionOr<MarkedVector<Value>> Object::enumerable_own_property_names(Pro
// 7.3.26 CopyDataProperties ( target, source, excludedItems ), https://tc39.es/ecma262/#sec-copydataproperties
ThrowCompletionOr<void> Object::copy_data_properties(VM& vm, Value source, HashTable<PropertyKey> const& seen_names)
{
// 1. If source is either undefined or null, return unused.
if (source.is_nullish())
return {};
auto from_object = MUST(source.to_object(vm));
// 2. Let from be ! ToObject(source).
auto from = MUST(source.to_object(vm));
for (auto& next_key_value : TRY(from_object->internal_own_property_keys())) {
// 3. Let keys be ? from.[[OwnPropertyKeys]]().
auto keys = TRY(from->internal_own_property_keys());
// 4. For each element nextKey of keys, do
for (auto& next_key_value : keys) {
auto next_key = MUST(PropertyKey::from_value(vm, next_key_value));
// a. Let excluded be false.
// b. For each element e of excludedItems, do
// i. If SameValue(e, nextKey) is true, then
// 1. Set excluded to true.
if (seen_names.contains(next_key))
continue;
auto desc = TRY(from_object->internal_get_own_property(next_key));
// c. If excluded is false, then
// i. Let desc be ? from.[[GetOwnProperty]](nextKey).
auto desc = TRY(from->internal_get_own_property(next_key));
// ii. If desc is not undefined and desc.[[Enumerable]] is true, then
if (desc.has_value() && desc->attributes().is_enumerable()) {
auto prop_value = TRY(from_object->get(next_key));
TRY(create_data_property_or_throw(next_key, prop_value));
// 1. Let propValue be ? Get(from, nextKey).
auto prop_value = TRY(from->get(next_key));
// 2. Perform ! CreateDataPropertyOrThrow(target, nextKey, propValue).
MUST(create_data_property_or_throw(next_key, prop_value));
}
}
// 5. Return unused.
return {};
}
@ -455,14 +475,18 @@ PrivateElement* Object::private_element_find(PrivateName const& name)
if (!m_private_elements)
return nullptr;
auto element = m_private_elements->find_if([&](auto const& element) {
// 1. If O.[[PrivateElements]] contains a PrivateElement pe such that pe.[[Key]] is P, then
auto it = m_private_elements->find_if([&](auto const& element) {
return element.key == name;
});
if (element.is_end())
return nullptr;
if (!it.is_end()) {
// a. Return pe.
return &(*it);
}
return &(*element);
// 2. Return empty.
return nullptr;
}
// 7.3.28 PrivateFieldAdd ( O, P, value ), https://tc39.es/ecma262/#sec-privatefieldadd
@ -518,58 +542,87 @@ ThrowCompletionOr<void> Object::private_method_or_accessor_add(PrivateElement el
return {};
}
// 7.3.30 PrivateGet ( O, P ), https://tc39.es/ecma262/#sec-privateget
// 7.3.31 PrivateGet ( O, P ), https://tc39.es/ecma262/#sec-privateget
ThrowCompletionOr<Value> Object::private_get(PrivateName const& name)
{
auto& vm = this->vm();
// 1. Let entry be PrivateElementFind(O, P).
auto* entry = private_element_find(name);
// 2. If entry is empty, throw a TypeError exception.
if (!entry)
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
auto& value = entry->value;
if (entry->kind != PrivateElement::Kind::Accessor)
// 3. If entry.[[Kind]] is either field or method, then
if (entry->kind != PrivateElement::Kind::Accessor) {
// a. Return entry.[[Value]].
return value;
}
// Assert: entry.[[Kind]] is accessor.
VERIFY(value.is_accessor());
// 6. Let getter be entry.[[Get]].
auto* getter = value.as_accessor().getter();
// 5. If entry.[[Get]] is undefined, throw a TypeError exception.
if (!getter)
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldGetAccessorWithoutGetter, name.description);
// 8. Return ? Call(getter, Receiver).
// 7. Return ? Call(getter, O).
return TRY(call(vm, *getter, this));
}
// 7.3.31 PrivateSet ( O, P, value ), https://tc39.es/ecma262/#sec-privateset
// 7.3.32 PrivateSet ( O, P, value ), https://tc39.es/ecma262/#sec-privateset
ThrowCompletionOr<void> Object::private_set(PrivateName const& name, Value value)
{
auto& vm = this->vm();
// 1. Let entry be PrivateElementFind(O, P).
auto* entry = private_element_find(name);
// 2. If entry is empty, throw a TypeError exception.
if (!entry)
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
// 3. If entry.[[Kind]] is field, then
if (entry->kind == PrivateElement::Kind::Field) {
// a. Set entry.[[Value]] to value.
entry->value = value;
return {};
} else if (entry->kind == PrivateElement::Kind::Method) {
}
// 4. Else if entry.[[Kind]] is method, then
else if (entry->kind == PrivateElement::Kind::Method) {
// a. Throw a TypeError exception.
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldSetMethod, name.description);
}
// 5. Else,
// a. Assert: entry.[[Kind]] is accessor.
VERIFY(entry->kind == PrivateElement::Kind::Accessor);
auto& accessor = entry->value;
VERIFY(accessor.is_accessor());
// c. Let setter be entry.[[Set]].
auto* setter = accessor.as_accessor().setter();
// b. If entry.[[Set]] is undefined, throw a TypeError exception.
if (!setter)
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldSetAccessorWithoutSetter, name.description);
// d. Perform ? Call(setter, O, « value »).
TRY(call(vm, *setter, this, value));
// 6. Return unused.
return {};
}
// 7.3.32 DefineField ( receiver, fieldRecord ), https://tc39.es/ecma262/#sec-definefield
// 7.3.33 DefineField ( receiver, fieldRecord ), https://tc39.es/ecma262/#sec-definefield
ThrowCompletionOr<void> Object::define_field(ClassFieldDefinition const& field)
{
auto& vm = this->vm();
@ -605,7 +658,7 @@ ThrowCompletionOr<void> Object::define_field(ClassFieldDefinition const& field)
return {};
}
// 7.3.33 InitializeInstanceElements ( O, constructor ), https://tc39.es/ecma262/#sec-initializeinstanceelements
// 7.3.34 InitializeInstanceElements ( O, constructor ), https://tc39.es/ecma262/#sec-initializeinstanceelements
ThrowCompletionOr<void> Object::initialize_instance_elements(ECMAScriptFunctionObject& constructor)
{
// 1. Let methods be the value of constructor.[[PrivateMethods]].