Giter Club home page Giter Club logo

harmony-reflect's Issues

proxies not supported on this platform

I get this exception when calling Proxy(...).

Error: proxies not supported on this platform
at new global.Proxy (http://localhost:55503/Core/shared-html-widgets/3rdparty/reflect.js:1992:11)
at Object.ViewModelMarshallingService._getOrCreateRemoteObject (http://localhost:55503/Core/js/angular/services/view-model-marshalling-service.js?bust=1418052137254:489:37)

Here's are my Chrome version info:

Google Chrome 39.0.2171.71 (Build officiel) m
Révision 465742dffbc8f2edcb5dacd2afc8b095199172fc-refs/branch-heads/2171_62@{#12}
Système d'exploitation Windows
Blink 537.36 (@185310)
JavaScript V8 3.29.88.17
Flash 15.0.0.239
Agent utilisateur Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Ligne de commande "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --harmony-proxies --flag-switches-begin --javascript-harmony --flag-switches-end

"illegal access" when using JSON.stringify on a Proxy

I am getting a strange error when trying to stringify a Proxy object in node.js:

$ node --harmony
> var hr = require('harmony-reflect');
undefined
> JSON.stringify(new Proxy({}, {}));
illegal access

Just the plain string illegal access is thrown (not an Error object). Tested with node.js v0.10.26 and v0.11.13, same behavior.

Using proxies as prototypes

I’m trying to proxy every object in a group of objects where some might be the prototypes of others. Similar to this minimal example:

proto = {..}
proxiedProto = Proxy(proto, {
    set: function(target, name, value) {
        target[name] = value; return true; 
    }
});

obj = Object.create(proxiedProto);
proxiedObj = Proxy(obj, {
    set: function(target, name, value) {
        target[name] = value; return true; 
    }
});

The proposal for Direct Proxies in the ECMAScript wiki (http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies#interaction_with_prototypal_inheritance) suggests that setting a property of obj (for example in the set-trap of proxiedObj) will fire the set-trap of proxiedProto:

When a proxy is used as a prototype, some of its traps may get triggered not because the proxy itself was “touched” by external code, but rather an object that inherits (directly or indirectly) from the proxy

Now, I’m wondering about two things related to this quote:

First: Using the current version of this repository, whether the prototype’s set-trap fires or not seems to depend on whether the property in question was already defined in the prototype's target or not, at least in Chrome 30.0.1599.101 on my computer, as in the following two examples:

Example 1: as expected after reading the wiki:

proto = {age: 1}

proxiedProto = Proxy(proto, {
    set: function(target, name, value) {
        target[name] = value; return true;
    }
})

obj = Object.create(proxiedProto)
obj.age = 2 

console.log(obj.age === 2) // true
console.log(obj.hasOwnProperty('age')) // false
console.log(proto.age === 1) // false

Example 2: not as (I’ve) expected, only difference is that proto now is an empty object (without an ‘age’ property):

proto = {}

proxiedProto = Proxy(proto, {
    set: function(target, name, value) {
        target[name] = value; return true;
    }
})

obj = Object.create(proxiedProto)
obj.age = 2

console.log(obj.age === 2) // true
console.log(obj.hasOwnProperty('age')) // true
console.log(proto.age === undefined) // true 

Is this a bug?

Second: Given that the prototype’s trap should fire as in Example 1, is there a way to change the target in proxiedObj’s proxy-handler without triggering the set-trap of proxiedProto? Or is it basically not possible to change an inheriting object when the prototype is a proxy with a set-trap?


And there's one more question I've related to proxies as prototypes (not sure if it would be better to file another issue, let me know in that case): When proxies are used as prototypes, this can't be changed later-on. For example:

proxiedProto = Proxy({}, 
    {set: function(target, name, value) {
        target[name] = value; return true;
    }
});

obj = {};
console.log(obj.__proto__ === Object.prototype); // true

obj.__proto__ = proxiedProto;
console.log(obj.__proto__ === proxiedProto); // true

obj.__proto__ = Object.prototype;
console.log(obj.__proto__ === Object.prototype); // false
console.log(obj.__proto__ === proxiedProto); // true

Maybe that's also related to #18. At least it's similarly just a matter with Chrome and not in Firefox (25.0).

Using stringify on proxy object

hi

any reason why this is not working?

var obj  = {};
obj.name = "Func";
var t = JSON.stringify(obj); //working

var prx = new Proxy({}, {});
prx.name = "Func";
var t = JSON.stringify(prx); //not working

Proxy to Array fools most methods of checking whether Array is Array

I'm not quite sure how to motivate this problem without describing 3 different phenomena at once so please bear with me:

  1. JSON.stringify does not work on Proxy objects (it fails with "Illegal Access" exception).
  2. So I've been using Crockford's json2.js when I need to JSON-serialize Proxy objects. This works fine except if I have a Proxy to an Array (or to an object with an embedded Array), the generated JSON is just an object with numeric keys, not an Array (literally, more like { "0": 'foo', "1": 'bar' } instead of ['foo', 'bar'].
  3. The second thing is because the test json2.js uses to determine whether something is an array is the Object.prototype.toString.apply(candidate) === '[object Array]' test. Proxy to Array returns [object Object].

It's the third of these that I think is arguably a bug in the proxy implementation (or I'd like to know why not, and how to work around it!).

magi@ubuntu ~/src> node --harmony
> require('harmony-reflect')
> JSON2 = require('./json2')
> a = ['foo','bar']
[ 'foo', 'bar' ]
> p = Proxy(a, {})
{ '0': 'foo',
  '1': 'bar' }
> JSON.stringify(p)
illegal access
> JSON2.stringify(p)
'{"0":"foo","1":"bar"}'

Note there that the REPL's display of p shows it as an object with numeric keys, as I described in (2) above. So not only json2.js but also util.inspect (which the REPL uses) is treating p as a general Object, not as an Array.

Also note that the builtin JSON.stringify on a proxy just fails with "illegal access".

Here's the full battery of tests I can think of for whether something is an array (all of these return true for a, but mostly not for p):

> a instanceof Array
true
> Array.isArray(a)
true
> require('util').isArray(a)
true
> Object.prototype.toString.apply(a)
'[object Array]'
> p instanceof Array
true
> Array.isArray(p)
false
> require('util').isArray(p)
false
> Object.prototype.toString.apply(p)
'[object Object]'

So the instanceof test works on the proxy, but all the other tests fail. And a lot of code out there wants to use the Object.prototype.toString test. Now, the reasons for using the Object.prototype.toString test instead of the instanceof test might not be relevant to Node (namely, browser-side stuff with multiple frames or iframes). But is there any hope that Object.prototype.toString should be returning Array and not Object for arrays?

Some further details:

  • I was hoping that (1) would be fixed in more recent versions of Node, from https://chromiumcodereview.appspot.com/11312063 and https://code.google.com/p/v8/source/detail?r=12851.
  • (I don't know how to tell from Chromium or V8 bug reports what V8 version a fix goes into, but from the general timeframe of the fix, I was hoping this would be in V8 3.15.)
  • I just tried building Node.js from source, which currently comes with V8 3.16.17, and JSON.stringify(proxy) still fails as shown below.

Delete trap on nested proxies.

I am having an issue when using the delete operator on an object wrapped using nested proxies. An example program is:

var Reflect = require("harmony-reflect");

var handler = {
    deleteProperty: function(target,name,receiver) {
        return Reflect.deleteProperty(target,name,receiver);
    }
};

var o = {x: 1, y: 2};
var inner = new Proxy(o, handler);
var outer = new Proxy(inner, handler);

delete outer.x;

Which in turn produces this error trace:

/Users/jackw/Developer/harmony-test/node_modules/harmony-reflect/reflect.js:1717
      return handler.deleteProperty(target, name);
                     ^
TypeError: undefined is not a function
    at Object.global.Reflect.deleteProperty (/Users/jackw/Developer/harmony-test/node_modules/harmony-reflect/reflect.js:1717:22)
    at Object.handler.deleteProperty (/Users/jackw/Developer/harmony-test/test.js:5:24)
    at Object.Validator [as delete] (/Users/jackw/Developer/harmony-test/node_modules/harmony-reflect/reflect.js:818:20)
    at Object.<anonymous> (/Users/jackw/Developer/harmony-test/test.js:13:8)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)

Assuming this is a bug and not an incorrect example on my part, I believe the issue may be related to the difference in naming between the Validator trap delete and the Reflect function deleteProperty.

Wrong description of the repo or lack of some text in readme

Just wanted to point out that this library doesn't work as Proxy polyfill which might be implied from the project description or, maybe, I missed something in the readme which states how to bring Proxy into environment, that don't have those natively.

Cannot properly Proxy 'os' methods

I cannot get the following example to work:

require('harmonize')(['harmony_proxies']);
require('harmony-reflect');

var os = require('os');

var p = new Proxy(os, {});

console.log(os.type())
console.log(p.type())

This is what I get as output:

Linux
(...)file.js:9
console.log(p.type())
              ^

TypeError: Illegal invocation
    at Object.<anonymous> (/home/onaips/node-lazy-require/oi.js:9:15)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:467:10)
    at startup (node.js:134:18)
    at node.js:961:3

Looks like the this context is not being properly set. Is this a bug or I shouldn't be doing it?

Get/Set receivers don't work with inheritance in v8

I'm sure this is a known issue. The v8 legacy proxy implementation seems to have a bug with get and/or set. When using a proxy as a prototype, the get and set traps should get the actual receiver of the property access as an argument. But that doesn't seem to be the case. The traps always receive just the proxy object. Here's a test.

// for node.js
if(typeof require == 'function') {
  var load = require;
}

load('../reflect.js');

var RCVR = null;

function test() {
  var target = {}
  var proxy = Proxy(target, {
    get: function(target, name, receiver) {
      console.log('GET');
      RCVR = receiver;
    },
    set: function(target, name, val, receiver) {
      console.log('SET');
      RCVR = receiver;
      return true;
    }
  });
  var child = Object.create(proxy);

  child.foo;
  console.log('get :' + (RCVR === child));

  child.bar = 'bar';
  console.log('set :' + (RCVR === child));
}

I spent some time trying to come up with a way to work around this bug in v8 to get inheritance working with this proxy shim. But I can't see one. this is really unfortunate because without this, nice use cases like MethodSink just don't work. Should I file this bug with v8? It's unlikely that they'll fix it considering the old proposal is likely going away.

There may also be something wrong with this test. I ran it in FF (where all the current tests pass) and it fails there. For some reason the get/set traps don't seem to be called at all in FF. I don't get the GET output that confirms the trap. Any idea what I'm doing wrong?

Date, RegExp, some Array prototype built-ins fail on proxies

In the direct proxies spec, built-ins on Date and RegExp should auto-unwrap the proxy:

var d = new Date()               
var dp = Proxy(d,{})
Date.prototype.getTime.call(dp) // or simply: dp.getTime()
// should work, but currently fails

Similarly for e.g. RegExp.prototype.exec and RegExp.prototype.test
Similarly also for the Date and RegExp toString() method, as explained elsewhere.

All non-generic Date.prototype and RegExp.prototype methods should be patched to auto-unwrap proxies.

The spidermonkey shell uses non-standard toSource() invocations that also currently fail on proxies. Those should probably also auto-unwrap.

ES5 shim for proxies

I've been exploring various concepts for trying to bring ES6 features to ES5 supporting engines (without source rewriting). One example is of bringing Names to ES5 (http://bbenvie.com/articles/2012-06-06/ES6-Private-Names-Shim), and collections (https://github.com/Benvie/ES6-Harmony-Collections-Shim) are trivial to implement at an API compatible level and many other features are as well. Obviously anything related to syntax changes are out. Proxies represent an interesting in between, where the syntax is fully compatible but the underlying semantics are...complicated.

In fact, it's trivial to shim most of the features of proxies as this very repo shows. The direct proxy concept is implemented on top of the original proxy api almost entirely (from a user standpoint) due to the fact that almost all of the operations in JS are already only accessible via function calls, and some of the ones that aren't still defer to JS code anyway (toString, valueOf). The only ones that are non-obvious to shim are the literal operations: get, set, delete, has, in. Using ES5 and premeditation, you can even handle get and set for existing properties.

I don't have answers to this but I thought it could potentially be in the spirit of this specific project.

TypeError when calling enumerate on nested Proxy

The enumerate trap fails when called on a Proxy wrapping another Proxy:

require('harmony-reflect');

function wrap(obj) {
    return new Proxy(obj, {});
}

var proxy = wrap({a: 1, b: 2});
for (var prop in proxy) console.log(prop);

proxy = wrap(proxy);
for (var prop in proxy) console.log(prop);

Output:

$ node --harmony src/enumtest.js
a
b

TypeError: Object a,b has no method 'next'
    at Object.Validator.enumerate (node_modules/harmony-reflect/reflect.js:1141:28)
    at Object.<anonymous> (enumtest.js:11:18)
...

When explicitly implementing the trap (as return Reflect.enumerate(target)), the error changes to:

TypeError: enumerate trap should return an iterator, got: a,b
    at Object.Validator.enumerate (node_modules/harmony-reflect/reflect.js:1155:13)
    at Object.<anonymous> (enumtest.js:17:18)

This is with node v0.10.29 and [email protected].

License?

A LICENSE file would be helpful, otherwise I can't include this repo as a submodule.

Error: proxies not supported on this platform in OS X Mountain Lion

I built node 0.7.8 on OS X Mountain Lion and am getting the error:

Error: proxies not supported on this platform

when I try to call Proxy().

Here is the code - derived from the example, that causes this to happen.

function makeProfiler(target) {
var count = Object.create(null);
return {
proxy: harmonyReflect.Proxy(target, {
get: function(target, name, rcvr) {
count[name] = (count[name] || 0) + 1;
return harmonyReflect.Reflect.get(target, name, rcvr);
}
}),
stats: count
};
}

function runApp(o) {
o.foo; o.foo; o.foo;
o.bar; o.bar;
o.baz;
}

var harmonyReflect = require( 'harmony-reflect');
var target = { foo: 42, bar: 24 };
var profiler = makeProfiler(target);
runApp(profiler.proxy);

Here is the full stack trace:

Error: proxies not supported on this platform
at Object.Proxy (/Users/dylanbarrell/Documents/src/node/node_modules/harmony-reflect/reflect.js:1702:11)
at makeProfiler (repl:4:23)
at repl:1:16
at REPLServer.eval (repl.js:110:21)
at repl.js:259:20
at REPLServer.eval (repl.js:117:5)
at Interface. (repl.js:249:12)
at Interface.emit (events.js:87:17)
at Interface._onLine (readline.js:178:10)
at Interface._line (readline.js:499:8)

Possible incompatibility gulp/jscs

I'm having trouble with another package that began requiring harmony-reflect.
I started getting the following error (more details):

TypeError: Object prototype may only be an Object or null: true

I haven't been able to determine with what package the problem lies, but if you have any insight, it would be appreciated!

Original issue: jscs-dev/node-jscs#2026

Patches list in comments is not up-to-date

As commented in #50, // Patches: section in comments does not include:

  • defineProperty
  • defineProperties
  • getPrototypeOf
  • getOwnPropertyNames
  • setPrototypeOf
  • (maybe others, I used simple regex to find those)

Proxy not patched by shim when already defined as a function

Previously this shim would not patch up Proxy if it was already defined as a function (i.e. typeof Proxy === "function"). The rationale was that if Proxy is already defined as a function, the platform supports direct proxies and patching Proxy is not necessary.

Current firefox versions (FF 26+) do implement Proxy as a function and do support the direct proxies API, but various bugs remain so that patching Proxy is still valuable.

Commit ab5ca4c updates the library to always patch the global Proxy object if it is available, regardless of whether it is a function or not.

"cannot report inconsistent value for non-writable, non-configurable property"

I hope you won't mind a user-level question here.

I am using Chrome with this library to wrap 'window' in a proxy so that I might record and replay the DOM operations. On the operation 'window.document', I fail. I need to return the proxy of window.document so subsequent operations on the return will also enter the proxy code. However, window.document is own frozen data of window and the test in reflect.js line 1063 throws a TypeError. As far as I can see from the code, I could not succeed in wrapping returns from window.document, and yet my case seems quite similar to the ones discussed as use cases for Proxy. Any hints?

Collected documentation/discussion of implementation issues

I'm not sure where this would best exist, if anywhere at all, but it seems like it's already been useful just pulling together notes on a few bugs and issues with the various implementations and continuing iteration of those. While they should always be reported as bugs to the tracker for the implementation first, it still seems useful to note them and workarounds for the short term, and also as a kind of historical documentation of the various issues that inevitably come up along the way in implementing new APIs, especially one this grandiose. Individual bug tracs have a tendency to get deeply buried amongst the mountain of issues filed in engine repo history logs without much context to draw from after the fact.

Not working with react-native

I haven't figured out why yet, but requiring 'harmony-reflect' in react-native is giving me "SyntaxError: Unexpected end of script".

I am using harmony and the Proxy object is present.

confused about apply

I'm trying to basically write a dsl, translating dot and bracket notation into operations on a remote database. With a bit of help i came up with;

function QueryBuilder() {
if (this instanceof QueryBuilder == false) return new QueryBuilder();
var self = this;
var fn = function () {
//ignored
};
fn.self = self;
this.proxy = new Proxy(fn, QueryBuilderProxyHandler);
this.parts = [];
return this;
}

var QueryBuilderProxyHandler = {
get: function(target, name){
target.self.parts.push(name);
return target.self.proxy;
},
apply: function(target, thisValue, args) {
target.self.parts.push({that:thisValue, args: args});
return target.self.proxy;
}
}

var thing = new QueryBuilder();

thing.proxy.test.this.out(1);

console.log(thing);

This logs the operations, but is shared and requires multiple calls.
Next I updated an old example from https://github.com/DavidBruant/HarmonyProxyLab to use the new api;
(function() {
var DeclarativeObject, declo;

DeclarativeObject = function() {
var constructorTrap, firstHandler, getTrap, middleHandler, propNames;
propNames = void 0;
getTrap = function(rec, name) {
propNames.push(name);
return Proxy(constructorTrap, middleHandler);
};
middleHandler = {
get: getTrap
};
constructorTrap = function() {
return propNames.slice();
};
firstHandler = {
get: function(rec, name) {
propNames = [];
return getTrap.apply(this, arguments);
}
};
return Proxy({}, firstHandler);
};

declo = new DeclarativeObject();

console.log(declo.a.b.c.ef(48));

console.log(declo.xo['cc'].xo.ke());

}).call(this);

This works, but as soon as i try adding the apply method all i get are TypeErrors. What is the proper way to do this?

Array.concat() works incorrectly on proxies under V8

Something is wrong with Array.concat when it operates on a proxy. This may be a special case of issue #6 but I'm opening a new issue so we can more easily track the details.

var a = ['x', 'y'];
var h = {};
var aProxy = Proxy(a, h);
var aConcat = [].concat(a);
var aProxyConcat = [].concat(aProxy);

d8> print(aConcat.length);
2

d8> print(aProxyConcat.length);
1

I've confirmed that this bug exists with the latest version of harmony-reflect (0.0.7) and with today's trunk version of V8.

get handler with Symbol

I fail to use the Proxy get handler with a ES6 Symbol as property name:

var Reflect = require('harmony-reflect');

var p = new Proxy(Object.create(null), {

    get: function(target, property) {

        return 'bar';
    }
});


console.log( p['foo'] );
console.log( p[Symbol('fooSym')] );

harmony-reflect borks node repl

Installing harmony-reflect (version 1.4.2) in a node repl crashes it on TAB completion:

$ node --harmony_proxies
> require("harmony-reflect")
{ getOwnPropertyDescriptor: [Function],
  defineProperty: [Function],
  deleteProperty: [Function],
  getPrototypeOf: [Function],
  setPrototypeOf: [Function],
  preventExtensions: [Function],
  isExtensible: [Function],
  has: [Function],
  get: [Function],
  set: [Function],
  enumerate: [Function],
  ownKeys: [Function],
  apply: [Function],
  construct: [Function] }
> ** pressing TAB key **  readline.js:925
            throw err;
            ^

TypeError: Object prototype may only be an Object or null: true
    at setPrototypeOf (native)
    at Function.Object.setPrototypeOf (.../node_modules/harmony-reflect/reflect.js:1655:14)
    at Object.prim_defineProperty.set (.../node_modules/harmony-reflect/reflect.js:1634:21)
    at completionGroupsLoaded (repl.js:875:21)
    at REPLServer.complete (repl.js:767:11)
    at REPLServer.complete [as completer] (repl.js:315:10)
    at REPLServer.Interface._tabComplete (readline.js:375:8)
    at REPLServer.Interface._ttyWrite (readline.js:872:16)
    at ReadStream.onkeypress (readline.js:106:10)
    at emitTwo (events.js:100:13)
$ node -v
v5.5.0

Es6 Classes: Class constructors cannot be invoked without 'new'

Es6 Classes: Class constructors cannot be invoked without 'new' try following

  "use strict"

  var Reflect = require('harmony-reflect');

  class UsersController{

    constructor(name){
      this.name = name
    }

    hello(){
      return this.name
    }

  }

  var obj = Reflect.construct(UsersController, ["somename"])

  console.log(obj.hello())

valueOf,toString,... failing with proxies

Hello :]

require('harmony-reflect');

var myProxy = new Proxy({
    valueOf : function () {
        return 0;
    }
} ,{
    get : function (target, name) {
        return myProxy;
    }
});

console.log(myProxy * 1); // should say 0

And the error I get :

TypeError: Cannot convert object to primitive value
    at repl:1:21
    at REPLServer.self.eval (repl.js:110:21)
    at repl.js:249:20
    at REPLServer.self.eval (repl.js:122:7)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.EventEmitter.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)
    at Interface._ttyWrite (readline.js:760:14)
    at ReadStream.onkeypress (readline.js:99:10)

Looks like something is wrapped here by the library when it shouldn't but I'm not sure of this.
Any idea ?

Objects with TTL, safe to enumerate/iterate?

I'm writting a module that creates objects whose keys have a timeout and when it expires the keys are automatically deleted.

The code is very easy to follow:

"use strict";

require ("harmony-reflect");

var harmony = module.exports = {};

harmony.create = function (args){
    args = args || {};
    if (!("ttl" in args)) return {};
    if (typeof args.ttl !== "number" || args.ttl < 0){
        throw new Error ("Invalid ttl value.");
    }

    var timers = {};

    return Proxy ({}, {
        set: function (target, key, value, receiver){
            if (!(key in target) && args.ttl){
                timers[key] = setTimeout (function (){
                    delete target[key];
                    delete timers[key];
                    if (args.expire) args.expire (key);
                }, args.ttl);
            }
            return Reflect.set (target, key, value, receiver);
        },
        deleteProperty: function (target, key){
            var id = timers[key];
            if (id){
                clearTimeout (id);
                delete timers[key];
            }
            return Reflect.deleteProperty (target, key);
        }
    });
};

When a new key is added to the proxy a timeout is set and when the user manually deletes the key the timeout is cleared.

But I have a question. If I enumerate the keys with a for-in loop, what happens if the key is deleted because the timer expires WHILE the loop is being executed?

For example:

var ttl = require (...);
var o = ttl.create ({ ttl: 1000, expire: function (key){ ... } }); // o is the proxy

o.a = 1;
o.b = 2;
o.c = 3;

for (var p in o){
  ...
  // o.c expires and is deleted BEFORE p gets the value of "c".
}

What will happen in this case? The for-in loop checks the existence of the key before it is copied to the p variable?

Thanks

Can't trap invoke for all methods of a given proxy

I suspect this is because the get trap is overriding the apply trap because the method is accessed before it is invoked. But wanted to check it's not due to my own bad code. Thanks!...

require('harmony-reflect');
function getApplyProxy(fn) {
  console.log(fn); //logged as expected
  //get trap also required?...
  return Proxy(
    fn,
    { apply: function() {
       console.log(arguments)
    }}
  )
}

var fnMonitor = Proxy(
  {},
  { get: function(t,p) {
    return (typeof t[p] == 'function' ? getApplyProxy(t[p]) : t[p]);
  }}
);

var Obj = function() {};
Obj.prototype = fnMonitor;

var a = new Obj;
a.fn = function() {};
a.fn(); //undefined(!)

Possibly implement invoke trap

This is only possible to do in SpiderMonkey but it still may be worth doing.

var proxy = new Proxy({}, {});
proxy.method();

Will cause the following

1.) proxy.[[Get]]('method'), returns undefined
2.) proxy.[[Get]]('__noSuchMethod__')

