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 33 function 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 41 function TestForIn(properties, handler) { 42 TestWithProxies(TestForIn2, properties, handler) 43 } 44 45 function 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 52 TestForIn(["0", "a"], { 53 enumerate: function() { return [0, "a"] } 54 }) 55 56 TestForIn(["null", "a"], { 57 enumerate: function() { return this.enumerate2() }, 58 enumerate2: function() { return [null, "a"] } 59 }) 60 61 TestForIn(["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 74 TestForIn(["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 84 function TestForInDerived(properties, handler) { 85 TestWithProxies(TestForInDerived2, properties, handler) 86 } 87 88 function 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 103 TestForInDerived(["0", "a"], { 104 enumerate: function() { return [0, "a"] }, 105 getPropertyDescriptor: function(k) { 106 return k == "0" || k == "a" ? {configurable: true} : undefined 107 } 108 }) 109 110 TestForInDerived(["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 118 TestForInDerived(["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 135 function TestForInThrow(handler) { 136 TestWithProxies(TestForInThrow2, handler) 137 } 138 139 function 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 146 TestForInThrow({ 147 enumerate: function() { throw "myexn" } 148 }) 149 150 TestForInThrow({ 151 enumerate: function() { return this.enumerate2() }, 152 enumerate2: function() { throw "myexn" } 153 }) 154 155 TestForInThrow({ 156 getPropertyNames: function() { throw "myexn" } 157 }) 158 159 TestForInThrow({ 160 getPropertyNames: function() { return ["a"] }, 161 getPropertyDescriptor: function() { throw "myexn" } 162 }) 163 164 TestForInThrow(Proxy.create({ 165 get: function(pr, pk) { 166 return function() { throw "myexn" } 167 } 168 })) 169