function assert(b) { if (!b) throw new Error("Bad assertion"); } { let error = null; let target = { x: 40 }; let handler = { get has() { error = new Error(); throw error; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { "x" in proxy; } catch(e) { threw = true; assert(e === error); } assert(threw); } } { let error = null; let target = { x: 40 }; let handler = { has: function() { error = new Error(); throw error; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { "x" in proxy; } catch(e) { threw = true; assert(e === error); } assert(threw); } } { let target = { x: 40 }; let called = false; let handler = { has: function(theTarget, propName) { called = true; return propName in theTarget; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let result = "x" in proxy; assert(result); assert(called); called = false; } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: true, value: 45}); let called = false; let handler = { has: function(theTarget, propName) { called = true; return propName in theTarget; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let result = "x" in proxy; assert(result); assert(called); called = false; } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: true, value: 45}); let handler = { }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { if (i % 2) handler.has = null; else handler.has = undefined; let result = "x" in proxy; assert(result); } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: true, value: 45}); let handler = { has: function() { return false; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let result = "x" in proxy; assert(!result); } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: false, value: 45}); let handler = { has: function() { return false; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { "x" in proxy; } catch(e) { assert(e.toString() === "TypeError: Proxy 'has' must return 'true' for non-configurable properties"); threw = true; } assert(threw); } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: false, value: 45}); let handler = { has: function() { return false; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { "x" in proxy; } catch(e) { assert(e.toString() === "TypeError: Proxy 'has' must return 'true' for non-configurable properties"); threw = true; } assert(threw); } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: false, value: 45}); let handler = { has: function() { return null; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { "x" in proxy; } catch(e) { assert(e.toString() === "TypeError: Proxy 'has' must return 'true' for non-configurable properties"); threw = true; } assert(threw); } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: false, value: 45}); let handler = { has: function() { return undefined; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { "x" in proxy; } catch(e) { assert(e.toString() === "TypeError: Proxy 'has' must return 'true' for non-configurable properties"); threw = true; } assert(threw); } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: false, value: 45}); let handler = { has: function() { return 0; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { "x" in proxy; } catch(e) { assert(e.toString() === "TypeError: Proxy 'has' must return 'true' for non-configurable properties"); threw = true; } assert(threw); } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: false, value: 45}); let called = false; let handler = { has: function() { called = true; return 1; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let result = "x" in proxy; assert(result); assert(called); called = false; } } { let target = { }; Object.defineProperty(target, "x", { enumerable: true, configurable: false, value: 45}); let called = false; let handler = { has: function() { called = true; return "hello"; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let result = "x" in proxy; assert(result); assert(called); called = false; } } { let target = { }; let called = false; let handler = { has: function() { called = true; return true } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let result = "x" in proxy; assert(result); assert(called); called = false; } } { let proto = {x: 20}; let target = Object.create(proto); assert(target.__proto__ === proto); let called = false; let handler = { has: function(target, propName) { called = true; return propName in target; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let result = "x" in proxy; assert(result); assert(called); called = false; } } { let target = {x: 20}; let handler = { has: function(theTarget, propName) { assert(theTarget === target); called = true; return propName in theTarget; } }; let proxy = new Proxy(target, handler); let obj = Object.create(proxy); assert(Reflect.getPrototypeOf(obj) === proxy); let called = false; for (let i = 0; i < 500; i++) { let result = "x" in obj; assert(result); assert(called); called = false; } } { let error = null; let target = new Proxy({}, { getOwnPropertyDescriptor: function() { error = new Error(); throw error; } }); let handler = { has: function(theTarget, propName) { return false; } }; let proxy = new Proxy(target, handler); for (let i = 0; i < 500; i++) { let threw = false; try { "foo" in proxy; } catch(e) { assert(e === error); threw = true; } assert(threw); } } { let e1 = null; let e2 = null; let t1 = {}; let called1 = false; let h1 = { has: function(theTarget, propName) { called1 = true; e1 = new Error; throw e1; return false; } }; let p1 = new Proxy(t1, h1); let t2 = {}; t2.__proto__ = p1; let h2 = { has: function(theTarget, propName) { e2 = new Error; throw e2; return false; } }; let p2 = new Proxy(t2, h2); for (let i = 0; i < 500; i++) { let threw = false; try { 10 in p2; } catch(e) { assert(e === e2); threw = true; } assert(threw); assert(!called1); } } { let e1 = null; let e2 = null; let t1 = {}; let called1 = false; let h1 = { has: function(theTarget, propName) { called1 = true; e1 = new Error; throw e1; return false; } }; let p1 = new Proxy(t1, h1); let t2 = {}; t2.__proto__ = p1; let h2 = { has: function(theTarget, propName) { e2 = new Error; throw e2; return false; } }; let p2 = new Proxy(t2, h2); for (let i = 0; i < 500; i++) { let threw = false; try { "foo" in p2; } catch(e) { assert(e === e2); threw = true; } assert(threw); assert(!called1); } } { let called = false; let handler = { has: function(...args) { called = true; return Reflect.has(...args); } }; let proxy = new Proxy({}, handler); let foo = function() { assert(!Reflect.has(proxy, "x")); assert(called); called = false; } noInline(foo) for (let i = 0; i < 10000; i++) { foo(); } }