mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:47:34 +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
|
// 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)
|
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())
|
if (source.is_nullish())
|
||||||
return {};
|
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));
|
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))
|
if (seen_names.contains(next_key))
|
||||||
continue;
|
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()) {
|
if (desc.has_value() && desc->attributes().is_enumerable()) {
|
||||||
auto prop_value = TRY(from_object->get(next_key));
|
// 1. Let propValue be ? Get(from, nextKey).
|
||||||
TRY(create_data_property_or_throw(next_key, prop_value));
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,14 +475,18 @@ PrivateElement* Object::private_element_find(PrivateName const& name)
|
||||||
if (!m_private_elements)
|
if (!m_private_elements)
|
||||||
return nullptr;
|
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;
|
return element.key == name;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (element.is_end())
|
if (!it.is_end()) {
|
||||||
return nullptr;
|
// 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
|
// 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 {};
|
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)
|
ThrowCompletionOr<Value> Object::private_get(PrivateName const& name)
|
||||||
{
|
{
|
||||||
auto& vm = this->vm();
|
auto& vm = this->vm();
|
||||||
|
|
||||||
|
// 1. Let entry be PrivateElementFind(O, P).
|
||||||
auto* entry = private_element_find(name);
|
auto* entry = private_element_find(name);
|
||||||
|
|
||||||
|
// 2. If entry is empty, throw a TypeError exception.
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
|
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
|
||||||
|
|
||||||
auto& value = entry->value;
|
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;
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert: entry.[[Kind]] is accessor.
|
||||||
VERIFY(value.is_accessor());
|
VERIFY(value.is_accessor());
|
||||||
|
|
||||||
|
// 6. Let getter be entry.[[Get]].
|
||||||
auto* getter = value.as_accessor().getter();
|
auto* getter = value.as_accessor().getter();
|
||||||
|
|
||||||
|
// 5. If entry.[[Get]] is undefined, throw a TypeError exception.
|
||||||
if (!getter)
|
if (!getter)
|
||||||
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldGetAccessorWithoutGetter, name.description);
|
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));
|
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)
|
ThrowCompletionOr<void> Object::private_set(PrivateName const& name, Value value)
|
||||||
{
|
{
|
||||||
auto& vm = this->vm();
|
auto& vm = this->vm();
|
||||||
|
|
||||||
|
// 1. Let entry be PrivateElementFind(O, P).
|
||||||
auto* entry = private_element_find(name);
|
auto* entry = private_element_find(name);
|
||||||
|
|
||||||
|
// 2. If entry is empty, throw a TypeError exception.
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
|
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldDoesNotExistOnObject, name.description);
|
||||||
|
|
||||||
|
// 3. If entry.[[Kind]] is field, then
|
||||||
if (entry->kind == PrivateElement::Kind::Field) {
|
if (entry->kind == PrivateElement::Kind::Field) {
|
||||||
|
// a. Set entry.[[Value]] to value.
|
||||||
entry->value = value;
|
entry->value = value;
|
||||||
return {};
|
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);
|
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldSetMethod, name.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5. Else,
|
||||||
|
|
||||||
|
// a. Assert: entry.[[Kind]] is accessor.
|
||||||
VERIFY(entry->kind == PrivateElement::Kind::Accessor);
|
VERIFY(entry->kind == PrivateElement::Kind::Accessor);
|
||||||
|
|
||||||
auto& accessor = entry->value;
|
auto& accessor = entry->value;
|
||||||
VERIFY(accessor.is_accessor());
|
VERIFY(accessor.is_accessor());
|
||||||
|
|
||||||
|
// c. Let setter be entry.[[Set]].
|
||||||
auto* setter = accessor.as_accessor().setter();
|
auto* setter = accessor.as_accessor().setter();
|
||||||
|
|
||||||
|
// b. If entry.[[Set]] is undefined, throw a TypeError exception.
|
||||||
if (!setter)
|
if (!setter)
|
||||||
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldSetAccessorWithoutSetter, name.description);
|
return vm.throw_completion<TypeError>(ErrorType::PrivateFieldSetAccessorWithoutSetter, name.description);
|
||||||
|
|
||||||
|
// d. Perform ? Call(setter, O, « value »).
|
||||||
TRY(call(vm, *setter, this, value));
|
TRY(call(vm, *setter, this, value));
|
||||||
|
|
||||||
|
// 6. Return unused.
|
||||||
return {};
|
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)
|
ThrowCompletionOr<void> Object::define_field(ClassFieldDefinition const& field)
|
||||||
{
|
{
|
||||||
auto& vm = this->vm();
|
auto& vm = this->vm();
|
||||||
|
@ -605,7 +658,7 @@ ThrowCompletionOr<void> Object::define_field(ClassFieldDefinition const& field)
|
||||||
return {};
|
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)
|
ThrowCompletionOr<void> Object::initialize_instance_elements(ECMAScriptFunctionObject& constructor)
|
||||||
{
|
{
|
||||||
// 1. Let methods be the value of constructor.[[PrivateMethods]].
|
// 1. Let methods be the value of constructor.[[PrivateMethods]].
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue