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
7var target = {
8  "target_one": 1
9};
10target.__proto__ = {
11  "target_two": 2
12};
13var 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
28var proxy = new Proxy(target, handler);
29
30function TestForIn(receiver, expected) {
31  var result = [];
32  for (var k in receiver) {
33    result.push(k);
34  }
35  assertEquals(expected, result);
36}
37
38TestForIn(proxy, ["foo", "bar"]);
39
40// Test revoked proxy.
41var pair = Proxy.revocable(target, handler);
42TestForIn(pair.proxy, ["foo", "bar"]);
43pair.revoke();
44assertThrows(()=>{ TestForIn(pair.proxy, ["foo", "bar"]) }, TypeError);
45
46// Properly call traps on proxies on the prototype chain.
47var receiver = {
48  "receiver_one": 1
49};
50receiver.__proto__ = proxy;
51TestForIn(receiver, ["receiver_one", "foo", "bar"]);
52
53// Fall through to default behavior when trap is undefined.
54handler.enumerate = undefined;
55TestForIn(proxy, ["target_one", "target_two"]);
56delete handler.enumerate;
57TestForIn(proxy, ["target_one", "target_two"]);
58
59// Non-string keys must be filtered.
60function 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
68TestNonStringKey(1);
69TestNonStringKey(3.14);
70TestNonStringKey(Symbol("foo"));
71TestNonStringKey({bad: "value"});
72TestNonStringKey(null);
73TestNonStringKey(undefined);
74TestNonStringKey(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