From dd27490ee160f92aef4962e31ae7598ddd2fb26a Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Tue, 6 Jul 2021 23:53:34 +0300 Subject: LibJS: Throw if the trap result of OwnPropertyKeys contains duplicates --- .../Libraries/LibJS/Runtime/AbstractOperations.cpp | 8 +++----- .../Libraries/LibJS/Runtime/AbstractOperations.h | 2 +- Userland/Libraries/LibJS/Runtime/ErrorTypes.h | 2 ++ Userland/Libraries/LibJS/Runtime/ProxyObject.cpp | 20 +++++++++++++++----- 4 files changed, 21 insertions(+), 11 deletions(-) (limited to 'Userland') diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp index cfa0d90eaf..e5671eadef 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -57,7 +57,7 @@ size_t length_of_array_like(GlobalObject& global_object, Object const& object) } // 7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike -MarkedValueList create_list_from_array_like(GlobalObject& global_object, Value value, Function(Value)> check_value) +MarkedValueList create_list_from_array_like(GlobalObject& global_object, Value value, Function check_value) { auto& vm = global_object.vm(); auto& heap = global_object.heap(); @@ -76,11 +76,9 @@ MarkedValueList create_list_from_array_like(GlobalObject& global_object, Value v if (vm.exception()) return MarkedValueList { heap }; if (check_value) { - auto result = check_value(next); - if (result.is_error()) { - vm.throw_exception(global_object, result.release_error()); + check_value(next); + if (vm.exception()) return MarkedValueList { heap }; - } } list.append(next); } diff --git a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h index f70f51654b..1be5683d3e 100644 --- a/Userland/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Userland/Libraries/LibJS/Runtime/AbstractOperations.h @@ -21,7 +21,7 @@ Object* get_super_constructor(VM&); Reference make_super_property_reference(GlobalObject&, Value actual_this, StringOrSymbol const& property_key, bool strict); Value require_object_coercible(GlobalObject&, Value); size_t length_of_array_like(GlobalObject&, Object const&); -MarkedValueList create_list_from_array_like(GlobalObject&, Value, Function(Value)> = {}); +MarkedValueList create_list_from_array_like(GlobalObject&, Value, Function = {}); FunctionObject* species_constructor(GlobalObject&, Object const&, FunctionObject& default_constructor); GlobalObject* get_function_realm(GlobalObject&, FunctionObject const&); bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional const& current); diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h index 12acdf9988..fb374a8f13 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h @@ -132,6 +132,8 @@ "return value must match the target's extensibility") \ M(ProxyOwnPropertyKeysNotStringOrSymbol, "Proxy handler's ownKeys trap violates invariant: " \ "the type of each result list element is either String or Symbol") \ + M(ProxyOwnPropertyKeysDuplicates, "Proxy handler's ownKeys trap violates invariant: " \ + "the result list may not contain duplicate elements") \ M(ProxyPreventExtensionsReturn, "Proxy handler's preventExtensions trap violates " \ "invariant: cannot return true if the target object is extensible") \ M(ProxyRevoked, "An operation was performed on a revoked Proxy object") \ diff --git a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp index 8216918fd8..803ba3dd74 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -798,13 +798,23 @@ MarkedValueList ProxyObject::internal_own_property_keys() const return MarkedValueList { heap() }; // 8. Let trapResult be ? CreateListFromArrayLike(trapResultArray, « String, Symbol »). - auto trap_result = create_list_from_array_like(global_object, trap_result_array, [](auto value) -> Result { - if (!value.is_string() && !value.is_symbol()) - return ErrorType::ProxyOwnPropertyKeysNotStringOrSymbol; - return {}; + HashTable unique_keys; + auto trap_result = create_list_from_array_like(global_object, trap_result_array, [&](auto value) { + auto& vm = global_object.vm(); + if (!value.is_string() && !value.is_symbol()) { + vm.throw_exception(global_object, ErrorType::ProxyOwnPropertyKeysNotStringOrSymbol); + return; + } + auto property_key = value.to_property_key(global_object); + VERIFY(!vm.exception()); + unique_keys.set(property_key, AK::HashSetExistingEntryBehavior::Keep); }); - // FIXME: 9. If trapResult contains any duplicate entries, throw a TypeError exception. + // 9. If trapResult contains any duplicate entries, throw a TypeError exception. + if (unique_keys.size() != trap_result.size()) { + vm.throw_exception(global_object, ErrorType::ProxyOwnPropertyKeysDuplicates); + return MarkedValueList { heap() }; + } // 10. Let extensibleTarget be ? IsExtensible(target). auto extensible_target = m_target.is_extensible(); -- cgit v1.2.3