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