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

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


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


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-
> essential-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/fbdd87ff/attachment.html>


More information about the es-discuss mailing list