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