Skip to content

Instantly share code, notes, and snippets.

@tvcutsem
Created October 9, 2012 10:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tvcutsem/3857930 to your computer and use it in GitHub Desktop.
Save tvcutsem/3857930 to your computer and use it in GitHub Desktop.
membranes with dummy target and getPrototypeOf
load('reflect.js'); // https://github.com/tvcutsem/harmony-reflect/blob/master/reflect.js
function makeMembrane(initTarget) {
var cache = new WeakMap();
var revoked = false;
function wrap(target) {
if (Object(target) !== target) return target; // primitives are passed through
var wrapper = cache.get(target);
if (wrapper) return wrapper;
var dummyTarget;
if (typeof target === "function") {
dummyTarget = target;
} else {
dummyTarget = Object.create(wrap(Object.getPrototypeOf(target)));
}
wrapper = Proxy(dummyTarget, Proxy(dummyTarget, { // "double lifting"
get: function(dummyTarget, trapName) {
if (revoked) throw new TypeError("membrane revoked");
return function(dummyTarget /*, ...args*/) { // generic trap
var args = Array.prototype.slice.call(arguments, 1).map(wrap);
return wrap(Reflect[trapName].apply(undefined, [target].concat(args)));
}
}
}));
cache.set(target, wrapper);
return wrapper;
}
function revoke() { revoked = true; }
return {revoke: revoke, target: wrap(initTarget)};
}
function C(){};
var membrane = makeMembrane(C);
var wrappedC = membrane.target;
// the invariant is preserved across the membrane (both return true)
print(Object.getPrototypeOf(new C()) !== C.prototype.constructor);
print(Object.getPrototypeOf(new wrappedC()) !== wrappedC.prototype.constructor);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment