- 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