| Index: test/mjsunit/harmony/proxies.js
|
| ===================================================================
|
| --- test/mjsunit/harmony/proxies.js (revision 9531)
|
| +++ test/mjsunit/harmony/proxies.js (working copy)
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2008 the V8 project authors. All rights reserved.
|
| +// 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:
|
| @@ -28,9 +28,7 @@
|
| // Flags: --harmony-proxies
|
|
|
|
|
| -// TODO(rossberg): for-in for proxies not implemented.
|
| -// TODO(rossberg): inheritance from proxies not implemented.
|
| -// TODO(rossberg): function proxies as constructors not implemented.
|
| +// TODO(rossberg): for-in not implemented on proxies.
|
|
|
|
|
| // Helper.
|
| @@ -41,8 +39,93 @@
|
| }
|
|
|
|
|
| -// Getters.
|
|
|
| +// Getting property descriptors (Object.getOwnPropertyDescriptor).
|
| +
|
| +var key
|
| +
|
| +function TestGetOwnProperty(handler) {
|
| + TestWithProxies(TestGetOwnProperty2, handler)
|
| +}
|
| +
|
| +function TestGetOwnProperty2(handler, create) {
|
| + 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: function(k) {
|
| + key = k
|
| + return {value: 42, configurable: true}
|
| + }
|
| +})
|
| +
|
| +TestGetOwnProperty({
|
| + getOwnPropertyDescriptor: function(k) {
|
| + return this.getOwnPropertyDescriptor2(k)
|
| + },
|
| + getOwnPropertyDescriptor2: function(k) {
|
| + key = k
|
| + return {value: 42, configurable: true}
|
| + }
|
| +})
|
| +
|
| +TestGetOwnProperty({
|
| + getOwnPropertyDescriptor: function(k) {
|
| + key = k
|
| + return {get value() { return 42 }, get configurable() { return true }}
|
| + }
|
| +})
|
| +
|
| +TestGetOwnProperty(Proxy.create({
|
| + get: function(pr, pk) {
|
| + return function(k) { key = k; return {value: 42, configurable: true} }
|
| + }
|
| +}))
|
| +
|
| +
|
| +function TestGetOwnPropertyThrow(handler) {
|
| + TestWithProxies(TestGetOwnPropertyThrow2, handler)
|
| +}
|
| +
|
| +function TestGetOwnPropertyThrow2(handler, create) {
|
| + var p = create(handler)
|
| + assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn")
|
| + assertThrows(function(){ Object.getOwnPropertyDescriptor(p, 77) }, "myexn")
|
| +}
|
| +
|
| +TestGetOwnPropertyThrow({
|
| + getOwnPropertyDescriptor: function(k) { throw "myexn" }
|
| +})
|
| +
|
| +TestGetOwnPropertyThrow({
|
| + getOwnPropertyDescriptor: function(k) {
|
| + return this.getPropertyDescriptor2(k)
|
| + },
|
| + getOwnPropertyDescriptor2: function(k) { throw "myexn" }
|
| +})
|
| +
|
| +TestGetOwnPropertyThrow({
|
| + getOwnPropertyDescriptor: function(k) {
|
| + return {get value() { throw "myexn" }}
|
| + }
|
| +})
|
| +
|
| +TestGetOwnPropertyThrow(Proxy.create({
|
| + get: function(pr, pk) {
|
| + return function(k) { throw "myexn" }
|
| + }
|
| +}))
|
| +
|
| +
|
| +
|
| +// Getters (dot, brackets).
|
| +
|
| +var key
|
| +
|
| function TestGet(handler) {
|
| TestWithProxies(TestGet2, handler)
|
| }
|
| @@ -50,48 +133,56 @@
|
| function TestGet2(handler, create) {
|
| 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)
|
|
|
| - // TODO(rossberg): inheritance from proxies not yet implemented.
|
| - // var o = Object.create(p, {x: {value: 88}})
|
| - // assertEquals(42, o.a)
|
| - // assertEquals(42, o["b"])
|
| - // assertEquals(88, o.x)
|
| - // assertEquals(88, o["x"])
|
| + 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"])
|
| }
|
|
|
| TestGet({
|
| - get: function(r, k) { return 42 }
|
| + get: function(r, k) { key = k; return 42 }
|
| })
|
|
|
| TestGet({
|
| get: function(r, k) { return this.get2(r, k) },
|
| - get2: function(r, k) { return 42 }
|
| + get2: function(r, k) { key = k; return 42 }
|
| })
|
|
|
| TestGet({
|
| - getPropertyDescriptor: function(k) { return {value: 42} }
|
| + getPropertyDescriptor: function(k) { key = k; return {value: 42} }
|
| })
|
|
|
| TestGet({
|
| getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
|
| - getPropertyDescriptor2: function(k) { return {value: 42} }
|
| + getPropertyDescriptor2: function(k) { key = k; return {value: 42} }
|
| })
|
|
|
| TestGet({
|
| getPropertyDescriptor: function(k) {
|
| + key = k;
|
| return {get value() { return 42 }}
|
| }
|
| })
|
|
|
| TestGet({
|
| get: undefined,
|
| - getPropertyDescriptor: function(k) { return {value: 42} }
|
| + getPropertyDescriptor: function(k) { key = k; return {value: 42} }
|
| })
|
|
|
| TestGet(Proxy.create({
|
| get: function(pr, pk) {
|
| - return function(r, k) { return 42 }
|
| + return function(r, k) { key = k; return 42 }
|
| }
|
| }))
|
|
|
| @@ -103,11 +194,29 @@
|
| function TestGetCall2(handler, create) {
|
| 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("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("6655", "66" + o) // calls o.toString
|
| }
|
|
|
| TestGetCall({
|
| @@ -172,6 +281,15 @@
|
| var p = create(handler)
|
| assertThrows(function(){ p.a }, "myexn")
|
| assertThrows(function(){ p["b"] }, "myexn")
|
| + assertThrows(function(){ p[3] }, "myexn")
|
| +
|
| + var o = Object.create(p, {x: {value: 88}, '4': {value: 89}})
|
| + assertThrows(function(){ o.a }, "myexn")
|
| + assertThrows(function(){ o["b"] }, "myexn")
|
| + assertThrows(function(){ o[3] }, "myexn")
|
| + assertEquals(88, o.x)
|
| + assertEquals(88, o["x"])
|
| + assertEquals(89, o[4])
|
| }
|
|
|
| TestGetThrow({
|
| @@ -232,6 +350,9 @@
|
| assertEquals(43, p["b"] = 43)
|
| assertEquals("b", key)
|
| assertEquals(43, val)
|
| + assertEquals(44, p[77] = 44)
|
| + assertEquals("77", key)
|
| + assertEquals(44, val)
|
| }
|
|
|
| TestSet({
|
| @@ -304,7 +425,6 @@
|
| }))
|
|
|
|
|
| -
|
| function TestSetThrow(handler, create) {
|
| TestWithProxies(TestSetThrow2, handler)
|
| }
|
| @@ -313,6 +433,7 @@
|
| var p = create(handler)
|
| assertThrows(function(){ p.a = 42 }, "myexn")
|
| assertThrows(function(){ p["b"] = 42 }, "myexn")
|
| + assertThrows(function(){ p[22] = 42 }, "myexn")
|
| }
|
|
|
| TestSetThrow({
|
| @@ -424,7 +545,91 @@
|
| }))
|
|
|
|
|
| +var key
|
| +var val
|
|
|
| +function TestSetForDerived(handler, create) {
|
| + TestWithProxies(TestSetForDerived2, handler)
|
| +}
|
| +
|
| +function TestSetForDerived2(handler, create) {
|
| + var p = create(handler)
|
| + var o = Object.create(p, {x: {value: 88, writable: true},
|
| + '1': {value: 89, writable: true}})
|
| +
|
| + key = ""
|
| + assertEquals(48, o.x = 48)
|
| + assertEquals("", key) // trap not invoked
|
| + assertEquals(48, o.x)
|
| +
|
| + assertEquals(47, o[1] = 47)
|
| + assertEquals("", key) // trap not invoked
|
| + assertEquals(47, o[1])
|
| +
|
| + assertEquals(49, o.y = 49)
|
| + assertEquals("y", key)
|
| + assertEquals(49, o.y)
|
| +
|
| + assertEquals(50, o[2] = 50)
|
| + assertEquals("2", key)
|
| + assertEquals(50, o[2])
|
| +
|
| + assertEquals(44, o.p_writable = 44)
|
| + assertEquals("p_writable", key)
|
| + assertEquals(44, o.p_writable)
|
| +
|
| + assertEquals(45, o.p_nonwritable = 45)
|
| + assertEquals("p_nonwritable", key)
|
| + assertEquals(45, o.p_nonwritable)
|
| +
|
| + assertEquals(46, o.p_setter = 46)
|
| + assertEquals("p_setter", key)
|
| + assertEquals(46, val) // written to parent
|
| + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setter"))
|
| +
|
| + val = ""
|
| + assertEquals(47, o.p_nosetter = 47)
|
| + assertEquals("p_nosetter", key)
|
| + assertEquals("", val) // not written at all
|
| + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nosetter"));
|
| +
|
| + key = ""
|
| + assertThrows(function(){ "use strict"; o.p_nosetter = 50 }, TypeError)
|
| + assertEquals("p_nosetter", key)
|
| + assertEquals("", val) // not written at all
|
| +
|
| + assertThrows(function(){ o.p_nonconf = 53 }, TypeError)
|
| + assertEquals("p_nonconf", key)
|
| +
|
| + assertThrows(function(){ o.p_throw = 51 }, "myexn")
|
| + assertEquals("p_throw", key)
|
| +
|
| + assertThrows(function(){ o.p_setterthrow = 52 }, "myexn")
|
| + assertEquals("p_setterthrow", key)
|
| +}
|
| +
|
| +TestSetForDerived({
|
| + getOwnPropertyDescriptor: function(k) {
|
| + key = k;
|
| + switch (k) {
|
| + case "p_writable": return {writable: true, configurable: true}
|
| + case "p_nonwritable": return {writable: false, configurable: true}
|
| + case "p_setter":return {set: function(x) { val = x }, configurable: true}
|
| + case "p_nosetter": return {get: function() { return 1 }, configurable: true}
|
| + case "p_nonconf":return {}
|
| + case "p_throw": throw "myexn"
|
| + case "p_setterthrow": return {set: function(x) { throw "myexn" }}
|
| + default: return undefined
|
| + }
|
| + }
|
| +})
|
| +
|
| +
|
| +// TODO(rossberg): TestSetReject, returning false
|
| +// TODO(rossberg): TestGetProperty, TestSetProperty
|
| +
|
| +
|
| +
|
| // Property definition (Object.defineProperty and Object.defineProperties).
|
|
|
| var key
|
| @@ -453,6 +658,12 @@
|
| 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)
|
| @@ -487,7 +698,7 @@
|
| // assertEquals(77, desc.value)
|
|
|
| var props = {
|
| - 'bla': {},
|
| + '11': {},
|
| blub: {get: function() { return true }},
|
| '': {get value() { return 20 }},
|
| last: {value: 21, configurable: true, mine: "eyes"}
|
| @@ -527,6 +738,7 @@
|
| function TestDefineThrow2(handler, create) {
|
| var p = create(handler)
|
| assertThrows(function(){ Object.defineProperty(p, "a", {value: 44})}, "myexn")
|
| + assertThrows(function(){ Object.defineProperty(p, 0, {value: 44})}, "myexn")
|
|
|
| // TODO(rossberg): These tests require for-in on proxies.
|
| // var d1 = create({
|
| @@ -579,6 +791,8 @@
|
| 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)
|
| @@ -591,6 +805,8 @@
|
| 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)
|
| @@ -623,11 +839,13 @@
|
| var p = create(handler)
|
| assertThrows(function(){ delete p.a }, "myexn")
|
| assertThrows(function(){ delete p["b"] }, "myexn");
|
| + assertThrows(function(){ delete p[3] }, "myexn");
|
|
|
| (function() {
|
| "use strict"
|
| assertThrows(function(){ delete p.c }, "myexn")
|
| assertThrows(function(){ delete p["d"] }, "myexn")
|
| + assertThrows(function(){ delete p[4] }, "myexn");
|
| })()
|
| }
|
|
|
| @@ -778,6 +996,7 @@
|
| 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)
|
| @@ -830,7 +1049,7 @@
|
| })
|
|
|
| TestIn({
|
| - get: undefined,
|
| + has: undefined,
|
| getPropertyDescriptor: function(k) {
|
| key = k; return k < "z" ? {value: 42} : void 0
|
| }
|
| @@ -850,6 +1069,7 @@
|
| function TestInThrow2(handler, create) {
|
| var p = create(handler)
|
| assertThrows(function(){ return "a" in o }, "myexn")
|
| + assertThrows(function(){ return 99 in o }, "myexn")
|
| assertThrows(function(){ return !("a" in o) }, "myexn")
|
| assertThrows(function(){ return ("a" in o) ? 2 : 3 }, "myexn")
|
| assertThrows(function(){ if ("b" in o) {} }, "myexn")
|
| @@ -876,7 +1096,7 @@
|
| })
|
|
|
| TestInThrow({
|
| - get: undefined,
|
| + has: undefined,
|
| getPropertyDescriptor: function(k) { throw "myexn" }
|
| })
|
|
|
| @@ -891,7 +1111,159 @@
|
| }))
|
|
|
|
|
| +function TestInForDerived(handler) {
|
| + TestWithProxies(TestInForDerived2, handler)
|
| +}
|
|
|
| +function TestInForDerived2(handler, create) {
|
| + var p = create(handler)
|
| + var o = Object.create(p)
|
| +
|
| + assertTrue("a" in o)
|
| + assertEquals("a", key)
|
| + assertTrue(99 in o)
|
| + assertEquals("99", key)
|
| + assertFalse("z" in o)
|
| + assertEquals("z", key)
|
| +
|
| + assertEquals(2, ("a" in o) ? 2 : 0)
|
| + assertEquals(0, !("a" in o) ? 2 : 0)
|
| + assertEquals(0, ("zzz" in o) ? 2 : 0)
|
| + assertEquals(2, !("zzz" in o) ? 2 : 0)
|
| +
|
| + if ("b" in o) {
|
| + } else {
|
| + assertTrue(false)
|
| + }
|
| + assertEquals("b", key)
|
| +
|
| + if ("zz" in o) {
|
| + assertTrue(false)
|
| + }
|
| + assertEquals("zz", key)
|
| +
|
| + if (!("c" in o)) {
|
| + assertTrue(false)
|
| + }
|
| + assertEquals("c", key)
|
| +
|
| + if (!("zzz" in o)) {
|
| + } else {
|
| + assertTrue(false)
|
| + }
|
| + assertEquals("zzz", key)
|
| +}
|
| +
|
| +TestInForDerived({
|
| + getPropertyDescriptor: function(k) {
|
| + key = k; return k < "z" ? {value: 42, configurable: true} : void 0
|
| + }
|
| +})
|
| +
|
| +TestInForDerived({
|
| + getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
|
| + getPropertyDescriptor2: function(k) {
|
| + key = k; return k < "z" ? {value: 42, configurable: true} : void 0
|
| + }
|
| +})
|
| +
|
| +TestInForDerived({
|
| + getPropertyDescriptor: function(k) {
|
| + key = k;
|
| + return k < "z" ? {get value() { return 42 }, configurable: true} : void 0
|
| + }
|
| +})
|
| +
|
| +/* TODO(rossberg): this will work once we implement the newest proposal
|
| + * regarding default traps for getPropertyDescriptor.
|
| +TestInForDerived({
|
| + getOwnPropertyDescriptor: function(k) {
|
| + key = k; return k < "z" ? {value: 42, configurable: true} : void 0
|
| + }
|
| +})
|
| +
|
| +TestInForDerived({
|
| + getOwnPropertyDescriptor: function(k) {
|
| + return this.getOwnPropertyDescriptor2(k)
|
| + },
|
| + getOwnPropertyDescriptor2: function(k) {
|
| + key = k; return k < "z" ? {value: 42, configurable: true} : void 0
|
| + }
|
| +})
|
| +
|
| +TestInForDerived({
|
| + getOwnPropertyDescriptor: function(k) {
|
| + key = k;
|
| + return k < "z" ? {get value() { return 42 }, configurable: true} : void 0
|
| + }
|
| +})
|
| +*/
|
| +
|
| +TestInForDerived(Proxy.create({
|
| + get: function(pr, pk) {
|
| + return function(k) {
|
| + key = k; return k < "z" ? {value: 42, configurable: true} : void 0
|
| + }
|
| + }
|
| +}))
|
| +
|
| +
|
| +
|
| +// Property descriptor conversion.
|
| +
|
| +var descget
|
| +
|
| +function TestDescriptorGetOrder(handler) {
|
| + var p = Proxy.create(handler)
|
| + var o = Object.create(p, {b: {value: 0}})
|
| + TestDescriptorGetOrder2(function(n) { return p[n] }, "vV")
|
| + TestDescriptorGetOrder2(function(n) { return n in p }, "")
|
| + TestDescriptorGetOrder2(function(n) { return o[n] }, "vV")
|
| + TestDescriptorGetOrder2(function(n) { return n in o }, "eEcCvVwWgs")
|
| +}
|
| +
|
| +function TestDescriptorGetOrder2(f, access) {
|
| + descget = ""
|
| + assertTrue(f("a"))
|
| + assertEquals(access, descget)
|
| + descget = ""
|
| + assertTrue(f(99))
|
| + assertEquals(access, descget)
|
| + descget = ""
|
| + assertFalse(!!f("z"))
|
| + assertEquals("", descget)
|
| +}
|
| +
|
| +TestDescriptorGetOrder({
|
| + getPropertyDescriptor: function(k) {
|
| + if (k >= "z") return void 0
|
| + // Return a proxy as property descriptor, so that we can log accesses.
|
| + return Proxy.create({
|
| + get: function(r, attr) {
|
| + descget += attr[0].toUpperCase()
|
| + return true
|
| + },
|
| + has: function(attr) {
|
| + descget += attr[0]
|
| + switch (attr) {
|
| + case "writable":
|
| + case "enumerable":
|
| + case "configurable":
|
| + case "value":
|
| + return true
|
| + case "get":
|
| + case "set":
|
| + return false
|
| + default:
|
| + assertUnreachable()
|
| + }
|
| + }
|
| + })
|
| + }
|
| +})
|
| +
|
| +
|
| +
|
| // Own Properties (Object.prototype.hasOwnProperty).
|
|
|
| var key
|
| @@ -1006,34 +1378,46 @@
|
| // Instanceof (instanceof)
|
|
|
| function TestInstanceof() {
|
| - var o = {}
|
| + var o1 = {}
|
| var p1 = Proxy.create({})
|
| - var p2 = Proxy.create({}, o)
|
| + var p2 = Proxy.create({}, o1)
|
| var p3 = Proxy.create({}, p2)
|
| + var o2 = Object.create(p2)
|
|
|
| var f0 = function() {}
|
| - f0.prototype = o
|
| + f0.prototype = o1
|
| var f1 = function() {}
|
| f1.prototype = p1
|
| var f2 = function() {}
|
| f2.prototype = p2
|
| + var f3 = function() {}
|
| + f3.prototype = o2
|
|
|
| - assertTrue(o instanceof Object)
|
| - assertFalse(o instanceof f0)
|
| - assertFalse(o instanceof f1)
|
| - assertFalse(o instanceof f2)
|
| + assertTrue(o1 instanceof Object)
|
| + assertFalse(o1 instanceof f0)
|
| + assertFalse(o1 instanceof f1)
|
| + assertFalse(o1 instanceof f2)
|
| + assertFalse(o1 instanceof f3)
|
| assertFalse(p1 instanceof Object)
|
| assertFalse(p1 instanceof f0)
|
| assertFalse(p1 instanceof f1)
|
| assertFalse(p1 instanceof f2)
|
| + assertFalse(p1 instanceof f3)
|
| assertTrue(p2 instanceof Object)
|
| assertTrue(p2 instanceof f0)
|
| assertFalse(p2 instanceof f1)
|
| assertFalse(p2 instanceof f2)
|
| + assertFalse(p2 instanceof f3)
|
| assertTrue(p3 instanceof Object)
|
| assertTrue(p3 instanceof f0)
|
| assertFalse(p3 instanceof f1)
|
| assertTrue(p3 instanceof f2)
|
| + assertFalse(p3 instanceof f3)
|
| + assertTrue(o2 instanceof Object)
|
| + assertTrue(o2 instanceof f0)
|
| + assertFalse(o2 instanceof f1)
|
| + assertTrue(o2 instanceof f2)
|
| + assertFalse(o2 instanceof f3)
|
|
|
| var f = Proxy.createFunction({}, function() {})
|
| assertTrue(f instanceof Function)
|
| @@ -1046,43 +1430,57 @@
|
| // Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf).
|
|
|
| function TestPrototype() {
|
| - var o = {}
|
| + var o1 = {}
|
| var p1 = Proxy.create({})
|
| - var p2 = Proxy.create({}, o)
|
| + var p2 = Proxy.create({}, o1)
|
| var p3 = Proxy.create({}, p2)
|
| var p4 = Proxy.create({}, 666)
|
| + var o2 = Object.create(p3)
|
|
|
| - assertSame(Object.getPrototypeOf(o), Object.prototype)
|
| + assertSame(Object.getPrototypeOf(o1), Object.prototype)
|
| assertSame(Object.getPrototypeOf(p1), null)
|
| - assertSame(Object.getPrototypeOf(p2), o)
|
| + assertSame(Object.getPrototypeOf(p2), o1)
|
| assertSame(Object.getPrototypeOf(p3), p2)
|
| assertSame(Object.getPrototypeOf(p4), null)
|
| + assertSame(Object.getPrototypeOf(o2), p3)
|
|
|
| - assertTrue(Object.prototype.isPrototypeOf(o))
|
| + assertTrue(Object.prototype.isPrototypeOf(o1))
|
| assertFalse(Object.prototype.isPrototypeOf(p1))
|
| assertTrue(Object.prototype.isPrototypeOf(p2))
|
| assertTrue(Object.prototype.isPrototypeOf(p3))
|
| assertFalse(Object.prototype.isPrototypeOf(p4))
|
| - assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o))
|
| + assertTrue(Object.prototype.isPrototypeOf(o2))
|
| + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1))
|
| assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p1))
|
| assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2))
|
| assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3))
|
| assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p4))
|
| - assertFalse(Object.prototype.isPrototypeOf.call(o, o))
|
| - assertFalse(Object.prototype.isPrototypeOf.call(o, p1))
|
| - assertTrue(Object.prototype.isPrototypeOf.call(o, p2))
|
| - assertTrue(Object.prototype.isPrototypeOf.call(o, p3))
|
| - assertFalse(Object.prototype.isPrototypeOf.call(o, p4))
|
| + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2))
|
| + assertFalse(Object.prototype.isPrototypeOf.call(o1, o1))
|
| + assertFalse(Object.prototype.isPrototypeOf.call(o1, p1))
|
| + assertTrue(Object.prototype.isPrototypeOf.call(o1, p2))
|
| + assertTrue(Object.prototype.isPrototypeOf.call(o1, p3))
|
| + assertFalse(Object.prototype.isPrototypeOf.call(o1, p4))
|
| + assertTrue(Object.prototype.isPrototypeOf.call(o1, o2))
|
| assertFalse(Object.prototype.isPrototypeOf.call(p1, p1))
|
| - assertFalse(Object.prototype.isPrototypeOf.call(p1, o))
|
| + 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, p4))
|
| + assertFalse(Object.prototype.isPrototypeOf.call(p1, o2))
|
| assertFalse(Object.prototype.isPrototypeOf.call(p2, p1))
|
| assertFalse(Object.prototype.isPrototypeOf.call(p2, p2))
|
| assertTrue(Object.prototype.isPrototypeOf.call(p2, p3))
|
| assertFalse(Object.prototype.isPrototypeOf.call(p2, p4))
|
| + assertTrue(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, p4))
|
| + assertFalse(Object.prototype.isPrototypeOf.call(o2, o2))
|
|
|
| var f = Proxy.createFunction({}, function() {})
|
| assertSame(Object.getPrototypeOf(f), Function.prototype)
|
| @@ -1267,7 +1665,6 @@
|
| // Fixing (Object.freeze, Object.seal, Object.preventExtensions,
|
| // Object.isFrozen, Object.isSealed, Object.isExtensible)
|
|
|
| -// TODO(rossberg): use TestWithProxies to include funciton proxies
|
| function TestFix(names, handler) {
|
| var proto = {p: 77}
|
| var assertFixing = function(o, s, f, e) {
|
| @@ -1314,19 +1711,27 @@
|
| Object.keys(p3).sort())
|
| assertEquals(proto, Object.getPrototypeOf(p3))
|
| assertEquals(77, p3.p)
|
| +
|
| + var p = Proxy.create(handler, proto)
|
| + var o = Object.create(p)
|
| + assertFixing(p, false, false, true)
|
| + assertFixing(o, false, false, true)
|
| + Object.freeze(o)
|
| + assertFixing(p, false, false, true)
|
| + assertFixing(o, true, true, false)
|
| }
|
|
|
| TestFix([], {
|
| fix: function() { return {} }
|
| })
|
|
|
| -TestFix(["a", "b", "c", "d", "zz"], {
|
| +TestFix(["a", "b", "c", "3", "zz"], {
|
| fix: function() {
|
| return {
|
| a: {value: "a", writable: true, configurable: false, enumerable: true},
|
| b: {value: 33, writable: false, configurable: false, enumerable: true},
|
| c: {value: 0, writable: true, configurable: true, enumerable: true},
|
| - d: {value: true, writable: false, configurable: true, enumerable: true},
|
| + '3': {value: true, writable: false, configurable: true, enumerable: true},
|
| zz: {value: 0, enumerable: false}
|
| }
|
| }
|
| @@ -1426,6 +1831,13 @@
|
| assertEquals("my_proxy", Object.prototype.toLocaleString.call(f))
|
| assertEquals("toString", key)
|
| assertDoesNotThrow(function(){ Function.prototype.toString.call(f) })
|
| +
|
| + var o = Object.create(p)
|
| + key = ""
|
| + assertEquals("[object Object]", Object.prototype.toString.call(o))
|
| + assertEquals("", key)
|
| + assertEquals("my_proxy", Object.prototype.toLocaleString.call(o))
|
| + assertEquals("toString", key)
|
| }
|
|
|
| TestToString({
|
| @@ -1452,6 +1864,10 @@
|
| var f = Proxy.createFunction(handler, function() {})
|
| assertEquals("[object Function]", Object.prototype.toString.call(f))
|
| assertThrows(function(){ Object.prototype.toLocaleString.call(f) }, "myexn")
|
| +
|
| + var o = Object.create(p)
|
| + assertEquals("[object Object]", Object.prototype.toString.call(o))
|
| + assertThrows(function(){ Object.prototype.toLocaleString.call(o) }, "myexn")
|
| }
|
|
|
| TestToStringThrow({
|
| @@ -1510,6 +1926,11 @@
|
| 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({
|
| @@ -1586,23 +2007,30 @@
|
| // Calling (call, Function.prototype.call, Function.prototype.apply,
|
| // Function.prototype.bind).
|
|
|
| -var global = this
|
| +var global_object = this
|
| var receiver
|
|
|
| +function CreateFrozen(handler, callTrap, constructTrap) {
|
| + if (handler.fix === undefined) handler.fix = function() { return {} }
|
| + var f = Proxy.createFunction(handler, callTrap, constructTrap)
|
| + Object.freeze(f)
|
| + return f
|
| +}
|
| +
|
| function TestCall(isStrict, callTrap) {
|
| assertEquals(42, callTrap(5, 37))
|
| -// TODO(rossberg): unrelated bug: this does not succeed for optimized code.
|
| -// assertEquals(isStrict ? undefined : global, receiver)
|
| + // TODO(rossberg): unrelated bug: this does not succeed for optimized code:
|
| + // assertEquals(isStrict ? undefined : global_object, receiver)
|
|
|
| - var f = Proxy.createFunction({fix: function() { return {} }}, callTrap)
|
| + var f = Proxy.createFunction({}, callTrap)
|
| receiver = 333
|
| assertEquals(42, f(11, 31))
|
| - assertEquals(isStrict ? undefined : global, receiver)
|
| + assertEquals(isStrict ? undefined : global_object, receiver)
|
| var o = {}
|
| assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
|
| assertEquals(o, receiver)
|
| assertEquals(43, Function.prototype.call.call(f, null, 20, 23))
|
| - assertEquals(isStrict ? null : global, receiver)
|
| + assertEquals(isStrict ? null : global_object, receiver)
|
| assertEquals(44, Function.prototype.call.call(f, 2, 21, 23))
|
| assertEquals(2, receiver.valueOf())
|
| receiver = 333
|
| @@ -1616,11 +2044,11 @@
|
| assertEquals(32, Function.prototype.apply.call(ff, {}, [20]))
|
| assertEquals(o, receiver)
|
|
|
| - Object.freeze(f)
|
| + var f = CreateFrozen({}, callTrap)
|
| receiver = 333
|
| assertEquals(42, f(11, 31))
|
| -// TODO(rossberg): unrelated bug: this does not succeed for optimized code.
|
| -// assertEquals(isStrict ? undefined : global, receiver)
|
| + // TODO(rossberg): unrelated bug: this does not succeed for optimized code.
|
| + // assertEquals(isStrict ? undefined : global, receiver)
|
| receiver = 333
|
| assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
|
| assertEquals(o, receiver)
|
| @@ -1653,21 +2081,18 @@
|
| receiver = this; return x + y
|
| }))
|
|
|
| -var p = Proxy.createFunction({fix: function() {return {}}}, function(x, y) {
|
| +TestCall(false, CreateFrozen({}, function(x, y) {
|
| receiver = this; return x + y
|
| -})
|
| -TestCall(false, p)
|
| -Object.freeze(p)
|
| -TestCall(false, p)
|
| +}))
|
|
|
|
|
| function TestCallThrow(callTrap) {
|
| - var f = Proxy.createFunction({fix: function() {return {}}}, callTrap)
|
| + var f = Proxy.createFunction({}, callTrap)
|
| assertThrows(function(){ f(11) }, "myexn")
|
| assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
|
| assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
|
|
|
| - Object.freeze(f)
|
| + var f = CreateFrozen({}, callTrap)
|
| assertThrows(function(){ f(11) }, "myexn")
|
| assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
|
| assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
|
| @@ -1675,8 +2100,256 @@
|
|
|
| TestCallThrow(function() { throw "myexn" })
|
| TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" }))
|
| +TestCallThrow(CreateFrozen({}, function() { throw "myexn" }))
|
|
|
| -var p = Proxy.createFunction(
|
| - {fix: function() {return {}}}, function() { throw "myexn" })
|
| -Object.freeze(p)
|
| -TestCallThrow(p)
|
| +
|
| +
|
| +// Construction (new).
|
| +
|
| +var prototype = {}
|
| +var receiver
|
| +
|
| +var handlerWithPrototype = {
|
| + fix: function() { return {prototype: prototype} },
|
| + get: function(r, n) { assertEquals("prototype", n); return prototype }
|
| +}
|
| +
|
| +var handlerSansPrototype = {
|
| + fix: function() { return {} },
|
| + get: function(r, n) { assertEquals("prototype", n); return undefined }
|
| +}
|
| +
|
| +function ReturnUndef(x, y) { "use strict"; receiver = this; this.sum = x + y }
|
| +function ReturnThis(x, y) { "use strict"; receiver = this; this.sum = x + y; return this }
|
| +function ReturnNew(x, y) { "use strict"; receiver = this; return {sum: x + y} }
|
| +function ReturnNewWithProto(x, y) {
|
| + "use strict";
|
| + receiver = this;
|
| + var result = Object.create(prototype)
|
| + result.sum = x + y
|
| + return result
|
| +}
|
| +
|
| +function TestConstruct(proto, constructTrap) {
|
| + TestConstruct2(proto, constructTrap, handlerWithPrototype)
|
| + TestConstruct2(proto, constructTrap, handlerSansPrototype)
|
| +}
|
| +
|
| +function TestConstruct2(proto, constructTrap, handler) {
|
| + var f = Proxy.createFunction(handler, function() {}, constructTrap)
|
| + var o = new f(11, 31)
|
| + // TODO(rossberg): doesn't hold, due to unrelated bug.
|
| + // assertEquals(undefined, receiver)
|
| + assertEquals(42, o.sum)
|
| + assertSame(proto, Object.getPrototypeOf(o))
|
| +
|
| + var f = CreateFrozen(handler, function() {}, constructTrap)
|
| + var o = new f(11, 32)
|
| + // TODO(rossberg): doesn't hold, due to unrelated bug.
|
| + // assertEquals(undefined, receiver)
|
| + assertEquals(43, o.sum)
|
| + assertSame(proto, Object.getPrototypeOf(o))
|
| +}
|
| +
|
| +TestConstruct(Object.prototype, ReturnNew)
|
| +TestConstruct(prototype, ReturnNewWithProto)
|
| +
|
| +TestConstruct(Object.prototype, Proxy.createFunction({}, ReturnNew))
|
| +TestConstruct(prototype, Proxy.createFunction({}, ReturnNewWithProto))
|
| +
|
| +TestConstruct(Object.prototype, CreateFrozen({}, ReturnNew))
|
| +TestConstruct(prototype, CreateFrozen({}, ReturnNewWithProto))
|
| +
|
| +
|
| +function TestConstructFromCall(proto, returnsThis, callTrap) {
|
| + TestConstructFromCall2(proto, returnsThis, callTrap, handlerWithPrototype)
|
| + TestConstructFromCall2(proto, returnsThis, callTrap, handlerSansPrototype)
|
| +}
|
| +
|
| +function TestConstructFromCall2(proto, returnsThis, callTrap, handler) {
|
| + var f = Proxy.createFunction(handler, callTrap)
|
| + var o = new f(11, 31)
|
| + if (returnsThis) assertEquals(o, receiver)
|
| + assertEquals(42, o.sum)
|
| + assertSame(proto, Object.getPrototypeOf(o))
|
| +
|
| + var f = CreateFrozen(handler, callTrap)
|
| + var o = new f(11, 32)
|
| + if (returnsThis) assertEquals(o, receiver)
|
| + assertEquals(43, o.sum)
|
| + assertSame(proto, Object.getPrototypeOf(o))
|
| +}
|
| +
|
| +TestConstructFromCall(Object.prototype, true, ReturnUndef)
|
| +TestConstructFromCall(Object.prototype, true, ReturnThis)
|
| +TestConstructFromCall(Object.prototype, false, ReturnNew)
|
| +TestConstructFromCall(prototype, false, ReturnNewWithProto)
|
| +
|
| +TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnUndef))
|
| +TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnThis))
|
| +TestConstructFromCall(Object.prototype, false, Proxy.createFunction({}, ReturnNew))
|
| +TestConstructFromCall(prototype, false, Proxy.createFunction({}, ReturnNewWithProto))
|
| +
|
| +TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnUndef))
|
| +TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnThis))
|
| +TestConstructFromCall(Object.prototype, false, CreateFrozen({}, ReturnNew))
|
| +TestConstructFromCall(prototype, false, CreateFrozen({}, ReturnNewWithProto))
|
| +
|
| +ReturnUndef.prototype = prototype
|
| +ReturnThis.prototype = prototype
|
| +ReturnNew.prototype = prototype
|
| +ReturnNewWithProto.prototype = prototype
|
| +
|
| +TestConstructFromCall(prototype, true, ReturnUndef)
|
| +TestConstructFromCall(prototype, true, ReturnThis)
|
| +TestConstructFromCall(Object.prototype, false, ReturnNew)
|
| +TestConstructFromCall(prototype, false, ReturnNewWithProto)
|
| +
|
| +TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnUndef))
|
| +TestConstructFromCall(Object.prototype, true, Proxy.createFunction({}, ReturnThis))
|
| +TestConstructFromCall(Object.prototype, false, Proxy.createFunction({}, ReturnNew))
|
| +TestConstructFromCall(prototype, false, Proxy.createFunction({}, ReturnNewWithProto))
|
| +
|
| +TestConstructFromCall(prototype, true, Proxy.createFunction(handlerWithPrototype, ReturnUndef))
|
| +TestConstructFromCall(prototype, true, Proxy.createFunction(handlerWithPrototype, ReturnThis))
|
| +TestConstructFromCall(Object.prototype, false, Proxy.createFunction(handlerWithPrototype, ReturnNew))
|
| +TestConstructFromCall(prototype, false, Proxy.createFunction(handlerWithPrototype, ReturnNewWithProto))
|
| +
|
| +TestConstructFromCall(prototype, true, CreateFrozen(handlerWithPrototype, ReturnUndef))
|
| +TestConstructFromCall(prototype, true, CreateFrozen(handlerWithPrototype, ReturnThis))
|
| +TestConstructFromCall(Object.prototype, false, CreateFrozen(handlerWithPrototype, ReturnNew))
|
| +TestConstructFromCall(prototype, false, CreateFrozen(handlerWithPrototype, ReturnNewWithProto))
|
| +
|
| +
|
| +function TestConstructThrow(trap) {
|
| + TestConstructThrow2(Proxy.createFunction({fix: function() {return {}}}, trap))
|
| + TestConstructThrow2(Proxy.createFunction({fix: function() {return {}}},
|
| + function() {}, trap))
|
| +}
|
| +
|
| +function TestConstructThrow2(f) {
|
| + assertThrows(function(){ new f(11) }, "myexn")
|
| + Object.freeze(f)
|
| + assertThrows(function(){ new f(11) }, "myexn")
|
| +}
|
| +
|
| +TestConstructThrow(function() { throw "myexn" })
|
| +TestConstructThrow(Proxy.createFunction({}, function() { throw "myexn" }))
|
| +TestConstructThrow(CreateFrozen({}, function() { throw "myexn" }))
|
| +
|
| +
|
| +
|
| +// Getters and setters.
|
| +
|
| +var value
|
| +var receiver
|
| +
|
| +function TestAccessorCall(getterCallTrap, setterCallTrap) {
|
| + var handler = {fix: function() { return {} }}
|
| + var pgetter = Proxy.createFunction(handler, getterCallTrap)
|
| + var psetter = Proxy.createFunction(handler, setterCallTrap)
|
| +
|
| + var o = {}
|
| + var oo = Object.create(o)
|
| + Object.defineProperty(o, "a", {get: pgetter, set: psetter})
|
| + Object.defineProperty(o, "b", {get: pgetter})
|
| + Object.defineProperty(o, "c", {set: psetter})
|
| + Object.defineProperty(o, "3", {get: pgetter, set: psetter})
|
| + Object.defineProperty(oo, "a", {value: 43})
|
| +
|
| + receiver = ""
|
| + assertEquals(42, o.a)
|
| + assertSame(o, receiver)
|
| + receiver = ""
|
| + assertEquals(42, o.b)
|
| + assertSame(o, receiver)
|
| + receiver = ""
|
| + assertEquals(undefined, o.c)
|
| + assertEquals("", receiver)
|
| + receiver = ""
|
| + assertEquals(42, o["a"])
|
| + assertSame(o, receiver)
|
| + receiver = ""
|
| + assertEquals(42, o[3])
|
| + assertSame(o, receiver)
|
| +
|
| + receiver = ""
|
| + assertEquals(43, oo.a)
|
| + assertEquals("", receiver)
|
| + receiver = ""
|
| + assertEquals(42, oo.b)
|
| + assertSame(o, receiver)
|
| + receiver = ""
|
| + assertEquals(undefined, oo.c)
|
| + assertEquals("", receiver)
|
| + receiver = ""
|
| + assertEquals(43, oo["a"])
|
| + assertEquals("", receiver)
|
| + receiver = ""
|
| + assertEquals(42, oo[3])
|
| + assertSame(o, receiver)
|
| +
|
| + receiver = ""
|
| + assertEquals(50, o.a = 50)
|
| + assertSame(o, receiver)
|
| + assertEquals(50, value)
|
| + receiver = ""
|
| + assertEquals(51, o.b = 51)
|
| + assertEquals("", receiver)
|
| + assertEquals(50, value) // no setter
|
| + assertThrows(function() { "use strict"; o.b = 51 }, TypeError)
|
| + receiver = ""
|
| + assertEquals(52, o.c = 52)
|
| + assertSame(o, receiver)
|
| + assertEquals(52, value)
|
| + receiver = ""
|
| + assertEquals(53, o["a"] = 53)
|
| + assertSame(o, receiver)
|
| + assertEquals(53, value)
|
| + receiver = ""
|
| + assertEquals(54, o[3] = 54)
|
| + assertSame(o, receiver)
|
| + assertEquals(54, value)
|
| +
|
| + value = 0
|
| + receiver = ""
|
| + assertEquals(60, oo.a = 60)
|
| + assertEquals("", receiver)
|
| + assertEquals(0, value) // oo has own 'a'
|
| + assertEquals(61, oo.b = 61)
|
| + assertSame("", receiver)
|
| + assertEquals(0, value) // no setter
|
| + assertThrows(function() { "use strict"; oo.b = 61 }, TypeError)
|
| + receiver = ""
|
| + assertEquals(62, oo.c = 62)
|
| + assertSame(oo, receiver)
|
| + assertEquals(62, value)
|
| + receiver = ""
|
| + assertEquals(63, oo["c"] = 63)
|
| + assertSame(oo, receiver)
|
| + assertEquals(63, value)
|
| + receiver = ""
|
| + assertEquals(64, oo[3] = 64)
|
| + assertSame(oo, receiver)
|
| + assertEquals(64, value)
|
| +}
|
| +
|
| +TestAccessorCall(
|
| + function() { receiver = this; return 42 },
|
| + function(x) { receiver = this; value = x }
|
| +)
|
| +
|
| +TestAccessorCall(
|
| + function() { "use strict"; receiver = this; return 42 },
|
| + function(x) { "use strict"; receiver = this; value = x }
|
| +)
|
| +
|
| +TestAccessorCall(
|
| + Proxy.createFunction({}, function() { receiver = this; return 42 }),
|
| + Proxy.createFunction({}, function(x) { receiver = this; value = x })
|
| +)
|
| +
|
| +TestAccessorCall(
|
| + CreateFrozen({}, function() { receiver = this; return 42 }),
|
| + CreateFrozen({}, function(x) { receiver = this; value = x })
|
| +)
|
|
|