1// Copyright 2015 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5 6var properties = 7 ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}]; 8 9 10function TestForwarding(handler, myDelete, shouldThrow) { 11 var target = {}; 12 var proxy = new Proxy(target, handler); 13 14 assertFalse(target.hasOwnProperty("doesnotexist")); 15 assertTrue(myDelete(proxy, "doesnotexist")); 16 17 for (p of properties) { 18 target[p] = 42; 19 assertTrue(myDelete(proxy, p)); 20 assertFalse(target.hasOwnProperty(p)); 21 } 22 23 for (p of properties) { 24 Object.defineProperty(target, p, {value: 42, configurable: false}); 25 if (shouldThrow) { 26 assertThrows(() => myDelete(proxy, p), TypeError); 27 } else { 28 assertFalse(myDelete(proxy, p)); 29 } 30 assertTrue(target.hasOwnProperty(p)); 31 } 32}; 33 34 35(function () { 36 // No trap. 37 38 var handler = {}; 39 40 TestForwarding(handler, 41 (o, p) => delete o[p], false); 42 TestForwarding(handler, 43 (o, p) => Reflect.deleteProperty(o, p), false); 44 TestForwarding(handler, 45 (o, p) => {"use strict"; return delete o[p]}, true); 46 TestForwarding(handler, 47 (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false); 48})(); 49 50 51(function () { 52 // "Undefined" trap. 53 54 var handler = { deleteProperty: null }; 55 56 TestForwarding(handler, 57 (o, p) => delete o[p], false); 58 TestForwarding(handler, 59 (o, p) => Reflect.deleteProperty(o, p), false); 60 TestForwarding(handler, 61 (o, p) => {"use strict"; return delete o[p]}, true); 62 TestForwarding(handler, 63 (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false); 64})(); 65 66 67(function () { 68 // Invalid trap. 69 70 var target = {}; 71 var handler = { deleteProperty: true }; 72 var proxy = new Proxy(target, handler); 73 74 assertThrows(() => delete proxy[0], TypeError); 75 assertThrows(() => Reflect.deleteProperty(proxy, 0), TypeError); 76})(); 77 78 79function TestTrappingTrueish(myDelete) { 80 var handler = { deleteProperty() {return 42} }; 81 var target = {}; 82 var proxy = new Proxy(target, handler); 83 84 // Trap returns trueish and target doesn't own property. 85 for (p of properties) { 86 assertTrue(myDelete(proxy, p)); 87 } 88 89 // Trap returns trueish and target property is configurable. 90 for (p of properties) { 91 target[p] = 42; 92 assertTrue(myDelete(proxy, p)); 93 } 94 95 // Trap returns trueish but target property is not configurable. 96 for (p of properties) { 97 Object.defineProperty(target, p, {value: 42, configurable: false}); 98 assertThrows(() => myDelete(proxy, p), TypeError); 99 } 100}; 101 102 103TestTrappingTrueish( 104 (o, p) => delete o[p]); 105TestTrappingTrueish( 106 (o, p) => Reflect.deleteProperty(o, p)); 107TestTrappingTrueish( 108 (o, p) => {"use strict"; return delete o[p]}); 109TestTrappingTrueish( 110 (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}); 111 112 113function TestTrappingTrueish2(myDelete) { 114 var handler = { 115 deleteProperty(target, p) { 116 Object.defineProperty(target, p, {configurable: false}); 117 return 42 118 } 119 }; 120 var target = {}; 121 var proxy = new Proxy(target, handler); 122 123 // Trap returns trueish but target property is not configurable. In contrast 124 // to above, here the target property was configurable before the trap call. 125 for (p of properties) { 126 target[p] = 42; 127 assertThrows(() => myDelete(proxy, p), TypeError); 128 } 129}; 130 131 132TestTrappingTrueish2( 133 (o, p) => delete o[p]); 134TestTrappingTrueish2( 135 (o, p) => Reflect.deleteProperty(o, p)); 136TestTrappingTrueish2( 137 (o, p) => {"use strict"; return delete o[p]}); 138TestTrappingTrueish2( 139 (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}); 140 141 142function TestTrappingFalsish(myDelete, shouldThrow) { 143 var handler = { deleteProperty() {return ""} }; 144 var target = {}; 145 var proxy = new Proxy(target, handler); 146 147 var properties = 148 ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}]; 149 150 // Trap returns falsish and target doesn't own property. 151 for (p of properties) { 152 if (shouldThrow) { 153 assertThrows(() => myDelete(proxy, p), TypeError); 154 } else { 155 assertFalse(myDelete(proxy, p)); 156 } 157 } 158 159 // Trap returns falsish and target property is configurable. 160 for (p of properties) { 161 target[p] = 42; 162 if (shouldThrow) { 163 assertThrows(() => myDelete(proxy, p), TypeError); 164 } else { 165 assertFalse(myDelete(proxy, p)); 166 } 167 } 168 169 // Trap returns falsish and target property is not configurable. 170 for (p of properties) { 171 Object.defineProperty(target, p, {value: 42, configurable: false}); 172 if (shouldThrow) { 173 assertThrows(() => myDelete(proxy, p), TypeError); 174 } else { 175 assertFalse(myDelete(proxy, p)); 176 } 177 } 178}; 179 180 181TestTrappingFalsish( 182 (o, p) => delete o[p], false); 183TestTrappingFalsish( 184 (o, p) => Reflect.deleteProperty(o, p), false); 185TestTrappingFalsish( 186 (o, p) => {"use strict"; return delete o[p]}, true); 187TestTrappingFalsish( 188 (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false); 189