1// Copyright 2011 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// Flags: --harmony-proxies 29 30 31// Helper. 32 33function TestWithProxies(test, x, y, z) { 34 test(Proxy.create, x, y, z) 35 test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z) 36} 37 38 39// Iterate over a proxy. 40 41function TestForIn(properties, handler) { 42 TestWithProxies(TestForIn2, properties, handler) 43} 44 45function TestForIn2(create, properties, handler) { 46 var p = create(handler) 47 var found = [] 48 for (var x in p) found.push(x) 49 assertArrayEquals(properties, found) 50} 51 52TestForIn(["0", "a"], { 53 enumerate: function() { return [0, "a"] } 54}) 55 56TestForIn(["null", "a"], { 57 enumerate: function() { return this.enumerate2() }, 58 enumerate2: function() { return [null, "a"] } 59}) 60 61TestForIn(["b", "d"], { 62 getPropertyNames: function() { return ["a", "b", "c", "d", "e"] }, 63 getPropertyDescriptor: function(k) { 64 switch (k) { 65 case "a": return {enumerable: false, value: "3", configurable: true}; 66 case "b": return {enumerable: true, get get() {}, configurable: true}; 67 case "c": return {value: 4, configurable: true}; 68 case "d": return {get enumerable() { return true }, configurable: true}; 69 default: return undefined; 70 } 71 } 72}) 73 74TestForIn(["b", "a", "0", "c"], Proxy.create({ 75 get: function(pr, pk) { 76 return function() { return ["b", "a", 0, "c"] } 77 } 78})) 79 80 81 82// Iterate over an object with a proxy prototype. 83 84function TestForInDerived(properties, handler) { 85 TestWithProxies(TestForInDerived2, properties, handler) 86} 87 88function TestForInDerived2(create, properties, handler) { 89 var p = create(handler) 90 var o = Object.create(p) 91 o.z = 0 92 var found = [] 93 for (var x in o) found.push(x) 94 assertArrayEquals(["z"].concat(properties), found) 95 96 var oo = Object.create(o) 97 oo.y = 0 98 var found = [] 99 for (var x in oo) found.push(x) 100 assertArrayEquals(["y", "z"].concat(properties), found) 101} 102 103TestForInDerived(["0", "a"], { 104 enumerate: function() { return [0, "a"] }, 105 getPropertyDescriptor: function(k) { 106 return k == "0" || k == "a" ? {configurable: true} : undefined 107 } 108}) 109 110TestForInDerived(["null", "a"], { 111 enumerate: function() { return this.enumerate2() }, 112 enumerate2: function() { return [null, "a"] }, 113 getPropertyDescriptor: function(k) { 114 return k == "null" || k == "a" ? {configurable: true} : undefined 115 } 116}) 117 118TestForInDerived(["b", "d"], { 119 getPropertyNames: function() { return ["a", "b", "c", "d", "e"] }, 120 getPropertyDescriptor: function(k) { 121 switch (k) { 122 case "a": return {enumerable: false, value: "3", configurable: true}; 123 case "b": return {enumerable: true, get get() {}, configurable: true}; 124 case "c": return {value: 4, configurable: true}; 125 case "d": return {get enumerable() { return true }, configurable: true}; 126 default: return undefined; 127 } 128 } 129}) 130 131 132 133// Throw exception in enumerate trap. 134 135function TestForInThrow(handler) { 136 TestWithProxies(TestForInThrow2, handler) 137} 138 139function TestForInThrow2(create, handler) { 140 var p = create(handler) 141 var o = Object.create(p) 142 assertThrows(function(){ for (var x in p) {} }, "myexn") 143 assertThrows(function(){ for (var x in o) {} }, "myexn") 144} 145 146TestForInThrow({ 147 enumerate: function() { throw "myexn" } 148}) 149 150TestForInThrow({ 151 enumerate: function() { return this.enumerate2() }, 152 enumerate2: function() { throw "myexn" } 153}) 154 155TestForInThrow({ 156 getPropertyNames: function() { throw "myexn" } 157}) 158 159TestForInThrow({ 160 getPropertyNames: function() { return ["a"] }, 161 getPropertyDescriptor: function() { throw "myexn" } 162}) 163 164TestForInThrow(Proxy.create({ 165 get: function(pr, pk) { 166 return function() { throw "myexn" } 167 } 168})) 169