proxies.js revision 589d6979ff2ef66fca2d8fa51404c369ca5e9250
1// Copyright 2008 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 29 30 31// TODO(rossberg): for-in for proxies not implemented. 32// TODO(rossberg): inheritance from proxies not implemented. 33// TODO(rossberg): function proxies as constructors not implemented. 34 35 36// Helper. 37 38function TestWithProxies(test, handler) { 39 test(handler, Proxy.create) 40 test(handler, function(h) {return Proxy.createFunction(h, function() {})}) 41} 42 43 44// Getters. 45 46function TestGet(handler) { 47 TestWithProxies(TestGet2, handler) 48} 49 50function TestGet2(handler, create) { 51 var p = create(handler) 52 assertEquals(42, p.a) 53 assertEquals(42, p["b"]) 54 55 // TODO(rossberg): inheritance from proxies not yet implemented. 56 // var o = Object.create(p, {x: {value: 88}}) 57 // assertEquals(42, o.a) 58 // assertEquals(42, o["b"]) 59 // assertEquals(88, o.x) 60 // assertEquals(88, o["x"]) 61} 62 63TestGet({ 64 get: function(r, k) { return 42 } 65}) 66 67TestGet({ 68 get: function(r, k) { return this.get2(r, k) }, 69 get2: function(r, k) { return 42 } 70}) 71 72TestGet({ 73 getPropertyDescriptor: function(k) { return {value: 42} } 74}) 75 76TestGet({ 77 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 78 getPropertyDescriptor2: function(k) { return {value: 42} } 79}) 80 81TestGet({ 82 getPropertyDescriptor: function(k) { 83 return {get value() { return 42 }} 84 } 85}) 86 87TestGet({ 88 get: undefined, 89 getPropertyDescriptor: function(k) { return {value: 42} } 90}) 91 92TestGet(Proxy.create({ 93 get: function(pr, pk) { 94 return function(r, k) { return 42 } 95 } 96})) 97 98 99function TestGetCall(handler) { 100 TestWithProxies(TestGetCall2, handler) 101} 102 103function TestGetCall2(handler, create) { 104 var p = create(handler) 105 assertEquals(55, p.f()) 106 assertEquals(55, p.f("unused", "arguments")) 107 assertEquals(55, p.f.call(p)) 108 assertEquals(55, p.withargs(45, 5)) 109 assertEquals(55, p.withargs.call(p, 11, 22)) 110 assertEquals("6655", "66" + p) // calls p.toString 111} 112 113TestGetCall({ 114 get: function(r, k) { return function() { return 55 } } 115}) 116 117TestGetCall({ 118 get: function(r, k) { return this.get2(r, k) }, 119 get2: function(r, k) { return function() { return 55 } } 120}) 121 122TestGetCall({ 123 getPropertyDescriptor: function(k) { 124 return {value: function() { return 55 }} 125 } 126}) 127 128TestGetCall({ 129 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 130 getPropertyDescriptor2: function(k) { 131 return {value: function() { return 55 }} 132 } 133}) 134 135TestGetCall({ 136 getPropertyDescriptor: function(k) { 137 return {get value() { return function() { return 55 } }} 138 } 139}) 140 141TestGetCall({ 142 get: undefined, 143 getPropertyDescriptor: function(k) { 144 return {value: function() { return 55 }} 145 } 146}) 147 148TestGetCall({ 149 get: function(r, k) { 150 if (k == "gg") { 151 return function() { return 55 } 152 } else if (k == "withargs") { 153 return function(n, m) { return n + m * 2 } 154 } else { 155 return function() { return this.gg() } 156 } 157 } 158}) 159 160TestGetCall(Proxy.create({ 161 get: function(pr, pk) { 162 return function(r, k) { return function() { return 55 } } 163 } 164})) 165 166 167function TestGetThrow(handler) { 168 TestWithProxies(TestGetThrow2, handler) 169} 170 171function TestGetThrow2(handler, create) { 172 var p = create(handler) 173 assertThrows(function(){ p.a }, "myexn") 174 assertThrows(function(){ p["b"] }, "myexn") 175} 176 177TestGetThrow({ 178 get: function(r, k) { throw "myexn" } 179}) 180 181TestGetThrow({ 182 get: function(r, k) { return this.get2(r, k) }, 183 get2: function(r, k) { throw "myexn" } 184}) 185 186TestGetThrow({ 187 getPropertyDescriptor: function(k) { throw "myexn" } 188}) 189 190TestGetThrow({ 191 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 192 getPropertyDescriptor2: function(k) { throw "myexn" } 193}) 194 195TestGetThrow({ 196 getPropertyDescriptor: function(k) { 197 return {get value() { throw "myexn" }} 198 } 199}) 200 201TestGetThrow({ 202 get: undefined, 203 getPropertyDescriptor: function(k) { throw "myexn" } 204}) 205 206TestGetThrow(Proxy.create({ 207 get: function(pr, pk) { throw "myexn" } 208})) 209 210TestGetThrow(Proxy.create({ 211 get: function(pr, pk) { 212 return function(r, k) { throw "myexn" } 213 } 214})) 215 216 217 218// Setters. 219 220var key 221var val 222 223function TestSet(handler, create) { 224 TestWithProxies(TestSet2, handler) 225} 226 227function TestSet2(handler, create) { 228 var p = create(handler) 229 assertEquals(42, p.a = 42) 230 assertEquals("a", key) 231 assertEquals(42, val) 232 assertEquals(43, p["b"] = 43) 233 assertEquals("b", key) 234 assertEquals(43, val) 235} 236 237TestSet({ 238 set: function(r, k, v) { key = k; val = v; return true } 239}) 240 241TestSet({ 242 set: function(r, k, v) { return this.set2(r, k, v) }, 243 set2: function(r, k, v) { key = k; val = v; return true } 244}) 245 246TestSet({ 247 getOwnPropertyDescriptor: function(k) { return {writable: true} }, 248 defineProperty: function(k, desc) { key = k; val = desc.value } 249}) 250 251TestSet({ 252 getOwnPropertyDescriptor: function(k) { 253 return this.getOwnPropertyDescriptor2(k) 254 }, 255 getOwnPropertyDescriptor2: function(k) { return {writable: true} }, 256 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, 257 defineProperty2: function(k, desc) { key = k; val = desc.value } 258}) 259 260TestSet({ 261 getOwnPropertyDescriptor: function(k) { 262 return {get writable() { return true }} 263 }, 264 defineProperty: function(k, desc) { key = k; val = desc.value } 265}) 266 267TestSet({ 268 getOwnPropertyDescriptor: function(k) { 269 return {set: function(v) { key = k; val = v }} 270 } 271}) 272 273TestSet({ 274 getOwnPropertyDescriptor: function(k) { return null }, 275 getPropertyDescriptor: function(k) { return {writable: true} }, 276 defineProperty: function(k, desc) { key = k; val = desc.value } 277}) 278 279TestSet({ 280 getOwnPropertyDescriptor: function(k) { return null }, 281 getPropertyDescriptor: function(k) { 282 return {get writable() { return true }} 283 }, 284 defineProperty: function(k, desc) { key = k; val = desc.value } 285}) 286 287TestSet({ 288 getOwnPropertyDescriptor: function(k) { return null }, 289 getPropertyDescriptor: function(k) { 290 return {set: function(v) { key = k; val = v }} 291 } 292}) 293 294TestSet({ 295 getOwnPropertyDescriptor: function(k) { return null }, 296 getPropertyDescriptor: function(k) { return null }, 297 defineProperty: function(k, desc) { key = k, val = desc.value } 298}) 299 300TestSet(Proxy.create({ 301 get: function(pr, pk) { 302 return function(r, k, v) { key = k; val = v; return true } 303 } 304})) 305 306 307 308function TestSetThrow(handler, create) { 309 TestWithProxies(TestSetThrow2, handler) 310} 311 312function TestSetThrow2(handler, create) { 313 var p = create(handler) 314 assertThrows(function(){ p.a = 42 }, "myexn") 315 assertThrows(function(){ p["b"] = 42 }, "myexn") 316} 317 318TestSetThrow({ 319 set: function(r, k, v) { throw "myexn" } 320}) 321 322TestSetThrow({ 323 set: function(r, k, v) { return this.set2(r, k, v) }, 324 set2: function(r, k, v) { throw "myexn" } 325}) 326 327TestSetThrow({ 328 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 329 defineProperty: function(k, desc) { key = k; val = desc.value } 330}) 331 332TestSetThrow({ 333 getOwnPropertyDescriptor: function(k) { return {writable: true} }, 334 defineProperty: function(k, desc) { throw "myexn" } 335}) 336 337TestSetThrow({ 338 getOwnPropertyDescriptor: function(k) { 339 return this.getOwnPropertyDescriptor2(k) 340 }, 341 getOwnPropertyDescriptor2: function(k) { throw "myexn" }, 342 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, 343 defineProperty2: function(k, desc) { key = k; val = desc.value } 344}) 345 346TestSetThrow({ 347 getOwnPropertyDescriptor: function(k) { 348 return this.getOwnPropertyDescriptor2(k) 349 }, 350 getOwnPropertyDescriptor2: function(k) { return {writable: true} }, 351 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, 352 defineProperty2: function(k, desc) { throw "myexn" } 353}) 354 355TestSetThrow({ 356 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 357 defineProperty: function(k, desc) { key = k; val = desc.value } 358}) 359 360TestSetThrow({ 361 getOwnPropertyDescriptor: function(k) { 362 return {get writable() { return true }} 363 }, 364 defineProperty: function(k, desc) { throw "myexn" } 365}) 366 367TestSetThrow({ 368 getOwnPropertyDescriptor: function(k) { throw "myexn" } 369}) 370 371TestSetThrow({ 372 getOwnPropertyDescriptor: function(k) { 373 return {set: function(v) { throw "myexn" }} 374 } 375}) 376 377TestSetThrow({ 378 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 379 getPropertyDescriptor: function(k) { return {writable: true} }, 380 defineProperty: function(k, desc) { key = k; val = desc.value } 381}) 382 383TestSetThrow({ 384 getOwnPropertyDescriptor: function(k) { return null }, 385 getPropertyDescriptor: function(k) { throw "myexn" }, 386 defineProperty: function(k, desc) { key = k; val = desc.value } 387}) 388 389TestSetThrow({ 390 getOwnPropertyDescriptor: function(k) { return null }, 391 getPropertyDescriptor: function(k) { return {writable: true} }, 392 defineProperty: function(k, desc) { throw "myexn" } 393}) 394 395TestSetThrow({ 396 getOwnPropertyDescriptor: function(k) { return null }, 397 getPropertyDescriptor: function(k) { 398 return {get writable() { throw "myexn" }} 399 }, 400 defineProperty: function(k, desc) { key = k; val = desc.value } 401}) 402 403TestSetThrow({ 404 getOwnPropertyDescriptor: function(k) { return null }, 405 getPropertyDescriptor: function(k) { 406 return {set: function(v) { throw "myexn" }} 407 } 408}) 409 410TestSetThrow({ 411 getOwnPropertyDescriptor: function(k) { return null }, 412 getPropertyDescriptor: function(k) { return null }, 413 defineProperty: function(k, desc) { throw "myexn" } 414}) 415 416TestSetThrow(Proxy.create({ 417 get: function(pr, pk) { throw "myexn" } 418})) 419 420TestSetThrow(Proxy.create({ 421 get: function(pr, pk) { 422 return function(r, k, v) { throw "myexn" } 423 } 424})) 425 426 427 428// Property definition (Object.defineProperty and Object.defineProperties). 429 430var key 431var desc 432 433function TestDefine(handler) { 434 TestWithProxies(TestDefine2, handler) 435} 436 437function TestDefine2(handler, create) { 438 var p = create(handler) 439 assertEquals(p, Object.defineProperty(p, "a", {value: 44})) 440 assertEquals("a", key) 441 assertEquals(1, Object.getOwnPropertyNames(desc).length) 442 assertEquals(44, desc.value) 443 444 assertEquals(p, Object.defineProperty(p, "b", {value: 45, writable: false})) 445 assertEquals("b", key) 446 assertEquals(2, Object.getOwnPropertyNames(desc).length) 447 assertEquals(45, desc.value) 448 assertEquals(false, desc.writable) 449 450 assertEquals(p, Object.defineProperty(p, "c", {value: 46, enumerable: false})) 451 assertEquals("c", key) 452 assertEquals(2, Object.getOwnPropertyNames(desc).length) 453 assertEquals(46, desc.value) 454 assertEquals(false, desc.enumerable) 455 456 var attributes = {configurable: true, mine: 66, minetoo: 23} 457 assertEquals(p, Object.defineProperty(p, "d", attributes)) 458 assertEquals("d", key) 459 // Modifying the attributes object after the fact should have no effect. 460 attributes.configurable = false 461 attributes.mine = 77 462 delete attributes.minetoo 463 assertEquals(3, Object.getOwnPropertyNames(desc).length) 464 assertEquals(true, desc.configurable) 465 assertEquals(66, desc.mine) 466 assertEquals(23, desc.minetoo) 467 468 assertEquals(p, Object.defineProperty(p, "e", {get: function(){ return 5 }})) 469 assertEquals("e", key) 470 assertEquals(1, Object.getOwnPropertyNames(desc).length) 471 assertEquals(5, desc.get()) 472 473 assertEquals(p, Object.defineProperty(p, "zzz", {})) 474 assertEquals("zzz", key) 475 assertEquals(0, Object.getOwnPropertyNames(desc).length) 476 477// TODO(rossberg): This test requires for-in on proxies. 478// var d = create({ 479// get: function(r, k) { return (k === "value") ? 77 : void 0 }, 480// getOwnPropertyNames: function() { return ["value"] } 481// }) 482// assertEquals(1, Object.getOwnPropertyNames(d).length) 483// assertEquals(77, d.value) 484// assertEquals(p, Object.defineProperty(p, "p", d)) 485// assertEquals("p", key) 486// assertEquals(1, Object.getOwnPropertyNames(desc).length) 487// assertEquals(77, desc.value) 488 489 var props = { 490 'bla': {}, 491 blub: {get: function() { return true }}, 492 '': {get value() { return 20 }}, 493 last: {value: 21, configurable: true, mine: "eyes"} 494 } 495 Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false}) 496 assertEquals(p, Object.defineProperties(p, props)) 497 assertEquals("last", key) 498 assertEquals(2, Object.getOwnPropertyNames(desc).length) 499 assertEquals(21, desc.value) 500 assertEquals(true, desc.configurable) 501 assertEquals(undefined, desc.mine) // Arguably a bug in the spec... 502 503 var props = {bla: {get value() { throw "myexn" }}} 504 assertThrows(function(){ Object.defineProperties(p, props) }, "myexn") 505} 506 507TestDefine({ 508 defineProperty: function(k, d) { key = k; desc = d; return true } 509}) 510 511TestDefine({ 512 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, 513 defineProperty2: function(k, d) { key = k; desc = d; return true } 514}) 515 516TestDefine(Proxy.create({ 517 get: function(pr, pk) { 518 return function(k, d) { key = k; desc = d; return true } 519 } 520})) 521 522 523function TestDefineThrow(handler) { 524 TestWithProxies(TestDefineThrow2, handler) 525} 526 527function TestDefineThrow2(handler, create) { 528 var p = create(handler) 529 assertThrows(function(){ Object.defineProperty(p, "a", {value: 44})}, "myexn") 530 531// TODO(rossberg): These tests require for-in on proxies. 532// var d1 = create({ 533// get: function(r, k) { throw "myexn" }, 534// getOwnPropertyNames: function() { return ["value"] } 535// }) 536// assertThrows(function(){ Object.defineProperty(p, "p", d1) }, "myexn") 537// var d2 = create({ 538// get: function(r, k) { return 77 }, 539// getOwnPropertyNames: function() { throw "myexn" } 540// }) 541// assertThrows(function(){ Object.defineProperty(p, "p", d2) }, "myexn") 542 543 var props = {bla: {get value() { throw "otherexn" }}} 544 assertThrows(function(){ Object.defineProperties(p, props) }, "otherexn") 545} 546 547TestDefineThrow({ 548 defineProperty: function(k, d) { throw "myexn" } 549}) 550 551TestDefineThrow({ 552 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, 553 defineProperty2: function(k, d) { throw "myexn" } 554}) 555 556TestDefineThrow(Proxy.create({ 557 get: function(pr, pk) { throw "myexn" } 558})) 559 560TestDefineThrow(Proxy.create({ 561 get: function(pr, pk) { 562 return function(k, d) { throw "myexn" } 563 } 564})) 565 566 567 568// Property deletion (delete). 569 570var key 571 572function TestDelete(handler) { 573 TestWithProxies(TestDelete2, handler) 574} 575 576function TestDelete2(handler, create) { 577 var p = create(handler) 578 assertEquals(true, delete p.a) 579 assertEquals("a", key) 580 assertEquals(true, delete p["b"]) 581 assertEquals("b", key) 582 583 assertEquals(false, delete p.z1) 584 assertEquals("z1", key) 585 assertEquals(false, delete p["z2"]) 586 assertEquals("z2", key); 587 588 (function() { 589 "use strict" 590 assertEquals(true, delete p.c) 591 assertEquals("c", key) 592 assertEquals(true, delete p["d"]) 593 assertEquals("d", key) 594 595 assertThrows(function(){ delete p.z3 }, TypeError) 596 assertEquals("z3", key) 597 assertThrows(function(){ delete p["z4"] }, TypeError) 598 assertEquals("z4", key) 599 })() 600} 601 602TestDelete({ 603 delete: function(k) { key = k; return k < "z" } 604}) 605 606TestDelete({ 607 delete: function(k) { return this.delete2(k) }, 608 delete2: function(k) { key = k; return k < "z" } 609}) 610 611TestDelete(Proxy.create({ 612 get: function(pr, pk) { 613 return function(k) { key = k; return k < "z" } 614 } 615})) 616 617 618function TestDeleteThrow(handler) { 619 TestWithProxies(TestDeleteThrow2, handler) 620} 621 622function TestDeleteThrow2(handler, create) { 623 var p = create(handler) 624 assertThrows(function(){ delete p.a }, "myexn") 625 assertThrows(function(){ delete p["b"] }, "myexn"); 626 627 (function() { 628 "use strict" 629 assertThrows(function(){ delete p.c }, "myexn") 630 assertThrows(function(){ delete p["d"] }, "myexn") 631 })() 632} 633 634TestDeleteThrow({ 635 delete: function(k) { throw "myexn" } 636}) 637 638TestDeleteThrow({ 639 delete: function(k) { return this.delete2(k) }, 640 delete2: function(k) { throw "myexn" } 641}) 642 643TestDeleteThrow(Proxy.create({ 644 get: function(pr, pk) { throw "myexn" } 645})) 646 647TestDeleteThrow(Proxy.create({ 648 get: function(pr, pk) { 649 return function(k) { throw "myexn" } 650 } 651})) 652 653 654 655// Property descriptors (Object.getOwnPropertyDescriptor). 656 657function TestDescriptor(handler) { 658 TestWithProxies(TestDescriptor2, handler) 659} 660 661function TestDescriptor2(handler, create) { 662 var p = create(handler) 663 var descs = [ 664 {configurable: true}, 665 {value: 34, enumerable: true, configurable: true}, 666 {value: 3, writable: false, mine: "eyes", configurable: true}, 667 {get value() { return 20 }, get configurable() { return true }}, 668 {get: function() { "get" }, set: function() { "set" }, configurable: true} 669 ] 670 for (var i = 0; i < descs.length; ++i) { 671 assertEquals(p, Object.defineProperty(p, i, descs[i])) 672 var desc = Object.getOwnPropertyDescriptor(p, i) 673 for (prop in descs[i]) { 674 // TODO(rossberg): Ignore user attributes as long as the spec isn't 675 // fixed suitably. 676 if (prop != "mine") assertEquals(descs[i][prop], desc[prop]) 677 } 678 assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent")) 679 } 680} 681 682TestDescriptor({ 683 defineProperty: function(k, d) { this["__" + k] = d; return true }, 684 getOwnPropertyDescriptor: function(k) { return this["__" + k] } 685}) 686 687TestDescriptor({ 688 defineProperty: function(k, d) { this["__" + k] = d; return true }, 689 getOwnPropertyDescriptor: function(k) { 690 return this.getOwnPropertyDescriptor2(k) 691 }, 692 getOwnPropertyDescriptor2: function(k) { return this["__" + k] } 693}) 694 695 696function TestDescriptorThrow(handler) { 697 TestWithProxies(TestDescriptorThrow2, handler) 698} 699 700function TestDescriptorThrow2(handler, create) { 701 var p = create(handler) 702 assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn") 703} 704 705TestDescriptorThrow({ 706 getOwnPropertyDescriptor: function(k) { throw "myexn" } 707}) 708 709TestDescriptorThrow({ 710 getOwnPropertyDescriptor: function(k) { 711 return this.getOwnPropertyDescriptor2(k) 712 }, 713 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 714}) 715 716 717 718// Comparison. 719 720function TestComparison(eq) { 721 TestWithProxies(TestComparison2, eq) 722} 723 724function TestComparison2(eq, create) { 725 var p1 = create({}) 726 var p2 = create({}) 727 728 assertTrue(eq(p1, p1)) 729 assertTrue(eq(p2, p2)) 730 assertTrue(!eq(p1, p2)) 731 assertTrue(!eq(p1, {})) 732 assertTrue(!eq({}, p2)) 733 assertTrue(!eq({}, {})) 734} 735 736TestComparison(function(o1, o2) { return o1 == o2 }) 737TestComparison(function(o1, o2) { return o1 === o2 }) 738TestComparison(function(o1, o2) { return !(o1 != o2) }) 739TestComparison(function(o1, o2) { return !(o1 !== o2) }) 740 741 742 743// Type (typeof). 744 745function TestTypeof() { 746 assertEquals("object", typeof Proxy.create({})) 747 assertTrue(typeof Proxy.create({}) == "object") 748 assertTrue("object" == typeof Proxy.create({})) 749 750 assertEquals("function", typeof Proxy.createFunction({}, function() {})) 751 assertTrue(typeof Proxy.createFunction({}, function() {}) == "function") 752 assertTrue("function" == typeof Proxy.createFunction({}, function() {})) 753} 754 755TestTypeof() 756 757 758 759// Membership test (in). 760 761var key 762 763function TestIn(handler) { 764 TestWithProxies(TestIn2, handler) 765} 766 767function TestIn2(handler, create) { 768 var p = create(handler) 769 assertTrue("a" in p) 770 assertEquals("a", key) 771 assertTrue(99 in p) 772 assertEquals("99", key) 773 assertFalse("z" in p) 774 assertEquals("z", key) 775 776 assertEquals(2, ("a" in p) ? 2 : 0) 777 assertEquals(0, !("a" in p) ? 2 : 0) 778 assertEquals(0, ("zzz" in p) ? 2 : 0) 779 assertEquals(2, !("zzz" in p) ? 2 : 0) 780 781 if ("b" in p) { 782 } else { 783 assertTrue(false) 784 } 785 assertEquals("b", key) 786 787 if ("zz" in p) { 788 assertTrue(false) 789 } 790 assertEquals("zz", key) 791 792 if (!("c" in p)) { 793 assertTrue(false) 794 } 795 assertEquals("c", key) 796 797 if (!("zzz" in p)) { 798 } else { 799 assertTrue(false) 800 } 801 assertEquals("zzz", key) 802} 803 804TestIn({ 805 has: function(k) { key = k; return k < "z" } 806}) 807 808TestIn({ 809 has: function(k) { return this.has2(k) }, 810 has2: function(k) { key = k; return k < "z" } 811}) 812 813TestIn({ 814 getPropertyDescriptor: function(k) { 815 key = k; return k < "z" ? {value: 42} : void 0 816 } 817}) 818 819TestIn({ 820 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 821 getPropertyDescriptor2: function(k) { 822 key = k; return k < "z" ? {value: 42} : void 0 823 } 824}) 825 826TestIn({ 827 getPropertyDescriptor: function(k) { 828 key = k; return k < "z" ? {get value() { return 42 }} : void 0 829 } 830}) 831 832TestIn({ 833 get: undefined, 834 getPropertyDescriptor: function(k) { 835 key = k; return k < "z" ? {value: 42} : void 0 836 } 837}) 838 839TestIn(Proxy.create({ 840 get: function(pr, pk) { 841 return function(k) { key = k; return k < "z" } 842 } 843})) 844 845 846function TestInThrow(handler) { 847 TestWithProxies(TestInThrow2, handler) 848} 849 850function TestInThrow2(handler, create) { 851 var p = create(handler) 852 assertThrows(function(){ return "a" in o }, "myexn") 853 assertThrows(function(){ return !("a" in o) }, "myexn") 854 assertThrows(function(){ return ("a" in o) ? 2 : 3 }, "myexn") 855 assertThrows(function(){ if ("b" in o) {} }, "myexn") 856 assertThrows(function(){ if (!("b" in o)) {} }, "myexn") 857 assertThrows(function(){ if ("zzz" in o) {} }, "myexn") 858} 859 860TestInThrow({ 861 has: function(k) { throw "myexn" } 862}) 863 864TestInThrow({ 865 has: function(k) { return this.has2(k) }, 866 has2: function(k) { throw "myexn" } 867}) 868 869TestInThrow({ 870 getPropertyDescriptor: function(k) { throw "myexn" } 871}) 872 873TestInThrow({ 874 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 875 getPropertyDescriptor2: function(k) { throw "myexn" } 876}) 877 878TestInThrow({ 879 get: undefined, 880 getPropertyDescriptor: function(k) { throw "myexn" } 881}) 882 883TestInThrow(Proxy.create({ 884 get: function(pr, pk) { throw "myexn" } 885})) 886 887TestInThrow(Proxy.create({ 888 get: function(pr, pk) { 889 return function(k) { throw "myexn" } 890 } 891})) 892 893 894 895// Own Properties (Object.prototype.hasOwnProperty). 896 897var key 898 899function TestHasOwn(handler) { 900 TestWithProxies(TestHasOwn2, handler) 901} 902 903function TestHasOwn2(handler, create) { 904 var p = create(handler) 905 assertTrue(Object.prototype.hasOwnProperty.call(p, "a")) 906 assertEquals("a", key) 907 assertTrue(Object.prototype.hasOwnProperty.call(p, 99)) 908 assertEquals("99", key) 909 assertFalse(Object.prototype.hasOwnProperty.call(p, "z")) 910 assertEquals("z", key) 911} 912 913TestHasOwn({ 914 hasOwn: function(k) { key = k; return k < "z" } 915}) 916 917TestHasOwn({ 918 hasOwn: function(k) { return this.hasOwn2(k) }, 919 hasOwn2: function(k) { key = k; return k < "z" } 920}) 921 922TestHasOwn({ 923 getOwnPropertyDescriptor: function(k) { 924 key = k; return k < "z" ? {value: 42} : void 0 925 } 926}) 927 928TestHasOwn({ 929 getOwnPropertyDescriptor: function(k) { 930 return this.getOwnPropertyDescriptor2(k) 931 }, 932 getOwnPropertyDescriptor2: function(k) { 933 key = k; return k < "z" ? {value: 42} : void 0 934 } 935}) 936 937TestHasOwn({ 938 getOwnPropertyDescriptor: function(k) { 939 key = k; return k < "z" ? {get value() { return 42 }} : void 0 940 } 941}) 942 943TestHasOwn({ 944 hasOwn: undefined, 945 getOwnPropertyDescriptor: function(k) { 946 key = k; return k < "z" ? {value: 42} : void 0 947 } 948}) 949 950TestHasOwn(Proxy.create({ 951 get: function(pr, pk) { 952 return function(k) { key = k; return k < "z" } 953 } 954})) 955 956 957function TestHasOwnThrow(handler) { 958 TestWithProxies(TestHasOwnThrow2, handler) 959} 960 961function TestHasOwnThrow2(handler, create) { 962 var p = create(handler) 963 assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, "a")}, 964 "myexn") 965 assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, 99)}, 966 "myexn") 967} 968 969TestHasOwnThrow({ 970 hasOwn: function(k) { throw "myexn" } 971}) 972 973TestHasOwnThrow({ 974 hasOwn: function(k) { return this.hasOwn2(k) }, 975 hasOwn2: function(k) { throw "myexn" } 976}) 977 978TestHasOwnThrow({ 979 getOwnPropertyDescriptor: function(k) { throw "myexn" } 980}) 981 982TestHasOwnThrow({ 983 getOwnPropertyDescriptor: function(k) { 984 return this.getOwnPropertyDescriptor2(k) 985 }, 986 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 987}) 988 989TestHasOwnThrow({ 990 hasOwn: undefined, 991 getOwnPropertyDescriptor: function(k) { throw "myexn" } 992}) 993 994TestHasOwnThrow(Proxy.create({ 995 get: function(pr, pk) { throw "myexn" } 996})) 997 998TestHasOwnThrow(Proxy.create({ 999 get: function(pr, pk) { 1000 return function(k) { throw "myexn" } 1001 } 1002})) 1003 1004 1005 1006// Instanceof (instanceof) 1007 1008function TestInstanceof() { 1009 var o = {} 1010 var p1 = Proxy.create({}) 1011 var p2 = Proxy.create({}, o) 1012 var p3 = Proxy.create({}, p2) 1013 1014 var f0 = function() {} 1015 f0.prototype = o 1016 var f1 = function() {} 1017 f1.prototype = p1 1018 var f2 = function() {} 1019 f2.prototype = p2 1020 1021 assertTrue(o instanceof Object) 1022 assertFalse(o instanceof f0) 1023 assertFalse(o instanceof f1) 1024 assertFalse(o instanceof f2) 1025 assertFalse(p1 instanceof Object) 1026 assertFalse(p1 instanceof f0) 1027 assertFalse(p1 instanceof f1) 1028 assertFalse(p1 instanceof f2) 1029 assertTrue(p2 instanceof Object) 1030 assertTrue(p2 instanceof f0) 1031 assertFalse(p2 instanceof f1) 1032 assertFalse(p2 instanceof f2) 1033 assertTrue(p3 instanceof Object) 1034 assertTrue(p3 instanceof f0) 1035 assertFalse(p3 instanceof f1) 1036 assertTrue(p3 instanceof f2) 1037 1038 var f = Proxy.createFunction({}, function() {}) 1039 assertTrue(f instanceof Function) 1040} 1041 1042TestInstanceof() 1043 1044 1045 1046// Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). 1047 1048function TestPrototype() { 1049 var o = {} 1050 var p1 = Proxy.create({}) 1051 var p2 = Proxy.create({}, o) 1052 var p3 = Proxy.create({}, p2) 1053 var p4 = Proxy.create({}, 666) 1054 1055 assertSame(Object.getPrototypeOf(o), Object.prototype) 1056 assertSame(Object.getPrototypeOf(p1), null) 1057 assertSame(Object.getPrototypeOf(p2), o) 1058 assertSame(Object.getPrototypeOf(p3), p2) 1059 assertSame(Object.getPrototypeOf(p4), null) 1060 1061 assertTrue(Object.prototype.isPrototypeOf(o)) 1062 assertFalse(Object.prototype.isPrototypeOf(p1)) 1063 assertTrue(Object.prototype.isPrototypeOf(p2)) 1064 assertTrue(Object.prototype.isPrototypeOf(p3)) 1065 assertFalse(Object.prototype.isPrototypeOf(p4)) 1066 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o)) 1067 assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p1)) 1068 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2)) 1069 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3)) 1070 assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p4)) 1071 assertFalse(Object.prototype.isPrototypeOf.call(o, o)) 1072 assertFalse(Object.prototype.isPrototypeOf.call(o, p1)) 1073 assertTrue(Object.prototype.isPrototypeOf.call(o, p2)) 1074 assertTrue(Object.prototype.isPrototypeOf.call(o, p3)) 1075 assertFalse(Object.prototype.isPrototypeOf.call(o, p4)) 1076 assertFalse(Object.prototype.isPrototypeOf.call(p1, p1)) 1077 assertFalse(Object.prototype.isPrototypeOf.call(p1, o)) 1078 assertFalse(Object.prototype.isPrototypeOf.call(p1, p2)) 1079 assertFalse(Object.prototype.isPrototypeOf.call(p1, p3)) 1080 assertFalse(Object.prototype.isPrototypeOf.call(p1, p4)) 1081 assertFalse(Object.prototype.isPrototypeOf.call(p2, p1)) 1082 assertFalse(Object.prototype.isPrototypeOf.call(p2, p2)) 1083 assertTrue(Object.prototype.isPrototypeOf.call(p2, p3)) 1084 assertFalse(Object.prototype.isPrototypeOf.call(p2, p4)) 1085 assertFalse(Object.prototype.isPrototypeOf.call(p3, p2)) 1086 1087 var f = Proxy.createFunction({}, function() {}) 1088 assertSame(Object.getPrototypeOf(f), Function.prototype) 1089 assertTrue(Object.prototype.isPrototypeOf(f)) 1090 assertTrue(Object.prototype.isPrototypeOf.call(Function.prototype, f)) 1091} 1092 1093TestPrototype() 1094 1095 1096 1097// Property names (Object.getOwnPropertyNames, Object.keys). 1098 1099function TestPropertyNames(names, handler) { 1100 TestWithProxies(TestPropertyNames2, [names, handler]) 1101} 1102 1103function TestPropertyNames2(names_handler, create) { 1104 var p = create(names_handler[1]) 1105 assertArrayEquals(names_handler[0], Object.getOwnPropertyNames(p)) 1106} 1107 1108TestPropertyNames([], { 1109 getOwnPropertyNames: function() { return [] } 1110}) 1111 1112TestPropertyNames(["a", "zz", " ", "0"], { 1113 getOwnPropertyNames: function() { return ["a", "zz", " ", 0] } 1114}) 1115 1116TestPropertyNames(["throw", "function "], { 1117 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1118 getOwnPropertyNames2: function() { return ["throw", "function "] } 1119}) 1120 1121TestPropertyNames(["[object Object]"], { 1122 get getOwnPropertyNames() { 1123 return function() { return [{}] } 1124 } 1125}) 1126 1127 1128function TestPropertyNamesThrow(handler) { 1129 TestWithProxies(TestPropertyNamesThrow2, handler) 1130} 1131 1132function TestPropertyNamesThrow2(handler, create) { 1133 var p = create(handler) 1134 assertThrows(function(){ Object.getOwnPropertyNames(p) }, "myexn") 1135} 1136 1137TestPropertyNamesThrow({ 1138 getOwnPropertyNames: function() { throw "myexn" } 1139}) 1140 1141TestPropertyNamesThrow({ 1142 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1143 getOwnPropertyNames2: function() { throw "myexn" } 1144}) 1145 1146 1147function TestKeys(names, handler) { 1148 TestWithProxies(TestKeys2, [names, handler]) 1149} 1150 1151function TestKeys2(names_handler, create) { 1152 var p = create(names_handler[1]) 1153 assertArrayEquals(names_handler[0], Object.keys(p)) 1154} 1155 1156TestKeys([], { 1157 keys: function() { return [] } 1158}) 1159 1160TestKeys(["a", "zz", " ", "0"], { 1161 keys: function() { return ["a", "zz", " ", 0] } 1162}) 1163 1164TestKeys(["throw", "function "], { 1165 keys: function() { return this.keys2() }, 1166 keys2: function() { return ["throw", "function "] } 1167}) 1168 1169TestKeys(["[object Object]"], { 1170 get keys() { 1171 return function() { return [{}] } 1172 } 1173}) 1174 1175TestKeys(["a", "0"], { 1176 getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] }, 1177 getOwnPropertyDescriptor: function(k) { return {enumerable: k.length == 1} } 1178}) 1179 1180TestKeys(["23", "zz", ""], { 1181 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1182 getOwnPropertyNames2: function() { return ["a", 23, "zz", "", 0] }, 1183 getOwnPropertyDescriptor: function(k) { 1184 return this.getOwnPropertyDescriptor2(k) 1185 }, 1186 getOwnPropertyDescriptor2: function(k) { return {enumerable: k.length != 1} } 1187}) 1188 1189TestKeys(["a", "b", "c", "5"], { 1190 get getOwnPropertyNames() { 1191 return function() { return ["0", 4, "a", "b", "c", 5] } 1192 }, 1193 get getOwnPropertyDescriptor() { 1194 return function(k) { return {enumerable: k >= "44"} } 1195 } 1196}) 1197 1198TestKeys([], { 1199 get getOwnPropertyNames() { 1200 return function() { return ["a", "b", "c"] } 1201 }, 1202 getOwnPropertyDescriptor: function(k) { return {} } 1203}) 1204 1205 1206function TestKeysThrow(handler) { 1207 TestWithProxies(TestKeysThrow2, handler) 1208} 1209 1210function TestKeysThrow2(handler, create) { 1211 var p = create(handler) 1212 assertThrows(function(){ Object.keys(p) }, "myexn") 1213} 1214 1215TestKeysThrow({ 1216 keys: function() { throw "myexn" } 1217}) 1218 1219TestKeysThrow({ 1220 keys: function() { return this.keys2() }, 1221 keys2: function() { throw "myexn" } 1222}) 1223 1224TestKeysThrow({ 1225 getOwnPropertyNames: function() { throw "myexn" }, 1226 getOwnPropertyDescriptor: function(k) { return true } 1227}) 1228 1229TestKeysThrow({ 1230 getOwnPropertyNames: function() { return [1, 2] }, 1231 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1232}) 1233 1234TestKeysThrow({ 1235 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1236 getOwnPropertyNames2: function() { throw "myexn" }, 1237}) 1238 1239TestKeysThrow({ 1240 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1241 getOwnPropertyNames2: function() { return [1, 2] }, 1242 getOwnPropertyDescriptor: function(k) { 1243 return this.getOwnPropertyDescriptor2(k) 1244 }, 1245 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 1246}) 1247 1248TestKeysThrow({ 1249 get getOwnPropertyNames() { throw "myexn" } 1250}) 1251 1252TestKeysThrow({ 1253 get getOwnPropertyNames() { 1254 return function() { throw "myexn" } 1255 }, 1256}) 1257 1258TestKeysThrow([], { 1259 get getOwnPropertyNames() { 1260 return function() { return [1, 2] } 1261 }, 1262 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1263}) 1264 1265 1266 1267// Fixing (Object.freeze, Object.seal, Object.preventExtensions, 1268// Object.isFrozen, Object.isSealed, Object.isExtensible) 1269 1270// TODO(rossberg): use TestWithProxies to include funciton proxies 1271function TestFix(names, handler) { 1272 var proto = {p: 77} 1273 var assertFixing = function(o, s, f, e) { 1274 assertEquals(s, Object.isSealed(o)) 1275 assertEquals(f, Object.isFrozen(o)) 1276 assertEquals(e, Object.isExtensible(o)) 1277 } 1278 1279 var p1 = Proxy.create(handler, proto) 1280 assertFixing(p1, false, false, true) 1281 Object.seal(p1) 1282 assertFixing(p1, true, names.length === 0, false) 1283 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p1).sort()) 1284 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), 1285 Object.keys(p1).sort()) 1286 assertEquals(proto, Object.getPrototypeOf(p1)) 1287 assertEquals(77, p1.p) 1288 for (var n in p1) { 1289 var desc = Object.getOwnPropertyDescriptor(p1, n) 1290 if (desc !== undefined) assertFalse(desc.configurable) 1291 } 1292 1293 var p2 = Proxy.create(handler, proto) 1294 assertFixing(p2, false, false, true) 1295 Object.freeze(p2) 1296 assertFixing(p2, true, true, false) 1297 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p2).sort()) 1298 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), 1299 Object.keys(p2).sort()) 1300 assertEquals(proto, Object.getPrototypeOf(p2)) 1301 assertEquals(77, p2.p) 1302 for (var n in p2) { 1303 var desc = Object.getOwnPropertyDescriptor(p2, n) 1304 if (desc !== undefined) assertFalse(desc.writable) 1305 if (desc !== undefined) assertFalse(desc.configurable) 1306 } 1307 1308 var p3 = Proxy.create(handler, proto) 1309 assertFixing(p3, false, false, true) 1310 Object.preventExtensions(p3) 1311 assertFixing(p3, names.length === 0, names.length === 0, false) 1312 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p3).sort()) 1313 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), 1314 Object.keys(p3).sort()) 1315 assertEquals(proto, Object.getPrototypeOf(p3)) 1316 assertEquals(77, p3.p) 1317} 1318 1319TestFix([], { 1320 fix: function() { return {} } 1321}) 1322 1323TestFix(["a", "b", "c", "d", "zz"], { 1324 fix: function() { 1325 return { 1326 a: {value: "a", writable: true, configurable: false, enumerable: true}, 1327 b: {value: 33, writable: false, configurable: false, enumerable: true}, 1328 c: {value: 0, writable: true, configurable: true, enumerable: true}, 1329 d: {value: true, writable: false, configurable: true, enumerable: true}, 1330 zz: {value: 0, enumerable: false} 1331 } 1332 } 1333}) 1334 1335TestFix(["a"], { 1336 fix: function() { return this.fix2() }, 1337 fix2: function() { 1338 return {a: {value: 4, writable: true, configurable: true, enumerable: true}} 1339 } 1340}) 1341 1342TestFix(["b"], { 1343 get fix() { 1344 return function() { 1345 return {b: {configurable: true, writable: true, enumerable: true}} 1346 } 1347 } 1348}) 1349 1350 1351function TestFixFunction(fix) { 1352 var f1 = Proxy.createFunction({ 1353 fix: function() { return {} } 1354 }, function() {}) 1355 fix(f1) 1356 assertEquals(0, f1.length) 1357 1358 var f2 = Proxy.createFunction({ 1359 fix: function() { return {length: {value: 3}} } 1360 }, function() {}) 1361 fix(f2) 1362 assertEquals(3, f2.length) 1363 1364 var f3 = Proxy.createFunction({ 1365 fix: function() { return {length: {value: "huh"}} } 1366 }, function() {}) 1367 fix(f3) 1368 assertEquals(0, f1.length) 1369} 1370 1371TestFixFunction(Object.seal) 1372TestFixFunction(Object.freeze) 1373TestFixFunction(Object.preventExtensions) 1374 1375 1376function TestFixThrow(handler) { 1377 TestWithProxies(TestFixThrow2, handler) 1378} 1379 1380function TestFixThrow2(handler) { 1381 var p = Proxy.create(handler, {}) 1382 assertThrows(function(){ Object.seal(p) }, "myexn") 1383 assertThrows(function(){ Object.freeze(p) }, "myexn") 1384 assertThrows(function(){ Object.preventExtensions(p) }, "myexn") 1385} 1386 1387TestFixThrow({ 1388 fix: function() { throw "myexn" } 1389}) 1390 1391TestFixThrow({ 1392 fix: function() { return this.fix2() }, 1393 fix2: function() { throw "myexn" } 1394}) 1395 1396TestFixThrow({ 1397 get fix() { throw "myexn" } 1398}) 1399 1400TestFixThrow({ 1401 get fix() { 1402 return function() { throw "myexn" } 1403 } 1404}) 1405 1406 1407 1408// String conversion (Object.prototype.toString, 1409// Object.prototype.toLocaleString, 1410// Function.prototype.toString) 1411 1412var key 1413 1414function TestToString(handler) { 1415 var p = Proxy.create(handler) 1416 key = "" 1417 assertEquals("[object Object]", Object.prototype.toString.call(p)) 1418 assertEquals("", key) 1419 assertEquals("my_proxy", Object.prototype.toLocaleString.call(p)) 1420 assertEquals("toString", key) 1421 1422 var f = Proxy.createFunction(handler, function() {}) 1423 key = "" 1424 assertEquals("[object Function]", Object.prototype.toString.call(f)) 1425 assertEquals("", key) 1426 assertEquals("my_proxy", Object.prototype.toLocaleString.call(f)) 1427 assertEquals("toString", key) 1428 assertDoesNotThrow(function(){ Function.prototype.toString.call(f) }) 1429} 1430 1431TestToString({ 1432 get: function(r, k) { key = k; return function() { return "my_proxy" } } 1433}) 1434 1435TestToString({ 1436 get: function(r, k) { return this.get2(r, k) }, 1437 get2: function(r, k) { key = k; return function() { return "my_proxy" } } 1438}) 1439 1440TestToString(Proxy.create({ 1441 get: function(pr, pk) { 1442 return function(r, k) { key = k; return function() { return "my_proxy" } } 1443 } 1444})) 1445 1446 1447function TestToStringThrow(handler) { 1448 var p = Proxy.create(handler) 1449 assertEquals("[object Object]", Object.prototype.toString.call(p)) 1450 assertThrows(function(){ Object.prototype.toLocaleString.call(p) }, "myexn") 1451 1452 var f = Proxy.createFunction(handler, function() {}) 1453 assertEquals("[object Function]", Object.prototype.toString.call(f)) 1454 assertThrows(function(){ Object.prototype.toLocaleString.call(f) }, "myexn") 1455} 1456 1457TestToStringThrow({ 1458 get: function(r, k) { throw "myexn" } 1459}) 1460 1461TestToStringThrow({ 1462 get: function(r, k) { return function() { throw "myexn" } } 1463}) 1464 1465TestToStringThrow({ 1466 get: function(r, k) { return this.get2(r, k) }, 1467 get2: function(r, k) { throw "myexn" } 1468}) 1469 1470TestToStringThrow(Proxy.create({ 1471 get: function(pr, pk) { throw "myexn" } 1472})) 1473 1474TestToStringThrow(Proxy.create({ 1475 get: function(pr, pk) { 1476 return function(r, k) { throw "myexn" } 1477 } 1478})) 1479 1480 1481 1482// Value conversion (Object.prototype.toValue) 1483 1484function TestValueOf(handler) { 1485 TestWithProxies(TestValueOf2, handler) 1486} 1487 1488function TestValueOf2(handler, create) { 1489 var p = create(handler) 1490 assertSame(p, Object.prototype.valueOf.call(p)) 1491} 1492 1493TestValueOf({}) 1494 1495 1496 1497// Enumerability (Object.prototype.propertyIsEnumerable) 1498 1499var key 1500 1501function TestIsEnumerable(handler) { 1502 TestWithProxies(TestIsEnumerable2, handler) 1503} 1504 1505function TestIsEnumerable2(handler, create) { 1506 var p = create(handler) 1507 assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a")) 1508 assertEquals("a", key) 1509 assertTrue(Object.prototype.propertyIsEnumerable.call(p, 2)) 1510 assertEquals("2", key) 1511 assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z")) 1512 assertEquals("z", key) 1513} 1514 1515TestIsEnumerable({ 1516 getOwnPropertyDescriptor: function(k) { 1517 key = k; return {enumerable: k < "z", configurable: true} 1518 }, 1519}) 1520 1521TestIsEnumerable({ 1522 getOwnPropertyDescriptor: function(k) { 1523 return this.getOwnPropertyDescriptor2(k) 1524 }, 1525 getOwnPropertyDescriptor2: function(k) { 1526 key = k; return {enumerable: k < "z", configurable: true} 1527 }, 1528}) 1529 1530TestIsEnumerable({ 1531 getOwnPropertyDescriptor: function(k) { 1532 key = k; return {get enumerable() { return k < "z" }, configurable: true} 1533 }, 1534}) 1535 1536TestIsEnumerable(Proxy.create({ 1537 get: function(pr, pk) { 1538 return function(k) { 1539 key = k; return {enumerable: k < "z", configurable: true} 1540 } 1541 } 1542})) 1543 1544 1545function TestIsEnumerableThrow(handler) { 1546 TestWithProxies(TestIsEnumerableThrow2, handler) 1547} 1548 1549function TestIsEnumerableThrow2(handler, create) { 1550 var p = create(handler) 1551 assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, "a") }, 1552 "myexn") 1553 assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, 11) }, 1554 "myexn") 1555} 1556 1557TestIsEnumerableThrow({ 1558 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1559}) 1560 1561TestIsEnumerableThrow({ 1562 getOwnPropertyDescriptor: function(k) { 1563 return this.getOwnPropertyDescriptor2(k) 1564 }, 1565 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 1566}) 1567 1568TestIsEnumerableThrow({ 1569 getOwnPropertyDescriptor: function(k) { 1570 return {get enumerable() { throw "myexn" }, configurable: true} 1571 }, 1572}) 1573 1574TestIsEnumerableThrow(Proxy.create({ 1575 get: function(pr, pk) { throw "myexn" } 1576})) 1577 1578TestIsEnumerableThrow(Proxy.create({ 1579 get: function(pr, pk) { 1580 return function(k) { throw "myexn" } 1581 } 1582})) 1583 1584 1585 1586// Calling (call, Function.prototype.call, Function.prototype.apply, 1587// Function.prototype.bind). 1588 1589var global = this 1590var receiver 1591 1592function TestCall(isStrict, callTrap) { 1593 assertEquals(42, callTrap(5, 37)) 1594// TODO(rossberg): unrelated bug: this does not succeed for optimized code. 1595// assertEquals(isStrict ? undefined : global, receiver) 1596 1597 var f = Proxy.createFunction({fix: function() { return {} }}, callTrap) 1598 receiver = 333 1599 assertEquals(42, f(11, 31)) 1600 assertEquals(isStrict ? undefined : global, receiver) 1601 var o = {} 1602 assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) 1603 assertEquals(o, receiver) 1604 assertEquals(43, Function.prototype.call.call(f, null, 20, 23)) 1605 assertEquals(isStrict ? null : global, receiver) 1606 assertEquals(44, Function.prototype.call.call(f, 2, 21, 23)) 1607 assertEquals(2, receiver.valueOf()) 1608 receiver = 333 1609 assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) 1610 assertEquals(o, receiver) 1611 var ff = Function.prototype.bind.call(f, o, 12) 1612 receiver = 333 1613 assertEquals(42, ff(30)) 1614 assertEquals(o, receiver) 1615 receiver = 333 1616 assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) 1617 assertEquals(o, receiver) 1618 1619 Object.freeze(f) 1620 receiver = 333 1621 assertEquals(42, f(11, 31)) 1622// TODO(rossberg): unrelated bug: this does not succeed for optimized code. 1623// assertEquals(isStrict ? undefined : global, receiver) 1624 receiver = 333 1625 assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) 1626 assertEquals(o, receiver) 1627 receiver = 333 1628 assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) 1629 assertEquals(o, receiver) 1630 receiver = 333 1631 assertEquals(42, ff(30)) 1632 assertEquals(o, receiver) 1633 receiver = 333 1634 assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) 1635 assertEquals(o, receiver) 1636} 1637 1638TestCall(false, function(x, y) { 1639 receiver = this; return x + y 1640}) 1641 1642TestCall(true, function(x, y) { 1643 "use strict"; 1644 receiver = this; return x + y 1645}) 1646 1647TestCall(false, Proxy.createFunction({}, function(x, y) { 1648 receiver = this; return x + y 1649})) 1650 1651TestCall(true, Proxy.createFunction({}, function(x, y) { 1652 "use strict"; 1653 receiver = this; return x + y 1654})) 1655 1656var p = Proxy.createFunction({fix: function() {return {}}}, function(x, y) { 1657 receiver = this; return x + y 1658}) 1659TestCall(false, p) 1660Object.freeze(p) 1661TestCall(false, p) 1662 1663 1664function TestCallThrow(callTrap) { 1665 var f = Proxy.createFunction({fix: function() {return {}}}, callTrap) 1666 assertThrows(function(){ f(11) }, "myexn") 1667 assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") 1668 assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") 1669 1670 Object.freeze(f) 1671 assertThrows(function(){ f(11) }, "myexn") 1672 assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") 1673 assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") 1674} 1675 1676TestCallThrow(function() { throw "myexn" }) 1677TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" })) 1678 1679var p = Proxy.createFunction( 1680 {fix: function() {return {}}}, function() { throw "myexn" }) 1681Object.freeze(p) 1682TestCallThrow(p) 1683