Question about direct proxies syncing their targets

David Bruant bruant.d at gmail.com
Sat Jan 14 02:44:53 PST 2012


Le 14/01/2012 03:09, Tab Atkins Jr. a écrit :
> On Fri, Jan 13, 2012 at 5:08 PM, David Bruant <bruant.d at gmail.com> wrote:
>> Le 14/01/2012 01:57, Tab Atkins Jr. a écrit :
>>> In the direct proxies proposal at
>>> <http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies>,
>>> there's the following line:
>>>
>>> get:
>>>  * Invariant checks:
>>>     * if property exists on target as a data property, updates the
>>> target’s property with the returned value
>> There is also the following line in introduction:
>> "A proxy ensures that its handler and its target do not contradict each
>> other as far as non-configurability and non-extensibility are concerned."
>>
>>> Consider an xrange object like from Python, which represents a numeric
>>> range (with a start, stop, and step) and exposes both an iterator and
>>> get traps.
>>>
>>> Am I correct in assuming that, since the target of an xrange proxy is
>>> an empty object, iterating through the xrange or getting specific
>>> values from it will *not* fill up the target in an attempt to
>>> synchronize it with the returned values from the get trap?
>> My understanding is that as long as the iteration and property gets
>> don't create or report non-writable and non-configurable properties,
>> nothing will be done to the target.
> Hmm, I'm not certain whether this answers my question or not.  Let me
> provide a more direct example.  Assume the following code:
>
> function xrange(start, stop, step) {
>   // do error checking, default args, etc.
>   var handler = {
>     get: function(target, i) {
>       var val = start + i * step;
>       return val < stop ? val : undefined;
>     },
>     iterate: function(target){...}
>   }
>   return new Proxy({}, handler);
> }
>
> var a = new xrange(0, 100, 2);
> print( a[5] ); // should print "10"
>
> In the above code, after the print statement, does the proxy's target
> have a '5' property set on it, or not?
Not it does not.

However, if you went for
-----
Object.defineProperty(a, 5, {value: 12, configurable:false,
writable:false});
a[5]; // throw a TypeError
-----
defineProperty trap would be called. Since you did not provide one, it
would by default forward to the target and would create a
non-configurable, non-writable property on the target.
When you try to get the property, the engine checks whether you can
legitimately return 10 without breaking an invariant. Since you do break
an invariant (by lying about the value of a non-writable,
non-configurable property), the engine throws a TypeError.

A main difference between the old and the new proxy design, absent traps
means that you want the operation to be forwarded to the target (which
we can imagine can lead to some optimizations) instead of throwing.

>> It seems that the case you describe would be a good candidate for
>> "virtual objects" [1]
>>
>> [1] http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api
> Yes, virtual objects are probably a better fit for this, as I'd want
> only a few traps to be valid, and the rest to fail with a TypeError.
That's what virtual handlers have been introduced for.

> However, I'm still interested in the answer for proxies.
Does it answer your question?

Tom Van Cutsem wrote a library [1] that runs on top of current V8 and
SpiderMonkey (and so Firefox and Chrome (chrome needs to go in
about:flags to activate proxies)) implementations to replace the old
proxy and with the new one. I think it's faithful to he current proposal
(most invariant checkink included).

Code you'd be interested to run after the insertion of the library would be
-----
var target = {};

function xrange(start, stop, step) {
  // do error checking, default args, etc.
  var handler = {
    get: function(target, i) {
      var val = start + i * step;
      return val < stop ? val : undefined;
    },
    iterate: function(target){...}
  }
  return new Proxy(target, handler);
}

var a = new xrange(0, 100, 2);
console.log( a[5] ); // should print "10"

console.log(5 in target); // should print false

Object.defineProperty(a, 5, {value: 12, configurable:false,
writable:false});

console.log(5 in target); // should print true
-----

David

[1]
http://code.google.com/p/es-lab/source/browse/trunk/src/proxies/DirectProxies.js


More information about the es-discuss mailing list