Home | History | Annotate | Download | only in harmony
      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