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 33function 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. 43var 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 51var global_object = this 52var receiver 53 54function 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 226TestCall(false, function(x, y) { 227 receiver = this 228 return x + y 229}) 230 231TestCall(true, function(x, y) { 232 "use strict" 233 receiver = this 234 return x + y 235}) 236 237TestCall(false, function() { 238 receiver = this 239 return arguments[0] + arguments[1] 240}) 241 242TestCall(false, Proxy.createFunction(handler, function(x, y) { 243 receiver = this 244 return x + y 245})) 246 247TestCall(true, Proxy.createFunction(handler, function(x, y) { 248 "use strict" 249 receiver = this 250 return x + y 251})) 252 253TestCall(false, CreateFrozen(handler, function(x, y) { 254 receiver = this 255 return x + y 256})) 257 258 259 260// Using intrinsics as call traps. 261 262function TestCallIntrinsic(type, callTrap) { 263 var f = Proxy.createFunction({}, callTrap) 264 var x = f() 265 assertTrue(typeof x == type) 266} 267 268TestCallIntrinsic("boolean", Boolean) 269TestCallIntrinsic("number", Number) 270TestCallIntrinsic("string", String) 271TestCallIntrinsic("object", Object) 272TestCallIntrinsic("function", Function) 273 274 275 276// Throwing from call trap. 277 278function 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 306TestCallThrow(function() { throw "myexn" }) 307TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" })) 308TestCallThrow(CreateFrozen({}, function() { throw "myexn" })) 309 310 311 312// Construction (new). 313 314var prototype = {myprop: 0} 315var receiver 316 317var 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 326var 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 335function ReturnUndef(x, y) { 336 "use strict"; 337 receiver = this; 338 this.sum = x + y; 339} 340 341function ReturnThis(x, y) { 342 "use strict"; 343 receiver = this; 344 this.sum = x + y; 345 return this; 346} 347 348function ReturnNew(x, y) { 349 "use strict"; 350 receiver = this; 351 return {sum: x + y}; 352} 353 354function 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 362function TestConstruct(proto, constructTrap) { 363 TestConstruct2(proto, constructTrap, handlerWithPrototype) 364 TestConstruct2(proto, constructTrap, handlerSansPrototype) 365} 366 367function 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 381TestConstruct(Object.prototype, ReturnNew) 382TestConstruct(prototype, ReturnNewWithProto) 383 384TestConstruct(Object.prototype, Proxy.createFunction(handler, ReturnNew)) 385TestConstruct(prototype, Proxy.createFunction(handler, ReturnNewWithProto)) 386 387TestConstruct(Object.prototype, CreateFrozen(handler, ReturnNew)) 388TestConstruct(prototype, CreateFrozen(handler, ReturnNewWithProto)) 389 390 391 392// Construction with derived construct trap. 393 394function TestConstructFromCall(proto, returnsThis, callTrap) { 395 TestConstructFromCall2(prototype, returnsThis, callTrap, handlerWithPrototype) 396 TestConstructFromCall2(proto, returnsThis, callTrap, handlerSansPrototype) 397} 398 399function 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 416TestConstructFromCall(Object.prototype, true, ReturnUndef) 417TestConstructFromCall(Object.prototype, true, ReturnThis) 418TestConstructFromCall(Object.prototype, false, ReturnNew) 419TestConstructFromCall(prototype, false, ReturnNewWithProto) 420 421TestConstructFromCall(Object.prototype, true, 422 Proxy.createFunction(handler, ReturnUndef)) 423TestConstructFromCall(Object.prototype, true, 424 Proxy.createFunction(handler, ReturnThis)) 425TestConstructFromCall(Object.prototype, false, 426 Proxy.createFunction(handler, ReturnNew)) 427TestConstructFromCall(prototype, false, 428 Proxy.createFunction(handler, ReturnNewWithProto)) 429 430TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnUndef)) 431TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnThis)) 432TestConstructFromCall(Object.prototype, false, CreateFrozen({}, ReturnNew)) 433TestConstructFromCall(prototype, false, CreateFrozen({}, ReturnNewWithProto)) 434 435ReturnUndef.prototype = prototype 436ReturnThis.prototype = prototype 437ReturnNew.prototype = prototype 438ReturnNewWithProto.prototype = prototype 439 440TestConstructFromCall(prototype, true, ReturnUndef) 441TestConstructFromCall(prototype, true, ReturnThis) 442TestConstructFromCall(Object.prototype, false, ReturnNew) 443TestConstructFromCall(prototype, false, ReturnNewWithProto) 444 445TestConstructFromCall(Object.prototype, true, 446 Proxy.createFunction(handler, ReturnUndef)) 447TestConstructFromCall(Object.prototype, true, 448 Proxy.createFunction(handler, ReturnThis)) 449TestConstructFromCall(Object.prototype, false, 450 Proxy.createFunction(handler, ReturnNew)) 451TestConstructFromCall(prototype, false, 452 Proxy.createFunction(handler, ReturnNewWithProto)) 453 454TestConstructFromCall(prototype, true, 455 Proxy.createFunction(handlerWithPrototype, ReturnUndef)) 456TestConstructFromCall(prototype, true, 457 Proxy.createFunction(handlerWithPrototype, ReturnThis)) 458TestConstructFromCall(Object.prototype, false, 459 Proxy.createFunction(handlerWithPrototype, ReturnNew)) 460TestConstructFromCall(prototype, false, 461 Proxy.createFunction(handlerWithPrototype, 462 ReturnNewWithProto)) 463 464TestConstructFromCall(prototype, true, 465 CreateFrozen(handlerWithPrototype, ReturnUndef)) 466TestConstructFromCall(prototype, true, 467 CreateFrozen(handlerWithPrototype, ReturnThis)) 468TestConstructFromCall(Object.prototype, false, 469 CreateFrozen(handlerWithPrototype, ReturnNew)) 470TestConstructFromCall(prototype, false, 471 CreateFrozen(handlerWithPrototype, ReturnNewWithProto)) 472 473 474 475// Throwing from the construct trap. 476 477function TestConstructThrow(trap) { 478 TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} }, 479 trap)) 480 TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} }, 481 function() {}, 482 trap)) 483} 484 485function TestConstructThrow2(f) { 486 assertThrows(function(){ new f(11) }, "myexn") 487 Object.freeze(f) 488 assertThrows(function(){ new f(11) }, "myexn") 489} 490 491TestConstructThrow(function() { throw "myexn" }) 492TestConstructThrow(Proxy.createFunction({}, function() { throw "myexn" })) 493TestConstructThrow(CreateFrozen({}, function() { throw "myexn" })) 494 495 496 497// Using function proxies as getters and setters. 498 499var value 500var receiver 501 502function 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 592TestAccessorCall( 593 function() { receiver = this; return 42 }, 594 function(x) { receiver = this; value = x } 595) 596 597TestAccessorCall( 598 function() { "use strict"; receiver = this; return 42 }, 599 function(x) { "use strict"; receiver = this; value = x } 600) 601 602TestAccessorCall( 603 Proxy.createFunction({}, function() { receiver = this; return 42 }), 604 Proxy.createFunction({}, function(x) { receiver = this; value = x }) 605) 606 607TestAccessorCall( 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 616function 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 623TestHigherOrder(function(x) { return x }) 624TestHigherOrder(function(x) { "use strict"; return x }) 625TestHigherOrder(Proxy.createFunction({}, function(x) { return x })) 626TestHigherOrder(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/* 634function 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 747TestCalls() 748*/ 749