From e2986718d562450532943942ba82781bf2c96306 Mon Sep 17 00:00:00 2001 From: Michael Ficarra Date: Mon, 18 Sep 2023 10:26:18 -0600 Subject: [PATCH 1/4] make @@toStringTag and constructor prototype properties funky accessors --- spec.html | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/spec.html b/spec.html index c64c64d..fdf306d 100644 --- a/spec.html +++ b/spec.html @@ -289,7 +289,35 @@

Iterator.prototype

Iterator.prototype.constructor

-

The initial value of %Iterator.prototype%.constructor is %Iterator%.

+

`Iterator.prototype.constructor` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* }. The [[Get]] and [[Set]] attributes are defined as follows:

+ + +

get Iterator.prototype.constructor

+

The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:

+ + 1. Return %Iterator%. + +
+ + +

set Iterator.prototype.constructor

+

The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called:

+ + 1. Let _O_ be ? RequireObjectCoercible(*this* value). + 1. If _O_ is %Iterator.prototype%, then + 1. Return *undefined*. + 1. Let _desc_ be ? _O_.[[GetOwnProperty]](*"constructor"*). + 1. If IsDataDescriptor(_desc_) is *true* and _desc_.[[Writable]] is *false*, then + 1. Return *undefined*. + 1. Let _newDesc_ be the PropertyDescriptor { [[Value]]: _v_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true* }. + 1. Perform ? _O_.[[DefineOwnProperty]](*"constructor"*, _newDesc_). + 1. Return *undefined*. + +
+ + +

Unlike the *"constructor"* property on most built-in prototypes, for web-compatibility reasons this property must be an accessor.

+
@@ -563,9 +591,34 @@

Iterator.prototype.find ( _predicate_ )

Iterator.prototype [ @@toStringTag ]

-

The initial value of the @@toStringTag property is the String value "Iterator".

+

`Iterator.prototype[@@toStringTag]` is an accessor property with attributes { [[Enumerable]]: *false*, [[Configurable]]: *true* }. The [[Get]] and [[Set]] attributes are defined as follows:

+ + +

get Iterator.prototype [ @@toStringTag ]

+

The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:

+ + 1. Return *"Iterator"*. + +
+ + +

set Iterator.prototype [ @@toStringTag ]

+

The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called:

+ + 1. Let _O_ be ? RequireObjectCoercible(*this* value). + 1. If _O_ is %Iterator.prototype%, then + 1. Return *undefined*. + 1. Let _desc_ be ? _O_.[[GetOwnProperty]](@@toStringTag). + 1. If IsDataDescriptor(_desc_) is *true* and _desc_.[[Writable]] is *false*, then + 1. Return *undefined*. + 1. Let _newDesc_ be the PropertyDescriptor { [[Value]]: _v_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true* }. + 1. Perform ? _O_.[[DefineOwnProperty]](@@toStringTag, _newDesc_). + 1. Return *undefined*. + +
+ -

Unlike the @@toStringTag on most built-in classes, for web-compatibility reasons this property must be writable.

+

Unlike the @@toStringTag property on most built-in prototypes, for web-compatibility reasons this property must be an accessor.

From f481720639bd6c5cefaca300a3b1e23d26603265 Mon Sep 17 00:00:00 2001 From: Michael Ficarra Date: Thu, 12 Oct 2023 12:53:07 -0600 Subject: [PATCH 2/4] throw instead of silently doing nothing --- spec.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec.html b/spec.html index fdf306d..f11d3a4 100644 --- a/spec.html +++ b/spec.html @@ -308,7 +308,7 @@

set Iterator.prototype.constructor

1. Return *undefined*. 1. Let _desc_ be ? _O_.[[GetOwnProperty]](*"constructor"*). 1. If IsDataDescriptor(_desc_) is *true* and _desc_.[[Writable]] is *false*, then - 1. Return *undefined*. + 1. Throw a *TypeError* exception. 1. Let _newDesc_ be the PropertyDescriptor { [[Value]]: _v_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true* }. 1. Perform ? _O_.[[DefineOwnProperty]](*"constructor"*, _newDesc_). 1. Return *undefined*. @@ -610,7 +610,7 @@

set Iterator.prototype [ @@toStringTag ]

