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