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 <[email protected]> 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:[email protected]] > Sent: Thursday, September 7, 2017 3:55 PM > To: Alex Kodat <[email protected]> > Cc: [email protected] > Subject: Re: Not own property getters > > Why can't you use proxy for this? > > On 7 Sep 2017 10:05 pm, "Alex Kodat" <mailto:[email protected]> 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:[email protected] > https://mail.mozilla.org/listinfo/es-discuss > >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