If you implement the get trap to check for 'noSuchMethod' that can be reflected as the invoke trap.

automatic unwrapping

I believe this behavior was introduced in harmony-reflect v0.0.5 while fixing #13.

The auto-unwrapping assumes Object.prototype.toString will only be called on objects. But lots of code calls it on other types to figure out what type they're dealing with.

Here's what one would normally expect for this behavior:

magi@ubuntu ~/s/d/foo> node --harmony
> ({}).toString.apply(1)
'[object Number]'
> ({}).toString.apply(true)
'[object Boolean]'
> ({}).toString.apply('asdf')
'[object String]'
> ({}).toString.apply(null)
'[object Null]'
> ({}).toString.apply(undefined)
'[object Undefined]'
> ({}).toString.apply([])
'[object Array]'
> ({}).toString.apply({})
'[object Object]'

Here's what you get with harmony-proxies v0.0.5:

magi@ubuntu ~/s/d/foo> node --harmony
> require('harmony-reflect')
{ snip }
> ({}).toString.apply(1)
TypeError: Invalid value used as weak map key
    at WeakMap.get (native)
    at Number.builtin (/home/magi/node_modules/harmony-reflect/reflect.js:1500:34)
    at repl:1:16
> ({}).toString.apply(true)
TypeError: Invalid value used as weak map key
    at WeakMap.get (native)
    at Boolean.builtin (/home/magi/node_modules/harmony-reflect/reflect.js:1500:34)
    at repl:1:16