1. Return *undefined*. 1. Let _desc_ be ? _O_.[[GetOwnProperty]](@@toStringTag). 1. If IsDataDescriptor(_desc_) is *true* and _desc_.[[Writable]] is *false*, then - 1. Return *undefined*. + 1. Throw a *TypeError* exception. 1. Let _newDesc_ be the PropertyDescriptor { [[Value]]: _v_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true* }. 1. Perform ? _O_.[[DefineOwnProperty]](@@toStringTag, _newDesc_). 1. Return *undefined*. From 7d48c4359c060c72a8013530e8dd852641557c21 Mon Sep 17 00:00:00 2001 From: Michael Ficarra Date: Thu, 12 Oct 2023 12:53:07 -0600 Subject: [PATCH 3/4] throw when this value is Iterator.prototype --- spec.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec.html b/spec.html index f11d3a4..843d89c 100644 --- a/spec.html +++ b/spec.html @@ -305,7 +305,7 @@

set Iterator.prototype.constructor

1. Let _O_ be ? RequireObjectCoercible(*this* value). 1. If _O_ is %Iterator.prototype%, then - 1. Return *undefined*. + 1. Throw a *TypeError* exception. 1. Let _desc_ be ? _O_.[[GetOwnProperty]](*"constructor"*). 1. If IsDataDescriptor(_desc_) is *true* and _desc_.[[Writable]] is *false*, then 1. Throw a *TypeError* exception. @@ -607,7 +607,7 @@

set Iterator.prototype [ @@toStringTag ]

1. Let _O_ be ? RequireObjectCoercible(*this* value). 1. If _O_ is %Iterator.prototype%, then - 1. Return *undefined*. + 1. Throw a *TypeError* exception. 1. Let _desc_ be ? _O_.[[GetOwnProperty]](@@toStringTag). 1. If IsDataDescriptor(_desc_) is *true* and _desc_.[[Writable]] is *false*, then 1. Throw a *TypeError* exception. From d7410769e5efe71e1e01c4970eb927e62ba9782f Mon Sep 17 00:00:00 2001 From: Michael Ficarra Date: Mon, 16 Oct 2023 20:22:05 -0600 Subject: [PATCH 4/4] rewrite funky setter and extract as an AO --- spec.html | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/spec.html b/spec.html index 843d89c..df00d08 100644 --- a/spec.html +++ b/spec.html @@ -107,6 +107,30 @@

Well-Known Intrinsic Objects

Abstract Operations

+ +

+ SetterThatIgnoresPrototypeProperties ( + _home_: an Object, + _p_: a property key, + _v_: an ECMAScript language value, + ): either a normal completion containing ~unused~ or a throw completion +

+
+
+ + 1. Let _O_ be ? RequireObjectCoercible(*this* value). + 1. If _O_ is _home_, then + 1. NOTE: Throwing here emulates assignment to a non-writable data property on the _home_ object in strict mode code. + 1. Throw a *TypeError* exception. + 1. Let _desc_ be ? _O_.[[GetOwnProperty]](_p_). + 1. If _desc_ is *undefined*, then + 1. Perform ? CreateDataPropertyOrThrow(_O_, _p_, _v_). + 1. Else, + 1. Perform ? Set(_O_, _p_, _v_, *true*). + 1. Return ~unused~. + +
+

Operations on Iterator Objects

@@ -303,14 +327,7 @@

get Iterator.prototype.constructor

set Iterator.prototype.constructor

The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called:

- 1. Let _O_ be ? RequireObjectCoercible(*this* value). - 1. If _O_ is %Iterator.prototype%, then - 1. Throw a *TypeError* exception. - 1. Let _desc_ be ? _O_.[[GetOwnProperty]](*"constructor"*). - 1. If IsDataDescriptor(_desc_) is *true* and _desc_.[[Writable]] is *false*, then - 1. Throw a *TypeError* exception. - 1. Let _newDesc_ be the PropertyDescriptor { [[Value]]: _v_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true* }. - 1. Perform ? _O_.[[DefineOwnProperty]](*"constructor"*, _newDesc_). + 1. Perform ? SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, *"constructor"*, _v_). 1. Return *undefined*.
@@ -605,14 +622,7 @@

get Iterator.prototype [ @@toStringTag ]

set Iterator.prototype [ @@toStringTag ]

The value of the [[Set]] attribute is a built-in function that takes an argument _v_. It performs the following steps when called:

- 1. Let _O_ be ? RequireObjectCoercible(*this* value). - 1. If _O_ is %Iterator.prototype%, then - 1. Throw a *TypeError* exception. - 1. Let _desc_ be ? _O_.[[GetOwnProperty]](@@toStringTag). - 1. If IsDataDescriptor(_desc_) is *true* and _desc_.[[Writable]] is *false*, then - 1. Throw a *TypeError* exception. - 1. Let _newDesc_ be the PropertyDescriptor { [[Value]]: _v_, [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true* }. - 1. Perform ? _O_.[[DefineOwnProperty]](@@toStringTag, _newDesc_). + 1. Perform ? SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, %Symbol.toStringTag%, _v_). 1. Return *undefined*.