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