> ({}).toString.apply('asdf')
TypeError: Invalid value used as weak map key
    at WeakMap.get (native)
    at String.builtin (/home/magi/node_modules/harmony-reflect/reflect.js:1500:34)
    at repl:1:16
> ({}).toString.apply(null)
TypeError: Invalid value used as weak map key
    at WeakMap.get (native)
    at builtin (/home/magi/node_modules/harmony-reflect/reflect.js:1500:34)
    at repl:1:16
> ({}).toString.apply(undefined)
TypeError: Invalid value used as weak map key
    at WeakMap.get (native)
    at builtin (/home/magi/node_modules/harmony-reflect/reflect.js:1500:34)
    at repl:1:16
> ({}).toString.apply([])
'[object Array]'
> ({}).toString.apply({})
'[object Object]'

Add basic Proxy support for non-supported platforms

Would it be possible to add at least traps for Object.* static methods on platforms that do not support real proxies?

I'm currently playing with some code where at least such basic support would be useful, and from my understanding it shouldn't be hard to implement it since overrides for those methods are already implemented and just need some basic Proxy implementation for storing and accessing handlers.

Object.create puzzle

I'm trying to figure out what I am doing wrong. In the following code I create aProxy which only logs the get() call. Then I call Object.create(aProxy). I'm trying to puzzle out the resulting object's behavior and deal with it.

