---------- Forwarded message ---------- From: Ranando King <[email protected]> Date: Sat, Jan 13, 2018 at 2:35 PM Subject: Re: An idea to extend the functionality of Proxy objects. To: Isiah Meadows <[email protected]>
Sorry clicked send before editing. The first version is the original, the second the modified version. This this the kind of thing you were referring to? I admit that doing this makes it more clear that the prototype handler methods are being called, and I can see the value in doing so, but this would indeed require a fairly large rewording to the invariant requirements. Hopefully, however, it is clear that such a rewording doesn't change the intent of the requirement. On Sat, Jan 13, 2018 at 2:32 PM, Ranando King <[email protected]> wrote: > After thinking about it a bit more, maybe you mean something like this: > > [[SetPrototypeOf]] (V) > > - The Type of the return value must be Boolean. > - If target is non-extensible, [[SetPrototypeOf]] must return false, > unless V is the SameValue > <https://tc39.github.io/ecma262/#sec-samevalue> as the target's > observed [[GetPrototypeOf]] value. > > After thinking about it a bit more, maybe you mean something like this: > > [[SetPrototypeOf]] (V) > > - The Type of the return value must be Boolean. > - *If [[IsExtensible]] returns false*, [[SetPrototypeOf]] must return > false, unless V is the SameValue > <https://tc39.github.io/ecma262/#sec-samevalue> as *that returned by > [[GetPrototypeOf]]*. > > > After thinking about it a bit more, maybe you mean something like this: > > > On Sat, Jan 13, 2018 at 2:23 PM, Ranando King <[email protected]> wrote: > >> While I understand what you're getting at, The invariants would *not* change >> under my idea. In fact, I've thought about it carefully and crafted the >> wording change from my suggestion specifically so that the invariants >> wouldn't change. My goal is simply to change this process: >> >> some action on proxied target -> >> [[ProxyHandler]] method called -> >> [[ProxyHandler]] method results checked by testing against >> Reflect.<methods>(target...) -> >> error on failure -> return result >> >> into >> >> some action on proxied target -> >> [[ProxyHandler]] method called -> >> [[ProxyHandler]] method results checked by testing against >> [[ProxyHandler]].<methods>(target...) -> >> error on failure -> return result >> >> so that the developers proxy handler implementation is solely responsible >> for ensuring that the invariant requirements are maintained. The <methods> >> in question are exactly those described by the invariants. The only thing >> that is changing is that [[ProxyHandler]] would be the authority for the >> information used to ensure that the invariants have not been violated. >> >> The gist is that while currently, given a caller, a proxy, and a target, >> the target constrains what the caller can do with the proxy, what I want is >> to reverse it so that the proxy constrains what the caller can do with the >> target, and all still without violating the existing invariant >> requirements. Does that make what I'm after a little clearer? >> >> On Fri, Jan 12, 2018 at 9:07 PM, Isiah Meadows <[email protected]> >> wrote: >> >>> Not full, but changes of some kind will likely be required, and you >>> should address and document how those would be changed. >>> >>> On Fri, Jan 12, 2018, 20:41 Ranando King <[email protected]> wrote: >>> > >>> > You're right about the mistake with Object.seal. I wasn't too focused >>> on that part when writing the example code. So are you suggesting that I >>> also prepare a fully detailed rewrite of the invariant rules for comparison? >>> > >>> > On Fri, Jan 12, 2018 at 6:44 PM, Isiah Meadows <[email protected]> >>> wrote: >>> >> >>> >> Make sure to compare your changes to the [invariants of the essential >>> >> internal methods][1], since changes to them would require some >>> >> *significant* justification. And yes, your proposal would require >>> >> changes to them. (I'm not a TC39 member, but I've read up enough about >>> >> their decisions to make some educated guesses, and core changes tend >>> >> to be met with extreme skepticism.) >>> >> >>> >> Also, note that you probably meant to, in `SourceFile.js`, use >>> >> `Object.seal(obj)`, not `obj.seal()` (it's a static method, not an >>> >> instance method). >>> >> >>> >> [1]: https://tc39.github.io/ecma262/#sec-invariants-of-the-essent >>> ial-internal-methods >>> >> ----- >>> >> >>> >> Isiah Meadows >>> >> [email protected] >>> >> >>> >> Looking for web consulting? Or a new website? >>> >> Send me an email and we can get started. >>> >> www.isiahmeadows.com >>> >> >>> >> >>> >> On Fri, Jan 12, 2018 at 5:38 PM, Ranando King <[email protected]> >>> wrote: >>> >> > I have an idea I’d like to propose with regards to Proxy objects. I >>> would >>> >> > like to make a change to spec section 6.1.7.3 (as seen in the >>> latest draft). >>> >> > The change is as follows: >>> >> > >>> >> > The Internal Methods of Objects of an ECMAScript engine must >>> conform to the >>> >> > list of invariants specified below. Ordinary ECMAScript Objects as >>> well as >>> >> > all standard exotic objects in this specification maintain these >>> invariants. >>> >> > ECMAScript Proxy objects maintain these invariants by means of >>> runtime >>> >> > checks on the result of traps invoked on the [[ProxyHandler]] >>> object using >>> >> > either the corresponding traps on the [[ProxyHandler]] should the >>> needed >>> >> > trap be defined, or the default internal method otherwise. >>> >> > >>> >> > Put simply, the change that I’m requesting would have the runtime >>> checks >>> >> > verify the selfconsistency of the results returned by the >>> [[ProxyHandler]] >>> >> > object instead of testing the [[ProxyHandler]] results against the >>> target. >>> >> > The rationale behind this change is to allow Proxy objects the >>> freedom to >>> >> > behave in a manner that is inconsistent with the behavior that >>> would have >>> >> > been should the target have been accessed directly, while still >>> requiring >>> >> > that the consistency of the behavior of the essential internal >>> methods be >>> >> > upheld. In this way, a Proxy object would be able to project new >>> properties >>> >> > for a proxied target even if the target object is not extensible, >>> or even >>> >> > completely hide non-configurable properties. The requirement to do >>> so would >>> >> > be implementation of the appropriate [[ProxyHandler]] methods so as >>> to >>> >> > satisfy all of the corresponding invariants for all implemented >>> handlers. >>> >> > The ECMAScript engine would then see results consistent with >>> expectations, >>> >> > despite the fact that the results are inconsistent with the actual >>> nature of >>> >> > the proxied target object. >>> >> > >>> >> > An example might be the case of a library to mock objects. >>> >> > >>> >> > /* SourceFile.js */ >>> >> > var obj = { bar: "The real bar. Accept no imitations!", fubar: >>> "Always has >>> >> > been." }; >>> >> > obj.seal(); >>> >> > >>> >> > export default obj; >>> >> > >>> >> > /* TestFile.js */ >>> >> > import testObj from "SourceFile"; >>> >> > >>> >> > var mock = new Proxy(testObj, { >>> >> > has: function(target, key) { >>> >> > var retval = false; >>> >> > if (key == "foo") { //add the foo property >>> >> > retval = true; >>> >> > } >>> >> > else if (key != "bar") { //hide the bar property >>> >> > retval = (key in target); >>> >> > } >>> >> > >>> >> > return retval; >>> >> > }, >>> >> > ownKeys: function(target) { >>> >> > var retval = Reflect.ownKeys(target); >>> >> > var barIndex = retval.indexOf(bar); >>> >> > >>> >> > if (barIndex != -1) >>> >> > retval.splice(barIndex, 1); >>> >> > >>> >> > retval.push("foo"); >>> >> > return retval; >>> >> > }, >>> >> > defineProperty: function(target, key, descriptor) { >>> >> > var retval = true; >>> >> > if ((key == "foo") || (key == "bar")) { >>> >> > retval = false; >>> >> > } >>> >> > else { >>> >> > Reflect.defineProperty(target, key, descriptor); >>> >> > } >>> >> > >>> >> > return retval; >>> >> > }, >>> >> > get: function(target, key) { >>> >> > var retval = undefined; >>> >> > >>> >> > if (key == "foo") { >>> >> > retval = "You got the fake property!" >>> >> > } >>> >> > else if (key != "bar") { >>> >> > retval = Reflect.deleteProperty(target, key); >>> >> > } >>> >> > >>> >> > return retval; >>> >> > }, >>> >> > set: function(target, key, value) { >>> >> > var retval = false; >>> >> > if ((key != "foo") && (key != "bar")) >>> >> > retval = Reflect.set(target, key); >>> >> > } >>> >> > return retval; >>> >> > }, >>> >> > deleteProperty: function(target, key) { >>> >> > var retval = false; >>> >> > if ((key != "foo") && (key != "bar")) >>> >> > retval = Reflect.deleteProperty(target, key); >>> >> > } >>> >> > return retval; >>> >> > }, >>> >> > getOwnPropertyDescriptor: function(target, key) { >>> >> > var retval; >>> >> > if (key == "foo") { >>> >> > retval = { >>> >> > enumerable: true, >>> >> > writable: false, >>> >> > configurable: false, >>> >> > value: "You got the fake property!" >>> >> > }; >>> >> > } >>> >> > else if (key != "bar") { >>> >> > retval = Reflect.getOwnPropertyDescriptor(target, key); >>> >> > } >>> >> > return retval; >>> >> > } >>> >> > }); >>> >> > >>> >> > console.log(mock.fubar); // "Always has been" >>> >> > console.log(mock.foo); // #1 >>> >> > console.log(mock.bar); // #2 >>> >> > >>> >> > >>> >> > Currently, if the above code were run, an error would be thrown at >>> comment >>> >> > #1. Even if that line was commented out, an error would be thrown >>> at comment >>> >> > #2. With my proposed change, the code would run successfully. >>> Comment #1 >>> >> > would be "You got the fake property!" and comment #2 would be >>> undefined. As >>> >> > a matter of completeness, if the handler only contained the "get" >>> and "set" >>> >> > methods, this code would throw an error just as it currently would. >>> The >>> >> > reason that it works with all of the handlers this that these >>> handlers >>> >> > ensure that a consistent description of the is being presented to >>> the >>> >> > interpreter since the interpreter would rely on the methods of the >>> proxy >>> >> > object's handler to supply the data needed to validate the response >>> of the >>> >> > original call. >>> >> > >>> >> > _______________________________________________ >>> >> > es-discuss mailing list >>> >> > [email protected] >>> >> > https://mail.mozilla.org/listinfo/es-discuss >>> >> > >>> > >>> > >>> >> >> >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

