Suggestion: Proxy.[[GetOwnProperty]] caching non-configurable, non-writable data descriptors?

Alex Vincent ajvincent at gmail.com
Thu Oct 5 09:50:52 UTC 2017


Proxies are a little slow right now, and maybe the rules of ECMAScript can
safely allow for caching a non-configurable, non-writable data descriptor.

Specifically, in ValidateAndApplyPropertyDescriptor from ES8 (section
9.1.6.3, step 7a-iii), we've already shown current and desc both have the
following traits:

   1. isDataDescriptor(current) and isDataDescriptor(desc) return true
   2. [[Configurable]] is false
   3. [[Writable]] is false
   4. SameValue(Desc.[[Value]], current.[[Value]]) is true
   5. The [[GetOwnProperty]] or [[DefineOwnProperty]] internal method is
   executing, indirectly calling ValidateAndApplyPropertyDescriptor for this
   case.
   6. The [[Get]] or [[Set]] internal methods is probably executing,
   calling [[GetOwnProperty]] or [[DefineOwnProperty]] for this case.

That is a very specific set of traits.  As I understand it, it means the
proxy target's property named P in Proxy.[[GetOwnProperty]] is permanently
locked and can never change - and so neither can the proxy ever report a
different value.  Therefore, calling on the proxy handler for that property
a second time is, at least in my view, either redundant or unnecessarily
expensive.

I would suggest that implementers in section 9.5 (Proxy internals)
optionally have a private Map where values that are non-configurable and
non-writable are stored.  Then [[GetOwnProperty]] could insert a couple of
new steps into its algorithm.  Between steps 4 and 5 of the current
algorithm, I would add:  "If the optional [[Map]] object exists and
[[Map]].has(P) returns true, return [[Map]].get(P)."  In step 17 of the
current algorithm, I would add a substep:  "If isDataDescriptor(resultDesc)
and resultDesc.[[Writable]] is false and the optional [[Map]] object
exists, call [[Map]].set(P, resultDesc).  (If the [[Map]] internal slot
exists but does not contain a Map, the [[Map]] may be filled with a Map at
this time.)"

I would also suggest similar changes for [[DefineOwnProperty]]. (Section
9.5.6)

Alternatively, if storing a specific descriptor in the Map is unpalatable,
the specification could request storing resultDesc.[[Value]] in step 17,
and create a new non-configurable, non-writable descriptor before the
current step 5.

Also, if a Map is too expensive, the spec could allow for an equivalent
native map<string, JSValue> or whatever other appropriate data structure
fills the need.

Counter-point (1):  if the intent of the proxy is to treat all property
look-ups equally, then caching the non-writable, non-configurable
descriptors goes against that intent - because now the trap is invoked only
once for properties returning this type of descriptor.  But there's a lot
of steps, including invoking a custom proxy handler trap with an unknown
number of steps, and a lot of complexity in that trap to ensure what it
returns will pass all the assertions in the spec.

Counter-point (2):  I don't know how common it is to have a property
descriptor that meets all six criteria at the beginning of this post, in
particular that both [[Configurable]] and [[Writable]] are false.  So this
does add another pointer, at least to null initially, for the [[Map]]
slot.  This is why I am proposing the [[Map]] slot as optional for
implementers.  Let the engines decide whether it's warranted or not as an
optimization.

Thoughts?


Alex Vincent

Hayward, CA, USA
-- 
"The first step in confirming there is a bug in someone else's work is
confirming there are no bugs in your own."
-- Alexander J. Vincent, June 30, 2001
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20171005/6d0d4324/attachment-0001.html>


More information about the es-discuss mailing list