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
      6 
      7 var target = {
      8   "target_one": 1
      9 };
     10 target.__proto__ = {
     11   "target_two": 2
     12 };
     13 var handler = {
     14   enumerate: function(target) {
     15     function* keys() {
     16       yield "foo";
     17       yield "bar";
     18     }
     19     return keys();
     20   },
     21   // For-in calls "has" on every iteration, so for TestForIn() below to
     22   // detect all results of the "enumerate" trap, "has" must return true.
     23   has: function(target, name) {
     24     return true;
     25   }
     26 }
     27 
     28 var proxy = new Proxy(target, handler);
     29 
     30 function TestForIn(receiver, expected) {
     31   var result = [];
     32   for (var k in receiver) {
     33     result.push(k);
     34   }
     35   assertEquals(expected, result);
     36 }
     37 
     38 TestForIn(proxy, ["foo", "bar"]);
     39 
     40 // Test revoked proxy.
     41 var pair = Proxy.revocable(target, handler);
     42 TestForIn(pair.proxy, ["foo", "bar"]);
     43 pair.revoke();
     44 assertThrows(()=>{ TestForIn(pair.proxy, ["foo", "bar"]) }, TypeError);
     45 
     46 // Properly call traps on proxies on the prototype chain.
     47 var receiver = {
     48   "receiver_one": 1
     49 };
     50 receiver.__proto__ = proxy;
     51 TestForIn(receiver, ["receiver_one", "foo", "bar"]);
     52 
     53 // Fall through to default behavior when trap is undefined.
     54 handler.enumerate = undefined;
     55 TestForIn(proxy, ["target_one", "target_two"]);
     56 delete handler.enumerate;
     57 TestForIn(proxy, ["target_one", "target_two"]);
     58 
     59 // Non-string keys must be filtered.
     60 function TestNonStringKey(key) {
     61   handler.enumerate = function(target) {
     62     function* keys() { yield key; }
     63     return keys();
     64   }
     65   assertThrows("for (var k in proxy) {}", TypeError);
     66 }
     67 
     68 TestNonStringKey(1);
     69 TestNonStringKey(3.14);
     70 TestNonStringKey(Symbol("foo"));
     71 TestNonStringKey({bad: "value"});
     72 TestNonStringKey(null);
     73 TestNonStringKey(undefined);
     74 TestNonStringKey(true);
     75 
     76 (function testProtoProxyEnumerate() {
     77   var keys = ['a', 'b', 'c', 'd'];
     78   var handler = {
     79    enumerate() { return keys[Symbol.iterator]() },
     80    has(target, key) { return false }
     81   };
     82   var proxy = new Proxy({}, handler);
     83   var seen_keys = [];
     84   for (var i in proxy) {
     85     seen_keys.push(i);
     86   }
     87   assertEquals([], seen_keys);
     88 
     89   handler.has = function(target, key) { return true };
     90   for (var i in proxy) {
     91     seen_keys.push(i);
     92   }
     93   assertEquals(keys, seen_keys);
     94 
     95   o = {__proto__:proxy};
     96   handler.has = function(target, key) { return false };
     97   seen_keys = [];
     98   for (var i in o) {
     99     seen_keys.push(i);
    100   }
    101   assertEquals([], seen_keys);
    102 
    103   handler.has = function(target, key) { return true };
    104   seen_keys = [];
    105   for (var i in o) {
    106     seen_keys.push(i);
    107   }
    108   assertEquals(keys, seen_keys);
    109 })();
    110