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 8 var properties = 9 ["bla", "0", 1, Symbol(), {[Symbol.toPrimitive]() {return "a"}}]; 10 11 12 function 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 81 function 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 105 TestTrappingTrueish( 106 (o, p) => delete o[p]); 107 TestTrappingTrueish( 108 (o, p) => Reflect.deleteProperty(o, p)); 109 TestTrappingTrueish( 110 (o, p) => {"use strict"; return delete o[p]}); 111 TestTrappingTrueish( 112 (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}); 113 114 115 function 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 134 TestTrappingTrueish2( 135 (o, p) => delete o[p]); 136 TestTrappingTrueish2( 137 (o, p) => Reflect.deleteProperty(o, p)); 138 TestTrappingTrueish2( 139 (o, p) => {"use strict"; return delete o[p]}); 140 TestTrappingTrueish2( 141 (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}); 142 143 144 function 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 183 TestTrappingFalsish( 184 (o, p) => delete o[p], false); 185 TestTrappingFalsish( 186 (o, p) => Reflect.deleteProperty(o, p), false); 187 TestTrappingFalsish( 188 (o, p) => {"use strict"; return delete o[p]}, true); 189 TestTrappingFalsish( 190 (o, p) => {"use strict"; return Reflect.deleteProperty(o, p)}, false); 191