Not own property getters

Michał Wadas michalwadas at gmail.com
Thu Sep 7 23:58:37 UTC 2017


a) you can enable assertions in code only in development and make operaton
noop in production - that's pretty common in C++ and many other languages
b) isn't somewhere there proposal to change a bit Proxy semantics to
improve performance and simplify implementation?
c) would be property access to garderoby objects ever bottleneck in your
application?

On Fri, 8 Sep 2017 at 01:25, Alex Kodat <alexkodat at gmail.com> wrote:

> If I run the following:
>
> let foo = {a: 0, b: 1, c:1};
> let bar = (
>   new Proxy(
>     foo,
>     {get:
>       (target, prop) => {
>         if (prop in target) return target[prop];
>         if (typeof prop == "symbol") return target[prop];
>         if (prop == "inspect") return;
>         if (prop == "toJSON") return;
>         throw Error("Bad property: " +  prop);
>       }
>     }
>   )
> );
> // bar = foo;
>
> for (let i = 0; i < 1000000; i++) {
>   bar.a = bar.b;
>   bar.b = bar.c;
>   bar.c = bar.c + i;
> }
>
> with the bar = foo assignment above commented out (so using a proxy) and
> not commented out (so direct object access) and V8 (Chrome), SpiderMonkey
> (Firefox), and Chakra (Edge) the difference between proxy and not was about
> a factor of 300-500 (perhaps unsurprisingly, all the JS engines were
> close-ish to each other).
>
> While perhaps this can be improved, it’s a lot to ask of an optimizer to
> detect a proxy and figure out what it's doing to the degree that V8 (and I
> suspect other browsers) detect that bar.a is always at the same offset in
> bar and always an integer (as long as bar's shape doesn't change) and so
> optimize the call to a handful of machine language instructions. Let's say
> some superstar gets the difference down to a factor of 20 (I suspect that's
> unlikely). That's still a big price to pay for detecting errors or say
> automatically returning 0 for an undefined property.
>
> ----
> Alex Kodat
>
> From: Michał Wadas [mailto:michalwadas at gmail.com]
> Sent: Thursday, September 7, 2017 3:55 PM
> To: Alex Kodat <alexkodat at gmail.com>
> Cc: es-discuss at mozilla.org
> Subject: Re: Not own property getters
>
> Why can't you use proxy for this?
>
> On 7 Sep 2017 10:05 pm, "Alex Kodat" <mailto:alexkodat at gmail.com> wrote:
> In a previous post I had proposed an Object.guard (originally badly named
> as
> Object.lock) to make it possible to catch references to non-existent
> properties in code that uses an object.
>
> While that proposal didn't exactly generate a lot of enthusiasm, I now
> realize that there would be a better way of accomplished what I had
> proposed
> with a more general purpose facility. Specifically, if there were an
> Object.notOwnPropertyValue(<object>, <getter>) function that indicated a
> getter to be invoked on  a request for a not own property of the object. If
> a request for a not own property of <object> is received <getter> is called
> with this set to the receiver and the only argument set to the requested
> property.
>
> My proposed Object.guard function could just be accomplished by something
> like
>
>    Object.notOwnPropertyValue(myObject, (prop) => {throw Error("Bad
> property: " + prop);})
>
> For the purposes of catching bad property references, this is better than
> my
> previous proposal because it eliminates the need for [[Get]] (P, Receiver)
> to maintain a guard barrier state as it works it way down the prototype
> chain. Instead, if someone wanted to not throw for properties on the
> prototype chain, the notOwnPropertyValue getter could itself check for the
> property in the receiver's prototype chain:
>
>    Object.notOwnPropertyValue(
>      myObject,
>      (prop) => {
>        if (prop in Object.getPrototypeOf(myObject) return
> Object.getPrototypeOf(myObject)[prop];
>        throw Error("Bad property: " + prop);
>      }
>    }
>
> Obviously this could be done more tidily and efficiently but hopefully the
> point is clear.
>
> A simple alternative use (to a bad property reference catcher) of this
> capability would be something like
>
>    let counts = {};
>    Object.notOwnPropertyValue(counts, () => 0);
>    someStringArray.forEach((s) => counts[s]++;);
>
> Note that I suspect for most purposes one would set
> Object.notOwnPropertyValue on a prototype so there'd be no cost to getting
> a
> property off any prototypes until a property has not been found yet when we
> get to a prototype with Object.notOwnPropertyValue set. So for my purposes,
> I'd create some Guard (my own class) object that would be just above Object
> in the prototype chain of most of my classes that would throw on an invalid
> property reference (my choice whether or not to allow Object.prototype
> properties to be accessed via property accessors on the Guard class
> objects).
>
> I believe this would be relatively simple to implement and, beyond the
> definition of Object.notOwnPropertyValue, would require only a minor change
> to the [[Get]] (P, Receiver) description in the spec:
>
> 1. Assert: IsPropertyKey(P) is true.
> 2. Let desc be O.[[GetOwnProperty]](P).
> 3. ReturnIfAbrupt(desc).
> 4. If desc is undefined, then
>    Insert 1 =>. Let getter be O.[[GetNotOwnProperty]].
>    Insert 2 =>. If getter is not undefined return Call(getter, Receiver, P)
>
>    a. Let parent be O.[[GetPrototypeOf]]().
>    b. ReturnIfAbrupt(parent).
>    c. If parent is null, return undefined.
>    d. Return parent.[[Get]](P, Receiver).
> 5. If IsDataDescriptor(desc) is true, return desc.[[Value]].
> 6. Otherwise, IsAccessorDescriptor(desc) must be true so, let getter be
> desc.[[Get]].
> 7. If getter is undefined, return undefined.
> 8. Return Call(getter, Receiver).
>
> An alternative would allow argument 1 of Object.notOwnPropertyValue to be a
> non-function value in which case it would simply be returned rather than
> called. In the weird case where you want the result of a not own property
> reference to be a function, you'd have to define a getter that returns the
> function. Some sort of formal memoization support would, of course, obviate
> the need for a non-function not own property value. So maybe the function
> described here should be called Object.notOwnPropertyGetter.
>
> Implementation could be accomplished by having a slot in every object for a
> notOwnPropertyValue getter or by a bit indicating that there is indeed such
> a getter and then a hidden Symbol property that references the getter. The
> latter means that the cost of this feature is one bit per simple object and
> a bit more overhead if the bit is on. Plus, presumably
> Object.getOwnPropertySymbols would have to be smart enough not to display
> the hidden Symbol. But, this is an implementation detail.
>
> Finally a big hand wave for now about how one implements the ability to get
> rid of a not own property getter -- there are a lot of ways this can be
> accomplished and it's not worth discussing if there's a truck-sized hole in
> this proposal or if someone tells me that this is the Nth time this feature
> has been proposed (I did find the Firefox __noSuchMethod__ Object.prototype
> method). I suspect another response will be to tell me to use a proxy but
> that would be an insanely heavyweight way of accomplishing such a simple
> task.
>
> If no one blows a hole in this proposal, I guess I'll figure out how to
> turn
> it into a formal proposal so I can be the proud owner of a stage 0
> proposal.
>
> Thanks
>
> ----
> Alex Kodat
>
>
> _______________________________________________
> es-discuss mailing list
> mailto:es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170907/1a6e2f68/attachment-0001.html>


More information about the es-discuss mailing list