| 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 })
 | 
| +)
 | 
| 
 |