From 6477f61fb18afd212b92a97d57ee5bde1b701cc1 Mon Sep 17 00:00:00 2001 From: Sorck Date: Sat, 11 Jun 2022 18:19:43 +0000 Subject: [PATCH] Implement Object.prototype.__lookupSetter__ (#2113) This Pull Request closes #2067 It changes the following: - Implement `Object.prototype.__lookupSetter__` This passes all tests from `./test262/test/built-ins/Object/prototype/__lookupSetter__/` ``` Loading the test suite... Test suite loaded, starting tests... Suite __lookupSetter__: `lookup-own-get-err` (strict mode): starting `lookup-own-get-err` (strict mode): Passed `lookup-own-get-err`: starting `lookup-own-get-err`: Passed `length` (strict mode): starting `length` (strict mode): Passed `length`: starting `length`: Passed `lookup-proto-proto-err` (strict mode): starting `lookup-proto-proto-err` (strict mode): Passed `lookup-proto-proto-err`: starting `lookup-proto-proto-err`: Passed `lookup-own-acsr-wo-setter` (strict mode): starting `lookup-own-acsr-wo-setter` (strict mode): Passed `lookup-own-acsr-wo-setter`: starting `lookup-own-acsr-wo-setter`: Passed `lookup-not-found` (strict mode): starting `lookup-not-found` (strict mode): Passed `lookup-not-found`: starting `lookup-not-found`: Passed `lookup-proto-acsr-wo-setter` (strict mode): starting `lookup-proto-acsr-wo-setter` (strict mode): Passed `lookup-proto-acsr-wo-setter`: starting `lookup-proto-acsr-wo-setter`: Passed `lookup-proto-acsr-w-setter` (strict mode): starting `lookup-proto-acsr-w-setter` (strict mode): Passed `lookup-proto-acsr-w-setter`: starting `lookup-proto-acsr-w-setter`: Passed `name` (strict mode): starting `name` (strict mode): Passed `name`: starting `name`: Passed `lookup-own-acsr-w-setter` (strict mode): starting `lookup-own-acsr-w-setter` (strict mode): Passed `lookup-own-acsr-w-setter`: starting `lookup-own-acsr-w-setter`: Passed `lookup-own-proto-err` (strict mode): starting `lookup-own-proto-err` (strict mode): Passed `lookup-own-proto-err`: starting `lookup-own-proto-err`: Passed `lookup-proto-data` (strict mode): starting `lookup-proto-data` (strict mode): Passed `lookup-proto-data`: starting `lookup-proto-data`: Passed `lookup-own-data` (strict mode): starting `lookup-own-data` (strict mode): Passed `lookup-own-data`: starting `lookup-own-data`: Passed `lookup-proto-get-err` (strict mode): starting `lookup-proto-get-err` (strict mode): Passed `lookup-proto-get-err`: starting `lookup-proto-get-err`: Passed `prop-desc` (strict mode): starting `prop-desc` (strict mode): Passed `prop-desc`: starting `prop-desc`: Passed `key-invalid` (strict mode): starting `key-invalid` (strict mode): Passed `key-invalid`: starting `key-invalid`: Passed `this-non-obj` (strict mode): starting `this-non-obj` (strict mode): Passed `this-non-obj`: starting `this-non-obj`: Passed Suite __lookupSetter__ results: total: 32, passed: 32, ignored: 0, failed: 0 (panics: 0), conformance: 100.00% Results: Total tests: 32 Passed tests: 32 Ignored tests: 0 Failed tests: 0 (panics: 0) Conformance: 100.00% ``` --- boa_engine/src/builtins/object/mod.rs | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/boa_engine/src/builtins/object/mod.rs b/boa_engine/src/builtins/object/mod.rs index 8e428e7495b..891360ded7e 100644 --- a/boa_engine/src/builtins/object/mod.rs +++ b/boa_engine/src/builtins/object/mod.rs @@ -74,6 +74,7 @@ impl BuiltIn for Object { .method(Self::legacy_define_getter, "__defineGetter__", 2) .method(Self::legacy_define_setter, "__defineSetter__", 2) .method(Self::legacy_lookup_getter, "__lookupGetter__", 1) + .method(Self::legacy_lookup_setter, "__lookupSetter__", 1) .static_method(Self::create, "create", 2) .static_method(Self::set_prototype_of, "setPrototypeOf", 2) .static_method(Self::get_prototype_of, "getPrototypeOf", 1) @@ -329,6 +330,50 @@ impl Object { } } } + /// `Object.prototype.__lookupSetter__(prop)` + /// + /// Returns the function bound as a getter to the specified property. + /// + /// More information: + /// - [ECMAScript reference][spec] + /// - [MDN documentation][mdn] + /// + /// [spec]: https://tc39.es/ecma262/#sec-object.prototype.__lookupSetter__ + /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__lookupSetter__ + pub fn legacy_lookup_setter( + this: &JsValue, + args: &[JsValue], + context: &mut Context, + ) -> JsResult { + // 1. Let O be ? ToObject(this value). + let mut obj = this.to_object(context)?; + + // 2. Let key be ? ToPropertyKey(P). + let key = args.get_or_undefined(0).to_property_key(context)?; + + // 3. Repeat + loop { + // a. Let desc be ? O.[[GetOwnProperty]](key). + let desc = obj.__get_own_property__(&key, context)?; + + // b. If desc is not undefined, then + if let Some(current_desc) = desc { + // i. If IsAccessorDescriptor(desc) is true, return desc.[[Set]]. + return if current_desc.is_accessor_descriptor() { + Ok(current_desc.expect_set().into()) + } else { + // ii. Return undefined. + Ok(JsValue::undefined()) + }; + } + match obj.__get_prototype_of__(context)? { + // c. Set O to ? O.[[GetPrototypeOf]](). + Some(o) => obj = o, + // d. If O is null, return undefined. + None => return Ok(JsValue::undefined()), + } + } + } /// `Object.create( proto, [propertiesObject] )` ///