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:
parent
63624a3a67
commit
f0dd425492
1 changed files with 69 additions and 16 deletions
|
@ -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]].
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue