Home | History | Annotate | Download | only in harmony
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 // Flags: --harmony-proxies --allow-natives-syntax
     29 
     30 
     31 // Helper.
     32 
     33 function CreateFrozen(handler, callTrap, constructTrap) {
     34   if (handler.fix === undefined) handler.fix = function() { return {} }
     35   var f = Proxy.createFunction(handler, callTrap, constructTrap)
     36   Object.freeze(f)
     37   return f
     38 }
     39 
     40 
     41 // Ensures that checking the "length" property of a function proxy doesn't
     42 // crash due to lack of a [[Get]] method.
     43 var handler = {
     44   get : function(r, n) { return n == "length" ? 2 : undefined }
     45 }
     46 
     47 
     48 // Calling (call, Function.prototype.call, Function.prototype.apply,
     49 //          Function.prototype.bind).
     50 
     51 var global_object = this
     52 var receiver
     53 
     54 function TestCall(isStrict, callTrap) {
     55   assertEquals(42, callTrap(5, 37))
     56   // TODO(rossberg): strict mode seems to be broken on x64...
     57   // assertSame(isStrict ? undefined : global_object, receiver)
     58 
     59   var handler = {
     60     get: function(r, k) {
     61       return k == "length" ? 2 : Function.prototype[k]
     62     }
     63   }
     64   var f = Proxy.createFunction(handler, callTrap)
     65   var o = {f: f}
     66   global_object.f = f
     67 
     68   receiver = 333
     69   assertEquals(42, f(11, 31))
     70   // TODO(rossberg): strict mode seems to be broken on x64...
     71   // assertSame(isStrict ? undefined : global_object, receiver)
     72   receiver = 333
     73   assertEquals(42, o.f(10, 32))
     74   assertSame(o, receiver)
     75   receiver = 333
     76   assertEquals(42, o["f"](9, 33))
     77   assertSame(o, receiver)
     78   receiver = 333
     79   assertEquals(42, (1, o).f(8, 34))
     80   assertSame(o, receiver)
     81   receiver = 333
     82   assertEquals(42, (1, o)["f"](7, 35))
     83   assertSame(o, receiver)
     84   receiver = 333
     85   assertEquals(42, f.call(o, 32, 10))
     86   assertSame(o, receiver)
     87   receiver = 333
     88   assertEquals(42, f.call(undefined, 33, 9))
     89   assertSame(isStrict ? undefined : global_object, receiver)
     90   receiver = 333
     91   assertEquals(42, f.call(null, 33, 9))
     92   assertSame(isStrict ? null : global_object, receiver)
     93   receiver = 333
     94   assertEquals(44, f.call(2, 21, 23))
     95   assertSame(2, receiver.valueOf())
     96   receiver = 333
     97   assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
     98   assertSame(o, receiver)
     99   receiver = 333
    100   assertEquals(43, Function.prototype.call.call(f, null, 20, 23))
    101   assertSame(isStrict ? null : global_object, receiver)
    102   assertEquals(44, Function.prototype.call.call(f, 2, 21, 23))
    103   assertEquals(2, receiver.valueOf())
    104   receiver = 333
    105   assertEquals(32, f.apply(o, [16, 16]))
    106   assertSame(o, receiver)
    107   receiver = 333
    108   assertEquals(32, Function.prototype.apply.call(f, o, [17, 15]))
    109   assertSame(o, receiver)
    110   receiver = 333
    111   assertEquals(42, %Call(o, 11, 31, f))
    112   assertSame(o, receiver)
    113   receiver = 333
    114   assertEquals(42, %Call(null, 11, 31, f))
    115   assertSame(isStrict ? null : global_object, receiver)
    116   receiver = 333
    117   assertEquals(42, %Apply(f, o, [11, 31], 0, 2))
    118   assertSame(o, receiver)
    119   receiver = 333
    120   assertEquals(42, %Apply(f, null, [11, 31], 0, 2))
    121   assertSame(isStrict ? null : global_object, receiver)
    122   receiver = 333
    123   assertEquals(42, %_CallFunction(o, 11, 31, f))
    124   assertSame(o, receiver)
    125   receiver = 333
    126   assertEquals(42, %_CallFunction(null, 11, 31, f))
    127   assertSame(isStrict ? null : global_object, receiver)
    128 
    129   var ff = Function.prototype.bind.call(f, o, 12)
    130   assertTrue(ff.length <= 1)  // TODO(rossberg): Not spec'ed yet, be lax.
    131   receiver = 333
    132   assertEquals(42, ff(30))
    133   assertSame(o, receiver)
    134   receiver = 333
    135   assertEquals(33, Function.prototype.call.call(ff, {}, 21))
    136   assertSame(o, receiver)
    137   receiver = 333
    138   assertEquals(32, Function.prototype.apply.call(ff, {}, [20]))
    139   assertSame(o, receiver)
    140   receiver = 333
    141   assertEquals(23, %Call({}, 11, ff))
    142   assertSame(o, receiver)
    143   receiver = 333
    144   assertEquals(23, %Call({}, 11, 3, ff))
    145   assertSame(o, receiver)
    146   receiver = 333
    147   assertEquals(24, %Apply(ff, {}, [12, 13], 0, 1))
    148   assertSame(o, receiver)
    149   receiver = 333
    150   assertEquals(24, %Apply(ff, {}, [12, 13], 0, 2))
    151   assertSame(o, receiver)
    152   receiver = 333
    153   assertEquals(34, %_CallFunction({}, 22, ff))
    154   assertSame(o, receiver)
    155   receiver = 333
    156   assertEquals(34, %_CallFunction({}, 22, 3, ff))
    157   assertSame(o, receiver)
    158 
    159   var fff = Function.prototype.bind.call(ff, o, 30)
    160   assertEquals(0, fff.length)
    161   receiver = 333
    162   assertEquals(42, fff())
    163   assertSame(o, receiver)
    164   receiver = 333
    165   assertEquals(42, Function.prototype.call.call(fff, {}))
    166   assertSame(o, receiver)
    167   receiver = 333
    168   assertEquals(42, Function.prototype.apply.call(fff, {}))
    169   assertSame(o, receiver)
    170   receiver = 333
    171   assertEquals(42, %Call({}, fff))
    172   assertSame(o, receiver)
    173   receiver = 333
    174   assertEquals(42, %Call({}, 11, 3, fff))
    175   assertSame(o, receiver)
    176   receiver = 333
    177   assertEquals(42, %Apply(fff, {}, [], 0, 0))
    178   assertSame(o, receiver)
    179   receiver = 333
    180   assertEquals(42, %Apply(fff, {}, [12, 13], 0, 0))
    181   assertSame(o, receiver)
    182   receiver = 333
    183   assertEquals(42, %Apply(fff, {}, [12, 13], 0, 2))
    184   assertSame(o, receiver)
    185   receiver = 333
    186   assertEquals(42, %_CallFunction({}, fff))
    187   assertSame(o, receiver)
    188   receiver = 333
    189   assertEquals(42, %_CallFunction({}, 3, 4, 5, fff))
    190   assertSame(o, receiver)
    191 
    192   var f = CreateFrozen({}, callTrap)
    193   receiver = 333
    194   assertEquals(42, f(11, 31))
    195   assertSame(isStrict ? undefined : global_object, receiver)
    196   var o = {f: f}
    197   receiver = 333
    198   assertEquals(42, o.f(10, 32))
    199   assertSame(o, receiver)
    200   receiver = 333
    201   assertEquals(42, o["f"](9, 33))
    202   assertSame(o, receiver)
    203   receiver = 333
    204   assertEquals(42, (1, o).f(8, 34))
    205   assertSame(o, receiver)
    206   receiver = 333
    207   assertEquals(42, (1, o)["f"](7, 35))
    208   assertSame(o, receiver)
    209   receiver = 333
    210   assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
    211   assertSame(o, receiver)
    212   receiver = 333
    213   assertEquals(32, Function.prototype.apply.call(f, o, [17, 15]))
    214   assertSame(o, receiver)
    215   receiver = 333
    216   assertEquals(23, %Call(o, 11, 12, f))
    217   assertSame(o, receiver)
    218   receiver = 333
    219   assertEquals(27, %Apply(f, o, [12, 13, 14], 1, 2))
    220   assertSame(o, receiver)
    221   receiver = 333
    222   assertEquals(42, %_CallFunction(o, 18, 24, f))
    223   assertSame(o, receiver)
    224 }
    225 
    226 TestCall(false, function(x, y) {
    227   receiver = this
    228   return x + y
    229 })
    230 
    231 TestCall(true, function(x, y) {
    232   "use strict"
    233   receiver = this
    234   return x + y
    235 })
    236 
    237 TestCall(false, function() {
    238   receiver = this
    239   return arguments[0] + arguments[1]
    240 })
    241 
    242 TestCall(false, Proxy.createFunction(handler, function(x, y) {
    243   receiver = this
    244   return x + y
    245 }))
    246 
    247 TestCall(true, Proxy.createFunction(handler, function(x, y) {
    248   "use strict"
    249   receiver = this
    250   return x + y
    251 }))
    252 
    253 TestCall(false, CreateFrozen(handler, function(x, y) {
    254   receiver = this
    255   return x + y
    256 }))
    257 
    258 
    259 
    260 // Using intrinsics as call traps.
    261 
    262 function TestCallIntrinsic(type, callTrap) {
    263   var f = Proxy.createFunction({}, callTrap)
    264   var x = f()
    265   assertTrue(typeof x == type)
    266 }
    267 
    268 TestCallIntrinsic("boolean", Boolean)
    269 TestCallIntrinsic("number", Number)
    270 TestCallIntrinsic("string", String)
    271 TestCallIntrinsic("object", Object)
    272 TestCallIntrinsic("function", Function)
    273 
    274 
    275 
    276 // Throwing from call trap.
    277 
    278 function TestCallThrow(callTrap) {
    279   var f = Proxy.createFunction({}, callTrap)
    280   assertThrows(function(){ f(11) }, "myexn")
    281   assertThrows(function(){ ({x: f}).x(11) }, "myexn")
    282   assertThrows(function(){ ({x: f})["x"](11) }, "myexn")
    283   assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
    284   assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
    285   assertThrows(function(){ %Call({}, f) }, "myexn")
    286   assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn")
    287   assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn")
    288   assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn")
    289   assertThrows(function(){ %_CallFunction({}, f) }, "myexn")
    290   assertThrows(function(){ %_CallFunction({}, 1, 2, f) }, "myexn")
    291 
    292   var f = CreateFrozen({}, callTrap)
    293   assertThrows(function(){ f(11) }, "myexn")
    294   assertThrows(function(){ ({x: f}).x(11) }, "myexn")
    295   assertThrows(function(){ ({x: f})["x"](11) }, "myexn")
    296   assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
    297   assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
    298   assertThrows(function(){ %Call({}, f) }, "myexn")
    299   assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn")
    300   assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn")
    301   assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn")
    302   assertThrows(function(){ %_CallFunction({}, f) }, "myexn")
    303   assertThrows(function(){ %_CallFunction({}, 1, 2, f) }, "myexn")
    304 }
    305 
    306 TestCallThrow(function() { throw "myexn" })
    307 TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" }))
    308 TestCallThrow(CreateFrozen({}, function() { throw "myexn" }))
    309 
    310 
    311 
    312 // Construction (new).
    313 
    314 var prototype = {myprop: 0}
    315 var receiver
    316 
    317 var handlerWithPrototype = {
    318   fix: function() { return { prototype: { value: prototype } }; },
    319   get: function(r, n) {
    320     if (n == "length") return 2;
    321     assertEquals("prototype", n);
    322     return prototype;
    323   }
    324 }
    325 
    326 var handlerSansPrototype = {
    327   fix: function() { return { length: { value: 2 } } },
    328   get: function(r, n) {
    329     if (n == "length") return 2;
    330     assertEquals("prototype", n);
    331     return undefined;
    332   }
    333 }
    334 
    335 function ReturnUndef(x, y) {
    336   "use strict";
    337   receiver = this;
    338   this.sum = x + y;
    339 }
    340 
    341 function ReturnThis(x, y) {
    342   "use strict";
    343   receiver = this;
    344   this.sum = x + y;
    345   return this;
    346 }
    347 
    348 function ReturnNew(x, y) {
    349   "use strict";
    350   receiver = this;
    351   return {sum: x + y};
    352 }
    353 
    354 function ReturnNewWithProto(x, y) {
    355   "use strict";
    356   receiver = this;
    357   var result = Object.create(prototype);
    358   result.sum = x + y;
    359   return result;
    360 }
    361 
    362 function TestConstruct(proto, constructTrap) {
    363   TestConstruct2(proto, constructTrap, handlerWithPrototype)
    364   TestConstruct2(proto, constructTrap, handlerSansPrototype)
    365 }
    366 
    367 function TestConstruct2(proto, constructTrap, handler) {
    368   var f = Proxy.createFunction(handler, function() {}, constructTrap)
    369   var o = new f(11, 31)
    370   assertEquals(undefined, receiver)
    371   assertEquals(42, o.sum)
    372   assertSame(proto, Object.getPrototypeOf(o))
    373 
    374   var f = CreateFrozen(handler, function() {}, constructTrap)
    375   var o = new f(11, 32)
    376   assertEquals(undefined, receiver)
    377   assertEquals(43, o.sum)
    378   assertSame(proto, Object.getPrototypeOf(o))
    379 }
    380 
    381 TestConstruct(Object.prototype, ReturnNew)
    382 TestConstruct(prototype, ReturnNewWithProto)
    383 
    384 TestConstruct(Object.prototype, Proxy.createFunction(handler, ReturnNew))
    385 TestConstruct(prototype, Proxy.createFunction(handler, ReturnNewWithProto))
    386 
    387 TestConstruct(Object.prototype, CreateFrozen(handler, ReturnNew))
    388 TestConstruct(prototype, CreateFrozen(handler, ReturnNewWithProto))
    389 
    390 
    391 
    392 // Construction with derived construct trap.
    393 
    394 function TestConstructFromCall(proto, returnsThis, callTrap) {
    395   TestConstructFromCall2(prototype, returnsThis, callTrap, handlerWithPrototype)
    396   TestConstructFromCall2(proto, returnsThis, callTrap, handlerSansPrototype)
    397 }
    398 
    399 function TestConstructFromCall2(proto, returnsThis, callTrap, handler) {
    400   // TODO(rossberg): handling of prototype for derived construct trap will be
    401   // fixed in a separate change. Commenting out checks below for now.
    402   var f = Proxy.createFunction(handler, callTrap)
    403   var o = new f(11, 31)
    404   if (returnsThis) assertEquals(o, receiver)
    405   assertEquals(42, o.sum)
    406   // assertSame(proto, Object.getPrototypeOf(o))
    407 
    408   var g = CreateFrozen(handler, callTrap)
    409   // assertSame(f.prototype, g.prototype)
    410   var o = new g(11, 32)
    411   if (returnsThis) assertEquals(o, receiver)
    412   assertEquals(43, o.sum)
    413   // assertSame(proto, Object.getPrototypeOf(o))
    414 }
    415 
    416 TestConstructFromCall(Object.prototype, true, ReturnUndef)
    417 TestConstructFromCall(Object.prototype, true, ReturnThis)
    418 TestConstructFromCall(Object.prototype, false, ReturnNew)
    419 TestConstructFromCall(prototype, false, ReturnNewWithProto)
    420 
    421 TestConstructFromCall(Object.prototype, true,
    422                       Proxy.createFunction(handler, ReturnUndef))
    423 TestConstructFromCall(Object.prototype, true,
    424                       Proxy.createFunction(handler, ReturnThis))
    425 TestConstructFromCall(Object.prototype, false,
    426                       Proxy.createFunction(handler, ReturnNew))
    427 TestConstructFromCall(prototype, false,
    428                       Proxy.createFunction(handler, ReturnNewWithProto))
    429 
    430 TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnUndef))
    431 TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnThis))
    432 TestConstructFromCall(Object.prototype, false, CreateFrozen({}, ReturnNew))
    433 TestConstructFromCall(prototype, false, CreateFrozen({}, ReturnNewWithProto))
    434 
    435 ReturnUndef.prototype = prototype
    436 ReturnThis.prototype = prototype
    437 ReturnNew.prototype = prototype
    438 ReturnNewWithProto.prototype = prototype
    439 
    440 TestConstructFromCall(prototype, true, ReturnUndef)
    441 TestConstructFromCall(prototype, true, ReturnThis)
    442 TestConstructFromCall(Object.prototype, false, ReturnNew)
    443 TestConstructFromCall(prototype, false, ReturnNewWithProto)
    444 
    445 TestConstructFromCall(Object.prototype, true,
    446                       Proxy.createFunction(handler, ReturnUndef))
    447 TestConstructFromCall(Object.prototype, true,
    448                       Proxy.createFunction(handler, ReturnThis))
    449 TestConstructFromCall(Object.prototype, false,
    450                       Proxy.createFunction(handler, ReturnNew))
    451 TestConstructFromCall(prototype, false,
    452                       Proxy.createFunction(handler, ReturnNewWithProto))
    453 
    454 TestConstructFromCall(prototype, true,
    455                       Proxy.createFunction(handlerWithPrototype, ReturnUndef))
    456 TestConstructFromCall(prototype, true,
    457                       Proxy.createFunction(handlerWithPrototype, ReturnThis))
    458 TestConstructFromCall(Object.prototype, false,
    459                       Proxy.createFunction(handlerWithPrototype, ReturnNew))
    460 TestConstructFromCall(prototype, false,
    461                       Proxy.createFunction(handlerWithPrototype,
    462                                            ReturnNewWithProto))
    463 
    464 TestConstructFromCall(prototype, true,
    465                       CreateFrozen(handlerWithPrototype, ReturnUndef))
    466 TestConstructFromCall(prototype, true,
    467                       CreateFrozen(handlerWithPrototype, ReturnThis))
    468 TestConstructFromCall(Object.prototype, false,
    469                       CreateFrozen(handlerWithPrototype, ReturnNew))
    470 TestConstructFromCall(prototype, false,
    471                       CreateFrozen(handlerWithPrototype, ReturnNewWithProto))
    472 
    473 
    474 
    475 // Throwing from the construct trap.
    476 
    477 function TestConstructThrow(trap) {
    478   TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} },
    479                                            trap))
    480   TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} },
    481                                            function() {},
    482                                            trap))
    483 }
    484 
    485 function TestConstructThrow2(f) {
    486   assertThrows(function(){ new f(11) }, "myexn")
    487   Object.freeze(f)
    488   assertThrows(function(){ new f(11) }, "myexn")
    489 }
    490 
    491 TestConstructThrow(function() { throw "myexn" })
    492 TestConstructThrow(Proxy.createFunction({}, function() { throw "myexn" }))
    493 TestConstructThrow(CreateFrozen({}, function() { throw "myexn" }))
    494 
    495 
    496 
    497 // Using function proxies as getters and setters.
    498 
    499 var value
    500 var receiver
    501 
    502 function TestAccessorCall(getterCallTrap, setterCallTrap) {
    503   var handler = { fix: function() { return {} } }
    504   var pgetter = Proxy.createFunction(handler, getterCallTrap)
    505   var psetter = Proxy.createFunction(handler, setterCallTrap)
    506 
    507   var o = {}
    508   var oo = Object.create(o)
    509   Object.defineProperty(o, "a", {get: pgetter, set: psetter})
    510   Object.defineProperty(o, "b", {get: pgetter})
    511   Object.defineProperty(o, "c", {set: psetter})
    512   Object.defineProperty(o, "3", {get: pgetter, set: psetter})
    513   Object.defineProperty(oo, "a", {value: 43})
    514 
    515   receiver = ""
    516   assertEquals(42, o.a)
    517   assertSame(o, receiver)
    518   receiver = ""
    519   assertEquals(42, o.b)
    520   assertSame(o, receiver)
    521   receiver = ""
    522   assertEquals(undefined, o.c)
    523   assertEquals("", receiver)
    524   receiver = ""
    525   assertEquals(42, o["a"])
    526   assertSame(o, receiver)
    527   receiver = ""
    528   assertEquals(42, o[3])
    529   assertSame(o, receiver)
    530 
    531   receiver = ""
    532   assertEquals(43, oo.a)
    533   assertEquals("", receiver)
    534   receiver = ""
    535   assertEquals(42, oo.b)
    536   assertSame(oo, receiver)
    537   receiver = ""
    538   assertEquals(undefined, oo.c)
    539   assertEquals("", receiver)
    540   receiver = ""
    541   assertEquals(43, oo["a"])
    542   assertEquals("", receiver)
    543   receiver = ""
    544   assertEquals(42, oo[3])
    545   assertSame(oo, receiver)
    546 
    547   receiver = ""
    548   assertEquals(50, o.a = 50)
    549   assertSame(o, receiver)
    550   assertEquals(50, value)
    551   receiver = ""
    552   assertEquals(51, o.b = 51)
    553   assertEquals("", receiver)
    554   assertEquals(50, value)  // no setter
    555   assertThrows(function() { "use strict"; o.b = 51 }, TypeError)
    556   receiver = ""
    557   assertEquals(52, o.c = 52)
    558   assertSame(o, receiver)
    559   assertEquals(52, value)
    560   receiver = ""
    561   assertEquals(53, o["a"] = 53)
    562   assertSame(o, receiver)
    563   assertEquals(53, value)
    564   receiver = ""
    565   assertEquals(54, o[3] = 54)
    566   assertSame(o, receiver)
    567   assertEquals(54, value)
    568 
    569   value = 0
    570   receiver = ""
    571   assertEquals(60, oo.a = 60)
    572   assertEquals("", receiver)
    573   assertEquals(0, value)  // oo has own 'a'
    574   assertEquals(61, oo.b = 61)
    575   assertSame("", receiver)
    576   assertEquals(0, value)  // no setter
    577   assertThrows(function() { "use strict"; oo.b = 61 }, TypeError)
    578   receiver = ""
    579   assertEquals(62, oo.c = 62)
    580   assertSame(oo, receiver)
    581   assertEquals(62, value)
    582   receiver = ""
    583   assertEquals(63, oo["c"] = 63)
    584   assertSame(oo, receiver)
    585   assertEquals(63, value)
    586   receiver = ""
    587   assertEquals(64, oo[3] = 64)
    588   assertSame(oo, receiver)
    589   assertEquals(64, value)
    590 }
    591 
    592 TestAccessorCall(
    593   function() { receiver = this; return 42 },
    594   function(x) { receiver = this; value = x }
    595 )
    596 
    597 TestAccessorCall(
    598   function() { "use strict"; receiver = this; return 42 },
    599   function(x) { "use strict"; receiver = this; value = x }
    600 )
    601 
    602 TestAccessorCall(
    603   Proxy.createFunction({}, function() { receiver = this; return 42 }),
    604   Proxy.createFunction({}, function(x) { receiver = this; value = x })
    605 )
    606 
    607 TestAccessorCall(
    608   CreateFrozen({}, function() { receiver = this; return 42 }),
    609   CreateFrozen({}, function(x) { receiver = this; value = x })
    610 )
    611 
    612 
    613 
    614 // Passing a proxy function to higher-order library functions.
    615 
    616 function TestHigherOrder(f) {
    617   assertEquals(6, [6, 2].map(f)[0])
    618   assertEquals(4, [5, 2].reduce(f, 4))
    619   assertTrue([1, 2].some(f))
    620   assertEquals("a.b.c", "a.b.c".replace(".", f))
    621 }
    622 
    623 TestHigherOrder(function(x) { return x })
    624 TestHigherOrder(function(x) { "use strict"; return x })
    625 TestHigherOrder(Proxy.createFunction({}, function(x) { return x }))
    626 TestHigherOrder(CreateFrozen({}, function(x) { return x }))
    627 
    628 
    629 
    630 // TODO(rossberg): Ultimately, I want to have the following test function
    631 // run through, but it currently fails on so many cases (some not even
    632 // involving proxies), that I leave that for later...
    633 /*
    634 function TestCalls() {
    635   var handler = {
    636     get: function(r, k) {
    637       return k == "length" ? 2 : Function.prototype[k]
    638     }
    639   }
    640   var bind = Function.prototype.bind
    641   var o = {}
    642 
    643   var traps = [
    644     function(x, y) {
    645       return {receiver: this, result: x + y, strict: false}
    646     },
    647     function(x, y) { "use strict";
    648       return {receiver: this, result: x + y, strict: true}
    649     },
    650     function() {
    651       var x = arguments[0], y = arguments[1]
    652       return {receiver: this, result: x + y, strict: false}
    653     },
    654     Proxy.createFunction(handler, function(x, y) {
    655       return {receiver: this, result: x + y, strict: false}
    656     }),
    657     Proxy.createFunction(handler, function() {
    658       var x = arguments[0], y = arguments[1]
    659       return {receiver: this, result: x + y, strict: false}
    660     }),
    661     Proxy.createFunction(handler, function(x, y) { "use strict"
    662       return {receiver: this, result: x + y, strict: true}
    663     }),
    664     CreateFrozen(handler, function(x, y) {
    665       return {receiver: this, result: x + y, strict: false}
    666     }),
    667     CreateFrozen(handler, function(x, y) { "use strict"
    668       return {receiver: this, result: x + y, strict: true}
    669     }),
    670   ]
    671   var creates = [
    672     function(trap) { return trap },
    673     function(trap) { return CreateFrozen({}, callTrap) },
    674     function(trap) { return Proxy.createFunction(handler, callTrap) },
    675     function(trap) {
    676       return Proxy.createFunction(handler, CreateFrozen({}, callTrap))
    677     },
    678     function(trap) {
    679       return Proxy.createFunction(handler, Proxy.createFunction(handler, callTrap))
    680     },
    681   ]
    682   var binds = [
    683     function(f, o, x, y) { return f },
    684     function(f, o, x, y) { return bind.call(f, o) },
    685     function(f, o, x, y) { return bind.call(f, o, x) },
    686     function(f, o, x, y) { return bind.call(f, o, x, y) },
    687     function(f, o, x, y) { return bind.call(f, o, x, y, 5) },
    688     function(f, o, x, y) { return bind.call(bind.call(f, o), {}, x, y) },
    689     function(f, o, x, y) { return bind.call(bind.call(f, o, x), {}, y) },
    690     function(f, o, x, y) { return bind.call(bind.call(f, o, x, y), {}, 5) },
    691   ]
    692   var calls = [
    693     function(f, x, y) { return f(x, y) },
    694     function(f, x, y) { var g = f; return g(x, y) },
    695     function(f, x, y) { with ({}) return f(x, y) },
    696     function(f, x, y) { var g = f; with ({}) return g(x, y) },
    697     function(f, x, y, o) { with (o) return f(x, y) },
    698     function(f, x, y, o) { return f.call(o, x, y) },
    699     function(f, x, y, o) { return f.apply(o, [x, y]) },
    700     function(f, x, y, o) { return Function.prototype.call.call(f, o, x, y) },
    701     function(f, x, y, o) { return Function.prototype.apply.call(f, o, [x, y]) },
    702     function(f, x, y, o) { return %_CallFunction(o, x, y, f) },
    703     function(f, x, y, o) { return %Call(o, x, y, f) },
    704     function(f, x, y, o) { return %Apply(f, o, [null, x, y, null], 1, 2) },
    705     function(f, x, y, o) { return %Apply(f, o, arguments, 2, 2) },
    706     function(f, x, y, o) { if (typeof o == "object") return o.f(x, y) },
    707     function(f, x, y, o) { if (typeof o == "object") return o["f"](x, y) },
    708     function(f, x, y, o) { if (typeof o == "object") return (1, o).f(x, y) },
    709     function(f, x, y, o) { if (typeof o == "object") return (1, o)["f"](x, y) },
    710   ]
    711   var receivers = [o, global_object, undefined, null, 2, "bla", true]
    712   var expectedNonStricts = [o, global_object, global_object, global_object]
    713 
    714   for (var t = 0; t < traps.length; ++t) {
    715     for (var i = 0; i < creates.length; ++i) {
    716       for (var j = 0; j < binds.length; ++j) {
    717         for (var k = 0; k < calls.length; ++k) {
    718           for (var m = 0; m < receivers.length; ++m) {
    719             for (var n = 0; n < receivers.length; ++n) {
    720               var bound = receivers[m]
    721               var receiver = receivers[n]
    722               var func = binds[j](creates[i](traps[t]), bound, 31, 11)
    723               var expected = j > 0 ? bound : receiver
    724               var expectedNonStrict = expectedNonStricts[j > 0 ? m : n]
    725               o.f = func
    726               global_object.f = func
    727               var x = calls[k](func, 11, 31, receiver)
    728               if (x !== undefined) {
    729                 assertEquals(42, x.result)
    730                 if (calls[k].length < 4)
    731                   assertSame(x.strict ? undefined : global_object, x.receiver)
    732                 else if (x.strict)
    733                   assertSame(expected, x.receiver)
    734                 else if (expectedNonStrict === undefined)
    735                   assertSame(expected, x.receiver.valueOf())
    736                 else
    737                   assertSame(expectedNonStrict, x.receiver)
    738               }
    739             }
    740           }
    741         }
    742       }
    743     }
    744   }
    745 }
    746 
    747 TestCalls()
    748 */
    749