Friday, 9 June 2017

Apparent pollution with multiple Proxy objects for the same target

I'm attempting to create multiple Proxy wrappers for the same target object in JavaScript, with each individual wrapper having slightly different properties which affect how the wrapped functionality operates. These properties are assigned to and accessed from the receiver object in the set and get handlers. However, when I examine the generated Proxies, all of them have the property set I expect to have been assigned to the last Proxy created.

const obj = {};

const proxies = ['one', 'two'].map(name => {
  console.log(`proxy ${name}`);

  const proxy = new Proxy(obj, {
    get: (target, prop, receiver) => {
      if (prop === 'name') { return receiver.name; }

      return target[prop];
    },
    set: (target, prop, val, receiver) => {
      if (prop === 'name') {
        console.log(`setting name ${val} on receiver`);
        Object.defineProperty(receiver, prop, {
            value: val,
            configurable: true,
            enumerable: true}
        );
      } else {
        console.log(`setting ${prop} ${val} on target`);
        target[prop] = val;
      }

      return true;
    }
  });

  proxy.name = name;

  return proxy;
});

console.log();
console.log(proxies);

My expected result: [{name: 'one'}, {name: 'two'}].

The actual result: [{name: 'two'}, {name: 'two'}]. Even though they appear identical, they are not strictly equal.

If I omit const obj and create my objects with new Proxy({}, ...) I get the expected result -- a proxy one and a proxy two, presumably since the target reference is not shared between them. So: what on earth? From my understanding, using the receiver to store name should prevent it from being propagated to the target object, yet it seems to be doing so anyway.



via dmfay

No comments:

Post a Comment