Fwd: An idea to extend the functionality of Proxy objects.

Ranando King kingmph at gmail.com
Mon Jan 15 15:39:34 UTC 2018


---------- Forwarded message ----------
From: Ranando King <kingmph at gmail.com>
Date: Sat, Jan 13, 2018 at 2:32 PM
Subject: Re: An idea to extend the functionality of Proxy objects.
To: Isiah Meadows <isiahmeadows at gmail.com>


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 <kingmph at gmail.com> 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 <isiahmeadows at gmail.com>
> 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 <kingmph at gmail.com> 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 <isiahmeadows at gmail.com>
>> 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
>> >> me at isiahmeadows.com
>> >>
>> >> 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 <kingmph at gmail.com>
>> 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
>> >> > 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/20180115/6481f9da/attachment-0001.html>


More information about the es-discuss mailing list