diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index 765559451b..7a07e2472e 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -173,15 +173,13 @@ ThrowCompletionOr get_function_realm(GlobalObject& global_object, Functi { auto& vm = global_object.vm(); - // 1. Assert: ! IsCallable(obj) is true. - - // 2. If obj has a [[Realm]] internal slot, then + // 1. If obj has a [[Realm]] internal slot, then if (function.realm()) { // a. Return obj.[[Realm]]. return function.realm(); } - // 3. If obj is a bound function exotic object, then + // 2. If obj is a bound function exotic object, then if (is(function)) { auto& bound_function = static_cast(function); @@ -192,7 +190,7 @@ ThrowCompletionOr get_function_realm(GlobalObject& global_object, Functi return get_function_realm(global_object, target); } - // 4. If obj is a Proxy exotic object, then + // 3. If obj is a Proxy exotic object, then if (is(function)) { auto& proxy = static_cast(function); @@ -208,7 +206,7 @@ ThrowCompletionOr get_function_realm(GlobalObject& global_object, Functi return get_function_realm(global_object, static_cast(proxy_target)); } - // 5. Return the current Realm Record. + // 4. Return the current Realm Record. return vm.current_realm(); } @@ -1161,7 +1159,6 @@ CanonicalIndex canonical_numeric_index_string(PropertyKey const& property_key, C if (mode != CanonicalIndexMode::DetectNumericRoundtrip) return CanonicalIndex(CanonicalIndex::Type::Undefined, 0); - // 1. Assert: Type(argument) is String. auto& argument = property_key.as_string(); // Handle trivial cases without a full round trip test @@ -1194,17 +1191,17 @@ CanonicalIndex canonical_numeric_index_string(PropertyKey const& property_key, C if (char first_non_zero = argument.characters()[current_index]; first_non_zero < '0' || first_non_zero > '9') return CanonicalIndex(CanonicalIndex::Type::Undefined, 0); - // 3. Let n be ! ToNumber(argument). + // 2. Let n be ! ToNumber(argument). char* endptr; auto n = Value(strtod(argument.characters(), &endptr)); if (endptr != argument.characters() + argument.length()) return CanonicalIndex(CanonicalIndex::Type::Undefined, 0); - // 4. If SameValue(! ToString(n), argument) is false, return undefined. + // 3. If SameValue(! ToString(n), argument) is false, return undefined. if (n.to_string_without_side_effects() != argument) return CanonicalIndex(CanonicalIndex::Type::Undefined, 0); - // 5. Return n. + // 4. Return n. return CanonicalIndex(CanonicalIndex::Type::Numeric, 0); } diff --git a/Userland/Libraries/LibJS/Runtime/Array.cpp b/Userland/Libraries/LibJS/Runtime/Array.cpp index 51128f3f97..0c3bdc3a04 100644 --- a/Userland/Libraries/LibJS/Runtime/Array.cpp +++ b/Userland/Libraries/LibJS/Runtime/Array.cpp @@ -29,13 +29,11 @@ ThrowCompletionOr Array::create(GlobalObject& global_object, size_t leng // 7.3.18 CreateArrayFromList ( elements ), https://tc39.es/ecma262/#sec-createarrayfromlist Array* Array::create_from(GlobalObject& global_object, Vector const& elements) { - // 1. Assert: elements is a List whose elements are all ECMAScript language values. - - // 2. Let array be ! ArrayCreate(0). + // 1. Let array be ! ArrayCreate(0). auto* array = MUST(Array::create(global_object, 0)); - // 3. Let n be 0. - // 4. For each element e of elements, do + // 2. Let n be 0. + // 3. For each element e of elements, do for (u32 n = 0; n < elements.size(); ++n) { // a. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), e). MUST(array->create_data_property_or_throw(n, elements[n])); @@ -43,7 +41,7 @@ Array* Array::create_from(GlobalObject& global_object, Vector const& elem // b. Set n to n + 1. } - // 5. Return array. + // 4. Return array. return array; } @@ -161,16 +159,15 @@ ThrowCompletionOr Array::internal_define_own_property(PropertyKey const& p { auto& vm = this->vm(); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. If P is "length", then + // 1. If P is "length", then if (property_key.is_string() && property_key.as_string() == vm.names.length.as_string()) { // a. Return ? ArraySetLength(A, Desc). return set_length(property_descriptor); } - // 3. Else if P is an array index, then + // 2. Else if P is an array index, then if (property_key.is_number()) { // a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). // b. Assert: ! IsDataDescriptor(oldLenDesc) is true. @@ -199,7 +196,7 @@ ThrowCompletionOr Array::internal_define_own_property(PropertyKey const& p return true; } - // 4. Return OrdinaryDefineOwnProperty(A, P, Desc). + // 3. Return OrdinaryDefineOwnProperty(A, P, Desc). return Object::internal_define_own_property(property_key, property_descriptor); } diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp index 08a7d8fd25..32810d33d4 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.cpp +++ b/Userland/Libraries/LibJS/Runtime/Object.cpp @@ -82,12 +82,9 @@ ThrowCompletionOr Object::is_extensible() const // 7.3.2 Get ( O, P ), https://tc39.es/ecma262/#sec-get-o-p ThrowCompletionOr Object::get(PropertyKey const& property_key) const { - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 3. Return ? O.[[Get]](P, O). + // 1. Return ? O.[[Get]](P, O). return TRY(internal_get(property_key, this)); } @@ -96,38 +93,30 @@ ThrowCompletionOr Object::get(PropertyKey const& property_key) const // 7.3.4 Set ( O, P, V, Throw ), https://tc39.es/ecma262/#sec-set-o-p-v-throw ThrowCompletionOr Object::set(PropertyKey const& property_key, Value value, ShouldThrowExceptions throw_exceptions) { - VERIFY(!value.is_empty()); auto& vm = this->vm(); - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); + VERIFY(!value.is_empty()); - // 3. Assert: Type(Throw) is Boolean. - - // 4. Let success be ? O.[[Set]](P, V, O). + // 1. Let success be ? O.[[Set]](P, V, O). auto success = TRY(internal_set(property_key, value, this)); - // 5. If success is false and Throw is true, throw a TypeError exception. + // 2. If success is false and Throw is true, throw a TypeError exception. if (!success && throw_exceptions == ShouldThrowExceptions::Yes) { // FIXME: Improve/contextualize error message return vm.throw_completion(global_object(), ErrorType::ObjectSetReturnedFalse); } - // 6. Return success. + // 3. Return success. return success; } // 7.3.5 CreateDataProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createdataproperty ThrowCompletionOr Object::create_data_property(PropertyKey const& property_key, Value value) { - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }. + // 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }. auto new_descriptor = PropertyDescriptor { .value = value, .writable = true, @@ -135,21 +124,17 @@ ThrowCompletionOr Object::create_data_property(PropertyKey const& property .configurable = true, }; - // 4. Return ? O.[[DefineOwnProperty]](P, newDesc). + // 2. Return ? O.[[DefineOwnProperty]](P, newDesc). return internal_define_own_property(property_key, new_descriptor); } // 7.3.6 CreateMethodProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createmethodproperty ThrowCompletionOr Object::create_method_property(PropertyKey const& property_key, Value value) { + VERIFY(property_key.is_valid()); VERIFY(!value.is_empty()); - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. - VERIFY(property_key.is_valid()); - - // 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }. + // 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }. auto new_descriptor = PropertyDescriptor { .value = value, .writable = true, @@ -157,39 +142,36 @@ ThrowCompletionOr Object::create_method_property(PropertyKey const& proper .configurable = true, }; - // 4. Return ? O.[[DefineOwnProperty]](P, newDesc). + // 2. Return ? O.[[DefineOwnProperty]](P, newDesc). return internal_define_own_property(property_key, new_descriptor); } // 7.3.7 CreateDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createdatapropertyorthrow ThrowCompletionOr Object::create_data_property_or_throw(PropertyKey const& property_key, Value value) { - VERIFY(!value.is_empty()); auto& vm = this->vm(); - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); + VERIFY(!value.is_empty()); - // 3. Let success be ? CreateDataProperty(O, P, V). + // 1. Let success be ? CreateDataProperty(O, P, V). auto success = TRY(create_data_property(property_key, value)); - // 4. If success is false, throw a TypeError exception. + // 2. If success is false, throw a TypeError exception. if (!success) { // FIXME: Improve/contextualize error message return vm.throw_completion(global_object(), ErrorType::ObjectDefineOwnPropertyReturnedFalse); } - // 5. Return success. + // 3. Return success. return success; } // 7.3.8 CreateNonEnumerableDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createnonenumerabledatapropertyorthrow ThrowCompletionOr Object::create_non_enumerable_data_property_or_throw(PropertyKey const& property_key, Value value) { - VERIFY(!value.is_empty()); VERIFY(property_key.is_valid()); + VERIFY(!value.is_empty()); // 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }. auto new_description = PropertyDescriptor { .value = value, .writable = true, .enumerable = false, .configurable = true }; @@ -203,21 +185,18 @@ ThrowCompletionOr Object::define_property_or_throw(PropertyKey const& prop { auto& vm = this->vm(); - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 3. Let success be ? O.[[DefineOwnProperty]](P, desc). + // 1. Let success be ? O.[[DefineOwnProperty]](P, desc). auto success = TRY(internal_define_own_property(property_key, property_descriptor)); - // 4. If success is false, throw a TypeError exception. + // 2. If success is false, throw a TypeError exception. if (!success) { // FIXME: Improve/contextualize error message return vm.throw_completion(global_object(), ErrorType::ObjectDefineOwnPropertyReturnedFalse); } - // 5. Return success. + // 3. Return success. return success; } @@ -226,52 +205,43 @@ ThrowCompletionOr Object::delete_property_or_throw(PropertyKey const& prop { auto& vm = this->vm(); - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 3. Let success be ? O.[[Delete]](P). + // 1. Let success be ? O.[[Delete]](P). auto success = TRY(internal_delete(property_key)); - // 4. If success is false, throw a TypeError exception. + // 2. If success is false, throw a TypeError exception. if (!success) { // FIXME: Improve/contextualize error message return vm.throw_completion(global_object(), ErrorType::ObjectDeleteReturnedFalse); } - // 5. Return success. + // 3. Return success. return success; } // 7.3.12 HasProperty ( O, P ), https://tc39.es/ecma262/#sec-hasproperty ThrowCompletionOr Object::has_property(PropertyKey const& property_key) const { - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 3. Return ? O.[[HasProperty]](P). + // 1. Return ? O.[[HasProperty]](P). return internal_has_property(property_key); } // 7.3.13 HasOwnProperty ( O, P ), https://tc39.es/ecma262/#sec-hasownproperty ThrowCompletionOr Object::has_own_property(PropertyKey const& property_key) const { - // 1. Assert: Type(O) is Object. - - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 3. Let desc be ? O.[[GetOwnProperty]](P). + // 1. Let desc be ? O.[[GetOwnProperty]](P). auto descriptor = TRY(internal_get_own_property(property_key)); - // 4. If desc is undefined, return false. + // 2. If desc is undefined, return false. if (!descriptor.has_value()) return false; - // 5. Return true. + // 3. Return true. return true; } @@ -280,22 +250,17 @@ ThrowCompletionOr Object::set_integrity_level(IntegrityLevel level) { auto& global_object = this->global_object(); - // 1. Assert: Type(O) is Object. - - // 2. Assert: level is either sealed or frozen. - VERIFY(level == IntegrityLevel::Sealed || level == IntegrityLevel::Frozen); - - // 3. Let status be ? O.[[PreventExtensions]](). + // 1. Let status be ? O.[[PreventExtensions]](). auto status = TRY(internal_prevent_extensions()); - // 4. If status is false, return false. + // 2. If status is false, return false. if (!status) return false; - // 5. Let keys be ? O.[[OwnPropertyKeys]](). + // 3. Let keys be ? O.[[OwnPropertyKeys]](). auto keys = TRY(internal_own_property_keys()); - // 6. If level is sealed, then + // 4. If level is sealed, then if (level == IntegrityLevel::Sealed) { // a. For each element k of keys, do for (auto& key : keys) { @@ -305,7 +270,7 @@ ThrowCompletionOr Object::set_integrity_level(IntegrityLevel level) TRY(define_property_or_throw(property_key, { .configurable = false })); } } - // 7. Else, + // 5. Else, else { // a. Assert: level is frozen. @@ -338,30 +303,25 @@ ThrowCompletionOr Object::set_integrity_level(IntegrityLevel level) } } - // 8. Return true. + // 6. Return true. return true; } // 7.3.17 TestIntegrityLevel ( O, level ), https://tc39.es/ecma262/#sec-testintegritylevel ThrowCompletionOr Object::test_integrity_level(IntegrityLevel level) const { - // 1. Assert: Type(O) is Object. - - // 2. Assert: level is either sealed or frozen. - VERIFY(level == IntegrityLevel::Sealed || level == IntegrityLevel::Frozen); - - // 3. Let extensible be ? IsExtensible(O). + // 1. Let extensible be ? IsExtensible(O). auto extensible = TRY(is_extensible()); - // 4. If extensible is true, return false. - // 5. NOTE: If the object is extensible, none of its properties are examined. + // 2. If extensible is true, return false. + // 3. NOTE: If the object is extensible, none of its properties are examined. if (extensible) return false; - // 6. Let keys be ? O.[[OwnPropertyKeys]](). + // 4. Let keys be ? O.[[OwnPropertyKeys]](). auto keys = TRY(internal_own_property_keys()); - // 7. For each element k of keys, do + // 5. For each element k of keys, do for (auto& key : keys) { auto property_key = MUST(PropertyKey::from_value(global_object(), key)); @@ -383,7 +343,7 @@ ThrowCompletionOr Object::test_integrity_level(IntegrityLevel level) const } } - // 8. Return true. + // 6. Return true. return true; } @@ -395,15 +355,13 @@ ThrowCompletionOr> Object::enumerable_own_property_names(Pro auto& global_object = this->global_object(); - // 1. Assert: Type(O) is Object. - - // 2. Let ownKeys be ? O.[[OwnPropertyKeys]](). + // 1. Let ownKeys be ? O.[[OwnPropertyKeys]](). auto own_keys = TRY(internal_own_property_keys()); - // 3. Let properties be a new empty List. + // 2. Let properties be a new empty List. auto properties = MarkedVector { heap() }; - // 4. For each element key of ownKeys, do + // 3. For each element key of ownKeys, do for (auto& key : own_keys) { // a. If Type(key) is String, then if (!key.is_string()) @@ -443,7 +401,7 @@ ThrowCompletionOr> Object::enumerable_own_property_names(Pro } } - // 5. Return properties. + // 4. Return properties. return { move(properties) }; } @@ -602,23 +560,21 @@ ThrowCompletionOr Object::internal_get_prototype_of() const // 10.1.2 [[SetPrototypeOf]] ( V ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v ThrowCompletionOr Object::internal_set_prototype_of(Object* new_prototype) { - // 1. Assert: Either Type(V) is Object or Type(V) is Null. - - // 2. Let current be O.[[Prototype]]. - // 3. If SameValue(V, current) is true, return true. + // 1. Let current be O.[[Prototype]]. + // 2. If SameValue(V, current) is true, return true. if (prototype() == new_prototype) return true; - // 4. Let extensible be O.[[Extensible]]. - // 5. If extensible is false, return false. + // 3. Let extensible be O.[[Extensible]]. + // 4. If extensible is false, return false. if (!m_is_extensible) return false; - // 6. Let p be V. + // 5. Let p be V. auto* prototype = new_prototype; - // 7. Let done be false. - // 8. Repeat, while done is false, + // 6. Let done be false. + // 7. Repeat, while done is false, while (prototype) { // a. If p is null, set done to true. @@ -638,10 +594,10 @@ ThrowCompletionOr Object::internal_set_prototype_of(Object* new_prototype) prototype = prototype->prototype(); } - // 9. Set O.[[Prototype]] to V. + // 8. Set O.[[Prototype]] to V. set_prototype(new_prototype); - // 10. Return true. + // 9. Return true. return true; } @@ -665,21 +621,20 @@ ThrowCompletionOr Object::internal_prevent_extensions() // 10.1.5 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p ThrowCompletionOr> Object::internal_get_own_property(PropertyKey const& property_key) const { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. If O does not have an own property with key P, return undefined. + // 1. If O does not have an own property with key P, return undefined. auto maybe_storage_entry = storage_get(property_key); if (!maybe_storage_entry.has_value()) return Optional {}; - // 3. Let D be a newly created Property Descriptor with no fields. + // 2. Let D be a newly created Property Descriptor with no fields. PropertyDescriptor descriptor; - // 4. Let X be O's own property whose key is P. + // 3. Let X be O's own property whose key is P. auto [value, attributes] = *maybe_storage_entry; - // 5. If X is a data property, then + // 4. If X is a data property, then if (!value.is_accessor()) { // a. Set D.[[Value]] to the value of X's [[Value]] attribute. descriptor.value = value.value_or(js_undefined()); @@ -687,7 +642,7 @@ ThrowCompletionOr> Object::internal_get_own_propert // b. Set D.[[Writable]] to the value of X's [[Writable]] attribute. descriptor.writable = attributes.is_writable(); } - // 6. Else, + // 5. Else, else { // a. Assert: X is an accessor property. @@ -698,13 +653,13 @@ ThrowCompletionOr> Object::internal_get_own_propert descriptor.set = value.as_accessor().setter(); } - // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute. + // 6. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute. descriptor.enumerable = attributes.is_enumerable(); - // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute. + // 7. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute. descriptor.configurable = attributes.is_configurable(); - // 9. Return D. + // 8. Return D. return descriptor; } @@ -712,6 +667,7 @@ ThrowCompletionOr> Object::internal_get_own_propert ThrowCompletionOr Object::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor) { VERIFY(property_key.is_valid()); + // 1. Let current be ? O.[[GetOwnProperty]](P). auto current = TRY(internal_get_own_property(property_key)); @@ -725,26 +681,25 @@ ThrowCompletionOr Object::internal_define_own_property(PropertyKey const& // 10.1.7 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p ThrowCompletionOr Object::internal_has_property(PropertyKey const& property_key) const { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Let hasOwn be ? O.[[GetOwnProperty]](P). + // 1. Let hasOwn be ? O.[[GetOwnProperty]](P). auto has_own = TRY(internal_get_own_property(property_key)); - // 3. If hasOwn is not undefined, return true. + // 2. If hasOwn is not undefined, return true. if (has_own.has_value()) return true; - // 4. Let parent be ? O.[[GetPrototypeOf]](). + // 3. Let parent be ? O.[[GetPrototypeOf]](). auto* parent = TRY(internal_get_prototype_of()); - // 5. If parent is not null, then + // 4. If parent is not null, then if (parent) { // a. Return ? parent.[[HasProperty]](P). return parent->internal_has_property(property_key); } - // 6. Return false. + // 5. Return false. return false; } @@ -752,14 +707,12 @@ ThrowCompletionOr Object::internal_has_property(PropertyKey const& propert ThrowCompletionOr Object::internal_get(PropertyKey const& property_key, Value receiver) const { VERIFY(!receiver.is_empty()); - - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Let desc be ? O.[[GetOwnProperty]](P). + // 1. Let desc be ? O.[[GetOwnProperty]](P). auto descriptor = TRY(internal_get_own_property(property_key)); - // 3. If desc is undefined, then + // 2. If desc is undefined, then if (!descriptor.has_value()) { // a. Let parent be ? O.[[GetPrototypeOf]](). auto* parent = TRY(internal_get_prototype_of()); @@ -772,33 +725,31 @@ ThrowCompletionOr Object::internal_get(PropertyKey const& property_key, V return parent->internal_get(property_key, receiver); } - // 4. If IsDataDescriptor(desc) is true, return desc.[[Value]]. + // 3. If IsDataDescriptor(desc) is true, return desc.[[Value]]. if (descriptor->is_data_descriptor()) return *descriptor->value; - // 5. Assert: IsAccessorDescriptor(desc) is true. + // 4. Assert: IsAccessorDescriptor(desc) is true. VERIFY(descriptor->is_accessor_descriptor()); - // 6. Let getter be desc.[[Get]]. + // 5. Let getter be desc.[[Get]]. auto* getter = *descriptor->get; - // 7. If getter is undefined, return undefined. + // 6. If getter is undefined, return undefined. if (!getter) return js_undefined(); - // 8. Return ? Call(getter, Receiver). + // 7. Return ? Call(getter, Receiver). return TRY(call(global_object(), *getter, receiver)); } // 10.1.9 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver ThrowCompletionOr Object::internal_set(PropertyKey const& property_key, Value value, Value receiver) { + VERIFY(property_key.is_valid()); VERIFY(!value.is_empty()); VERIFY(!receiver.is_empty()); - // 1. Assert: IsPropertyKey(P) is true. - VERIFY(property_key.is_valid()); - // 2. Let ownDesc be ? O.[[GetOwnProperty]](P). auto own_descriptor = TRY(internal_get_own_property(property_key)); @@ -809,10 +760,11 @@ ThrowCompletionOr Object::internal_set(PropertyKey const& property_key, Va // 10.1.9.2 OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ), https://tc39.es/ecma262/#sec-ordinarysetwithowndescriptor ThrowCompletionOr Object::ordinary_set_with_own_descriptor(PropertyKey const& property_key, Value value, Value receiver, Optional own_descriptor) { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); + VERIFY(!value.is_empty()); + VERIFY(!receiver.is_empty()); - // 2. If ownDesc is undefined, then + // 1. If ownDesc is undefined, then if (!own_descriptor.has_value()) { // a. Let parent be ? O.[[GetPrototypeOf]](). auto* parent = TRY(internal_get_prototype_of()); @@ -834,7 +786,7 @@ ThrowCompletionOr Object::ordinary_set_with_own_descriptor(PropertyKey con } } - // 3. If IsDataDescriptor(ownDesc) is true, then + // 2. If IsDataDescriptor(ownDesc) is true, then if (own_descriptor->is_data_descriptor()) { // a. If ownDesc.[[Writable]] is false, return false. if (!*own_descriptor->writable) @@ -873,37 +825,36 @@ ThrowCompletionOr Object::ordinary_set_with_own_descriptor(PropertyKey con } } - // 4. Assert: IsAccessorDescriptor(ownDesc) is true. + // 3. Assert: IsAccessorDescriptor(ownDesc) is true. VERIFY(own_descriptor->is_accessor_descriptor()); - // 5. Let setter be ownDesc.[[Set]]. + // 4. Let setter be ownDesc.[[Set]]. auto* setter = *own_descriptor->set; - // 6. If setter is undefined, return false. + // 5. If setter is undefined, return false. if (!setter) return false; - // 7. Perform ? Call(setter, Receiver, « V »). + // 6. Perform ? Call(setter, Receiver, « V »). (void)TRY(call(global_object(), *setter, receiver, value)); - // 8. Return true. + // 7. Return true. return true; } // 10.1.10 [[Delete]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-delete-p ThrowCompletionOr Object::internal_delete(PropertyKey const& property_key) { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Let desc be ? O.[[GetOwnProperty]](P). + // 1. Let desc be ? O.[[GetOwnProperty]](P). auto descriptor = TRY(internal_get_own_property(property_key)); - // 3. If desc is undefined, return true. + // 2. If desc is undefined, return true. if (!descriptor.has_value()) return true; - // 4. If desc.[[Configurable]] is true, then + // 3. If desc.[[Configurable]] is true, then if (*descriptor->configurable) { // a. Remove the own property with name P from O. storage_delete(property_key); @@ -912,7 +863,7 @@ ThrowCompletionOr Object::internal_delete(PropertyKey const& property_key) return true; } - // 5. Return false. + // 4. Return false. return false; } @@ -953,16 +904,14 @@ ThrowCompletionOr> Object::internal_own_property_keys() cons // 10.4.7.2 SetImmutablePrototype ( O, V ), https://tc39.es/ecma262/#sec-set-immutable-prototype ThrowCompletionOr Object::set_immutable_prototype(Object* prototype) { - // 1. Assert: Either Type(V) is Object or Type(V) is Null. - - // 2. Let current be ? O.[[GetPrototypeOf]](). + // 1. Let current be ? O.[[GetPrototypeOf]](). auto* current = TRY(internal_get_prototype_of()); - // 3. If SameValue(V, current) is true, return true. + // 2. If SameValue(V, current) is true, return true. if (prototype == current) return true; - // 4. Return false. + // 3. Return false. return false; } @@ -1126,12 +1075,10 @@ ThrowCompletionOr Object::define_properties(Value properties) { auto& global_object = this->global_object(); - // 1. Assert: Type(O) is Object. - - // 2. Let props be ? ToObject(Properties). + // 1. Let props be ? ToObject(Properties). auto* props = TRY(properties.to_object(global_object)); - // 3. Let keys be ? props.[[OwnPropertyKeys]](). + // 2. Let keys be ? props.[[OwnPropertyKeys]](). auto keys = TRY(props->internal_own_property_keys()); struct NameAndDescriptor { @@ -1139,10 +1086,10 @@ ThrowCompletionOr Object::define_properties(Value properties) PropertyDescriptor descriptor; }; - // 4. Let descriptors be a new empty List. + // 3. Let descriptors be a new empty List. Vector descriptors; - // 5. For each element nextKey of keys, do + // 4. For each element nextKey of keys, do for (auto& next_key : keys) { auto property_key = MUST(PropertyKey::from_value(global_object, next_key)); @@ -1162,7 +1109,7 @@ ThrowCompletionOr Object::define_properties(Value properties) } } - // 6. For each element pair of descriptors, do + // 5. For each element pair of descriptors, do for (auto& [name, descriptor] : descriptors) { // a. Let P be the first element of pair. // b. Let desc be the second element of pair. @@ -1171,7 +1118,7 @@ ThrowCompletionOr Object::define_properties(Value properties) TRY(define_property_or_throw(name, descriptor)); } - // 7. Return O. + // 6. Return O. return this; } diff --git a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp index e2e9406a41..1bf50ed0e8 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Matthew Olsson - * Copyright (c) 2021, Linus Groh + * Copyright (c) 2021-2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -95,47 +95,46 @@ ThrowCompletionOr ProxyObject::internal_set_prototype_of(Object* prototype auto& vm = this->vm(); auto& global_object = this->global_object(); - // 1. Assert: Either Type(V) is Object or Type(V) is Null. - // 2. Let handler be O.[[ProxyHandler]]. + // 1. Let handler be O.[[ProxyHandler]]. - // 3. If handler is null, throw a TypeError exception. + // 2. If handler is null, throw a TypeError exception. if (m_is_revoked) return vm.throw_completion(global_object, ErrorType::ProxyRevoked); - // 4. Assert: Type(handler) is Object. - // 5. Let target be O.[[ProxyTarget]]. + // 3. Assert: Type(handler) is Object. + // 4. Let target be O.[[ProxyTarget]]. - // 6. Let trap be ? GetMethod(handler, "setPrototypeOf"). + // 5. Let trap be ? GetMethod(handler, "setPrototypeOf"). auto trap = TRY(Value(&m_handler).get_method(global_object, vm.names.setPrototypeOf)); - // 7. If trap is undefined, then + // 6. If trap is undefined, then if (!trap) { // a. Return ? target.[[SetPrototypeOf]](V). return m_target.internal_set_prototype_of(prototype); } - // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, V »)). + // 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, V »)). auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, prototype)).to_boolean(); - // 9. If booleanTrapResult is false, return false. + // 8. If booleanTrapResult is false, return false. if (!trap_result) return false; - // 10. Let extensibleTarget be ? IsExtensible(target). + // 9. Let extensibleTarget be ? IsExtensible(target). auto extensible_target = TRY(m_target.is_extensible()); - // 11. If extensibleTarget is true, return true. + // 10. If extensibleTarget is true, return true. if (extensible_target) return true; - // 12. Let targetProto be ? target.[[GetPrototypeOf]](). + // 11. Let targetProto be ? target.[[GetPrototypeOf]](). auto* target_proto = TRY(m_target.internal_get_prototype_of()); - // 13. If SameValue(V, targetProto) is false, throw a TypeError exception. + // 12. If SameValue(V, targetProto) is false, throw a TypeError exception. if (!same_value(prototype, target_proto)) return vm.throw_completion(global_object, ErrorType::ProxySetPrototypeOfNonExtensible); - // 14. Return true. + // 13. Return true. return true; } @@ -224,38 +223,37 @@ ThrowCompletionOr> ProxyObject::internal_get_own_pr auto& vm = this->vm(); auto& global_object = this->global_object(); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Let handler be O.[[ProxyHandler]]. + // 1. Let handler be O.[[ProxyHandler]]. - // 3. If handler is null, throw a TypeError exception. + // 2. If handler is null, throw a TypeError exception. if (m_is_revoked) return vm.throw_completion(global_object, ErrorType::ProxyRevoked); - // 4. Assert: Type(handler) is Object. - // 5. Let target be O.[[ProxyTarget]]. + // 3. Assert: Type(handler) is Object. + // 4. Let target be O.[[ProxyTarget]]. - // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor"). + // 5. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor"). auto trap = TRY(Value(&m_handler).get_method(global_object, vm.names.getOwnPropertyDescriptor)); - // 7. If trap is undefined, then + // 6. If trap is undefined, then if (!trap) { // a. Return ? target.[[GetOwnProperty]](P). return m_target.internal_get_own_property(property_key); } - // 8. Let trapResultObj be ? Call(trap, handler, « target, P »). + // 7. Let trapResultObj be ? Call(trap, handler, « target, P »). auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key))); - // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception. + // 8. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception. if (!trap_result.is_object() && !trap_result.is_undefined()) return vm.throw_completion(global_object, ErrorType::ProxyGetOwnDescriptorReturn); - // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). + // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). auto target_descriptor = TRY(m_target.internal_get_own_property(property_key)); - // 11. If trapResultObj is undefined, then + // 10. If trapResultObj is undefined, then if (trap_result.is_undefined()) { // a. If targetDesc is undefined, return undefined. if (!target_descriptor.has_value()) @@ -276,23 +274,23 @@ ThrowCompletionOr> ProxyObject::internal_get_own_pr return Optional {}; } - // 12. Let extensibleTarget be ? IsExtensible(target). + // 11. Let extensibleTarget be ? IsExtensible(target). auto extensible_target = TRY(m_target.is_extensible()); - // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj). + // 12. Let resultDesc be ? ToPropertyDescriptor(trapResultObj). auto result_desc = TRY(to_property_descriptor(global_object, trap_result)); - // 14. Call CompletePropertyDescriptor(resultDesc). + // 13. Call CompletePropertyDescriptor(resultDesc). result_desc.complete(); - // 15. Let valid be IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc). + // 14. Let valid be IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc). auto valid = is_compatible_property_descriptor(extensible_target, result_desc, target_descriptor); - // 16. If valid is false, throw a TypeError exception. + // 15. If valid is false, throw a TypeError exception. if (!valid) return vm.throw_completion(global_object, ErrorType::ProxyGetOwnDescriptorInvalidDescriptor); - // 17. If resultDesc.[[Configurable]] is false, then + // 16. If resultDesc.[[Configurable]] is false, then if (!*result_desc.configurable) { // a. If targetDesc is undefined or targetDesc.[[Configurable]] is true, then if (!target_descriptor.has_value() || *target_descriptor->configurable) @@ -307,7 +305,7 @@ ThrowCompletionOr> ProxyObject::internal_get_own_pr } } - // 18. Return resultDesc. + // 17. Return resultDesc. return result_desc; } @@ -317,44 +315,43 @@ ThrowCompletionOr ProxyObject::internal_define_own_property(PropertyKey co auto& vm = this->vm(); auto& global_object = this->global_object(); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Let handler be O.[[ProxyHandler]]. + // 1. Let handler be O.[[ProxyHandler]]. - // 3. If handler is null, throw a TypeError exception. + // 2. If handler is null, throw a TypeError exception. if (m_is_revoked) return vm.throw_completion(global_object, ErrorType::ProxyRevoked); - // 4. Assert: Type(handler) is Object. - // 5. Let target be O.[[ProxyTarget]]. + // 3. Assert: Type(handler) is Object. + // 4. Let target be O.[[ProxyTarget]]. - // 6. Let trap be ? GetMethod(handler, "defineProperty"). + // 5. Let trap be ? GetMethod(handler, "defineProperty"). auto trap = TRY(Value(&m_handler).get_method(global_object, vm.names.defineProperty)); - // 7. If trap is undefined, then + // 6. If trap is undefined, then if (!trap) { // a. Return ? target.[[DefineOwnProperty]](P, Desc). return m_target.internal_define_own_property(property_key, property_descriptor); } - // 8. Let descObj be FromPropertyDescriptor(Desc). + // 7. Let descObj be FromPropertyDescriptor(Desc). auto descriptor_object = from_property_descriptor(global_object, property_descriptor); - // 9. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)). + // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)). auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key), descriptor_object)).to_boolean(); - // 10. If booleanTrapResult is false, return false. + // 9. If booleanTrapResult is false, return false. if (!trap_result) return false; - // 11. Let targetDesc be ? target.[[GetOwnProperty]](P). + // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). auto target_descriptor = TRY(m_target.internal_get_own_property(property_key)); - // 12. Let extensibleTarget be ? IsExtensible(target). + // 11. Let extensibleTarget be ? IsExtensible(target). auto extensible_target = TRY(m_target.is_extensible()); - // 14. Else, let settingConfigFalse be false. + // 12. Else, let settingConfigFalse be false. bool setting_config_false = false; // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is false, then @@ -363,7 +360,7 @@ ThrowCompletionOr ProxyObject::internal_define_own_property(PropertyKey co setting_config_false = true; } - // 15. If targetDesc is undefined, then + // 14. If targetDesc is undefined, then if (!target_descriptor.has_value()) { // a. If extensibleTarget is false, throw a TypeError exception. if (!extensible_target) @@ -373,7 +370,7 @@ ThrowCompletionOr ProxyObject::internal_define_own_property(PropertyKey co if (setting_config_false) return vm.throw_completion(global_object, ErrorType::ProxyDefinePropNonConfigurableNonExisting); } - // 16. Else, + // 15. Else, else { // a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc, targetDesc) is false, throw a TypeError exception. if (!is_compatible_property_descriptor(extensible_target, property_descriptor, target_descriptor)) @@ -391,7 +388,7 @@ ThrowCompletionOr ProxyObject::internal_define_own_property(PropertyKey co } } - // 17. Return true. + // 16. Return true. return true; } @@ -401,31 +398,30 @@ ThrowCompletionOr ProxyObject::internal_has_property(PropertyKey const& pr auto& vm = this->vm(); auto& global_object = this->global_object(); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Let handler be O.[[ProxyHandler]]. + // 1. Let handler be O.[[ProxyHandler]]. - // 3. If handler is null, throw a TypeError exception. + // 2. If handler is null, throw a TypeError exception. if (m_is_revoked) return vm.throw_completion(global_object, ErrorType::ProxyRevoked); - // 4. Assert: Type(handler) is Object. - // 5. Let target be O.[[ProxyTarget]]. + // 3. Assert: Type(handler) is Object. + // 4. Let target be O.[[ProxyTarget]]. - // 6. Let trap be ? GetMethod(handler, "has"). + // 5. Let trap be ? GetMethod(handler, "has"). auto trap = TRY(Value(&m_handler).get_method(global_object, vm.names.has)); - // 7. If trap is undefined, then + // 6. If trap is undefined, then if (!trap) { // a. Return ? target.[[HasProperty]](P). return m_target.internal_has_property(property_key); } - // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)). + // 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)). auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key))).to_boolean(); - // 9. If booleanTrapResult is false, then + // 8. If booleanTrapResult is false, then if (!trap_result) { // a. Let targetDesc be ? target.[[GetOwnProperty]](P). auto target_descriptor = TRY(m_target.internal_get_own_property(property_key)); @@ -445,7 +441,7 @@ ThrowCompletionOr ProxyObject::internal_has_property(PropertyKey const& pr } } - // 10. Return booleanTrapResult. + // 9. Return booleanTrapResult. return trap_result; } @@ -457,17 +453,17 @@ ThrowCompletionOr ProxyObject::internal_get(PropertyKey const& property_k auto& vm = this->vm(); auto& global_object = this->global_object(); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); + VERIFY(!receiver.is_empty()); - // 2. Let handler be O.[[ProxyHandler]]. + // 1. Let handler be O.[[ProxyHandler]]. - // 3. If handler is null, throw a TypeError exception. + // 2. If handler is null, throw a TypeError exception. if (m_is_revoked) return vm.throw_completion(global_object, ErrorType::ProxyRevoked); - // 4. Assert: Type(handler) is Object. - // 5. Let target be O.[[ProxyTarget]]. + // 3. Assert: Type(handler) is Object. + // 4. Let target be O.[[ProxyTarget]]. // NOTE: We need to protect ourselves from a Proxy with the handler's prototype set to the // Proxy itself, which would by default bounce between these functions indefinitely and lead to @@ -485,22 +481,22 @@ ThrowCompletionOr ProxyObject::internal_get(PropertyKey const& property_k if (vm.did_reach_stack_space_limit()) return vm.throw_completion(global_object, ErrorType::CallStackSizeExceeded); - // 6. Let trap be ? GetMethod(handler, "get"). + // 5. Let trap be ? GetMethod(handler, "get"). auto trap = TRY(Value(&m_handler).get_method(global_object, vm.names.get)); - // 7. If trap is undefined, then + // 6. If trap is undefined, then if (!trap) { // a. Return ? target.[[Get]](P, Receiver). return m_target.internal_get(property_key, receiver); } - // 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »). + // 7. Let trapResult be ? Call(trap, handler, « target, P, Receiver »). auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key), receiver)); - // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). + // 8. Let targetDesc be ? target.[[GetOwnProperty]](P). auto target_descriptor = TRY(m_target.internal_get_own_property(property_key)); - // 10. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then + // 9. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then if (target_descriptor.has_value() && !*target_descriptor->configurable) { // a. If IsDataDescriptor(targetDesc) is true and targetDesc.[[Writable]] is false, then if (target_descriptor->is_data_descriptor() && !*target_descriptor->writable) { @@ -516,51 +512,49 @@ ThrowCompletionOr ProxyObject::internal_get(PropertyKey const& property_k } } - // 11. Return trapResult. + // 10. Return trapResult. return trap_result; } // 10.5.9 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver ThrowCompletionOr ProxyObject::internal_set(PropertyKey const& property_key, Value value, Value receiver) { - VERIFY(!value.is_empty()); - VERIFY(!receiver.is_empty()); - auto& vm = this->vm(); auto& global_object = this->global_object(); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); + VERIFY(!value.is_empty()); + VERIFY(!receiver.is_empty()); - // 2. Let handler be O.[[ProxyHandler]]. + // 1. Let handler be O.[[ProxyHandler]]. - // 3. If handler is null, throw a TypeError exception. + // 2. If handler is null, throw a TypeError exception. if (m_is_revoked) return vm.throw_completion(global_object, ErrorType::ProxyRevoked); - // 4. Assert: Type(handler) is Object. - // 5. Let target be O.[[ProxyTarget]]. + // 3. Assert: Type(handler) is Object. + // 4. Let target be O.[[ProxyTarget]]. - // 6. Let trap be ? GetMethod(handler, "set"). + // 5. Let trap be ? GetMethod(handler, "set"). auto trap = TRY(Value(&m_handler).get_method(global_object, vm.names.set)); - // 7. If trap is undefined, then + // 6. If trap is undefined, then if (!trap) { // a. Return ? target.[[Set]](P, V, Receiver). return m_target.internal_set(property_key, value, receiver); } - // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)). + // 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)). auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key), value, receiver)).to_boolean(); - // 9. If booleanTrapResult is false, return false. + // 8. If booleanTrapResult is false, return false. if (!trap_result) return false; - // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). + // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). auto target_descriptor = TRY(m_target.internal_get_own_property(property_key)); - // 11. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then + // 10. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then if (target_descriptor.has_value() && !*target_descriptor->configurable) { // a. If IsDataDescriptor(targetDesc) is true and targetDesc.[[Writable]] is false, then if (target_descriptor->is_data_descriptor() && !*target_descriptor->writable) { @@ -576,7 +570,7 @@ ThrowCompletionOr ProxyObject::internal_set(PropertyKey const& property_ke } } - // 12. Return true. + // 11. Return true. return true; } @@ -586,53 +580,52 @@ ThrowCompletionOr ProxyObject::internal_delete(PropertyKey const& property auto& vm = this->vm(); auto& global_object = this->global_object(); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Let handler be O.[[ProxyHandler]]. + // 1. Let handler be O.[[ProxyHandler]]. - // 3. If handler is null, throw a TypeError exception. + // 2. If handler is null, throw a TypeError exception. if (m_is_revoked) return vm.throw_completion(global_object, ErrorType::ProxyRevoked); - // 4. Assert: Type(handler) is Object. - // 5. Let target be O.[[ProxyTarget]]. + // 3. Assert: Type(handler) is Object. + // 4. Let target be O.[[ProxyTarget]]. - // 6. Let trap be ? GetMethod(handler, "deleteProperty"). + // 5. Let trap be ? GetMethod(handler, "deleteProperty"). auto trap = TRY(Value(&m_handler).get_method(global_object, vm.names.deleteProperty)); - // 7. If trap is undefined, then + // 6. If trap is undefined, then if (!trap) { // a. Return ? target.[[Delete]](P). return m_target.internal_delete(property_key); } - // 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)). + // 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)). auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key))).to_boolean(); - // 9. If booleanTrapResult is false, return false. + // 8. If booleanTrapResult is false, return false. if (!trap_result) return false; - // 10. Let targetDesc be ? target.[[GetOwnProperty]](P). + // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). auto target_descriptor = TRY(m_target.internal_get_own_property(property_key)); - // 11. If targetDesc is undefined, return true. + // 10. If targetDesc is undefined, return true. if (!target_descriptor.has_value()) return true; - // 12. If targetDesc.[[Configurable]] is false, throw a TypeError exception. + // 11. If targetDesc.[[Configurable]] is false, throw a TypeError exception. if (!*target_descriptor->configurable) return vm.throw_completion(global_object, ErrorType::ProxyDeleteNonConfigurable); - // 13. Let extensibleTarget be ? IsExtensible(target). + // 12. Let extensibleTarget be ? IsExtensible(target). auto extensible_target = TRY(m_target.is_extensible()); - // 14. If extensibleTarget is false, throw a TypeError exception. + // 13. If extensibleTarget is false, throw a TypeError exception. if (!extensible_target) return vm.throw_completion(global_object, ErrorType::ProxyDeleteNonExtensible); - // 15. Return true. + // 14. Return true. return true; } @@ -684,7 +677,7 @@ ThrowCompletionOr> ProxyObject::internal_own_property_keys() // 11. Let targetKeys be ? target.[[OwnPropertyKeys]](). auto target_keys = TRY(m_target.internal_own_property_keys()); - // 12. Assert: targetKeys is a List whose elements are only String and Symbol values. + // 12. Assert: targetKeys is a List of property keys. // 13. Assert: targetKeys contains no duplicate entries. // 14. Let targetConfigurableKeys be a new empty List. diff --git a/Userland/Libraries/LibJS/Runtime/StringObject.cpp b/Userland/Libraries/LibJS/Runtime/StringObject.cpp index 333482b916..8a9f1a9b86 100644 --- a/Userland/Libraries/LibJS/Runtime/StringObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringObject.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Andreas Kling - * Copyright (c) 2021, Linus Groh + * Copyright (c) 2021-2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -42,40 +42,38 @@ void StringObject::visit_edges(Cell::Visitor& visitor) // 10.4.3.5 StringGetOwnProperty ( S, P ), https://tc39.es/ecma262/#sec-stringgetownproperty static Optional string_get_own_property(StringObject const& string, PropertyKey const& property_key) { - // 1. Assert: S is an Object that has a [[StringData]] internal slot. - // 2. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 3. If Type(P) is not String, return undefined. + // 1. If Type(P) is not String, return undefined. // NOTE: The spec only uses string and symbol keys, and later coerces to numbers - // this is not the case for PropertyKey, so '!property_key.is_string()' would be wrong. if (property_key.is_symbol()) return {}; - // 4. Let index be ! CanonicalNumericIndexString(P). + // 2. Let index be ! CanonicalNumericIndexString(P). auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip); - // 5. If index is undefined, return undefined. - // 6. If IsIntegralNumber(index) is false, return undefined. - // 7. If index is -0𝔽, return undefined. + // 3. If index is undefined, return undefined. + // 4. If IsIntegralNumber(index) is false, return undefined. + // 5. If index is -0𝔽, return undefined. if (!index.is_index()) return {}; - // 8. Let str be S.[[StringData]]. - // 9. Assert: Type(str) is String. + // 6. Let str be S.[[StringData]]. + // 7. Assert: Type(str) is String. auto str = string.primitive_string().utf16_string_view(); - // 10. Let len be the length of str. + // 8. Let len be the length of str. auto length = str.length_in_code_units(); - // 11. If ℝ(index) < 0 or len ≤ ℝ(index), return undefined. + // 9. If ℝ(index) < 0 or len ≤ ℝ(index), return undefined. if (length <= index.as_index()) return {}; - // 12. Let resultStr be the String value of length 1, containing one code unit from str, specifically the code unit at index ℝ(index). + // 10. Let resultStr be the String value of length 1, containing one code unit from str, specifically the code unit at index ℝ(index). auto result_str = js_string(string.vm(), str.substring_view(index.as_index(), 1)); - // 13. Return the PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }. + // 11. Return the PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }. return PropertyDescriptor { .value = result_str, .writable = false, @@ -87,29 +85,28 @@ static Optional string_get_own_property(StringObject const& // 10.4.3.1 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-string-exotic-objects-getownproperty-p ThrowCompletionOr> StringObject::internal_get_own_property(PropertyKey const& property_key) const { - // Assert: IsPropertyKey(P) is true. + VERIFY(property_key.is_valid()); - // 2. Let desc be OrdinaryGetOwnProperty(S, P). + // 1. Let desc be OrdinaryGetOwnProperty(S, P). auto descriptor = MUST(Object::internal_get_own_property(property_key)); - // 3. If desc is not undefined, return desc. + // 2. If desc is not undefined, return desc. if (descriptor.has_value()) return descriptor; - // 4. Return ! StringGetOwnProperty(S, P). + // 3. Return ! StringGetOwnProperty(S, P). return string_get_own_property(*this, property_key); } // 10.4.3.2 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-string-exotic-objects-defineownproperty-p-desc ThrowCompletionOr StringObject::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor) { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Let stringDesc be ! StringGetOwnProperty(S, P). + // 1. Let stringDesc be ! StringGetOwnProperty(S, P). auto string_descriptor = string_get_own_property(*this, property_key); - // 3. If stringDesc is not undefined, then + // 2. If stringDesc is not undefined, then if (string_descriptor.has_value()) { // a. Let extensible be S.[[Extensible]]. auto extensible = m_is_extensible; @@ -118,7 +115,7 @@ ThrowCompletionOr StringObject::internal_define_own_property(PropertyKey c return is_compatible_property_descriptor(extensible, property_descriptor, string_descriptor); } - // 4. Return ! OrdinaryDefineOwnProperty(S, P, Desc). + // 3. Return ! OrdinaryDefineOwnProperty(S, P, Desc). return Object::internal_define_own_property(property_key, property_descriptor); } diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.h b/Userland/Libraries/LibJS/Runtime/TypedArray.h index 565b8597b0..fc12c82877 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.h +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, Andreas Kling - * Copyright (c) 2021, Linus Groh + * Copyright (c) 2021-2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -176,16 +176,13 @@ public: // 10.4.5.1 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-getownproperty-p virtual ThrowCompletionOr> internal_get_own_property(PropertyKey const& property_key) const override { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Assert: O is an Integer-Indexed exotic object. - // NOTE: If the property name is a number type (An implementation-defined optimized // property key type), it can be treated as a string property that will transparently be // converted into a canonical numeric index. - // 3. If Type(P) is String, then + // 1. If Type(P) is String, then // NOTE: This includes an implementation-defined optimization, see note above! if (property_key.is_string() || property_key.is_number()) { // a. Let numericIndex be ! CanonicalNumericIndexString(P). @@ -209,23 +206,20 @@ public: } } - // 4. Return OrdinaryGetOwnProperty(O, P). + // 2. Return OrdinaryGetOwnProperty(O, P). return Object::internal_get_own_property(property_key); } // 10.4.5.2 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-hasproperty-p virtual ThrowCompletionOr internal_has_property(PropertyKey const& property_key) const override { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Assert: O is an Integer-Indexed exotic object. - // NOTE: If the property name is a number type (An implementation-defined optimized // property key type), it can be treated as a string property that will transparently be // converted into a canonical numeric index. - // 3. If Type(P) is String, then + // 1. If Type(P) is String, then // NOTE: This includes an implementation-defined optimization, see note above! if (property_key.is_string() || property_key.is_number()) { // a. Let numericIndex be ! CanonicalNumericIndexString(P). @@ -235,23 +229,20 @@ public: return is_valid_integer_index(*this, numeric_index); } - // 4. Return ? OrdinaryHasProperty(O, P). + // 2. Return ? OrdinaryHasProperty(O, P). return Object::internal_has_property(property_key); } // 10.4.5.3 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-defineownproperty-p-desc virtual ThrowCompletionOr internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor) override { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Assert: O is an Integer-Indexed exotic object. - // NOTE: If the property name is a number type (An implementation-defined optimized // property key type), it can be treated as a string property that will transparently be // converted into a canonical numeric index. - // 3. If Type(P) is String, then + // 1. If Type(P) is String, then // NOTE: This includes an implementation-defined optimization, see note above! if (property_key.is_string() || property_key.is_number()) { // a. Let numericIndex be ! CanonicalNumericIndexString(P). @@ -287,7 +278,7 @@ public: } } - // 4. Return ! OrdinaryDefineOwnProperty(O, P, Desc). + // 2. Return ! OrdinaryDefineOwnProperty(O, P, Desc). return Object::internal_define_own_property(property_key, property_descriptor); } @@ -296,13 +287,12 @@ public: { VERIFY(!receiver.is_empty()); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); // NOTE: If the property name is a number type (An implementation-defined optimized // property key type), it can be treated as a string property that will transparently be // converted into a canonical numeric index. - // 2. If Type(P) is String, then + // 1. If Type(P) is String, then // NOTE: This includes an implementation-defined optimization, see note above! if (property_key.is_string() || property_key.is_number()) { // a. Let numericIndex be ! CanonicalNumericIndexString(P). @@ -314,7 +304,7 @@ public: } } - // 3. Return ? OrdinaryGet(O, P, Receiver). + // 2. Return ? OrdinaryGet(O, P, Receiver). return Object::internal_get(property_key, receiver); } @@ -324,13 +314,12 @@ public: VERIFY(!value.is_empty()); VERIFY(!receiver.is_empty()); - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); // NOTE: If the property name is a number type (An implementation-defined optimized // property key type), it can be treated as a string property that will transparently be // converted into a canonical numeric index. - // 2. If Type(P) is String, then + // 1. If Type(P) is String, then // NOTE: This includes an implementation-defined optimization, see note above! if (property_key.is_string() || property_key.is_number()) { // a. Let numericIndex be ! CanonicalNumericIndexString(P). @@ -345,22 +334,20 @@ public: } } - // 3. Return ? OrdinarySet(O, P, V, Receiver). + // 2. Return ? OrdinarySet(O, P, V, Receiver). return Object::internal_set(property_key, value, receiver); } // 10.4.5.6 [[Delete]] ( P ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-delete-p virtual ThrowCompletionOr internal_delete(PropertyKey const& property_key) override { - // 1. Assert: IsPropertyKey(P) is true. VERIFY(property_key.is_valid()); - // 2. Assert: O is an Integer-Indexed exotic object. // NOTE: If the property name is a number type (An implementation-defined optimized // property key type), it can be treated as a string property that will transparently be // converted into a canonical numeric index. - // 3. If Type(P) is String, then + // 1. If Type(P) is String, then // NOTE: This includes an implementation-defined optimization, see note above! if (property_key.is_string() || property_key.is_number()) { // a. Let numericIndex be ! CanonicalNumericIndexString(P). @@ -374,7 +361,7 @@ public: } } - // 4. Return ? OrdinaryDelete(O, P). + // 2. Return ? OrdinaryDelete(O, P). return Object::internal_delete(property_key); } @@ -386,9 +373,7 @@ public: // 1. Let keys be a new empty List. auto keys = MarkedVector { heap() }; - // 2. Assert: O is an Integer-Indexed exotic object. - - // 3. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is false, then + // 2. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is false, then if (!m_viewed_array_buffer->is_detached()) { // a. For each integer i starting with 0 such that i < O.[[ArrayLength]], in ascending order, do for (size_t i = 0; i < m_array_length; ++i) { @@ -397,7 +382,7 @@ public: } } - // 4. For each own property key P of O such that Type(P) is String and P is not an integer index, in ascending chronological order of property creation, do + // 3. For each own property key P of O such that Type(P) is String and P is not an integer index, in ascending chronological order of property creation, do for (auto& it : shape().property_table_ordered()) { if (it.key.is_string()) { // a. Add P as the last element of keys. @@ -405,7 +390,7 @@ public: } } - // 5. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do + // 4. For each own property key P of O such that Type(P) is Symbol, in ascending chronological order of property creation, do for (auto& it : shape().property_table_ordered()) { if (it.key.is_symbol()) { // a. Add P as the last element of keys. @@ -413,7 +398,7 @@ public: } } - // 6. Return keys. + // 5. Return keys. return { move(keys) }; }