Not own property getters

Michał Wadas michalwadas at gmail.com
Thu Sep 7 20:54:57 UTC 2017


Why can't you use proxy for this?

On 7 Sep 2017 10:05 pm, "Alex Kodat" <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
> 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/09506b77/attachment.html>


More information about the es-discuss mailing list