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 29 // Helper. 30 31 function TestWithProxies(test, x, y, z) { 32 test(function(h) { return new Proxy({}, h) }, x, y, z) 33 test(function(h) { 34 return new Proxy(function() {}, h) 35 }, x, y, z) 36 } 37 38 39 40 // Getting. 41 42 function TestWithGet(handler) { 43 TestWithProxies(TestWithGet2, handler) 44 } 45 46 var c = "global" 47 var key = "" 48 49 function TestWithGet2(create, handler) { 50 var b = "local" 51 52 var p = create(handler); 53 assertEquals("onproxy", p.a); 54 assertEquals(undefined, p.b); 55 assertEquals(undefined, p.c); 56 57 with (p) { 58 assertEquals("onproxy", a); 59 assertEquals("local", b); 60 assertEquals("global", c); 61 } 62 63 var o = Object.create(p, {d: {value: "own"}}) 64 with (o) { 65 assertEquals("onproxy", a) 66 assertEquals("local", b); 67 assertEquals("global", c) 68 assertEquals("own", d) 69 } 70 } 71 72 TestWithGet({ 73 get(target, k) { 74 key = k; 75 return k === "a" ? "onproxy" : undefined 76 }, 77 has(target, k) { return k === 'a' } 78 }) 79 80 TestWithGet({ 81 get: function(r, k) { return this.get2(r, k) }, 82 get2: function(r, k) { key = k; return k === "a" ? "onproxy" : undefined }, 83 has(target, k) { return k === 'a' } 84 }) 85 86 87 88 89 // Invoking. 90 91 function TestWithGetCall(handler) { 92 TestWithProxies(TestWithGetCall2, handler) 93 } 94 95 var receiver = null 96 var c = function() { return "global" } 97 98 function TestWithGetCall2(create, handler) { 99 var b = function() { return "local" } 100 101 var p = create(handler) 102 with (p) { 103 receiver = null 104 assertEquals("onproxy", a()) 105 assertSame(p, receiver) 106 assertEquals("local", b()) 107 assertEquals("global", c()) 108 } 109 110 var o = Object.create(p, {d: {value: function() { return "own" }}}) 111 with (o) { 112 receiver = null 113 assertEquals("onproxy", a()) 114 assertSame(o, receiver) 115 assertEquals("local", b()) 116 assertEquals("global", c()) 117 assertEquals("own", d()) 118 } 119 } 120 121 function onproxy() { receiver = this; return "onproxy" } 122 123 TestWithGetCall({ 124 get: function(r, k) { key = k; return k === "a" ? onproxy : undefined }, 125 has: function(t, k) { 126 key = k; 127 return k === "a"; 128 } 129 }) 130 131 TestWithGetCall({ 132 get: function(r, k) { return this.get2(r, k) }, 133 get2: function(r, k) { key = k; return k === "a" ? onproxy : undefined }, 134 has: function(t, k) { 135 key = k; 136 return k === "a"; 137 } 138 }) 139 140 TestWithGetCall({ 141 get: function(r, k) { key = k; return k === "a" ? onproxy : undefined }, 142 has: function(t, k) { 143 return this.has2(k) 144 }, 145 has2: function(k) { 146 key = k; 147 return k === "a"; 148 } 149 }) 150 151 TestWithGetCall({ 152 get: function(r, k) { key = k; return k === "a" ? onproxy : undefined }, 153 has: function(t, k) { 154 key = k; 155 return k === "a"; 156 } 157 }) 158 159 160 function TestWithGetCallThrow(handler) { 161 TestWithProxies(TestWithGetCallThrow2, handler) 162 } 163 164 function TestWithGetCallThrow2(create, handler) { 165 var b = function() { return "local" } 166 167 var p = create(handler) 168 with (p) { 169 assertThrowsEquals(function(){ a() }, "myexn") 170 assertEquals("local", b()) 171 assertEquals("global", c()) 172 } 173 174 var o = Object.create(p, {d: {value: function() { return "own" }}}) 175 with (o) { 176 assertThrowsEquals(function(){ a() }, "myexn") 177 assertEquals("local", b()) 178 assertEquals("global", c()) 179 assertEquals("own", d()) 180 } 181 } 182 183 function onproxythrow() { throw "myexn" } 184 185 TestWithGetCallThrow({ 186 has: function(r, k) { return k === "a"; }, 187 get: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined }, 188 }) 189 190 TestWithGetCallThrow({ 191 has: function(r, k) { return k === "a"; }, 192 get: function(r, k) { return this.get2(r, k) }, 193 get2: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined }, 194 }) 195 196 197 198 // Setting. 199 200 var key 201 var val 202 203 function TestWithSet(handler, hasSetter) { 204 TestWithProxies(TestWithSet2, handler, hasSetter) 205 } 206 207 var c = "global" 208 209 function TestWithSet2(create, handler, hasSetter) { 210 var b = "local" 211 212 var p = create(handler) 213 key = val = undefined 214 with (p) { 215 a = "set" 216 assertEquals("a", key) 217 assertEquals("set", val) 218 assertEquals("local", b) 219 assertEquals("global", c) 220 b = "local" 221 c = "global" 222 assertEquals("a", key) 223 assertEquals("set", val) 224 } 225 226 if (!hasSetter) return 227 228 var o = Object.create(p, {d: {value: "own"}}) 229 key = val = undefined 230 with (o) { 231 a = "set" 232 assertEquals("a", key) 233 assertEquals("set", val) 234 assertEquals("local", b) 235 assertEquals("global", c) 236 assertEquals("own", d) 237 b = "local" 238 c = "global" 239 d = "own" 240 assertEquals("a", key) 241 assertEquals("set", val) 242 } 243 } 244 245 TestWithSet({ 246 set: function(r, k, v) { key = k; val = v; return true }, 247 has: function(t, k) { 248 return k === "a" 249 } 250 }) 251 252 TestWithSet({ 253 set: function(r, k, v) { return this.set2(r, k, v) }, 254 set2: function(r, k, v) { key = k; val = v; return true }, 255 has: function(t, k) { 256 return k === "a" 257 } 258 }) 259 260 TestWithSet({ 261 has: function(t, k) { 262 return k === "a" 263 }, 264 defineProperty: function(t, k, desc) { key = k; val = desc.value } 265 }) 266 267 TestWithSet({ 268 has: function(t, k) { 269 return this.has2(k) 270 }, 271 has2: function(k) { 272 return k === "a" 273 }, 274 defineProperty: function(t, k, desc) { this.defineProperty2(k, desc) }, 275 defineProperty2: function(k, desc) { key = k; val = desc.value } 276 }) 277 278 TestWithSet({ 279 has: function(t, k) { 280 return k === "a" 281 }, 282 defineProperty: function(t, k, desc) { key = k; val = desc.value } 283 }) 284 285 TestWithSet({ 286 has: function(t, k) { 287 return this.has2(k) }, 288 has2: function(k) { 289 return k === "a" 290 }, 291 set: function(t, k, v) { key = k; val = v; return true } 292 }, true) 293 294 TestWithSet({ 295 has: function(t, k) { 296 return k === "a" 297 }, 298 defineProperty: function(t, k, desc) { key = k; val = desc.value } 299 }) 300 301 302 function TestWithSetThrow(handler, hasSetter) { 303 TestWithProxies(TestWithSetThrow2, handler, hasSetter) 304 } 305 306 function TestWithSetThrow2(create, handler, hasSetter) { 307 var p = create(handler) 308 assertThrowsEquals(function(){ 309 with (p) { 310 a = 1 311 } 312 }, "myexn") 313 314 if (!hasSetter) return 315 316 var o = Object.create(p, {}) 317 assertThrowsEquals(function(){ 318 with (o) { 319 a = 1 320 } 321 }, "myexn") 322 } 323 324 TestWithSetThrow({ 325 set: function() { throw "myexn" }, 326 has: function(t, k) { 327 return k === "a" 328 } 329 }) 330 331 TestWithSetThrow({ 332 has: function() { throw "myexn" }, 333 }) 334 335 TestWithSetThrow({ 336 has: function() { throw "myexn" }, 337 }) 338 339 TestWithSetThrow({ 340 has: function(t, k) { 341 return k === "a" 342 }, 343 defineProperty: function() { throw "myexn" } 344 }) 345 346 TestWithSetThrow({ 347 has: function(t, k) { 348 return k === "a" 349 }, 350 set: function() { throw "myexn" } 351 }, true) 352