diff options
Diffstat (limited to 'deps/v8/test/mjsunit/es6/proxies.js')
-rw-r--r-- | deps/v8/test/mjsunit/es6/proxies.js | 1506 |
1 files changed, 1506 insertions, 0 deletions
diff --git a/deps/v8/test/mjsunit/es6/proxies.js b/deps/v8/test/mjsunit/es6/proxies.js new file mode 100644 index 0000000000..3b9a4c5119 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/proxies.js @@ -0,0 +1,1506 @@ +// 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. + +// We change the stack size for the ARM64 simulator because at one point this +// test enters an infinite recursion which goes through the runtime and we +// overflow the system stack before the simulator stack. + +// Flags: --sim-stack-size=500 --allow-natives-syntax + + +// Helper. + +function TestWithProxies(test, x, y, z) { + // Separate function for nicer stack traces. + TestWithObjectProxy(test, x, y, z); + TestWithFunctionProxy(test, x, y, z); +} + +function TestWithObjectProxy(test, x, y, z) { + test((handler) => { return new Proxy({}, handler) }, x, y, z) + +} + +function TestWithFunctionProxy(test, x, y, z) { + test((handler) => { return new Proxy(() => {}, handler) }, x, y, z) +} + +// --------------------------------------------------------------------------- +// Getting property descriptors (Object.getOwnPropertyDescriptor). + +var key + +function TestGetOwnProperty(handler) { + TestWithProxies(TestGetOwnProperty2, handler) +} + +function TestGetOwnProperty2(create, handler) { + var p = create(handler) + assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value) + assertEquals("a", key) + assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value) + assertEquals("99", key) +} + +TestGetOwnProperty({ + getOwnPropertyDescriptor(target, k) { + key = k + return {value: 42, configurable: true} + } +}) + +TestGetOwnProperty({ + getOwnPropertyDescriptor(target, k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2(k) { + key = k + return {value: 42, configurable: true} + } +}) + +TestGetOwnProperty({ + getOwnPropertyDescriptor(target, k) { + key = k + return {get value() { return 42 }, get configurable() { return true }} + } +}) + +TestGetOwnProperty(new Proxy({}, { + get(target, pk, receiver) { + return function(t, k) { key = k; return {value: 42, configurable: true} } + } +})) + + +// --------------------------------------------------------------------------- +function TestGetOwnPropertyThrow(handler) { + TestWithProxies(TestGetOwnPropertyThrow2, handler) +} + +function TestGetOwnPropertyThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn") + assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, 77), "myexn") +} + +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" } +}) + +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { throw "myexn" } +}) + +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { + return {get value() { throw "myexn" }} + } +}) + +TestGetOwnPropertyThrow(new Proxy({}, { + get: function(pr, pk) { + return function(k) { throw "myexn" } + } +})) + + +// --------------------------------------------------------------------------- +// Getters (dot, brackets). + +var key + +function TestGet(handler) { + TestWithProxies(TestGet2, handler) +} + +function TestGet2(create, handler) { + var p = create(handler) + assertEquals(42, p.a) + assertEquals("a", key) + assertEquals(42, p["b"]) + assertEquals("b", key) + assertEquals(42, p[99]) + assertEquals("99", key) + assertEquals(42, (function(n) { return p[n] })("c")) + assertEquals("c", key) + assertEquals(42, (function(n) { return p[n] })(101)) + assertEquals("101", key) + + var o = Object.create(p, {x: {value: 88}}) + assertEquals(42, o.a) + assertEquals("a", key) + assertEquals(42, o["b"]) + assertEquals("b", key) + assertEquals(42, o[99]) + assertEquals("99", key) + assertEquals(88, o.x) + assertEquals(88, o["x"]) + assertEquals(42, (function(n) { return o[n] })("c")) + assertEquals("c", key) + assertEquals(42, (function(n) { return o[n] })(101)) + assertEquals("101", key) + assertEquals(88, (function(n) { return o[n] })("x")) +} + +TestGet({ + get(t, k, r) { key = k; return 42 } +}) + +TestGet({ + get(t, k, r) { return this.get2(r, k) }, + get2(r, k) { key = k; return 42 } +}) + +TestGet(new Proxy({}, { + get(pt, pk, pr) { + return function(t, k, r) { key = k; return 42 } + } +})) + + +// --------------------------------------------------------------------------- +function TestGetCall(handler) { + TestWithProxies(TestGetCall2, handler) +} + +function TestGetCall2(create, handler) { + var p = create(handler) + assertEquals(55, p.f()) + assertEquals(55, p["f"]()) + assertEquals(55, p.f("unused", "arguments")) + assertEquals(55, p.f.call(p)) + assertEquals(55, p["f"].call(p)) + assertEquals(55, p[101].call(p)) + assertEquals(55, p.withargs(45, 5)) + assertEquals(55, p.withargs.call(p, 11, 22)) + assertEquals(55, (function(n) { return p[n]() })("f")) + assertEquals(55, (function(n) { return p[n].call(p) })("f")) + assertEquals(55, (function(n) { return p[n](15, 20) })("withargs")) + assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs")) + assertEquals("6655", "66" + p) // calls p.toString + + var o = Object.create(p, {g: {value: function(x) { return x + 88 }}}) + assertEquals(55, o.f()) + assertEquals(55, o["f"]()) + assertEquals(55, o.f("unused", "arguments")) + assertEquals(55, o.f.call(o)) + assertEquals(55, o.f.call(p)) + assertEquals(55, o["f"].call(p)) + assertEquals(55, o[101].call(p)) + assertEquals(55, o.withargs(45, 5)) + assertEquals(55, o.withargs.call(p, 11, 22)) + assertEquals(90, o.g(2)) + assertEquals(91, o.g.call(o, 3)) + assertEquals(92, o.g.call(p, 4)) + assertEquals(55, (function(n) { return o[n]() })("f")) + assertEquals(55, (function(n) { return o[n].call(o) })("f")) + assertEquals(55, (function(n) { return o[n](15, 20) })("withargs")) + assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs")) + assertEquals(93, (function(n) { return o[n](5) })("g")) + assertEquals(94, (function(n) { return o[n].call(o, 6) })("g")) + assertEquals(95, (function(n) { return o[n].call(p, 7) })("g")) + assertEquals("6655", "66" + o) // calls o.toString +} + +TestGetCall({ + get(t, k, r) { return () => { return 55 } } +}) + +TestGetCall({ + get(t, k, r) { return this.get2(t, k, r) }, + get2(t, k, r) { return () => { return 55 } } +}) + +TestGetCall({ + get(t, k, r) { + if (k == "gg") { + return () => { return 55 } + } else if (k == "withargs") { + return (n, m) => { return n + m * 2 } + } else { + return () => { return r.gg() } + } + } +}) + +TestGetCall(new Proxy({}, { + get(pt, pk, pr) { + return (t, k, r) => { return () => { return 55 } } + } +})) + + +// --------------------------------------------------------------------------- +function TestGetThrow(handler) { + TestWithProxies(TestGetThrow2, handler) +} + +function TestGetThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(function(){ p.a }, "myexn") + assertThrowsEquals(function(){ p["b"] }, "myexn") + assertThrowsEquals(function(){ p[3] }, "myexn") + assertThrowsEquals(function(){ (function(n) { p[n] })("c") }, "myexn") + assertThrowsEquals(function(){ (function(n) { p[n] })(99) }, "myexn") + + var o = Object.create(p, {x: {value: 88}, '4': {value: 89}}) + assertThrowsEquals(function(){ o.a }, "myexn") + assertThrowsEquals(function(){ o["b"] }, "myexn") + assertThrowsEquals(function(){ o[3] }, "myexn") + assertThrowsEquals(function(){ (function(n) { o[n] })("c") }, "myexn") + assertThrowsEquals(function(){ (function(n) { o[n] })(99) }, "myexn") +} + +TestGetThrow({ + get(r, k) { throw "myexn" } +}) + +TestGetThrow({ + get(r, k) { return this.get2(r, k) }, + get2(r, k) { throw "myexn" } +}) + +TestGetThrow(new Proxy({}, { + get(pr, pk) { throw "myexn" } +})) + +TestGetThrow(new Proxy({}, { + get(pr, pk) { + return function(r, k) { throw "myexn" } + } +})) + + +// --------------------------------------------------------------------------- +// Setters. + +var key +var val + +function TestSet(handler) { + TestWithProxies(TestSet2, handler) +} + +function TestSet2(create, handler) { + var p = create(handler) + assertEquals(42, p.a = 42) + assertEquals("a", key) + assertEquals(42, val) + assertEquals(43, p["b"] = 43) + assertEquals("b", key) + assertEquals(43, val) + assertEquals(44, p[77] = 44) + assertEquals("77", key) + assertEquals(44, val) + + assertEquals(45, (function(n) { return p[n] = 45 })("c")) + assertEquals("c", key) + assertEquals(45, val) + assertEquals(46, (function(n) { return p[n] = 46 })(99)) + assertEquals("99", key) + assertEquals(46, val) + + assertEquals(47, p["0"] = 47) + assertEquals("0", key) + assertEquals(47, val) +} + +TestSet({ + set: function(r, k, v) { key = k; val = v; return true } +}) + +TestSet({ + set: function(r, k, v) { return this.set2(r, k, v) }, + set2: function(r, k, v) { key = k; val = v; return true } +}) + +TestSet(new Proxy({}, { + get(pk, pr) { + return (r, k, v) => { key = k; val = v; return true } + } +})) + + +// --------------------------------------------------------------------------- +function TestSetThrow(handler) { + TestWithProxies(TestSetThrow2, handler) +} + +function TestSetThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(function(){ p.a = 42 }, "myexn") + assertThrowsEquals(function(){ p["b"] = 42 }, "myexn") + assertThrowsEquals(function(){ p[22] = 42 }, "myexn") + assertThrowsEquals(function(){ (function(n) { p[n] = 45 })("c") }, "myexn") + assertThrowsEquals(function(){ (function(n) { p[n] = 46 })(99) }, "myexn") +} + +TestSetThrow({ + set: function(r, k, v) { throw "myexn" } +}) + +TestSetThrow({ + set: function(r, k, v) { return this.set2(r, k, v) }, + set2: function(r, k, v) { throw "myexn" } +}) + +TestSetThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" }, + defineProperty: function(k, desc) { key = k; val = desc.value } +}) + +TestSetThrow({ + getOwnPropertyDescriptor: function(k) { + return {configurable: true, writable: true} + }, + defineProperty: function(k, desc) { throw "myexn" } +}) + +TestSetThrow({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { throw "myexn" }, + defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, + defineProperty2: function(k, desc) { key = k; val = desc.value } +}) + +TestSetThrow({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { + return {configurable: true, writable: true} + }, + defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, + defineProperty2: function(k, desc) { throw "myexn" } +}) + +TestSetThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" }, + defineProperty: function(k, desc) { key = k; val = desc.value } +}) + +TestSetThrow({ + getOwnPropertyDescriptor: function(k) { + return { + get configurable() { return true }, + get writable() { return true } + } + }, + defineProperty: function(k, desc) { throw "myexn" } +}) + +TestSetThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" } +}) + +TestSetThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" }, + defineProperty: function(k, desc) { key = k; val = desc.value } +}) + +TestSetThrow(new Proxy({}, { + get: function(pr, pk) { throw "myexn" } +})) + +TestSetThrow(new Proxy({}, { + get: function(pr, pk) { + return function(r, k, v) { throw "myexn" } + } +})) + +// --------------------------------------------------------------------------- + +// Evil proxy-induced side-effects shouldn't crash. +TestWithProxies(function(create) { + var calls = 0 + var handler = { + getPropertyDescriptor: function() { + ++calls + return (calls % 2 == 1) + ? {get: function() { return 5 }, configurable: true} + : {set: function() { return false }, configurable: true} + } + } + var p = create(handler) + var o = Object.create(p) + // Make proxy prototype property read-only after CanPut check. + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestWithProxies(function(create) { + var handler = { + getPropertyDescriptor: function() { + Object.defineProperty(o, "x", {get: function() { return 5 }}); + return {set: function() {}} + } + } + var p = create(handler) + var o = Object.create(p) + // Make object property read-only after CanPut check. + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + + +// --------------------------------------------------------------------------- +// Property definition (Object.defineProperty and Object.defineProperties). + +var key +var desc + +function TestDefine(handler) { + TestWithProxies(TestDefine2, handler) +} + +function TestDefine2(create, handler) { + var p = create(handler) + assertEquals(p, Object.defineProperty(p, "a", {value: 44})) + assertEquals("a", key) + assertEquals(1, Object.getOwnPropertyNames(desc).length) + assertEquals(44, desc.value) + + assertEquals(p, Object.defineProperty(p, "b", {value: 45, writable: false})) + assertEquals("b", key) + assertEquals(2, Object.getOwnPropertyNames(desc).length) + assertEquals(45, desc.value) + assertEquals(false, desc.writable) + + assertEquals(p, Object.defineProperty(p, "c", {value: 46, enumerable: false})) + assertEquals("c", key) + assertEquals(2, Object.getOwnPropertyNames(desc).length) + assertEquals(46, desc.value) + assertEquals(false, desc.enumerable) + + assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false})) + assertEquals("101", key) + assertEquals(2, Object.getOwnPropertyNames(desc).length) + assertEquals(47, desc.value) + assertEquals(false, desc.enumerable) + + var attributes = {configurable: true, mine: 66, minetoo: 23} + assertEquals(p, Object.defineProperty(p, "d", attributes)) + assertEquals("d", key); + // Modifying the attributes object after the fact should have no effect. + attributes.configurable = false + attributes.mine = 77 + delete attributes.minetoo; + assertEquals(1, Object.getOwnPropertyNames(desc).length) + assertEquals(true, desc.configurable) + assertEquals(undefined, desc.mine) + assertEquals(undefined, desc.minetoo) + + assertEquals(p, Object.defineProperty(p, "e", {get: function(){ return 5 }})) + assertEquals("e", key) + assertEquals(1, Object.getOwnPropertyNames(desc).length) + assertEquals(5, desc.get()) + + assertEquals(p, Object.defineProperty(p, "zzz", {})) + assertEquals("zzz", key) + assertEquals(0, Object.getOwnPropertyNames(desc).length) + + var props = { + '11': {}, + blub: {get: function() { return true }}, + '': {get value() { return 20 }}, + last: {value: 21, configurable: true, mine: "eyes"} + } + Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false}) + assertEquals(p, Object.defineProperties(p, props)) + assertEquals("last", key) + assertEquals(2, Object.getOwnPropertyNames(desc).length) + assertEquals(21, desc.value) + assertEquals(true, desc.configurable) + assertEquals(undefined, desc.mine) // Arguably a bug in the spec... + + var props = {bla: {get value() { throw "myexn" }}} + assertThrowsEquals(function(){ Object.defineProperties(p, props) }, "myexn") +} + +TestDefine({ + defineProperty(t, k, d) { key = k; desc = d; return true } +}) + +TestDefine({ + defineProperty(t, k, d) { return this.defineProperty2(k, d) }, + defineProperty2(k, d) { key = k; desc = d; return true } +}) + + +// --------------------------------------------------------------------------- +function TestDefineThrow(handler) { + TestWithProxies(TestDefineThrow2, handler) +} + +function TestDefineThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(() => Object.defineProperty(p, "a", {value: 44}), "myexn") + assertThrowsEquals(() => Object.defineProperty(p, 0, {value: 44}), "myexn") + + var d1 = create({ + get: function(r, k) { throw "myexn" }, + getOwnPropertyNames: function() { return ["value"] } + }) + assertThrowsEquals(function(){ Object.defineProperty(p, "p", d1) }, "myexn") + var d2 = create({ + get: function(r, k) { return 77 }, + getOwnPropertyNames: function() { throw "myexn" } + }) + assertThrowsEquals(function(){ Object.defineProperty(p, "p", d2) }, "myexn") + + var props = {bla: {get value() { throw "otherexn" }}} + assertThrowsEquals(() => Object.defineProperties(p, props), "otherexn") +} + +TestDefineThrow({ + defineProperty: function(k, d) { throw "myexn" } +}) + +TestDefineThrow({ + defineProperty: function(k, d) { return this.defineProperty2(k, d) }, + defineProperty2: function(k, d) { throw "myexn" } +}) + +TestDefineThrow(new Proxy({}, { + get: function(pr, pk) { throw "myexn" } +})) + +TestDefineThrow(new Proxy({}, { + get: function(pr, pk) { + return function(k, d) { throw "myexn" } + } +})) + + + +// --------------------------------------------------------------------------- +// Property deletion (delete). + +var key + +function TestDelete(handler) { + TestWithProxies(TestDelete2, handler) +} + +function TestDelete2(create, handler) { + var p = create(handler) + assertEquals(true, delete p.a) + assertEquals("a", key) + assertEquals(true, delete p["b"]) + assertEquals("b", key) + assertEquals(true, delete p[1]) + assertEquals("1", key) + + assertEquals(false, delete p.z1) + assertEquals("z1", key) + assertEquals(false, delete p["z2"]) + assertEquals("z2", key); + + (function() { + "use strict" + assertEquals(true, delete p.c) + assertEquals("c", key) + assertEquals(true, delete p["d"]) + assertEquals("d", key) + assertEquals(true, delete p[2]) + assertEquals("2", key) + + assertThrows(function(){ delete p.z3 }, TypeError) + assertEquals("z3", key) + assertThrows(function(){ delete p["z4"] }, TypeError) + assertEquals("z4", key) + })() +} + +TestDelete({ + deleteProperty(target, k) { key = k; return k < "z" } +}) + +TestDelete({ + deleteProperty(target, k) { return this.delete2(k) }, + delete2: function(k) { key = k; return k < "z" } +}) + +TestDelete(new Proxy({}, { + get(pt, pk, pr) { + return (target, k) => { key = k; return k < "z" } + } +})) + + +// --------------------------------------------------------------------------- +function TestDeleteThrow(handler) { + TestWithProxies(TestDeleteThrow2, handler) +} + +function TestDeleteThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(function(){ delete p.a }, "myexn") + assertThrowsEquals(function(){ delete p["b"] }, "myexn"); + assertThrowsEquals(function(){ delete p[3] }, "myexn"); + + (function() { + "use strict" + assertThrowsEquals(function(){ delete p.c }, "myexn") + assertThrowsEquals(function(){ delete p["d"] }, "myexn") + assertThrowsEquals(function(){ delete p[4] }, "myexn"); + })() +} + +TestDeleteThrow({ + deleteProperty(t, k) { throw "myexn" } +}) + +TestDeleteThrow({ + deleteProperty(t, k) { return this.delete2(k) }, + delete2(k) { throw "myexn" } +}) + +TestDeleteThrow(new Proxy({}, { + get(pt, pk, pr) { throw "myexn" } +})) + +TestDeleteThrow(new Proxy({}, { + get(pt, pk, pr) { + return (k) => { throw "myexn" } + } +})) + + +// --------------------------------------------------------------------------- +// Property descriptors (Object.getOwnPropertyDescriptor). + +function TestDescriptor(handler) { + TestWithProxies(TestDescriptor2, handler) +} + +function TestDescriptor2(create, handler) { + var p = create(handler) + var descs = [ + {configurable: true}, + {value: 34, enumerable: true, configurable: true}, + {value: 3, writable: false, mine: "eyes", configurable: true}, + {get value() { return 20 }, get configurable() { return true }}, + {get: function() { "get" }, set: function() { "set" }, configurable: true} + ] + for (var i = 0; i < descs.length; ++i) { + assertEquals(p, Object.defineProperty(p, i, descs[i])) + var desc = Object.getOwnPropertyDescriptor(p, i) + for (prop in descs[i]) { + // TODO(rossberg): Ignore user attributes as long as the spec isn't + // fixed suitably. + if (prop != "mine") assertEquals(descs[i][prop], desc[prop]) + } + assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent")) + } +} + +TestDescriptor({ + defineProperty(t, k, d) { this["__" + k] = d; return true }, + getOwnPropertyDescriptor(t, k) { return this["__" + k] } +}) + +TestDescriptor({ + defineProperty(t, k, d) { this["__" + k] = d; return true }, + getOwnPropertyDescriptor(t, k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { return this["__" + k] } +}) + + +// --------------------------------------------------------------------------- +function TestDescriptorThrow(handler) { + TestWithProxies(TestDescriptorThrow2, handler) +} + +function TestDescriptorThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn") +} + +TestDescriptorThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" } +}) + +TestDescriptorThrow({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { throw "myexn" } +}) + + + +// --------------------------------------------------------------------------- +// Comparison. + +function TestComparison(eq) { + TestWithProxies(TestComparison2, eq) +} + +function TestComparison2(create, eq) { + var p1 = create({}) + var p2 = create({}) + + assertTrue(eq(p1, p1)) + assertTrue(eq(p2, p2)) + assertTrue(!eq(p1, p2)) + assertTrue(!eq(p1, {})) + assertTrue(!eq({}, p2)) + assertTrue(!eq({}, {})) +} + +TestComparison(function(o1, o2) { return o1 == o2 }) +TestComparison(function(o1, o2) { return o1 === o2 }) +TestComparison(function(o1, o2) { return !(o1 != o2) }) +TestComparison(function(o1, o2) { return !(o1 !== o2) }) + + + +// Type (typeof). + +function TestTypeof() { + assertEquals("object", typeof new Proxy({},{})) + assertTrue(typeof new Proxy({}, {}) == "object") + assertTrue("object" == typeof new Proxy({},{})) + + assertEquals("function", typeof new Proxy(function() {}, {})) + assertTrue(typeof new Proxy(function() {}, {}) == "function") + assertTrue("function" == typeof new Proxy(function() {},{})) +} + +TestTypeof() + + + +// --------------------------------------------------------------------------- +// Membership test (in). + +var key + +function TestIn(handler) { + TestWithProxies(TestIn2, handler) +} + +function TestIn2(create, handler) { + var p = create(handler) + assertTrue("a" in p) + assertEquals("a", key) + assertTrue(99 in p) + assertEquals("99", key) + assertFalse("z" in p) + assertEquals("z", key) + + assertEquals(2, ("a" in p) ? 2 : 0) + assertEquals(0, !("a" in p) ? 2 : 0) + assertEquals(0, ("zzz" in p) ? 2 : 0) + assertEquals(2, !("zzz" in p) ? 2 : 0) + + // Test compilation in conditionals. + if ("b" in p) { + } else { + assertTrue(false) + } + assertEquals("b", key) + + if ("zz" in p) { + assertTrue(false) + } + assertEquals("zz", key) + + if (!("c" in p)) { + assertTrue(false) + } + assertEquals("c", key) + + if (!("zzz" in p)) { + } else { + assertTrue(false) + } + assertEquals("zzz", key) +} + +TestIn({ + has(t, k) { key = k; return k < "z" } +}) + +TestIn({ + has(t, k) { return this.has2(k) }, + has2(k) { key = k; return k < "z" } +}) + +TestIn(new Proxy({},{ + get(pt, pk, pr) { + return (t, k) => { key = k; return k < "z" } + } +})) + + +// --------------------------------------------------------------------------- +function TestInThrow(handler) { + TestWithProxies(TestInThrow2, handler) +} + +function TestInThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(function(){ return "a" in p }, "myexn") + assertThrowsEquals(function(){ return 99 in p }, "myexn") + assertThrowsEquals(function(){ return !("a" in p) }, "myexn") + assertThrowsEquals(function(){ return ("a" in p) ? 2 : 3 }, "myexn") + assertThrowsEquals(function(){ if ("b" in p) {} }, "myexn") + assertThrowsEquals(function(){ if (!("b" in p)) {} }, "myexn") + assertThrowsEquals(function(){ if ("zzz" in p) {} }, "myexn") +} + +TestInThrow({ + has: function(k) { throw "myexn" } +}) + +TestInThrow({ + has: function(k) { return this.has2(k) }, + has2: function(k) { throw "myexn" } +}) + +TestInThrow(new Proxy({},{ + get: function(pr, pk) { throw "myexn" } +})) + +TestInThrow(new Proxy({},{ + get: function(pr, pk) { + return function(k) { throw "myexn" } + } +})) + + + +// --------------------------------------------------------------------------- +// Own Properties (Object.prototype.hasOwnProperty). + +var key + +function TestHasOwn(handler) { + TestWithProxies(TestHasOwn2, handler) +} + +function TestHasOwn2(create, handler) { + var p = create(handler) + assertTrue(Object.prototype.hasOwnProperty.call(p, "a")) + assertEquals("a", key) + assertTrue(Object.prototype.hasOwnProperty.call(p, 99)) + assertEquals("99", key) + assertFalse(Object.prototype.hasOwnProperty.call(p, "z")) + assertEquals("z", key) +} + +TestHasOwn({ + getOwnPropertyDescriptor(t, k) { + key = k; if (k < "z") return {configurable: true} + }, + has() { assertUnreachable() } +}) + +TestHasOwn({ + getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) }, + getOwnPropertyDescriptor2(k) { + key = k; if (k < "z") return {configurable: true} + } +}) + + + +// --------------------------------------------------------------------------- +function TestHasOwnThrow(handler) { + TestWithProxies(TestHasOwnThrow2, handler) +} + +function TestHasOwnThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, "a")}, + "myexn") + assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, 99)}, + "myexn") +} + +TestHasOwnThrow({ + getOwnPropertyDescriptor(t, k) { throw "myexn" } +}) + +TestHasOwnThrow({ + getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) }, + getOwnPropertyDescriptor2(k) { throw "myexn" } +}); + + +// --------------------------------------------------------------------------- +// Instanceof (instanceof) + +(function TestProxyInstanceof() { + var o1 = {} + var p1 = new Proxy({}, {}) + var p2 = new Proxy(o1, {}) + var p3 = new Proxy(p2, {}) + var o2 = Object.create(p2) + + var f0 = function() {} + f0.prototype = o1 + var f1 = function() {} + f1.prototype = p1 + var f2 = function() {} + f2.prototype = p2 + var f3 = function() {} + f3.prototype = o2 + + assertTrue(o1 instanceof Object) + assertFalse(o1 instanceof f0) + assertFalse(o1 instanceof f1) + assertFalse(o1 instanceof f2) + assertFalse(o1 instanceof f3) + assertTrue(p1 instanceof Object) + assertFalse(p1 instanceof f0) + assertFalse(p1 instanceof f1) + assertFalse(p1 instanceof f2) + assertFalse(p1 instanceof f3) + assertTrue(p2 instanceof Object) + assertFalse(p2 instanceof f0) + assertFalse(p2 instanceof f1) + assertFalse(p2 instanceof f2) + assertFalse(p2 instanceof f3) + assertTrue(p3 instanceof Object) + assertFalse(p3 instanceof f0) + assertFalse(p3 instanceof f1) + assertFalse(p3 instanceof f2) + assertFalse(p3 instanceof f3) + assertTrue(o2 instanceof Object) + assertFalse(o2 instanceof f0) + assertFalse(o2 instanceof f1) + assertTrue(o2 instanceof f2) + assertFalse(o2 instanceof f3) + + var f = new Proxy(function() {}, {}) + assertTrue(f instanceof Function) +})(); + + +(function TestInstanceofProxy() { + var o0 = Object.create(null) + var o1 = {} + var o2 = Object.create(o0) + var o3 = Object.create(o1) + var o4 = Object.create(o2) + var o5 = Object.create(o3) + + function handler(o) { + return { + get: function(r, p) { + // We want to test prototype lookup, so ensure the proxy + // offers OrdinaryHasInstance behavior. + if (p === Symbol.hasInstance) { + return undefined; + } + return o; + } + } + } + + var f0 = new Proxy(function() {}, handler(o0)) + var f1 = new Proxy(function() {}, handler(o1)) + var f2 = new Proxy(function() {}, handler(o2)) + var f3 = new Proxy(function() {}, handler(o3)) + var f4 = new Proxy(function() {}, handler(o4)) + var f5 = new Proxy(function() {}, handler(o4)) + + assertFalse(null instanceof f0) + assertFalse(o0 instanceof f0) + assertFalse(o0 instanceof f1) + assertFalse(o0 instanceof f2) + assertFalse(o0 instanceof f3) + assertFalse(o0 instanceof f4) + assertFalse(o0 instanceof f5) + assertFalse(o1 instanceof f0) + assertFalse(o1 instanceof f1) + assertFalse(o1 instanceof f2) + assertFalse(o1 instanceof f3) + assertFalse(o1 instanceof f4) + assertFalse(o1 instanceof f5) + assertTrue(o2 instanceof f0) + assertFalse(o2 instanceof f1) + assertFalse(o2 instanceof f2) + assertFalse(o2 instanceof f3) + assertFalse(o2 instanceof f4) + assertFalse(o2 instanceof f5) + assertFalse(o3 instanceof f0) + assertTrue(o3 instanceof f1) + assertFalse(o3 instanceof f2) + assertFalse(o3 instanceof f3) + assertFalse(o3 instanceof f4) + assertFalse(o3 instanceof f5) + assertTrue(o4 instanceof f0) + assertFalse(o4 instanceof f1) + assertTrue(o4 instanceof f2) + assertFalse(o4 instanceof f3) + assertFalse(o4 instanceof f4) + assertFalse(o4 instanceof f5) + assertFalse(o5 instanceof f0) + assertTrue(o5 instanceof f1) + assertFalse(o5 instanceof f2) + assertTrue(o5 instanceof f3) + assertFalse(o5 instanceof f4) + assertFalse(o5 instanceof f5) + + var f = new Proxy(function() {}, {}) + var ff = new Proxy(function() {}, handler(Function)) + assertTrue(f instanceof Function) + assertFalse(f instanceof ff) +})(); + + +// --------------------------------------------------------------------------- +// Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). + +(function TestPrototype() { + var o1 = {} + var p1 = new Proxy({}, {}) + var p2 = new Proxy(o1, {}) + var p3 = new Proxy(p2, {}) + var o2 = Object.create(p3) + + assertSame(Object.getPrototypeOf(o1), Object.prototype) + assertSame(Object.getPrototypeOf(p1), Object.prototype) + assertSame(Object.getPrototypeOf(p2), Object.prototype) + assertSame(Object.getPrototypeOf(p3), Object.prototype) + assertSame(Object.getPrototypeOf(o2), p3) + + assertTrue(Object.prototype.isPrototypeOf(o1)) + assertTrue(Object.prototype.isPrototypeOf(p1)) + assertTrue(Object.prototype.isPrototypeOf(p2)) + assertTrue(Object.prototype.isPrototypeOf(p3)) + assertTrue(Object.prototype.isPrototypeOf(o2)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p1)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, o1)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, p1)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, p2)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, p3)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, p1)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, o1)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, p2)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, p3)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(p2, p1)) + assertFalse(Object.prototype.isPrototypeOf.call(p2, p2)) + assertFalse(Object.prototype.isPrototypeOf.call(p2, p3)) + assertFalse(Object.prototype.isPrototypeOf.call(p2, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(p3, p2)) + assertTrue(Object.prototype.isPrototypeOf.call(p3, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, o1)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p1)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p2)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p3)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, o2)) + + var f = new Proxy(function() {}, {}) + assertSame(Object.getPrototypeOf(f), Function.prototype) + assertTrue(Object.prototype.isPrototypeOf(f)) + assertTrue(Object.prototype.isPrototypeOf.call(Function.prototype, f)) +})(); + + +// --------------------------------------------------------------------------- +function TestPropertyNamesThrow(handler) { + TestWithProxies(TestPropertyNamesThrow2, handler) +} + +function TestPropertyNamesThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(function(){ Object.getOwnPropertyNames(p) }, "myexn") +} + +TestPropertyNamesThrow({ + ownKeys() { throw "myexn" } +}) + +TestPropertyNamesThrow({ + ownKeys() { return this.getOwnPropertyNames2() }, + getOwnPropertyNames2() { throw "myexn" } +}) + +// --------------------------------------------------------------------------- + +function TestKeys(names, handler) { + var p = new Proxy({}, handler); + assertArrayEquals(names, Object.keys(p)) +} + +TestKeys([], { + ownKeys() { return [] } +}) + +TestKeys([], { + ownKeys() { return ["a", "zz", " ", "0", "toString"] } +}) + +TestKeys(["a", "zz", " ", "0", "toString"], { + ownKeys() { return ["a", "zz", " ", "0", "toString"] }, + getOwnPropertyDescriptor(t, p) { + return {configurable: true, enumerable: true} + } +}) + +TestKeys([], { + ownKeys() { return this.keys2() }, + keys2() { return ["throw", "function "] } +}) + +TestKeys(["throw", "function "], { + ownKeys() { return this.keys2() }, + keys2() { return ["throw", "function "] }, + getOwnPropertyDescriptor(t, p) { + return {configurable: true, enumerable: true} + } +}) + +TestKeys(["a", "0"], { + ownKeys() { return ["a", "23", "zz", "", "0"] }, + getOwnPropertyDescriptor(t, k) { + return k == "" ? + undefined : + { configurable: true, enumerable: k.length == 1} + } +}) + +TestKeys(["23", "zz", ""], { + ownKeys() { return this.getOwnPropertyNames2() }, + getOwnPropertyNames2() { return ["a", "23", "zz", "", "0"] }, + getOwnPropertyDescriptor(t, k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2(k) { + return {configurable: true, enumerable: k.length != 1 } + } +}) + +TestKeys([], { + get ownKeys() { + return function() { return ["a", "b", "c"] } + }, + getOwnPropertyDescriptor: function(k) { return {configurable: true} } +}) + + +// --------------------------------------------------------------------------- +function TestKeysThrow(handler) { + TestWithProxies(TestKeysThrow2, handler) +} + +function TestKeysThrow2(create, handler) { + var p = create(handler); + assertThrowsEquals(function(){ Object.keys(p) }, "myexn"); +} + +TestKeysThrow({ + ownKeys() { throw "myexn" } +}) + +TestKeysThrow({ + ownKeys() { return this.keys2() }, + keys2() { throw "myexn" } +}) + +TestKeysThrow({ + ownKeys() { return ['1'] }, + getOwnPropertyDescriptor: function() { throw "myexn" }, +}) + +TestKeysThrow({ + ownKeys() { return this.getOwnPropertyNames2() }, + getOwnPropertyNames2() { return ['1', '2'] }, + getOwnPropertyDescriptor(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2(k) { throw "myexn" } +}) + +TestKeysThrow({ + get ownKeys() { throw "myexn" } +}) + +TestKeysThrow({ + get ownKeys() { + return function() { throw "myexn" } + }, +}) + +TestKeysThrow({ + get ownKeys() { + return function() { return ['1', '2'] } + }, + getOwnPropertyDescriptor(k) { throw "myexn" } +}) + + + +// --------------------------------------------------------------------------- +// String conversion (Object.prototype.toString, +// Object.prototype.toLocaleString, +// Function.prototype.toString) + +var key + +function TestToString(handler) { + var p = new Proxy({}, handler) + key = "" + assertEquals("[object Object]", Object.prototype.toString.call(p)) + assertEquals(Symbol.toStringTag, key) + assertEquals("my_proxy", Object.prototype.toLocaleString.call(p)) + assertEquals("toString", key) + + var f = new Proxy(function() {}, handler) + key = "" + assertEquals("[object Function]", Object.prototype.toString.call(f)) + assertEquals(Symbol.toStringTag, key) + assertEquals("my_proxy", Object.prototype.toLocaleString.call(f)) + assertEquals("toString", key) + assertThrows(function(){ Function.prototype.toString.call(f) }) + + var o = Object.create(p) + key = "" + assertEquals("[object Object]", Object.prototype.toString.call(o)) + assertEquals(Symbol.toStringTag, key) + assertEquals("my_proxy", Object.prototype.toLocaleString.call(o)) + assertEquals("toString", key) +} + +TestToString({ + get: function(r, k) { key = k; return function() { return "my_proxy" } } +}) + +TestToString({ + get: function(r, k) { return this.get2(r, k) }, + get2: function(r, k) { key = k; return function() { return "my_proxy" } } +}) + +TestToString(new Proxy({}, { + get: function(pr, pk) { + return function(r, k) { key = k; return function() { return "my_proxy" } } + } +})) + + +function TestToStringThrow(handler) { + var p = new Proxy({}, handler) + assertThrowsEquals(() => Object.prototype.toString.call(p), "myexn") + assertThrowsEquals(() => Object.prototype.toLocaleString.call(p), "myexn") + + var f = new Proxy(function(){}, handler) + assertThrowsEquals(() => Object.prototype.toString.call(f), "myexn") + assertThrowsEquals(() => Object.prototype.toLocaleString.call(f), "myexn") + + var o = Object.create(p) + assertThrowsEquals(() => Object.prototype.toString.call(o), "myexn") + assertThrowsEquals(() => Object.prototype.toLocaleString.call(o), "myexn") +} + +TestToStringThrow({ + get: function(r, k) { throw "myexn" } +}) + +TestToStringThrow({ + get: function(r, k) { return this.get2(r, k) }, + get2: function(r, k) { throw "myexn" } +}) + +TestToStringThrow(new Proxy({}, { + get: function(pr, pk) { throw "myexn" } +})) + +TestToStringThrow(new Proxy({}, { + get: function(pr, pk) { + return function(r, k) { throw "myexn" } + } +})) + + +// --------------------------------------------------------------------------- +// Value conversion (Object.prototype.toValue) + +function TestValueOf(handler) { + TestWithProxies(TestValueOf2, handler) +} + +function TestValueOf2(create, handler) { + var p = create(handler) + assertSame(p, Object.prototype.valueOf.call(p)) +} + +TestValueOf({}) + + + +// --------------------------------------------------------------------------- +// Enumerability (Object.prototype.propertyIsEnumerable) + +var key + +function TestIsEnumerable(handler) { + TestWithProxies(TestIsEnumerable2, handler) +} + +function TestIsEnumerable2(create, handler) { + var p = create(handler) + assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a")) + assertEquals("a", key) + assertTrue(Object.prototype.propertyIsEnumerable.call(p, 2)) + assertEquals("2", key) + assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z")) + assertEquals("z", key) + + var o = Object.create(p) + key = "" + assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a")) + assertEquals("", key) // trap not invoked +} + +TestIsEnumerable({ + getOwnPropertyDescriptor(t, k) { + key = k; + return {enumerable: k < "z", configurable: true} + }, +}) + +TestIsEnumerable({ + getOwnPropertyDescriptor: function(t, k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { + key = k; + return {enumerable: k < "z", configurable: true} + }, +}) + +TestIsEnumerable({ + getOwnPropertyDescriptor: function(t, k) { + key = k; + return {get enumerable() { return k < "z" }, configurable: true} + }, +}) + +TestIsEnumerable(new Proxy({}, { + get: function(pt, pk, pr) { + return function(t, k) { + key = k; + return {enumerable: k < "z", configurable: true} + } + } +})) + + +// --------------------------------------------------------------------------- +function TestIsEnumerableThrow(handler) { + TestWithProxies(TestIsEnumerableThrow2, handler) +} + +function TestIsEnumerableThrow2(create, handler) { + var p = create(handler) + assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, "a"), + "myexn") + assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, 11), + "myexn") +} + +TestIsEnumerableThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" } +}) + +TestIsEnumerableThrow({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { throw "myexn" } +}) + +TestIsEnumerableThrow({ + getOwnPropertyDescriptor: function(k) { + return {get enumerable() { throw "myexn" }, configurable: true} + }, +}) + +TestIsEnumerableThrow(new Proxy({}, { + get: function(pr, pk) { throw "myexn" } +})) + +TestIsEnumerableThrow(new Proxy({}, { + get: function(pr, pk) { + return function(k) { throw "myexn" } + } +})); + + + +// --------------------------------------------------------------------------- +// Constructor functions with proxy prototypes. + +(function TestConstructorWithProxyPrototype() { + TestWithProxies(TestConstructorWithProxyPrototype2, {}) +})(); + +function TestConstructorWithProxyPrototype2(create, handler) { + function C() {}; + C.prototype = create(handler); + + var o = new C; + assertSame(C.prototype, Object.getPrototypeOf(o)); +}; + + +(function TestOptWithProxyPrototype() { + var handler = { + get(t, k) { + return 10; + } + }; + + function C() {}; + C.prototype = new Proxy({}, handler); + var o = new C(); + + function f() { + return o.x; + } + assertEquals(10, f()); + assertEquals(10, f()); + %OptimizeFunctionOnNextCall(f); + assertEquals(10, f()); +})(); |