(function() {
    var obj = {};
    var handler = {
        get: function(target, name, receiver) {
            console.log('get ' + name);
            return target[name];
        }
    };
    var aProxy = Proxy(obj, handler);
    var created = Object.create(aProxy);
    console.log('created.__proto__', created.__proto__);
    console.log('created.__proto__ === aProxy ', created.__proto__ === aProxy);
    console.log('Object.getPrototypeOf(created) === aProxy ', Object.getPrototypeOf(created) === aProxy);
})();

When the code runs, the handler is called twice and we log an object, false and true:

get __proto__ testObjectCreated.html:9
created.__proto__ Object {} testObjectCreated.html:15
get __proto__ testObjectCreated.html:9
created.__proto__ === aProxy  false testObjectCreated.html:17
Object.getPrototypeOf(created) === aProxy  true testObjectCreated.html:18

This code acts as if created.__proto__ first calls [[Get]] on created, finds nothing in own properties, then calls [[Get]] on the first proto chain link, finds a proxy, triggers the .get trap, logs, then returns Object as the proto value of {} and logs it.

The subsequent lines show that created.__proto__ is not equivalent to Object.getPrototypeOf(created); the former is actually created.__proto__._proto__ while the latter is the correct created.__proto__.

Since created is not a proxy, to workaround this we need to discover in the get handler that we are a proxy for proto and return ourselves. Then we have to avoid getting the wrong result if we call aProxy.__proto__.

