// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var properties = ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}]; function TestForwarding(handler, myDelete, shouldThrow) { var target = {}; var proxy = new Proxy(target, handler); assertFalse(target.hasOwnProperty("doesnotexist")); assertTrue(myDelete(proxy, "doesnotexist")); for (p of properties) { target[p] = 42; assertTrue(myDelete(proxy, p)); assertFalse(target.hasOwnProperty(p)); } for (p of properties) { Object.defineProperty(target, p, {value: 42, configurable: false}); if (shouldThrow) { assertThrows(() => myDelete(proxy, p), TypeError); } else { assertFalse(myDelete(proxy, p)); } assertTrue(target.hasOwnProperty(p)); } }; (function () { // No trap. var handler = {}; TestForwarding(handler, (o, p) => delete o[p], false); TestForwarding(handler, (o, p) => Reflect.deleteProperty(o, p), false); TestForwarding(handler, (o, p) => {"use strict"; return delete o[p]}, true); TestForwarding(handler, (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false); })(); (function () { // "Undefined" trap. var handler = { deleteProperty: null }; TestForwarding(handler, (o, p) => delete o[p], false); TestForwarding(handler, (o, p) => Reflect.deleteProperty(o, p), false); TestForwarding(handler, (o, p) => {"use strict"; return delete o[p]}, true); TestForwarding(handler, (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false); })(); (function () { // Invalid trap. var target = {}; var handler = { deleteProperty: true }; var proxy = new Proxy(target, handler); assertThrows(() => delete proxy[0], TypeError); assertThrows(() => Reflect.deleteProperty(proxy, 0), TypeError); })(); function TestTrappingTrueish(myDelete) { var handler = { deleteProperty() {return 42} }; var target = {}; var proxy = new Proxy(target, handler); // Trap returns trueish and target doesn't own property. for (p of properties) { assertTrue(myDelete(proxy, p)); } // Trap returns trueish and target property is configurable. for (p of properties) { target[p] = 42; assertTrue(myDelete(proxy, p)); } // Trap returns trueish but target property is not configurable. for (p of properties) { Object.defineProperty(target, p, {value: 42, configurable: false}); assertThrows(() => myDelete(proxy, p), TypeError); } }; TestTrappingTrueish( (o, p) => delete o[p]); TestTrappingTrueish( (o, p) => Reflect.deleteProperty(o, p)); TestTrappingTrueish( (o, p) => {"use strict"; return delete o[p]}); TestTrappingTrueish( (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}); function TestTrappingTrueish2(myDelete) { var handler = { deleteProperty(target, p) { Object.defineProperty(target, p, {configurable: false}); return 42 } }; var target = {}; var proxy = new Proxy(target, handler); // Trap returns trueish but target property is not configurable. In contrast // to above, here the target property was configurable before the trap call. for (p of properties) { target[p] = 42; assertThrows(() => myDelete(proxy, p), TypeError); } }; TestTrappingTrueish2( (o, p) => delete o[p]); TestTrappingTrueish2( (o, p) => Reflect.deleteProperty(o, p)); TestTrappingTrueish2( (o, p) => {"use strict"; return delete o[p]}); TestTrappingTrueish2( (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}); function TestTrappingFalsish(myDelete, shouldThrow) { var handler = { deleteProperty() {return ""} }; var target = {}; var proxy = new Proxy(target, handler); var properties = ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}]; // Trap returns falsish and target doesn't own property. for (p of properties) { if (shouldThrow) { assertThrows(() => myDelete(proxy, p), TypeError); } else { assertFalse(myDelete(proxy, p)); } } // Trap returns falsish and target property is configurable. for (p of properties) { target[p] = 42; if (shouldThrow) { assertThrows(() => myDelete(proxy, p), TypeError); } else { assertFalse(myDelete(proxy, p)); } } // Trap returns falsish and target property is not configurable. for (p of properties) { Object.defineProperty(target, p, {value: 42, configurable: false}); if (shouldThrow) { assertThrows(() => myDelete(proxy, p), TypeError); } else { assertFalse(myDelete(proxy, p)); } } }; TestTrappingFalsish( (o, p) => delete o[p], false); TestTrappingFalsish( (o, p) => Reflect.deleteProperty(o, p), false); TestTrappingFalsish( (o, p) => {"use strict"; return delete o[p]}, true); TestTrappingFalsish( (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false);