function assert(b) { if (!b) throw new Error("Bad assertion"); } assert(Proxy instanceof Function); assert(Proxy.length === 2); assert(Proxy.prototype === undefined); { for (let i = 0; i < 100; i++) assert((new Proxy({}, {})).__proto__ === Object.prototype); } { for (let i = 0; i < 100; i++) { let threw = false; try { new Proxy({}, 20); } catch(e) { threw = true; assert(e.toString() === "TypeError: A Proxy's 'handler' should be an Object"); } assert(threw); } } { for (let i = 0; i < 100; i++) { let threw = false; try { new Proxy({}, ""); } catch(e) { threw = true; assert(e.toString() === "TypeError: A Proxy's 'handler' should be an Object"); } assert(threw); } } { for (let i = 0; i < 100; i++) { let threw = false; try { new Proxy(20, {}); } catch(e) { threw = true; assert(e.toString() === "TypeError: A Proxy's 'target' should be an Object"); } assert(threw); } } { for (let i = 0; i < 100; i++) { let threw = false; try { new Proxy("", {}); } catch(e) { threw = true; assert(e.toString() === "TypeError: A Proxy's 'target' should be an Object"); } assert(threw); } } { // When we call Proxy it should throw for (let i = 0; i < 100; i++) { let threw = false; try { Proxy({}, {}); } catch(e) { threw = true; assert(e.toString() === "TypeError: calling Proxy constructor without new is invalid"); } assert(threw === true); } let theTarget = { x: 30 }; let handler = { get: function(target, propName, proxyArg) { assert(target === theTarget); assert(proxyArg === proxy); if (propName === "y") return 45; assert(propName === "x"); return target[propName]; } }; let proxy = new Proxy(theTarget, handler); for (let i = 0; i < 1000; i++) { assert(proxy.x === 30); assert(proxy.y === 45); assert(proxy["x"] === 30); assert(proxy["y"] === 45); } } { let handler = {get: null}; let target = {x: 20}; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { if (i % 2) proxy.foo; else proxy["foo"]; } catch(e) { threw = true; } assert(!threw); } } { let handler = {get: {}}; let target = {x: 20}; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { if (i % 2) proxy.foo; else proxy["foo"]; } catch(e) { threw = true; assert(e.toString() === "TypeError: 'get' property of a Proxy's handler object should be callable"); } assert(threw); } } { let handler = {}; let target = {x: 20}; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { assert(proxy.x === 20); assert(proxy.y === undefined); } } { let handler = {}; let target = [1, 2, 3]; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { assert(proxy[0] === 1); assert(proxy[1] === 2); assert(proxy[2] === 3); } } { let theTarget = [1, 2, 3]; let handler = { get: function(target, propName, proxyArg) { switch (propName) { case "0": case "1": return 100; case "2": case "length": return target[propName]; } assert(false); } }; let proxy = new Proxy(theTarget, handler); for (let i = 0; i < 500; i++) { assert(proxy[0] === 100); assert(proxy[1] === 100); assert(proxy[2] === 3); assert(proxy.length === 3); assert(proxy["length"] === 3); } } { let wasCalled = false; let theTarget = { get x() { wasCalled = true; return 25; } }; let j = 0; let handler = { get: function(target, propName, proxyArg) { assert(target === theTarget); let x = j++; if (x % 2) return target[propName]; else return "hello"; } }; let proxy = new Proxy(theTarget, handler); for (let i = 0; i < 500; i++) { if (i % 2) assert(proxy.x === 25); else assert(proxy.x === "hello"); } assert(wasCalled); } { let theTarget = { x: 40 }; let handler = { get: function(target, propName, proxyArg) { return 30; } }; let proxy = new Proxy(theTarget, handler); for (let i = 0; i < 500; i++) { assert(proxy.x === 30); } handler.get = undefined; for (let i = 0; i < 500; i++) { assert(proxy.x === 40); } } { let error = null; let theTarget = new Proxy({}, { getOwnPropertyDescriptor: function(theTarget, propName) { error = new Error("hello!") throw error; } }); let handler = { get: function(target, propName, proxyArg) { return 30; } }; let proxy = new Proxy(theTarget, handler); for (let i = 0; i < 500; i++) { try { proxy.x; } catch(e) { assert(e === error); } } } { let field = Symbol(); let theTarget = { [field]: 40 }; let handler = { get: function(target, propName, proxyArg) { assert(propName === field); return target[field]; } }; let proxy = new Proxy(theTarget, handler); for (let i = 0; i < 500; i++) { assert(proxy[field] === 40); } } { let prop = Symbol(); let theTarget = { }; Object.defineProperty(theTarget, prop, { enumerable: true, configurable: true }); let called = false; let handler = { getOwnPropertyDescriptor: function(target, propName) { assert(prop === propName); called = true; return { enumerable: true, configurable: true }; } }; let proxy = new Proxy(theTarget, handler); for (let i = 0; i < 100; i++) { let pDesc = Object.getOwnPropertyDescriptor(proxy, prop); assert(pDesc.configurable); assert(pDesc.enumerable); assert(called); called = false; } } { let prop = Symbol(); let theTarget = { }; Object.defineProperty(theTarget, prop, { enumerable: true, configurable: true }); let called = false; let handler = { has: function(target, propName) { assert(prop === propName); called = true; return true; } }; let proxy = new Proxy(theTarget, handler); for (let i = 0; i < 100; i++) { let result = prop in proxy; assert(result); assert(called); called = false; } }