Have you encountered this and do you have any suggestions?

Extending proxy classes

I am in a situation where i want to proxy a base class ( not it's instance ) and let other classes extend that base class and call magical static methods.

var handler = {
  get: function(target,name){
    if(target[name]){
      return target[name]
    }else{
      // call some magic method
      return 'foo'
    }
  },
}

class Model{

}

var proxyModel  = new Proxy(Model,handler)

class User extends proxyModel{

}

But it fails saying 17270 segmentation fault iojs --harmony_proxies test/poly.js

Strange 'illegal access' error in stack trace

I noticed that when using your attributes.js example I get a strange <error: illegal access> error in the stack trace of any method that I call when the class is wrapped in AttributeProxy. It doesn't "seem" to affect anything, but was wondering if this is normal? Thanks.

In node.js:

require('harmony-reflect');

function AttributeProxy(target) {
  return Proxy(target, {
    get: function(target, name, receiver) {
      if (name in target) { return target[name]; }
      // everything not found on the target object itself should
      // be looked up in the target's _attributes map
      return target._attributes[name];
    },
    set: function(target, name, val, receiver) {
      if (name in target) {
        target[name] = val;
        return true;
      }
      // everything not found on the target object itself should
      // be added to the target's _attributes map
      target._attributes[name] = val;
      return true;
    }
  });
}

var Person = function() {
   this._attributes = {};
   return AttributeProxy(this);
};

Person.prototype.walk = function() {
  console.log('Person is walking');
  console.log(new Error().stack);
};

var Female = function() {
  // call "super" constructor
  return Person.call(this);
}
// make Female inherit from Person
Female.prototype = Object.create(Person.prototype);
Female.prototype.shop = function() {
  console.log('Female is shopping');
  console.log(new Error().stack);
}

console.log(new Error().stack);

// tests
var person = new Person();
person.hair = 'black';
person.walk(); // methods are called normally

var female = new Female();
female.hair = 'blonde';
female.walk(); // methods are called normally
female.shop(); // methods are called normally

Output:

Error: Regular Stack Trace
    at Object.<anonymous> (/var/guestweb/new.jump.omnitarget.com/attributes_test.js:45:13)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
Person is walking
Error: Person.walk
    at <error: illegal access>
    at Object.<anonymous> (/var/guestweb/new.jump.omnitarget.com/attributes_test.js:50:8)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
Person is walking
Error: Person.walk
    at <error: illegal access>
    at Object.<anonymous> (/var/guestweb/new.jump.omnitarget.com/attributes_test.js:54:8)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
Female is shopping
Error: Female.shop
    at <error: illegal access>
    at Object.<anonymous> (/var/guestweb/new.jump.omnitarget.com/attributes_test.js:55:8)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)

Remove deprecated methods/give option to turn this off

I'd like to use this module as a direct proxy shim, especially for educational purposes. However, I don't want people learning about and using the deprecated traps and reflect APIs.

I could manually monkey-patch the code, but it would be nice if there was a way to turn it off.

setPrototypeOf should throw TypeError if typeof newProto === 'undefined'

The first line of [[setPrototypeOf]] fails if the argument is undefined:
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots-setprototypeof-v

But reflect.js does not:

  function testSetPrototypeOf() {
    var obj = {};
    var shouldThrow;
    try {
      Object.setPrototypeOf(obj, undefined);
    } catch (ex) {
      shouldThrow = ex;
    }
    assert(shouldThrow);
  }

I believe the issue here is that reflect.js implements Object.setPrototypeOf(obj, newProto) using obj.__proto__ setter, but somehow these operations are not consistent on Chrome at least.

(proxied function).prototype = ...

Environment: Node.js

Example:

const f = function () {
};

const pf = Proxy(f, ...);

pf.prototype = {}; // This statement will cast exception

Error when using Reflect.construct on ES2015 classes

var Reflect = require('harmony-reflect')

var Foo = class{}

Reflect.construct(Foo, [])

This throws the following error:

TypeError: Class constructors cannot be invoked without 'new'
    at new <anonymous> (path/to/harmony-reflect/test/testReflect.js:313:19)
    at Object.global.Reflect.construct (path/to/harmony-reflect/reflect.js:1976:43)
    at path/to/harmony-reflect/test/testReflect.js:325:29
    at test (path/to/harmony-reflect/test/testReflect.js:328:4)
    at Object.<anonymous> (path/to/code/harmony-reflect/test/testReflect.js:333:3)
    at Module._compile (module.js:413:34)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)

Patched __proto__ (that uses Object.setPrototypeOf) fails and throws TypeError

There seems to be an issue with how proto is patched to use Object.setPrototypeOf.
Currently, setting the proto property of an object causes a TypeError:

TypeError: Generic use of proto accessor not allowed

The error occurs, for example, when using test/testProxies.html to run testProxies.js in the testSetPrototypeOf.

Is there another way to patch proto?

I used Chrome 29.0.1547.22 beta (with Experimental JavaScript for the old Harmony proxies and Harmony Weak Maps).

My current solution is to prevent the patch (not executing the function after _var _proto__setter), change Object.setPrototypeOf to directly set the proto property, and then consistently use

Object.setPrototypeOf(target, newProto)

instead of

target.proto = newProto

in the project... :-/

how to trap prototype method calls of ES6 class object?

Give ES6 class, how to trap prototype method calls?

class Account {
    constructor(name,  amount) {
        this.name = name;
        this.amount = amount;
    }
    withdraw(arg) {
        this.amount = this.amount - arg;
    }

    deposit(arg) {
        this.amount = this.amount + arg;
    }
}
var proxyAccount = new Proxy(new Account('sumo', 500) , {} );
proxyAccount.deposit(100); //want to trap this method call
proxyAccount.withdraw(50);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.