Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paradox between Object.freeze, ProxyHandler.get and ProxyHandler.getPrototypeOf #79

Closed
ajvincent opened this issue May 23, 2017 · 6 comments

Comments

@ajvincent
Copy link
Owner

ajvincent commented May 23, 2017

function wetA() {};
function wetB() {};
wetB.prototype = new wetA();
var wet_b = new wetB();

// Reflect.get(wetB, "prototype") === Reflect.getPrototypeOf(wet_b);

// boilerplate, not really that important
function valueType(value) {
  if (value === null)
    return "primitive";
  const type = typeof value;
  if ((type != "function") && (type != "object"))
    return "primitive";
  return type;
}

// The WeakMap for the "dry" object graph's proxies
const proxyMap = new WeakMap();

// The handler for the "dry" object graph's proxies
const h = {
  get: function(target, propName) {
    let rv = target[propName];
    if (valueType(rv) === "primitive")
      return rv;

    /*
    let desc = Reflect.getOwnPropertyDescriptor(target, propName);
    if (!desc.configurable)
      return rv;
    */

    // try to keep the property lookup in our object graph.
    if (!proxyMap.has(rv))
      proxyMap.set(rv, new Proxy(rv, this));
    return proxyMap.get(rv);
  },

  /*
  getPrototypeOf: function(target) {
    let rv = Reflect.getPrototypeOf(target);
    if (valueType(rv) === "primitive")
      return rv;

    // try to keep the prototype lookup in our object graph.
    if (!proxyMap.has(rv))
      proxyMap.set(rv, new Proxy(rv, this));
    return proxyMap.get(rv);
  }
  */
};

var dry_b = new Proxy(wet_b, h);
proxyMap.set(wet_b, dry_b);
var dryB = new Proxy(wetB, h);
proxyMap.set(wetB, dryB);

// Here's where things start going badly for a membrane.
Object.freeze(wet_b);
//Object.freeze(wetB);

it("wet prototype does match", function() {
  var proto1 = Reflect.getPrototypeOf(wet_b);
  var proto2 = Reflect.get(wetB, "prototype");
  expect(proto1).toBe(proto2);
});
  
it("dry prototype cannot match", function() {
  var proto1 = Reflect.getPrototypeOf(dry_b);
  var proto2 = Reflect.get(dryB, "prototype");
  expect(proto1).not.toBe(proto2);
});

But we would expect that:
Reflect.get(dryB, "prototype") === Reflect.getPrototypeOf(dry_b);

Because
Reflect.get(wetB, "prototype") === Reflect.getPrototypeOf(wet_b);

@ajvincent
Copy link
Owner Author

Uncommenting
Object.freeze(wetB)

causes an error at
var proto2 = Reflect.get(dryB, "prototype");

because
Reflect.getOwnPropertyDescriptor(wetB, "prototype").configurable === false
so
Reflect.get(wetB, "prototype") === Reflect.get(dryB, "prototype")
should be true but isn't.

@ajvincent
Copy link
Owner Author

Uncommenting
h.getPrototypeOf

causes an error at
var proto1 = Reflect.getPrototypeOf(dry_b);

because
Reflect.getPrototypeOf(dry_b) === Reflect.getPrototypeOf(wet_b);

should be true but isn't.

@ajvincent
Copy link
Owner Author

ajvincent commented May 23, 2017

Uncommenting

    let desc = Reflect.getOwnPropertyDescriptor(target, propName);
    if (!desc.configurable)
      return rv;

in h.get works. It means that

var proto1 = Reflect.getPrototypeOf(dry_b);
var proto2 = Reflect.get(dryB, "prototype");
proto1 === proto2;

But then Reflect.getPrototypeOf(dry_b) doesn't belong to the dry object graph. (It was supposed to be protected by a .getPrototypeOf trap, but that doesn't work because of the previous comment.)

@ajvincent
Copy link
Owner Author

ajvincent commented May 23, 2017

In short, we've landed on a paradox, whereby the dry object graph cannot easily maintain the same assertion between Reflect.getPrototypeOf(dry_b) and Reflect.get(dryB, "prototype") as is known for wet_b and wetB respectively. My attempts to work around this are going nowhere.

@ajvincent
Copy link
Owner Author

ajvincent commented May 23, 2017

I need to be able to write h such that:

  • Object.freeze(wet_b); works
  • Object.freeze(wetB); works
  • No errors are thrown for failed JavaScript engine assertions on proxies
  • Reflect.getPrototypeOf(wet_b) === Reflect.get(wetB, "prototype");
  • Reflect.getPrototypeOf(dry_b) === Reflect.get(dryB, "prototype");
  • Reflect.get(wetB, "prototype") !== Reflect.get(dryB, "prototype");
  • wet_b, wetB and wetB.prototype are clearly from the "wet" object graph
  • dry_b, dryB and dryB.prototype are clearly from the "dry" object graph

@ajvincent
Copy link
Owner Author

This should be fixed now in the membrane code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant