diff options
author | Linus Groh <mail@linusgroh.de> | 2021-10-20 17:57:01 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-10-20 18:46:24 +0100 |
commit | cf109533dea3917f559dc7e0a051dbf8d531051a (patch) | |
tree | f836ac40d8cda7a1193f988203b5e904575fc1fc /Userland | |
parent | ca09f20dcfc61db3ffdf7ecf63c1b104490b9332 (diff) | |
download | serenity-cf109533dea3917f559dc7e0a051dbf8d531051a.zip |
LibJS: Add ErrorTypes for Promise ownKeys trap invariant violations
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ErrorTypes.h | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ProxyObject.cpp | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-ownKeys.js | 56 |
3 files changed, 65 insertions, 3 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h index bd91b3d827..09a1ffacfc 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h @@ -152,6 +152,12 @@ "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(ProxyOwnPropertyKeysSkippedNonconfigurableProperty, "Proxy handler's ownKeys trap violates invariant: " \ + "cannot skip non-configurable property '{}'") \ + M(ProxyOwnPropertyKeysNonExtensibleSkippedProperty, "Proxy handler's ownKeys trap violates invariant: " \ + "cannot skip property '{}' of non-extensible object") \ + M(ProxyOwnPropertyKeysNonExtensibleNewProperty, "Proxy handler's ownKeys trap violates invariant: " \ + "cannot report new property '{}' of non-extensible object") \ 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 2a47c2909f..1390ebb6c9 100644 --- a/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ProxyObject.cpp @@ -728,7 +728,7 @@ ThrowCompletionOr<MarkedValueList> ProxyObject::internal_own_property_keys() con for (auto& key : target_nonconfigurable_keys) { // a. If key is not an element of uncheckedResultKeys, throw a TypeError exception. if (!unchecked_result_keys.contains_slow(key)) - return vm.throw_completion<TypeError>(global_object, ErrorType::FixmeAddAnErrorString); + return vm.throw_completion<TypeError>(global_object, ErrorType::ProxyOwnPropertyKeysSkippedNonconfigurableProperty, key.to_string_without_side_effects()); // b. Remove key from uncheckedResultKeys. unchecked_result_keys.remove_first_matching([&](auto& value) { @@ -744,7 +744,7 @@ ThrowCompletionOr<MarkedValueList> ProxyObject::internal_own_property_keys() con for (auto& key : target_configurable_keys) { // a. If key is not an element of uncheckedResultKeys, throw a TypeError exception. if (!unchecked_result_keys.contains_slow(key)) - return vm.throw_completion<TypeError>(global_object, ErrorType::FixmeAddAnErrorString); + return vm.throw_completion<TypeError>(global_object, ErrorType::ProxyOwnPropertyKeysNonExtensibleSkippedProperty, key.to_string_without_side_effects()); // b. Remove key from uncheckedResultKeys. unchecked_result_keys.remove_first_matching([&](auto& value) { @@ -754,7 +754,7 @@ ThrowCompletionOr<MarkedValueList> ProxyObject::internal_own_property_keys() con // 22. If uncheckedResultKeys is not empty, throw a TypeError exception. if (!unchecked_result_keys.is_empty()) - return vm.throw_completion<TypeError>(global_object, ErrorType::FixmeAddAnErrorString); + return vm.throw_completion<TypeError>(global_object, ErrorType::ProxyOwnPropertyKeysNonExtensibleNewProperty, unchecked_result_keys[0].to_string_without_side_effects()); // 23. Return trapResult. return { move(trap_result) }; diff --git a/Userland/Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-ownKeys.js b/Userland/Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-ownKeys.js new file mode 100644 index 0000000000..6dba73c337 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-ownKeys.js @@ -0,0 +1,56 @@ +// TODO: Add "[[OwnPropertyKeys]] trap normal behavior" tests + +describe("[[OwnPropertyKeys]] invariants", () => { + // TODO: Add tests for other [[OwnPropertyKeys]] trap invariants + + test("cannot report new property of non-extensible object", () => { + const target = Object.preventExtensions({}); + const handler = { + ownKeys() { + return ["foo", "bar", "baz"]; + }, + }; + const proxy = new Proxy(target, handler); + + expect(() => { + Reflect.ownKeys(proxy); + }).toThrowWithMessage( + TypeError, + "Proxy handler's ownKeys trap violates invariant: cannot report new property 'foo' of non-extensible object" + ); + }); + + test("cannot skip property of non-extensible object", () => { + const target = Object.preventExtensions({ foo: null }); + const handler = { + ownKeys() { + return ["bar", "baz"]; + }, + }; + const proxy = new Proxy(target, handler); + + expect(() => { + Reflect.ownKeys(proxy); + }).toThrowWithMessage( + TypeError, + "Proxy handler's ownKeys trap violates invariant: cannot skip property 'foo' of non-extensible object" + ); + }); + + test("cannot skip non-configurable property", () => { + const target = Object.defineProperty({}, "foo", { configurable: false }); + const handler = { + ownKeys() { + return ["bar", "baz"]; + }, + }; + const proxy = new Proxy(target, handler); + + expect(() => { + Reflect.ownKeys(proxy); + }).toThrowWithMessage( + TypeError, + "Proxy handler's ownKeys trap violates invariant: cannot skip non-configurable property 'foo'" + ); + }); +}); |