| Index: test/mjsunit/harmony/proxies-example-membrane.js
|
| diff --git a/test/mjsunit/harmony/proxies-example-membrane.js b/test/mjsunit/harmony/proxies-example-membrane.js
|
| index 9cfb105fd7bfb0a9525ad6ceff16c89ebcd8d078..892de22f8c251f30006fee887a2c378db61538fb 100644
|
| --- a/test/mjsunit/harmony/proxies-example-membrane.js
|
| +++ b/test/mjsunit/harmony/proxies-example-membrane.js
|
| @@ -28,168 +28,54 @@
|
| // Flags: --harmony --harmony-proxies
|
|
|
|
|
| -// A simple no-op handler. Adapted from:
|
| -// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#examplea_no-op_forwarding_proxy
|
| -
|
| -function createHandler(obj) {
|
| - return {
|
| - getOwnPropertyDescriptor: function(name) {
|
| - var desc = Object.getOwnPropertyDescriptor(obj, name);
|
| - if (desc !== undefined) desc.configurable = true;
|
| - return desc;
|
| - },
|
| - getPropertyDescriptor: function(name) {
|
| - var desc = Object.getOwnPropertyDescriptor(obj, name);
|
| - //var desc = Object.getPropertyDescriptor(obj, name); // not in ES5
|
| - if (desc !== undefined) desc.configurable = true;
|
| - return desc;
|
| - },
|
| - getOwnPropertyNames: function() {
|
| - return Object.getOwnPropertyNames(obj);
|
| - },
|
| - getPropertyNames: function() {
|
| - return Object.getOwnPropertyNames(obj);
|
| - //return Object.getPropertyNames(obj); // not in ES5
|
| - },
|
| - defineProperty: function(name, desc) {
|
| - Object.defineProperty(obj, name, desc);
|
| - },
|
| - delete: function(name) {
|
| - return delete obj[name];
|
| - },
|
| - fix: function() {
|
| - if (Object.isFrozen(obj)) {
|
| - var result = {};
|
| - Object.getOwnPropertyNames(obj).forEach(function(name) {
|
| - result[name] = Object.getOwnPropertyDescriptor(obj, name);
|
| - });
|
| - return result;
|
| - }
|
| - // As long as obj is not frozen, the proxy won't allow itself to be fixed
|
| - return undefined; // will cause a TypeError to be thrown
|
| - },
|
| - has: function(name) { return name in obj; },
|
| - hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
|
| - get: function(receiver, name) { return obj[name]; },
|
| - set: function(receiver, name, val) {
|
| - obj[name] = val; // bad behavior when set fails in sloppy mode
|
| - return true;
|
| - },
|
| - keys: function() { return Object.keys(obj); }
|
| - };
|
| -}
|
| -
|
| -
|
| -
|
| -// Auxiliary definitions enabling tracking of object identity in output.
|
| -
|
| -var objectMap = new WeakMap;
|
| -var objectCounter = 0;
|
| -
|
| -function registerObject(x, s) {
|
| - if (x === Object(x) && !objectMap.has(x))
|
| - objectMap.set(x, ++objectCounter + (s == undefined ? "" : ":" + s));
|
| -}
|
| -
|
| -registerObject(this, "global");
|
| -registerObject(Object.prototype, "Object.prototype");
|
| -
|
| -function str(x) {
|
| - if (x === Object(x)) return "[" + typeof x + " " + objectMap.get(x) + "]";
|
| - if (typeof x == "string") return "\"" + x + "\"";
|
| - return "" + x;
|
| -}
|
| -
|
| -
|
|
|
| // A simple membrane. Adapted from:
|
| // http://wiki.ecmascript.org/doku.php?id=harmony:proxies#a_simple_membrane
|
|
|
| function createSimpleMembrane(target) {
|
| - var enabled = true;
|
| + let enabled = true;
|
|
|
| function wrap(obj) {
|
| - registerObject(obj);
|
| - print("wrap enter", str(obj));
|
| - try {
|
| - var x = wrap2(obj);
|
| - registerObject(x, "wrapped");
|
| - print("wrap exit", str(obj), "as", str(x));
|
| - return x;
|
| - } catch(e) {
|
| - print("wrap exception", str(e));
|
| - throw e;
|
| - }
|
| - }
|
| -
|
| - function wrap2(obj) {
|
| - if (obj !== Object(obj)) {
|
| - return obj;
|
| - }
|
| -
|
| - function wrapCall(fun, that, args) {
|
| - registerObject(that);
|
| - print("wrapCall enter", fun, str(that));
|
| - try {
|
| - var x = wrapCall2(fun, that, args);
|
| - print("wrapCall exit", fun, str(that), "returning", str(x));
|
| - return x;
|
| - } catch(e) {
|
| - print("wrapCall exception", fun, str(that), str(e));
|
| - throw e;
|
| - }
|
| - }
|
| + if (obj !== Object(obj)) return obj;
|
|
|
| - function wrapCall2(fun, that, args) {
|
| - if (!enabled) { throw new Error("disabled"); }
|
| - try {
|
| - return wrap(fun.apply(that, Array.prototype.map.call(args, wrap)));
|
| - } catch (e) {
|
| - throw wrap(e);
|
| - }
|
| - }
|
| -
|
| - var baseHandler = createHandler(obj);
|
| - var handler = new Proxy({}, Object.freeze({
|
| - get: function(receiver, name) {
|
| - return function() {
|
| - var arg = (name === "get" || name == "set") ? arguments[1] : "";
|
| - print("handler enter", name, arg);
|
| - var x = wrapCall(baseHandler[name], baseHandler, arguments);
|
| - print("handler exit", name, arg, "returning", str(x));
|
| - return x;
|
| + let handler = new Proxy({}, {get: function(_, key) {
|
| + if (!enabled) throw new Error("disabled");
|
| + switch (key) {
|
| + case "apply":
|
| + return (_, that, args) => {
|
| + try {
|
| + return wrap(Reflect.apply(
|
| + obj, wrap(that), args.map((x) => wrap(x))));
|
| + } catch(e) {
|
| + throw wrap(e);
|
| + }
|
| }
|
| - }
|
| - }));
|
| - registerObject(baseHandler, "basehandler");
|
| - registerObject(handler, "handler");
|
| -
|
| - if (typeof obj === "function") {
|
| - function callTrap() {
|
| - print("call trap enter", str(obj), str(this));
|
| - var x = wrapCall(obj, wrap(this), arguments);
|
| - print("call trap exit", str(obj), str(this), "returning", str(x));
|
| - return x;
|
| - }
|
| - function constructTrap() {
|
| - if (!enabled) { throw new Error("disabled"); }
|
| - try {
|
| - function forward(args) { return obj.apply(this, args) }
|
| - return wrap(new forward(Array.prototype.map.call(arguments, wrap)));
|
| - } catch (e) {
|
| - throw wrap(e);
|
| + case "construct":
|
| + return (_, args, newt) => {
|
| + try {
|
| + return wrap(Reflect.construct(
|
| + obj, args.map((x) => wrap(x)), wrap(newt)));
|
| + } catch(e) {
|
| + throw wrap(e);
|
| + }
|
| + }
|
| + default:
|
| + return (_, ...args) => {
|
| + try {
|
| + return wrap(Reflect[key](obj, ...(args.map(wrap))));
|
| + } catch(e) {
|
| + throw wrap(e);
|
| + }
|
| }
|
| }
|
| - return Proxy.createFunction(handler, callTrap, constructTrap);
|
| - } else {
|
| - var prototype = wrap(Object.getPrototypeOf(obj));
|
| - return new Proxy(prototype, handler);
|
| - }
|
| + }});
|
| +
|
| + return new Proxy(obj, handler);
|
| }
|
|
|
| - var gate = Object.freeze({
|
| - enable: function() { enabled = true; },
|
| - disable: function() { enabled = false; }
|
| + const gate = Object.freeze({
|
| + enable: () => enabled = true,
|
| + disable: () => enabled = false
|
| });
|
|
|
| return Object.freeze({
|
| @@ -199,309 +85,227 @@ function createSimpleMembrane(target) {
|
| }
|
|
|
|
|
| -var o = {
|
| - a: 6,
|
| - b: {bb: 8},
|
| - f: function(x) { return x },
|
| - g: function(x) { return x.a },
|
| - h: function(x) { this.q = x }
|
| -};
|
| -o[2] = {c: 7};
|
| -var m = createSimpleMembrane(o);
|
| -var w = m.wrapper;
|
| -print("o =", str(o))
|
| -print("w =", str(w));
|
| -
|
| -var f = w.f;
|
| -var x = f(66);
|
| -var x = f({a: 1});
|
| -var x = w.f({a: 1});
|
| -var a = x.a;
|
| -assertEquals(6, w.a);
|
| -assertEquals(8, w.b.bb);
|
| -assertEquals(7, w[2]["c"]);
|
| -assertEquals(undefined, w.c);
|
| -assertEquals(1, w.f(1));
|
| -assertEquals(1, w.f({a: 1}).a);
|
| -assertEquals(2, w.g({a: 2}));
|
| -assertEquals(3, (w.r = {a: 3}).a);
|
| -assertEquals(3, w.r.a);
|
| -assertEquals(3, o.r.a);
|
| -w.h(3);
|
| -assertEquals(3, w.q);
|
| -assertEquals(3, o.q);
|
| -assertEquals(4, (new w.h(4)).q);
|
| -
|
| -var wb = w.b;
|
| -var wr = w.r;
|
| -var wf = w.f;
|
| -var wf3 = w.f(3);
|
| -var wfx = w.f({a: 6});
|
| -var wgx = w.g({a: {aa: 7}});
|
| -var wh4 = new w.h(4);
|
| -m.gate.disable();
|
| -assertEquals(3, wf3);
|
| -assertThrows(function() { w.a }, Error);
|
| -assertThrows(function() { w.r }, Error);
|
| -assertThrows(function() { w.r = {a: 4} }, Error);
|
| -assertThrows(function() { o.r.a }, Error);
|
| -assertEquals("object", typeof o.r);
|
| -assertEquals(5, (o.r = {a: 5}).a);
|
| -assertEquals(5, o.r.a);
|
| -assertThrows(function() { w[1] }, Error);
|
| -assertThrows(function() { w.c }, Error);
|
| -assertThrows(function() { wb.bb }, Error);
|
| -assertThrows(function() { wr.a }, Error);
|
| -assertThrows(function() { wf(4) }, Error);
|
| -assertThrows(function() { wfx.a }, Error);
|
| -assertThrows(function() { wgx.aa }, Error);
|
| -assertThrows(function() { wh4.q }, Error);
|
| +// Test the simple membrane.
|
| +{
|
| + var o = {
|
| + a: 6,
|
| + b: {bb: 8},
|
| + f: function(x) { return x },
|
| + g: function(x) { return x.a },
|
| + h: function(x) { this.q = x }
|
| + };
|
| + o[2] = {c: 7};
|
| + var m = createSimpleMembrane(o);
|
| + var w = m.wrapper;
|
| + var f = w.f;
|
| + var x = f(66);
|
| + var x = f({a: 1});
|
| + var x = w.f({a: 1});
|
| + var a = x.a;
|
| + assertEquals(6, w.a);
|
| + assertEquals(8, w.b.bb);
|
| + assertEquals(7, w[2]["c"]);
|
| + assertEquals(undefined, w.c);
|
| + assertEquals(1, w.f(1));
|
| + assertEquals(1, w.f({a: 1}).a);
|
| + assertEquals(2, w.g({a: 2}));
|
| + assertEquals(3, (w.r = {a: 3}).a);
|
| + assertEquals(3, w.r.a);
|
| + assertEquals(3, o.r.a);
|
| + w.h(3);
|
| + assertEquals(3, w.q);
|
| + assertEquals(3, o.q);
|
| + assertEquals(4, (new w.h(4)).q);
|
| +
|
| + var wb = w.b;
|
| + var wr = w.r;
|
| + var wf = w.f;
|
| + var wf3 = w.f(3);
|
| + var wfx = w.f({a: 6});
|
| + var wgx = w.g({a: {aa: 7}});
|
| + var wh4 = new w.h(4);
|
| + m.gate.disable();
|
| + assertEquals(3, wf3);
|
| + assertThrows(function() { w.a }, Error);
|
| + assertThrows(function() { w.r }, Error);
|
| + assertThrows(function() { w.r = {a: 4} }, Error);
|
| + assertThrows(function() { o.r.a }, Error);
|
| + assertEquals("object", typeof o.r);
|
| + assertEquals(5, (o.r = {a: 5}).a);
|
| + assertEquals(5, o.r.a);
|
| + assertThrows(function() { w[1] }, Error);
|
| + assertThrows(function() { w.c }, Error);
|
| + assertThrows(function() { wb.bb }, Error);
|
| + assertThrows(function() { wr.a }, Error);
|
| + assertThrows(function() { wf(4) }, Error);
|
| + assertThrows(function() { wfx.a }, Error);
|
| + assertThrows(function() { wgx.aa }, Error);
|
| + assertThrows(function() { wh4.q }, Error);
|
| +
|
| + m.gate.enable();
|
| + assertEquals(6, w.a);
|
| + assertEquals(5, w.r.a);
|
| + assertEquals(5, o.r.a);
|
| + assertEquals(7, w.r = 7);
|
| + assertEquals(7, w.r);
|
| + assertEquals(7, o.r);
|
| + assertEquals(8, w.b.bb);
|
| + assertEquals(7, w[2]["c"]);
|
| + assertEquals(undefined, w.c);
|
| + assertEquals(8, wb.bb);
|
| + assertEquals(3, wr.a);
|
| + assertEquals(4, wf(4));
|
| + assertEquals(3, wf3);
|
| + assertEquals(6, wfx.a);
|
| + assertEquals(7, wgx.aa);
|
| + assertEquals(4, wh4.q);
|
| +}
|
|
|
| -m.gate.enable();
|
| -assertEquals(6, w.a);
|
| -assertEquals(5, w.r.a);
|
| -assertEquals(5, o.r.a);
|
| -assertEquals(7, w.r = 7);
|
| -assertEquals(7, w.r);
|
| -assertEquals(7, o.r);
|
| -assertEquals(8, w.b.bb);
|
| -assertEquals(7, w[2]["c"]);
|
| -assertEquals(undefined, w.c);
|
| -assertEquals(8, wb.bb);
|
| -assertEquals(3, wr.a);
|
| -assertEquals(4, wf(4));
|
| -assertEquals(3, wf3);
|
| -assertEquals(6, wfx.a);
|
| -assertEquals(7, wgx.aa);
|
| -assertEquals(4, wh4.q);
|
|
|
|
|
| // An identity-preserving membrane. Adapted from:
|
| // http://wiki.ecmascript.org/doku.php?id=harmony:proxies#an_identity-preserving_membrane
|
|
|
| -function createMembrane(wetTarget) {
|
| - var wet2dry = new WeakMap();
|
| - var dry2wet = new WeakMap();
|
| +function createMembrane(target) {
|
| + const wet2dry = 0;
|
| + const dry2wet = 1;
|
|
|
| - function asDry(obj) {
|
| - registerObject(obj)
|
| - print("asDry enter", str(obj))
|
| - try {
|
| - var x = asDry2(obj);
|
| - registerObject(x, "dry");
|
| - print("asDry exit", str(obj), "as", str(x));
|
| - return x;
|
| - } catch(e) {
|
| - print("asDry exception", str(e));
|
| - throw e;
|
| - }
|
| - }
|
| - function asDry2(wet) {
|
| - if (wet !== Object(wet)) {
|
| - // primitives provide only irrevocable knowledge, so don't
|
| - // bother wrapping it.
|
| - return wet;
|
| - }
|
| - var dryResult = wet2dry.get(wet);
|
| - if (dryResult) { return dryResult; }
|
| + function flip(dir) { return (dir + 1) % 2 }
|
|
|
| - var wetHandler = createHandler(wet);
|
| - var dryRevokeHandler = new Proxy({}, Object.freeze({
|
| - get: function(receiver, name) {
|
| - return function() {
|
| - var arg = (name === "get" || name == "set") ? arguments[1] : "";
|
| - print("dry handler enter", name, arg);
|
| - var optWetHandler = dry2wet.get(dryRevokeHandler);
|
| - try {
|
| - var x = asDry(optWetHandler[name].apply(
|
| - optWetHandler, Array.prototype.map.call(arguments, asWet)));
|
| - print("dry handler exit", name, arg, "returning", str(x));
|
| - return x;
|
| - } catch (eWet) {
|
| - var x = asDry(eWet);
|
| - print("dry handler exception", name, arg, "throwing", str(x));
|
| - throw x;
|
| - }
|
| - };
|
| - }
|
| - }));
|
| - dry2wet.set(dryRevokeHandler, wetHandler);
|
| + let maps = [new WeakMap(), new WeakMap()];
|
|
|
| - if (typeof wet === "function") {
|
| - function callTrap() {
|
| - print("dry call trap enter", str(this));
|
| - var x = asDry(wet.apply(
|
| - asWet(this), Array.prototype.map.call(arguments, asWet)));
|
| - print("dry call trap exit", str(this), "returning", str(x));
|
| - return x;
|
| - }
|
| - function constructTrap() {
|
| - function forward(args) { return wet.apply(this, args) }
|
| - return asDry(new forward(Array.prototype.map.call(arguments, asWet)));
|
| - }
|
| - dryResult =
|
| - Proxy.createFunction(dryRevokeHandler, callTrap, constructTrap);
|
| - } else {
|
| - dryResult =
|
| - new Proxy(asDry(Object.getPrototypeOf(wet)), dryRevokeHandler);
|
| - }
|
| - wet2dry.set(wet, dryResult);
|
| - dry2wet.set(dryResult, wet);
|
| - return dryResult;
|
| - }
|
| + let revoked = false;
|
|
|
| - function asWet(obj) {
|
| - registerObject(obj)
|
| - print("asWet enter", str(obj))
|
| - try {
|
| - var x = asWet2(obj)
|
| - registerObject(x, "wet")
|
| - print("asWet exit", str(obj), "as", str(x))
|
| - return x
|
| - } catch(e) {
|
| - print("asWet exception", str(e))
|
| - throw e
|
| - }
|
| - }
|
| - function asWet2(dry) {
|
| - if (dry !== Object(dry)) {
|
| - // primitives provide only irrevocable knowledge, so don't
|
| - // bother wrapping it.
|
| - return dry;
|
| - }
|
| - var wetResult = dry2wet.get(dry);
|
| - if (wetResult) { return wetResult; }
|
| + function wrap(dir, obj) {
|
| + if (obj !== Object(obj)) return obj;
|
| +
|
| + let wrapper = maps[dir].get(obj);
|
| + if (wrapper) return wrapper;
|
|
|
| - var dryHandler = createHandler(dry);
|
| - var wetRevokeHandler = new Proxy({}, Object.freeze({
|
| - get: function(receiver, name) {
|
| - return function() {
|
| - var arg = (name === "get" || name == "set") ? arguments[1] : "";
|
| - print("wet handler enter", name, arg);
|
| - var optDryHandler = wet2dry.get(wetRevokeHandler);
|
| + let handler = new Proxy({}, {get: function(_, key) {
|
| + if (revoked) throw new Error("revoked");
|
| + switch (key) {
|
| + case "apply":
|
| + return (_, that, args) => {
|
| try {
|
| - var x = asWet(optDryHandler[name].apply(
|
| - optDryHandler, Array.prototype.map.call(arguments, asDry)));
|
| - print("wet handler exit", name, arg, "returning", str(x));
|
| - return x;
|
| - } catch (eDry) {
|
| - var x = asWet(eDry);
|
| - print("wet handler exception", name, arg, "throwing", str(x));
|
| - throw x;
|
| + return wrap(dir, Reflect.apply(
|
| + obj, wrap(flip(dir), that),
|
| + args.map((x) => wrap(flip(dir), x))));
|
| + } catch(e) {
|
| + throw wrap(dir, e);
|
| }
|
| - };
|
| + }
|
| + case "construct":
|
| + return (_, args, newt) => {
|
| + try {
|
| + return wrap(dir, Reflect.construct(
|
| + obj, args.map((x) => wrap(flip(dir), x)),
|
| + wrap(flip(dir), newt)));
|
| + } catch(e) {
|
| + throw wrap(dir, e);
|
| + }
|
| + }
|
| + default:
|
| + return (_, ...args) => {
|
| + try {
|
| + return wrap(dir, Reflect[key](
|
| + obj, ...(args.map((x) => wrap(flip(dir), x)))))
|
| + } catch(e) {
|
| + throw wrap(dir, e);
|
| + }
|
| + }
|
| }
|
| - }));
|
| - wet2dry.set(wetRevokeHandler, dryHandler);
|
| + }});
|
|
|
| - if (typeof dry === "function") {
|
| - function callTrap() {
|
| - print("wet call trap enter", str(this));
|
| - var x = asWet(dry.apply(
|
| - asDry(this), Array.prototype.map.call(arguments, asDry)));
|
| - print("wet call trap exit", str(this), "returning", str(x));
|
| - return x;
|
| - }
|
| - function constructTrap() {
|
| - function forward(args) { return dry.apply(this, args) }
|
| - return asWet(new forward(Array.prototype.map.call(arguments, asDry)));
|
| - }
|
| - wetResult =
|
| - Proxy.createFunction(wetRevokeHandler, callTrap, constructTrap);
|
| - } else {
|
| - wetResult =
|
| - new Proxy(asWet(Object.getPrototypeOf(dry)), wetRevokeHandler);
|
| - }
|
| - dry2wet.set(dry, wetResult);
|
| - wet2dry.set(wetResult, dry);
|
| - return wetResult;
|
| + wrapper = new Proxy(obj, handler);
|
| + maps[dir].set(obj, wrapper);
|
| + maps[flip(dir)].set(wrapper, obj);
|
| + return wrapper;
|
| }
|
|
|
| - var gate = Object.freeze({
|
| - revoke: function() {
|
| - dry2wet = wet2dry = Object.freeze({
|
| - get: function(key) { throw new Error("revoked"); },
|
| - set: function(key, val) { throw new Error("revoked"); }
|
| - });
|
| - }
|
| + const gate = Object.freeze({
|
| + revoke: () => revoked = true
|
| });
|
|
|
| - return Object.freeze({ wrapper: asDry(wetTarget), gate: gate });
|
| + return Object.freeze({
|
| + wrapper: wrap(wet2dry, target),
|
| + gate: gate
|
| + });
|
| }
|
|
|
|
|
| -var receiver
|
| -var argument
|
| -var o = {
|
| - a: 6,
|
| - b: {bb: 8},
|
| - f: function(x) { receiver = this; argument = x; return x },
|
| - g: function(x) { receiver = this; argument = x; return x.a },
|
| - h: function(x) { receiver = this; argument = x; this.q = x },
|
| - s: function(x) { receiver = this; argument = x; this.x = {y: x}; return this }
|
| +// Test the identity-preserving membrane.
|
| +{
|
| + var receiver
|
| + var argument
|
| + var o = {
|
| + a: 6,
|
| + b: {bb: 8},
|
| + f: function(x) {receiver = this; argument = x; return x},
|
| + g: function(x) {receiver = this; argument = x; return x.a},
|
| + h: function(x) {receiver = this; argument = x; this.q = x},
|
| + s: function(x) {receiver = this; argument = x; this.x = {y: x}; return this}
|
| + }
|
| + o[2] = {c: 7}
|
| + var m = createMembrane(o)
|
| + var w = m.wrapper
|
| + var f = w.f
|
| + var x = f(66)
|
| + var x = f({a: 1})
|
| + var x = w.f({a: 1})
|
| + var a = x.a
|
| + assertEquals(6, w.a)
|
| + assertEquals(8, w.b.bb)
|
| + assertEquals(7, w[2]["c"])
|
| + assertEquals(undefined, w.c)
|
| + assertEquals(1, w.f(1))
|
| + assertSame(o, receiver)
|
| + assertEquals(1, w.f({a: 1}).a)
|
| + assertSame(o, receiver)
|
| + assertEquals(2, w.g({a: 2}))
|
| + assertSame(o, receiver)
|
| + assertSame(w, w.f(w))
|
| + assertSame(o, receiver)
|
| + assertSame(o, argument)
|
| + assertSame(o, w.f(o))
|
| + assertSame(o, receiver)
|
| + // Note that argument !== o, since o isn't dry, so gets wrapped wet again.
|
| + assertEquals(3, (w.r = {a: 3}).a)
|
| + assertEquals(3, w.r.a)
|
| + assertEquals(3, o.r.a)
|
| + w.h(3)
|
| + assertEquals(3, w.q)
|
| + assertEquals(3, o.q)
|
| + assertEquals(4, (new w.h(4)).q)
|
| + assertEquals(5, w.s(5).x.y)
|
| + assertSame(o, receiver)
|
| +
|
| + var wb = w.b
|
| + var wr = w.r
|
| + var wf = w.f
|
| + var wf3 = w.f(3)
|
| + var wfx = w.f({a: 6})
|
| + var wgx = w.g({a: {aa: 7}})
|
| + var wh4 = new w.h(4)
|
| + var ws5 = w.s(5)
|
| + var ws5x = ws5.x
|
| + m.gate.revoke()
|
| + assertEquals(3, wf3)
|
| + assertThrows(function() { w.a }, Error)
|
| + assertThrows(function() { w.r }, Error)
|
| + assertThrows(function() { w.r = {a: 4} }, Error)
|
| + assertThrows(function() { o.r.a }, Error)
|
| + assertEquals("object", typeof o.r)
|
| + assertEquals(5, (o.r = {a: 5}).a)
|
| + assertEquals(5, o.r.a)
|
| + assertThrows(function() { w[1] }, Error)
|
| + assertThrows(function() { w.c }, Error)
|
| + assertThrows(function() { wb.bb }, Error)
|
| + assertEquals(3, wr.a)
|
| + assertThrows(function() { wf(4) }, Error)
|
| + assertEquals(6, wfx.a)
|
| + assertEquals(7, wgx.aa)
|
| + assertThrows(function() { wh4.q }, Error)
|
| + assertThrows(function() { ws5.x }, Error)
|
| + assertThrows(function() { ws5x.y }, Error)
|
| }
|
| -o[2] = {c: 7}
|
| -var m = createMembrane(o)
|
| -var w = m.wrapper
|
| -print("o =", str(o))
|
| -print("w =", str(w))
|
| -
|
| -var f = w.f
|
| -var x = f(66)
|
| -var x = f({a: 1})
|
| -var x = w.f({a: 1})
|
| -var a = x.a
|
| -assertEquals(6, w.a)
|
| -assertEquals(8, w.b.bb)
|
| -assertEquals(7, w[2]["c"])
|
| -assertEquals(undefined, w.c)
|
| -assertEquals(1, w.f(1))
|
| -assertSame(o, receiver)
|
| -assertEquals(1, w.f({a: 1}).a)
|
| -assertSame(o, receiver)
|
| -assertEquals(2, w.g({a: 2}))
|
| -assertSame(o, receiver)
|
| -assertSame(w, w.f(w))
|
| -assertSame(o, receiver)
|
| -assertSame(o, argument)
|
| -assertSame(o, w.f(o))
|
| -assertSame(o, receiver)
|
| -// Note that argument !== o, since o isn't dry, so gets wrapped wet again.
|
| -assertEquals(3, (w.r = {a: 3}).a)
|
| -assertEquals(3, w.r.a)
|
| -assertEquals(3, o.r.a)
|
| -w.h(3)
|
| -assertEquals(3, w.q)
|
| -assertEquals(3, o.q)
|
| -assertEquals(4, (new w.h(4)).q)
|
| -assertEquals(5, w.s(5).x.y)
|
| -assertSame(o, receiver)
|
| -
|
| -var wb = w.b
|
| -var wr = w.r
|
| -var wf = w.f
|
| -var wf3 = w.f(3)
|
| -var wfx = w.f({a: 6})
|
| -var wgx = w.g({a: {aa: 7}})
|
| -var wh4 = new w.h(4)
|
| -var ws5 = w.s(5)
|
| -var ws5x = ws5.x
|
| -m.gate.revoke()
|
| -assertEquals(3, wf3)
|
| -assertThrows(function() { w.a }, Error)
|
| -assertThrows(function() { w.r }, Error)
|
| -assertThrows(function() { w.r = {a: 4} }, Error)
|
| -assertThrows(function() { o.r.a }, Error)
|
| -assertEquals("object", typeof o.r)
|
| -assertEquals(5, (o.r = {a: 5}).a)
|
| -assertEquals(5, o.r.a)
|
| -assertThrows(function() { w[1] }, Error)
|
| -assertThrows(function() { w.c }, Error)
|
| -assertThrows(function() { wb.bb }, Error)
|
| -assertEquals(3, wr.a)
|
| -assertThrows(function() { wf(4) }, Error)
|
| -assertEquals(6, wfx.a)
|
| -assertEquals(7, wgx.aa)
|
| -assertThrows(function() { wh4.q }, Error)
|
| -assertThrows(function() { ws5.x }, Error)
|
| -assertThrows(function() { ws5x.y }, Error)
|
|
|