- From: Timothy Gu <notifications@github.com>
- Date: Thu, 20 Feb 2020 17:00:12 -0800
- To: heycam/webidl <webidl@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <heycam/webidl/pull/840/review/362326611@github.com>
TimothyGu commented on this pull request.
Couldn't spot any errors in the proxy traps themselves, but some editorial comments are provided.
> @@ -13629,6 +13800,250 @@ internal method as follows.
1. Return <a abstract-op>OrdinaryGetOwnProperty</a>(|O|, |P|).
</div>
+<h3 id="es-observable-arrays">Observable array exotic objects</h3>
+
+An <dfn>observable array exotic object</dfn> is a specific type of ECMAScript
+[=Proxy exotic object=] which is created using the proxy hooks defined in this section. They are
+defined in this manner because the ECMAScript specification includes special treatment for
+[=Proxy exotic objects=] that have <code>Array</code> instances as their proxy target, and we want
+to ensure that [=observable array types=] are exposed to ECMAScript code with this special treatment
+intact.
+
+The proxy traps used by observable array exotic objects work to ensure a number of invariants beyond
+those of normal <code>Array</code> instances:
+
+* The arrays have no holes, i.e. every property in the inclusive range 0 through
+ <code>observableArray.length</code> will be filled with a value compatible with the specified
<code>observableArray.length</code> – 1? Or use something like "every property in the interval [0, <code>observableArray.length</code>".
> + properties, while the <code>length</code> property remains as a non-configurable,
+ non-enumerable, and writable data property.
+* Adding additional properties to the array cannot be prevented using, for example,
+ <code>Object.preventExtensions()</code>.
+
+<div algorithm>
+ To <dfn lt="creating an observable array exotic object">create an observable array exotic object</dfn>
+ in a [=Realm=] |realm|, given Web IDL type |T| and algorithms |setAlgorithm| and |deleteAlgorithm|:
+
+ 1. Let |innerArray| be [=!=] [$ArrayCreate$](0).
+ 1. Let |handler| be [$ObjectCreate$](<emu-val>null</emu-val>, « \[[Type]], \[[SetAlgorithm]], \[[DeleteAlgorithm]], \[[BackingList]] »).
+ 1. Set |handler|.\[[Type]] to |T|.
+ 1. Set |handler|.\[[SetAlgorithm]] to |setAlgorithm|.
+ 1. Set |handler|.\[[DeleteAlgorithm]] to |deleteAlgorithm|.
+ 1. Let |defineProperty| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-defineProperty]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "defineProperty", |defineProperty|).
Use `<code>` with string literals, per Infra. But I wonder if we could do a spec-for loop, which will be easier to read, IMO.
> + 1. Let |defineProperty| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-defineProperty]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "defineProperty", |defineProperty|).
+ 1. Let |deleteProperty| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-deleteProperty]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "deleteProperty", |deleteProperty|).
+ 1. Let |get| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-get]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "get", |get|).
+ 1. Let |getOwnPropertyDescriptor| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-getOwnPropertyDescriptor]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "getOwnPropertyDescriptor", |getOwnPropertyDescriptor|).
+ 1. Let |has| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-has]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "has", |has|).
+ 1. Let |preventExtensions| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-preventExtensions]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "preventExtensions", |preventExtensions|).
+ 1. Let |set| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-set]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "set", |set|).
+ 1. Let |ownKeys| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-ownKeys]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "ownKeys", |ownKeys|).
Could we use an alphabetical order here?
> + 1. Perform [=!=] [$CreateDataProperty$](|handler|, "preventExtensions", |preventExtensions|).
+ 1. Let |set| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-set]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "set", |set|).
+ 1. Let |ownKeys| be [=!=] [$CreateBuiltinFunction$](the steps from [[#es-observable-array-ownKeys]], « », |realm|).
+ 1. Perform [=!=] [$CreateDataProperty$](|handler|, "ownKeys", |ownKeys|).
+ 1. Return [=!=] [$ProxyCreate$](|innerArray|, |handler|).
+</div>
+
+<h4 id="es-observable-array-defineProperty"><code>defineProperty</code></h4>
+
+<div algorithm="observable array exotic object defineProperty trap">
+ The steps for the <code>defineProperty</code> proxy trap for
+ [=observable array exotic objects=], given |O|, |P|, and |descriptorObj| are as follows:
+
+ 1. Let |handler| be the <emu-val>this</emu-val> value.
+ 1. Let |descriptor| be [=?=] [$ToPropertyDescriptor$](|descriptorObj|).
Can this ever throw?
> + 1. Return [=!=] [$ProxyCreate$](|innerArray|, |handler|).
+</div>
+
+<h4 id="es-observable-array-defineProperty"><code>defineProperty</code></h4>
+
+<div algorithm="observable array exotic object defineProperty trap">
+ The steps for the <code>defineProperty</code> proxy trap for
+ [=observable array exotic objects=], given |O|, |P|, and |descriptorObj| are as follows:
+
+ 1. Let |handler| be the <emu-val>this</emu-val> value.
+ 1. Let |descriptor| be [=?=] [$ToPropertyDescriptor$](|descriptorObj|).
+ 1. If |P| is "length", then:
+ 1. If [=!=] [$IsAccessorDescriptor$](|descriptor|) is <emu-val>true</emu-val>, then return
+ <emu-val>false</emu-val>.
+ 1. If |descriptor| has a \[[Configurable]] field and |descriptor|.\[[Configurable]] is
+ <emu-val>true</emu-val>, return <emu-val>false</emu-val>.
More concise wording:
> If _descriptor_.[[Configurable]] is present and has the value **true**, return **false**.
or
> If _descriptor_.[[Configurable]] is present and it is **true**, return **false**.
> +
+<h4 id="es-observable-array-deleteProperty"><code>deleteProperty</code></h4>
+
+<div algorithm="observable array exotic object deleteProperty trap">
+ The steps for the <code>deleteProperty</code> proxy trap for
+ [=observable array exotic objects=], given |O| and |P|, are as follows:
+
+ 1. Let |handler| be the <emu-val>this</emu-val> value.
+ 1. If |P| is "length", then return <emu-val>false</emu-val>.
+ 1. If |P| [=is an array index=], then:
+ 1. Let |oldLen| be |handler|.\[[BackingList]]'s [=list/size=].
+ 1. Let |index| be [=!=] [$ToUint32$](|P|).
+ 1. If |index| ≠ |oldLen| − 1, then return
+ <emu-val>false</emu-val>.
+ 1. Perform the algorithm steps given by |handler|.\[[DeleteAlgorithm]], given
+ |handler|.\[[BackingList]][|index|] and |index|.
Can we just say
> Perform _handler_.[[DeleteAlgorithm]](_handler_.[[BackingList]][_index_], _index_).
> @@ -13629,6 +13800,250 @@ internal method as follows.
1. Return <a abstract-op>OrdinaryGetOwnProperty</a>(|O|, |P|).
</div>
+<h3 id="es-observable-arrays">Observable array exotic objects</h3>
+
+An <dfn>observable array exotic object</dfn> is a specific type of ECMAScript
+[=Proxy exotic object=] which is created using the proxy hooks defined in this section. They are
The ES spec calls them traps rather than hooks.
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/heycam/webidl/pull/840#pullrequestreview-362326611
Received on Friday, 21 February 2020 01:00:27 UTC