| // Copyright 2011 the V8 project authors. All rights reserved. |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials provided |
| // with the distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| |
| // Helper. |
| |
| function TestWithProxies(test, x, y, z) { |
| test(function(h) { return new Proxy({}, h) }, x, y, z) |
| test(function(h) { |
| return new Proxy(function() {}, h) |
| }, x, y, z) |
| } |
| |
| |
| |
| // Getting. |
| |
| function TestWithGet(handler) { |
| TestWithProxies(TestWithGet2, handler) |
| } |
| |
| var c = "global" |
| var key = "" |
| |
| function TestWithGet2(create, handler) { |
| var b = "local" |
| |
| var p = create(handler); |
| assertEquals("onproxy", p.a); |
| assertEquals(undefined, p.b); |
| assertEquals(undefined, p.c); |
| |
| with (p) { |
| assertEquals("onproxy", a); |
| assertEquals("local", b); |
| assertEquals("global", c); |
| } |
| |
| var o = Object.create(p, {d: {value: "own"}}) |
| with (o) { |
| assertEquals("onproxy", a) |
| assertEquals("local", b); |
| assertEquals("global", c) |
| assertEquals("own", d) |
| } |
| } |
| |
| TestWithGet({ |
| get(target, k) { |
| key = k; |
| return k === "a" ? "onproxy" : undefined |
| }, |
| has(target, k) { return k === 'a' } |
| }) |
| |
| TestWithGet({ |
| get: function(r, k) { return this.get2(r, k) }, |
| get2: function(r, k) { key = k; return k === "a" ? "onproxy" : undefined }, |
| has(target, k) { return k === 'a' } |
| }) |
| |
| |
| |
| |
| // Invoking. |
| |
| function TestWithGetCall(handler) { |
| TestWithProxies(TestWithGetCall2, handler) |
| } |
| |
| var receiver = null |
| var c = function() { return "global" } |
| |
| function TestWithGetCall2(create, handler) { |
| var b = function() { return "local" } |
| |
| var p = create(handler) |
| with (p) { |
| receiver = null |
| assertEquals("onproxy", a()) |
| assertSame(p, receiver) |
| assertEquals("local", b()) |
| assertEquals("global", c()) |
| } |
| |
| var o = Object.create(p, {d: {value: function() { return "own" }}}) |
| with (o) { |
| receiver = null |
| assertEquals("onproxy", a()) |
| assertSame(o, receiver) |
| assertEquals("local", b()) |
| assertEquals("global", c()) |
| assertEquals("own", d()) |
| } |
| } |
| |
| function onproxy() { receiver = this; return "onproxy" } |
| |
| TestWithGetCall({ |
| get: function(r, k) { key = k; return k === "a" ? onproxy : undefined }, |
| has: function(t, k) { |
| key = k; |
| return k === "a"; |
| } |
| }) |
| |
| TestWithGetCall({ |
| get: function(r, k) { return this.get2(r, k) }, |
| get2: function(r, k) { key = k; return k === "a" ? onproxy : undefined }, |
| has: function(t, k) { |
| key = k; |
| return k === "a"; |
| } |
| }) |
| |
| TestWithGetCall({ |
| get: function(r, k) { key = k; return k === "a" ? onproxy : undefined }, |
| has: function(t, k) { |
| return this.has2(k) |
| }, |
| has2: function(k) { |
| key = k; |
| return k === "a"; |
| } |
| }) |
| |
| TestWithGetCall({ |
| get: function(r, k) { key = k; return k === "a" ? onproxy : undefined }, |
| has: function(t, k) { |
| key = k; |
| return k === "a"; |
| } |
| }) |
| |
| |
| function TestWithGetCallThrow(handler) { |
| TestWithProxies(TestWithGetCallThrow2, handler) |
| } |
| |
| function TestWithGetCallThrow2(create, handler) { |
| var b = function() { return "local" } |
| |
| var p = create(handler) |
| with (p) { |
| assertThrowsEquals(function(){ a() }, "myexn") |
| assertEquals("local", b()) |
| assertEquals("global", c()) |
| } |
| |
| var o = Object.create(p, {d: {value: function() { return "own" }}}) |
| with (o) { |
| assertThrowsEquals(function(){ a() }, "myexn") |
| assertEquals("local", b()) |
| assertEquals("global", c()) |
| assertEquals("own", d()) |
| } |
| } |
| |
| function onproxythrow() { throw "myexn" } |
| |
| TestWithGetCallThrow({ |
| has: function(r, k) { return k === "a"; }, |
| get: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined }, |
| }) |
| |
| TestWithGetCallThrow({ |
| has: function(r, k) { return k === "a"; }, |
| get: function(r, k) { return this.get2(r, k) }, |
| get2: function(r, k) { key = k; return k === "a" ? onproxythrow : undefined }, |
| }) |
| |
| |
| |
| // Setting. |
| |
| var key |
| var val |
| |
| function TestWithSet(handler, hasSetter) { |
| TestWithProxies(TestWithSet2, handler, hasSetter) |
| } |
| |
| var c = "global" |
| |
| function TestWithSet2(create, handler, hasSetter) { |
| var b = "local" |
| |
| var p = create(handler) |
| key = val = undefined |
| with (p) { |
| a = "set" |
| assertEquals("a", key) |
| assertEquals("set", val) |
| assertEquals("local", b) |
| assertEquals("global", c) |
| b = "local" |
| c = "global" |
| assertEquals("a", key) |
| assertEquals("set", val) |
| } |
| |
| if (!hasSetter) return |
| |
| var o = Object.create(p, {d: {value: "own"}}) |
| key = val = undefined |
| with (o) { |
| a = "set" |
| assertEquals("a", key) |
| assertEquals("set", val) |
| assertEquals("local", b) |
| assertEquals("global", c) |
| assertEquals("own", d) |
| b = "local" |
| c = "global" |
| d = "own" |
| assertEquals("a", key) |
| assertEquals("set", val) |
| } |
| } |
| |
| TestWithSet({ |
| set: function(r, k, v) { key = k; val = v; return true }, |
| has: function(t, k) { |
| return k === "a" |
| } |
| }) |
| |
| TestWithSet({ |
| set: function(r, k, v) { return this.set2(r, k, v) }, |
| set2: function(r, k, v) { key = k; val = v; return true }, |
| has: function(t, k) { |
| return k === "a" |
| } |
| }) |
| |
| TestWithSet({ |
| has: function(t, k) { |
| return k === "a" |
| }, |
| defineProperty: function(t, k, desc) { key = k; val = desc.value } |
| }) |
| |
| TestWithSet({ |
| has: function(t, k) { |
| return this.has2(k) |
| }, |
| has2: function(k) { |
| return k === "a" |
| }, |
| defineProperty: function(t, k, desc) { this.defineProperty2(k, desc) }, |
| defineProperty2: function(k, desc) { key = k; val = desc.value } |
| }) |
| |
| TestWithSet({ |
| has: function(t, k) { |
| return k === "a" |
| }, |
| defineProperty: function(t, k, desc) { key = k; val = desc.value } |
| }) |
| |
| TestWithSet({ |
| has: function(t, k) { |
| return this.has2(k) }, |
| has2: function(k) { |
| return k === "a" |
| }, |
| set: function(t, k, v) { key = k; val = v; return true } |
| }, true) |
| |
| TestWithSet({ |
| has: function(t, k) { |
| return k === "a" |
| }, |
| defineProperty: function(t, k, desc) { key = k; val = desc.value } |
| }) |
| |
| |
| function TestWithSetThrow(handler, hasSetter) { |
| TestWithProxies(TestWithSetThrow2, handler, hasSetter) |
| } |
| |
| function TestWithSetThrow2(create, handler, hasSetter) { |
| var p = create(handler) |
| assertThrowsEquals(function(){ |
| with (p) { |
| a = 1 |
| } |
| }, "myexn") |
| |
| if (!hasSetter) return |
| |
| var o = Object.create(p, {}) |
| assertThrowsEquals(function(){ |
| with (o) { |
| a = 1 |
| } |
| }, "myexn") |
| } |
| |
| TestWithSetThrow({ |
| set: function() { throw "myexn" }, |
| has: function(t, k) { |
| return k === "a" |
| } |
| }) |
| |
| TestWithSetThrow({ |
| has: function() { throw "myexn" }, |
| }) |
| |
| TestWithSetThrow({ |
| has: function() { throw "myexn" }, |
| }) |
| |
| TestWithSetThrow({ |
| has: function(t, k) { |
| return k === "a" |
| }, |
| defineProperty: function() { throw "myexn" } |
| }) |
| |
| TestWithSetThrow({ |
| has: function(t, k) { |
| return k === "a" |
| }, |
| set: function() { throw "myexn" } |
| }, true) |