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

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


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


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/6f02c86d/attachment-0001.html>


More information about the es-discuss mailing list