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