proxies.js revision 5d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0b
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 29 30 31// Helper. 32 33function TestWithProxies(test, x, y, z) { 34 test(Proxy.create, x, y, z) 35 test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z) 36} 37 38 39 40// Getting property descriptors (Object.getOwnPropertyDescriptor). 41 42var key 43 44function TestGetOwnProperty(handler) { 45 TestWithProxies(TestGetOwnProperty2, handler) 46} 47 48function TestGetOwnProperty2(create, handler) { 49 var p = create(handler) 50 assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value) 51 assertEquals("a", key) 52 assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value) 53 assertEquals("99", key) 54} 55 56TestGetOwnProperty({ 57 getOwnPropertyDescriptor: function(k) { 58 key = k 59 return {value: 42, configurable: true} 60 } 61}) 62 63TestGetOwnProperty({ 64 getOwnPropertyDescriptor: function(k) { 65 return this.getOwnPropertyDescriptor2(k) 66 }, 67 getOwnPropertyDescriptor2: function(k) { 68 key = k 69 return {value: 42, configurable: true} 70 } 71}) 72 73TestGetOwnProperty({ 74 getOwnPropertyDescriptor: function(k) { 75 key = k 76 return {get value() { return 42 }, get configurable() { return true }} 77 } 78}) 79 80TestGetOwnProperty(Proxy.create({ 81 get: function(pr, pk) { 82 return function(k) { key = k; return {value: 42, configurable: true} } 83 } 84})) 85 86 87function TestGetOwnPropertyThrow(handler) { 88 TestWithProxies(TestGetOwnPropertyThrow2, handler) 89} 90 91function TestGetOwnPropertyThrow2(create, handler) { 92 var p = create(handler) 93 assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn") 94 assertThrows(function(){ Object.getOwnPropertyDescriptor(p, 77) }, "myexn") 95} 96 97TestGetOwnPropertyThrow({ 98 getOwnPropertyDescriptor: function(k) { throw "myexn" } 99}) 100 101TestGetOwnPropertyThrow({ 102 getOwnPropertyDescriptor: function(k) { 103 return this.getPropertyDescriptor2(k) 104 }, 105 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 106}) 107 108TestGetOwnPropertyThrow({ 109 getOwnPropertyDescriptor: function(k) { 110 return {get value() { throw "myexn" }} 111 } 112}) 113 114TestGetOwnPropertyThrow(Proxy.create({ 115 get: function(pr, pk) { 116 return function(k) { throw "myexn" } 117 } 118})) 119 120 121 122// Getters (dot, brackets). 123 124var key 125 126function TestGet(handler) { 127 TestWithProxies(TestGet2, handler) 128} 129 130function TestGet2(create, handler) { 131 var p = create(handler) 132 assertEquals(42, p.a) 133 assertEquals("a", key) 134 assertEquals(42, p["b"]) 135 assertEquals("b", key) 136 assertEquals(42, p[99]) 137 assertEquals("99", key) 138 assertEquals(42, (function(n) { return p[n] })("c")) 139 assertEquals("c", key) 140 assertEquals(42, (function(n) { return p[n] })(101)) 141 assertEquals("101", key) 142 143 var o = Object.create(p, {x: {value: 88}}) 144 assertEquals(42, o.a) 145 assertEquals("a", key) 146 assertEquals(42, o["b"]) 147 assertEquals("b", key) 148 assertEquals(42, o[99]) 149 assertEquals("99", key) 150 assertEquals(88, o.x) 151 assertEquals(88, o["x"]) 152 assertEquals(42, (function(n) { return o[n] })("c")) 153 assertEquals("c", key) 154 assertEquals(42, (function(n) { return o[n] })(101)) 155 assertEquals("101", key) 156 assertEquals(88, (function(n) { return o[n] })("x")) 157} 158 159TestGet({ 160 get: function(r, k) { key = k; return 42 } 161}) 162 163TestGet({ 164 get: function(r, k) { return this.get2(r, k) }, 165 get2: function(r, k) { key = k; return 42 } 166}) 167 168TestGet({ 169 getPropertyDescriptor: function(k) { key = k; return {value: 42} } 170}) 171 172TestGet({ 173 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 174 getPropertyDescriptor2: function(k) { key = k; return {value: 42} } 175}) 176 177TestGet({ 178 getPropertyDescriptor: function(k) { 179 key = k; 180 return {get value() { return 42 }} 181 } 182}) 183 184TestGet({ 185 get: undefined, 186 getPropertyDescriptor: function(k) { key = k; return {value: 42} } 187}) 188 189TestGet(Proxy.create({ 190 get: function(pr, pk) { 191 return function(r, k) { key = k; return 42 } 192 } 193})) 194 195 196function TestGetCall(handler) { 197 TestWithProxies(TestGetCall2, handler) 198} 199 200function TestGetCall2(create, handler) { 201 var p = create(handler) 202 assertEquals(55, p.f()) 203 assertEquals(55, p["f"]()) 204 assertEquals(55, p.f("unused", "arguments")) 205 assertEquals(55, p.f.call(p)) 206 assertEquals(55, p["f"].call(p)) 207 assertEquals(55, p[101].call(p)) 208 assertEquals(55, p.withargs(45, 5)) 209 assertEquals(55, p.withargs.call(p, 11, 22)) 210 assertEquals(55, (function(n) { return p[n]() })("f")) 211 assertEquals(55, (function(n) { return p[n].call(p) })("f")) 212 assertEquals(55, (function(n) { return p[n](15, 20) })("withargs")) 213 assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs")) 214 assertEquals("6655", "66" + p) // calls p.toString 215 216 var o = Object.create(p, {g: {value: function(x) { return x + 88 }}}) 217 assertEquals(55, o.f()) 218 assertEquals(55, o["f"]()) 219 assertEquals(55, o.f("unused", "arguments")) 220 assertEquals(55, o.f.call(o)) 221 assertEquals(55, o.f.call(p)) 222 assertEquals(55, o["f"].call(p)) 223 assertEquals(55, o[101].call(p)) 224 assertEquals(55, o.withargs(45, 5)) 225 assertEquals(55, o.withargs.call(p, 11, 22)) 226 assertEquals(90, o.g(2)) 227 assertEquals(91, o.g.call(o, 3)) 228 assertEquals(92, o.g.call(p, 4)) 229 assertEquals(55, (function(n) { return o[n]() })("f")) 230 assertEquals(55, (function(n) { return o[n].call(o) })("f")) 231 assertEquals(55, (function(n) { return o[n](15, 20) })("withargs")) 232 assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs")) 233 assertEquals(93, (function(n) { return o[n](5) })("g")) 234 assertEquals(94, (function(n) { return o[n].call(o, 6) })("g")) 235 assertEquals(95, (function(n) { return o[n].call(p, 7) })("g")) 236 assertEquals("6655", "66" + o) // calls o.toString 237} 238 239TestGetCall({ 240 get: function(r, k) { return function() { return 55 } } 241}) 242 243TestGetCall({ 244 get: function(r, k) { return this.get2(r, k) }, 245 get2: function(r, k) { return function() { return 55 } } 246}) 247 248TestGetCall({ 249 getPropertyDescriptor: function(k) { 250 return {value: function() { return 55 }} 251 } 252}) 253 254TestGetCall({ 255 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 256 getPropertyDescriptor2: function(k) { 257 return {value: function() { return 55 }} 258 } 259}) 260 261TestGetCall({ 262 getPropertyDescriptor: function(k) { 263 return {get value() { return function() { return 55 } }} 264 } 265}) 266 267TestGetCall({ 268 get: undefined, 269 getPropertyDescriptor: function(k) { 270 return {value: function() { return 55 }} 271 } 272}) 273 274TestGetCall({ 275 get: function(r, k) { 276 if (k == "gg") { 277 return function() { return 55 } 278 } else if (k == "withargs") { 279 return function(n, m) { return n + m * 2 } 280 } else { 281 return function() { return this.gg() } 282 } 283 } 284}) 285 286TestGetCall(Proxy.create({ 287 get: function(pr, pk) { 288 return function(r, k) { return function() { return 55 } } 289 } 290})) 291 292 293function TestGetThrow(handler) { 294 TestWithProxies(TestGetThrow2, handler) 295} 296 297function TestGetThrow2(create, handler) { 298 var p = create(handler) 299 assertThrows(function(){ p.a }, "myexn") 300 assertThrows(function(){ p["b"] }, "myexn") 301 assertThrows(function(){ p[3] }, "myexn") 302 assertThrows(function(){ (function(n) { p[n] })("c") }, "myexn") 303 assertThrows(function(){ (function(n) { p[n] })(99) }, "myexn") 304 305 var o = Object.create(p, {x: {value: 88}, '4': {value: 89}}) 306 assertThrows(function(){ o.a }, "myexn") 307 assertThrows(function(){ o["b"] }, "myexn") 308 assertThrows(function(){ o[3] }, "myexn") 309 assertThrows(function(){ (function(n) { o[n] })("c") }, "myexn") 310 assertThrows(function(){ (function(n) { o[n] })(99) }, "myexn") 311} 312 313TestGetThrow({ 314 get: function(r, k) { throw "myexn" } 315}) 316 317TestGetThrow({ 318 get: function(r, k) { return this.get2(r, k) }, 319 get2: function(r, k) { throw "myexn" } 320}) 321 322TestGetThrow({ 323 getPropertyDescriptor: function(k) { throw "myexn" } 324}) 325 326TestGetThrow({ 327 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 328 getPropertyDescriptor2: function(k) { throw "myexn" } 329}) 330 331TestGetThrow({ 332 getPropertyDescriptor: function(k) { 333 return {get value() { throw "myexn" }} 334 } 335}) 336 337TestGetThrow({ 338 get: undefined, 339 getPropertyDescriptor: function(k) { throw "myexn" } 340}) 341 342TestGetThrow(Proxy.create({ 343 get: function(pr, pk) { throw "myexn" } 344})) 345 346TestGetThrow(Proxy.create({ 347 get: function(pr, pk) { 348 return function(r, k) { throw "myexn" } 349 } 350})) 351 352 353 354// Setters. 355 356var key 357var val 358 359function TestSet(handler) { 360 TestWithProxies(TestSet2, handler) 361} 362 363function TestSet2(create, handler) { 364 var p = create(handler) 365 assertEquals(42, p.a = 42) 366 assertEquals("a", key) 367 assertEquals(42, val) 368 assertEquals(43, p["b"] = 43) 369 assertEquals("b", key) 370 assertEquals(43, val) 371 assertEquals(44, p[77] = 44) 372 assertEquals("77", key) 373 assertEquals(44, val) 374 375 assertEquals(45, (function(n) { return p[n] = 45 })("c")) 376 assertEquals("c", key) 377 assertEquals(45, val) 378 assertEquals(46, (function(n) { return p[n] = 46 })(99)) 379 assertEquals("99", key) 380 assertEquals(46, val) 381} 382 383TestSet({ 384 set: function(r, k, v) { key = k; val = v; return true } 385}) 386 387TestSet({ 388 set: function(r, k, v) { return this.set2(r, k, v) }, 389 set2: function(r, k, v) { key = k; val = v; return true } 390}) 391 392TestSet({ 393 getOwnPropertyDescriptor: function(k) { return {writable: true} }, 394 defineProperty: function(k, desc) { key = k; val = desc.value } 395}) 396 397TestSet({ 398 getOwnPropertyDescriptor: function(k) { 399 return this.getOwnPropertyDescriptor2(k) 400 }, 401 getOwnPropertyDescriptor2: function(k) { return {writable: true} }, 402 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, 403 defineProperty2: function(k, desc) { key = k; val = desc.value } 404}) 405 406TestSet({ 407 getOwnPropertyDescriptor: function(k) { 408 return {get writable() { return true }} 409 }, 410 defineProperty: function(k, desc) { key = k; val = desc.value } 411}) 412 413TestSet({ 414 getOwnPropertyDescriptor: function(k) { 415 return {set: function(v) { key = k; val = v }} 416 } 417}) 418 419TestSet({ 420 getOwnPropertyDescriptor: function(k) { return null }, 421 getPropertyDescriptor: function(k) { return {writable: true} }, 422 defineProperty: function(k, desc) { key = k; val = desc.value } 423}) 424 425TestSet({ 426 getOwnPropertyDescriptor: function(k) { return null }, 427 getPropertyDescriptor: function(k) { 428 return {get writable() { return true }} 429 }, 430 defineProperty: function(k, desc) { key = k; val = desc.value } 431}) 432 433TestSet({ 434 getOwnPropertyDescriptor: function(k) { return null }, 435 getPropertyDescriptor: function(k) { 436 return {set: function(v) { key = k; val = v }} 437 } 438}) 439 440TestSet({ 441 getOwnPropertyDescriptor: function(k) { return null }, 442 getPropertyDescriptor: function(k) { return null }, 443 defineProperty: function(k, desc) { key = k, val = desc.value } 444}) 445 446TestSet(Proxy.create({ 447 get: function(pr, pk) { 448 return function(r, k, v) { key = k; val = v; return true } 449 } 450})) 451 452 453function TestSetThrow(handler) { 454 TestWithProxies(TestSetThrow2, handler) 455} 456 457function TestSetThrow2(create, handler) { 458 var p = create(handler) 459 assertThrows(function(){ p.a = 42 }, "myexn") 460 assertThrows(function(){ p["b"] = 42 }, "myexn") 461 assertThrows(function(){ p[22] = 42 }, "myexn") 462 assertThrows(function(){ (function(n) { p[n] = 45 })("c") }, "myexn") 463 assertThrows(function(){ (function(n) { p[n] = 46 })(99) }, "myexn") 464} 465 466TestSetThrow({ 467 set: function(r, k, v) { throw "myexn" } 468}) 469 470TestSetThrow({ 471 set: function(r, k, v) { return this.set2(r, k, v) }, 472 set2: function(r, k, v) { throw "myexn" } 473}) 474 475TestSetThrow({ 476 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 477 defineProperty: function(k, desc) { key = k; val = desc.value } 478}) 479 480TestSetThrow({ 481 getOwnPropertyDescriptor: function(k) { return {writable: true} }, 482 defineProperty: function(k, desc) { throw "myexn" } 483}) 484 485TestSetThrow({ 486 getOwnPropertyDescriptor: function(k) { 487 return this.getOwnPropertyDescriptor2(k) 488 }, 489 getOwnPropertyDescriptor2: function(k) { throw "myexn" }, 490 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, 491 defineProperty2: function(k, desc) { key = k; val = desc.value } 492}) 493 494TestSetThrow({ 495 getOwnPropertyDescriptor: function(k) { 496 return this.getOwnPropertyDescriptor2(k) 497 }, 498 getOwnPropertyDescriptor2: function(k) { return {writable: true} }, 499 defineProperty: function(k, desc) { this.defineProperty2(k, desc) }, 500 defineProperty2: function(k, desc) { throw "myexn" } 501}) 502 503TestSetThrow({ 504 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 505 defineProperty: function(k, desc) { key = k; val = desc.value } 506}) 507 508TestSetThrow({ 509 getOwnPropertyDescriptor: function(k) { 510 return {get writable() { return true }} 511 }, 512 defineProperty: function(k, desc) { throw "myexn" } 513}) 514 515TestSetThrow({ 516 getOwnPropertyDescriptor: function(k) { throw "myexn" } 517}) 518 519TestSetThrow({ 520 getOwnPropertyDescriptor: function(k) { 521 return {set: function(v) { throw "myexn" }} 522 } 523}) 524 525TestSetThrow({ 526 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 527 getPropertyDescriptor: function(k) { return {writable: true} }, 528 defineProperty: function(k, desc) { key = k; val = desc.value } 529}) 530 531TestSetThrow({ 532 getOwnPropertyDescriptor: function(k) { return null }, 533 getPropertyDescriptor: function(k) { throw "myexn" }, 534 defineProperty: function(k, desc) { key = k; val = desc.value } 535}) 536 537TestSetThrow({ 538 getOwnPropertyDescriptor: function(k) { return null }, 539 getPropertyDescriptor: function(k) { return {writable: true} }, 540 defineProperty: function(k, desc) { throw "myexn" } 541}) 542 543TestSetThrow({ 544 getOwnPropertyDescriptor: function(k) { return null }, 545 getPropertyDescriptor: function(k) { 546 return {get writable() { throw "myexn" }} 547 }, 548 defineProperty: function(k, desc) { key = k; val = desc.value } 549}) 550 551TestSetThrow({ 552 getOwnPropertyDescriptor: function(k) { return null }, 553 getPropertyDescriptor: function(k) { 554 return {set: function(v) { throw "myexn" }} 555 } 556}) 557 558TestSetThrow({ 559 getOwnPropertyDescriptor: function(k) { return null }, 560 getPropertyDescriptor: function(k) { return null }, 561 defineProperty: function(k, desc) { throw "myexn" } 562}) 563 564TestSetThrow(Proxy.create({ 565 get: function(pr, pk) { throw "myexn" } 566})) 567 568TestSetThrow(Proxy.create({ 569 get: function(pr, pk) { 570 return function(r, k, v) { throw "myexn" } 571 } 572})) 573 574 575var key 576var val 577 578function TestSetForDerived(handler) { 579 TestWithProxies(TestSetForDerived2, handler) 580} 581 582function TestSetForDerived2(create, handler) { 583 var p = create(handler) 584 var o = Object.create(p, {x: {value: 88, writable: true}, 585 '1': {value: 89, writable: true}}) 586 587 key = "" 588 assertEquals(48, o.x = 48) 589 assertEquals("", key) // trap not invoked 590 assertEquals(48, o.x) 591 592 assertEquals(47, o[1] = 47) 593 assertEquals("", key) // trap not invoked 594 assertEquals(47, o[1]) 595 596 assertEquals(49, o.y = 49) 597 assertEquals("y", key) 598 assertEquals(49, o.y) 599 600 assertEquals(50, o[2] = 50) 601 assertEquals("2", key) 602 assertEquals(50, o[2]) 603 604 assertEquals(44, o.p_writable = 44) 605 assertEquals("p_writable", key) 606 assertEquals(44, o.p_writable) 607 608 assertEquals(45, o.p_nonwritable = 45) 609 assertEquals("p_nonwritable", key) 610 assertEquals(45, o.p_nonwritable) 611 612 assertEquals(46, o.p_setter = 46) 613 assertEquals("p_setter", key) 614 assertEquals(46, val) // written to parent 615 assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setter")) 616 617 val = "" 618 assertEquals(47, o.p_nosetter = 47) 619 assertEquals("p_nosetter", key) 620 assertEquals("", val) // not written at all 621 assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nosetter")); 622 623 key = "" 624 assertThrows(function(){ "use strict"; o.p_nosetter = 50 }, TypeError) 625 assertEquals("p_nosetter", key) 626 assertEquals("", val) // not written at all 627 628 assertThrows(function(){ o.p_nonconf = 53 }, TypeError) 629 assertEquals("p_nonconf", key) 630 631 assertThrows(function(){ o.p_throw = 51 }, "myexn") 632 assertEquals("p_throw", key) 633 634 assertThrows(function(){ o.p_setterthrow = 52 }, "myexn") 635 assertEquals("p_setterthrow", key) 636} 637 638TestSetForDerived({ 639 getPropertyDescriptor: function(k) { 640 key = k; 641 switch (k) { 642 case "p_writable": return {writable: true, configurable: true} 643 case "p_nonwritable": return {writable: false, configurable: true} 644 case "p_setter":return {set: function(x) { val = x }, configurable: true} 645 case "p_nosetter": return {get: function() { return 1 }, configurable: true} 646 case "p_nonconf":return {} 647 case "p_throw": throw "myexn" 648 case "p_setterthrow": return {set: function(x) { throw "myexn" }} 649 default: return undefined 650 } 651 } 652}) 653 654 655// Evil proxy-induced side-effects shouldn't crash. 656// TODO(rossberg): proper behaviour isn't really spec'ed yet, so ignore results. 657 658TestWithProxies(function(create) { 659 var calls = 0 660 var handler = { 661 getPropertyDescriptor: function() { 662 ++calls 663 return (calls % 2 == 1) 664 ? {get: function() { return 5 }, configurable: true} 665 : {set: function() { return false }, configurable: true} 666 } 667 } 668 var p = create(handler) 669 var o = Object.create(p) 670 // Make proxy prototype property read-only after CanPut check. 671 try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } 672}) 673 674TestWithProxies(function(create) { 675 var handler = { 676 getPropertyDescriptor: function() { 677 Object.defineProperty(o, "x", {get: function() { return 5 }}); 678 return {set: function() {}} 679 } 680 } 681 var p = create(handler) 682 var o = Object.create(p) 683 // Make object property read-only after CanPut check. 684 try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } 685}) 686 687 688 689// TODO(rossberg): TestSetReject, returning false 690// TODO(rossberg): TestGetProperty, TestSetProperty 691 692 693 694// Property definition (Object.defineProperty and Object.defineProperties). 695 696var key 697var desc 698 699function TestDefine(handler) { 700 TestWithProxies(TestDefine2, handler) 701} 702 703function TestDefine2(create, handler) { 704 var p = create(handler) 705 assertEquals(p, Object.defineProperty(p, "a", {value: 44})) 706 assertEquals("a", key) 707 assertEquals(1, Object.getOwnPropertyNames(desc).length) 708 assertEquals(44, desc.value) 709 710 assertEquals(p, Object.defineProperty(p, "b", {value: 45, writable: false})) 711 assertEquals("b", key) 712 assertEquals(2, Object.getOwnPropertyNames(desc).length) 713 assertEquals(45, desc.value) 714 assertEquals(false, desc.writable) 715 716 assertEquals(p, Object.defineProperty(p, "c", {value: 46, enumerable: false})) 717 assertEquals("c", key) 718 assertEquals(2, Object.getOwnPropertyNames(desc).length) 719 assertEquals(46, desc.value) 720 assertEquals(false, desc.enumerable) 721 722 assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false})) 723 assertEquals("101", key) 724 assertEquals(2, Object.getOwnPropertyNames(desc).length) 725 assertEquals(47, desc.value) 726 assertEquals(false, desc.enumerable) 727 728 var attributes = {configurable: true, mine: 66, minetoo: 23} 729 assertEquals(p, Object.defineProperty(p, "d", attributes)) 730 assertEquals("d", key) 731 // Modifying the attributes object after the fact should have no effect. 732 attributes.configurable = false 733 attributes.mine = 77 734 delete attributes.minetoo 735 assertEquals(3, Object.getOwnPropertyNames(desc).length) 736 assertEquals(true, desc.configurable) 737 assertEquals(66, desc.mine) 738 assertEquals(23, desc.minetoo) 739 740 assertEquals(p, Object.defineProperty(p, "e", {get: function(){ return 5 }})) 741 assertEquals("e", key) 742 assertEquals(1, Object.getOwnPropertyNames(desc).length) 743 assertEquals(5, desc.get()) 744 745 assertEquals(p, Object.defineProperty(p, "zzz", {})) 746 assertEquals("zzz", key) 747 assertEquals(0, Object.getOwnPropertyNames(desc).length) 748 749 var d = create({ 750 get: function(r, k) { return (k === "value") ? 77 : void 0 }, 751 getOwnPropertyNames: function() { return ["value"] }, 752 enumerate: function() { return ["value"] } 753 }) 754 assertEquals(1, Object.getOwnPropertyNames(d).length) 755 assertEquals(77, d.value) 756 assertEquals(p, Object.defineProperty(p, "p", d)) 757 assertEquals("p", key) 758 assertEquals(1, Object.getOwnPropertyNames(desc).length) 759 assertEquals(77, desc.value) 760 761 var props = { 762 '11': {}, 763 blub: {get: function() { return true }}, 764 '': {get value() { return 20 }}, 765 last: {value: 21, configurable: true, mine: "eyes"} 766 } 767 Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false}) 768 assertEquals(p, Object.defineProperties(p, props)) 769 assertEquals("last", key) 770 assertEquals(2, Object.getOwnPropertyNames(desc).length) 771 assertEquals(21, desc.value) 772 assertEquals(true, desc.configurable) 773 assertEquals(undefined, desc.mine) // Arguably a bug in the spec... 774 775 var props = {bla: {get value() { throw "myexn" }}} 776 assertThrows(function(){ Object.defineProperties(p, props) }, "myexn") 777} 778 779TestDefine({ 780 defineProperty: function(k, d) { key = k; desc = d; return true } 781}) 782 783TestDefine({ 784 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, 785 defineProperty2: function(k, d) { key = k; desc = d; return true } 786}) 787 788TestDefine(Proxy.create({ 789 get: function(pr, pk) { 790 return function(k, d) { key = k; desc = d; return true } 791 } 792})) 793 794 795function TestDefineThrow(handler) { 796 TestWithProxies(TestDefineThrow2, handler) 797} 798 799function TestDefineThrow2(create, handler) { 800 var p = create(handler) 801 assertThrows(function(){ Object.defineProperty(p, "a", {value: 44})}, "myexn") 802 assertThrows(function(){ Object.defineProperty(p, 0, {value: 44})}, "myexn") 803 804 var d1 = create({ 805 get: function(r, k) { throw "myexn" }, 806 getOwnPropertyNames: function() { return ["value"] } 807 }) 808 assertThrows(function(){ Object.defineProperty(p, "p", d1) }, "myexn") 809 var d2 = create({ 810 get: function(r, k) { return 77 }, 811 getOwnPropertyNames: function() { throw "myexn" } 812 }) 813 assertThrows(function(){ Object.defineProperty(p, "p", d2) }, "myexn") 814 815 var props = {bla: {get value() { throw "otherexn" }}} 816 assertThrows(function(){ Object.defineProperties(p, props) }, "otherexn") 817} 818 819TestDefineThrow({ 820 defineProperty: function(k, d) { throw "myexn" } 821}) 822 823TestDefineThrow({ 824 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, 825 defineProperty2: function(k, d) { throw "myexn" } 826}) 827 828TestDefineThrow(Proxy.create({ 829 get: function(pr, pk) { throw "myexn" } 830})) 831 832TestDefineThrow(Proxy.create({ 833 get: function(pr, pk) { 834 return function(k, d) { throw "myexn" } 835 } 836})) 837 838 839 840// Property deletion (delete). 841 842var key 843 844function TestDelete(handler) { 845 TestWithProxies(TestDelete2, handler) 846} 847 848function TestDelete2(create, handler) { 849 var p = create(handler) 850 assertEquals(true, delete p.a) 851 assertEquals("a", key) 852 assertEquals(true, delete p["b"]) 853 assertEquals("b", key) 854 assertEquals(true, delete p[1]) 855 assertEquals("1", key) 856 857 assertEquals(false, delete p.z1) 858 assertEquals("z1", key) 859 assertEquals(false, delete p["z2"]) 860 assertEquals("z2", key); 861 862 (function() { 863 "use strict" 864 assertEquals(true, delete p.c) 865 assertEquals("c", key) 866 assertEquals(true, delete p["d"]) 867 assertEquals("d", key) 868 assertEquals(true, delete p[2]) 869 assertEquals("2", key) 870 871 assertThrows(function(){ delete p.z3 }, TypeError) 872 assertEquals("z3", key) 873 assertThrows(function(){ delete p["z4"] }, TypeError) 874 assertEquals("z4", key) 875 })() 876} 877 878TestDelete({ 879 delete: function(k) { key = k; return k < "z" } 880}) 881 882TestDelete({ 883 delete: function(k) { return this.delete2(k) }, 884 delete2: function(k) { key = k; return k < "z" } 885}) 886 887TestDelete(Proxy.create({ 888 get: function(pr, pk) { 889 return function(k) { key = k; return k < "z" } 890 } 891})) 892 893 894function TestDeleteThrow(handler) { 895 TestWithProxies(TestDeleteThrow2, handler) 896} 897 898function TestDeleteThrow2(create, handler) { 899 var p = create(handler) 900 assertThrows(function(){ delete p.a }, "myexn") 901 assertThrows(function(){ delete p["b"] }, "myexn"); 902 assertThrows(function(){ delete p[3] }, "myexn"); 903 904 (function() { 905 "use strict" 906 assertThrows(function(){ delete p.c }, "myexn") 907 assertThrows(function(){ delete p["d"] }, "myexn") 908 assertThrows(function(){ delete p[4] }, "myexn"); 909 })() 910} 911 912TestDeleteThrow({ 913 delete: function(k) { throw "myexn" } 914}) 915 916TestDeleteThrow({ 917 delete: function(k) { return this.delete2(k) }, 918 delete2: function(k) { throw "myexn" } 919}) 920 921TestDeleteThrow(Proxy.create({ 922 get: function(pr, pk) { throw "myexn" } 923})) 924 925TestDeleteThrow(Proxy.create({ 926 get: function(pr, pk) { 927 return function(k) { throw "myexn" } 928 } 929})) 930 931 932 933// Property descriptors (Object.getOwnPropertyDescriptor). 934 935function TestDescriptor(handler) { 936 TestWithProxies(TestDescriptor2, handler) 937} 938 939function TestDescriptor2(create, handler) { 940 var p = create(handler) 941 var descs = [ 942 {configurable: true}, 943 {value: 34, enumerable: true, configurable: true}, 944 {value: 3, writable: false, mine: "eyes", configurable: true}, 945 {get value() { return 20 }, get configurable() { return true }}, 946 {get: function() { "get" }, set: function() { "set" }, configurable: true} 947 ] 948 for (var i = 0; i < descs.length; ++i) { 949 assertEquals(p, Object.defineProperty(p, i, descs[i])) 950 var desc = Object.getOwnPropertyDescriptor(p, i) 951 for (prop in descs[i]) { 952 // TODO(rossberg): Ignore user attributes as long as the spec isn't 953 // fixed suitably. 954 if (prop != "mine") assertEquals(descs[i][prop], desc[prop]) 955 } 956 assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent")) 957 } 958} 959 960TestDescriptor({ 961 defineProperty: function(k, d) { this["__" + k] = d; return true }, 962 getOwnPropertyDescriptor: function(k) { return this["__" + k] } 963}) 964 965TestDescriptor({ 966 defineProperty: function(k, d) { this["__" + k] = d; return true }, 967 getOwnPropertyDescriptor: function(k) { 968 return this.getOwnPropertyDescriptor2(k) 969 }, 970 getOwnPropertyDescriptor2: function(k) { return this["__" + k] } 971}) 972 973 974function TestDescriptorThrow(handler) { 975 TestWithProxies(TestDescriptorThrow2, handler) 976} 977 978function TestDescriptorThrow2(create, handler) { 979 var p = create(handler) 980 assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn") 981} 982 983TestDescriptorThrow({ 984 getOwnPropertyDescriptor: function(k) { throw "myexn" } 985}) 986 987TestDescriptorThrow({ 988 getOwnPropertyDescriptor: function(k) { 989 return this.getOwnPropertyDescriptor2(k) 990 }, 991 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 992}) 993 994 995 996// Comparison. 997 998function TestComparison(eq) { 999 TestWithProxies(TestComparison2, eq) 1000} 1001 1002function TestComparison2(create, eq) { 1003 var p1 = create({}) 1004 var p2 = create({}) 1005 1006 assertTrue(eq(p1, p1)) 1007 assertTrue(eq(p2, p2)) 1008 assertTrue(!eq(p1, p2)) 1009 assertTrue(!eq(p1, {})) 1010 assertTrue(!eq({}, p2)) 1011 assertTrue(!eq({}, {})) 1012} 1013 1014TestComparison(function(o1, o2) { return o1 == o2 }) 1015TestComparison(function(o1, o2) { return o1 === o2 }) 1016TestComparison(function(o1, o2) { return !(o1 != o2) }) 1017TestComparison(function(o1, o2) { return !(o1 !== o2) }) 1018 1019 1020 1021// Type (typeof). 1022 1023function TestTypeof() { 1024 assertEquals("object", typeof Proxy.create({})) 1025 assertTrue(typeof Proxy.create({}) == "object") 1026 assertTrue("object" == typeof Proxy.create({})) 1027 1028 assertEquals("function", typeof Proxy.createFunction({}, function() {})) 1029 assertTrue(typeof Proxy.createFunction({}, function() {}) == "function") 1030 assertTrue("function" == typeof Proxy.createFunction({}, function() {})) 1031} 1032 1033TestTypeof() 1034 1035 1036 1037// Membership test (in). 1038 1039var key 1040 1041function TestIn(handler) { 1042 TestWithProxies(TestIn2, handler) 1043} 1044 1045function TestIn2(create, handler) { 1046 var p = create(handler) 1047 assertTrue("a" in p) 1048 assertEquals("a", key) 1049 assertTrue(99 in p) 1050 assertEquals("99", key) 1051 assertFalse("z" in p) 1052 assertEquals("z", key) 1053 1054 assertEquals(2, ("a" in p) ? 2 : 0) 1055 assertEquals(0, !("a" in p) ? 2 : 0) 1056 assertEquals(0, ("zzz" in p) ? 2 : 0) 1057 assertEquals(2, !("zzz" in p) ? 2 : 0) 1058 1059 // Test compilation in conditionals. 1060 if ("b" in p) { 1061 } else { 1062 assertTrue(false) 1063 } 1064 assertEquals("b", key) 1065 1066 if ("zz" in p) { 1067 assertTrue(false) 1068 } 1069 assertEquals("zz", key) 1070 1071 if (!("c" in p)) { 1072 assertTrue(false) 1073 } 1074 assertEquals("c", key) 1075 1076 if (!("zzz" in p)) { 1077 } else { 1078 assertTrue(false) 1079 } 1080 assertEquals("zzz", key) 1081} 1082 1083TestIn({ 1084 has: function(k) { key = k; return k < "z" } 1085}) 1086 1087TestIn({ 1088 has: function(k) { return this.has2(k) }, 1089 has2: function(k) { key = k; return k < "z" } 1090}) 1091 1092TestIn({ 1093 getPropertyDescriptor: function(k) { 1094 key = k; return k < "z" ? {value: 42} : void 0 1095 } 1096}) 1097 1098TestIn({ 1099 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 1100 getPropertyDescriptor2: function(k) { 1101 key = k; return k < "z" ? {value: 42} : void 0 1102 } 1103}) 1104 1105TestIn({ 1106 getPropertyDescriptor: function(k) { 1107 key = k; return k < "z" ? {get value() { return 42 }} : void 0 1108 } 1109}) 1110 1111TestIn({ 1112 has: undefined, 1113 getPropertyDescriptor: function(k) { 1114 key = k; return k < "z" ? {value: 42} : void 0 1115 } 1116}) 1117 1118TestIn(Proxy.create({ 1119 get: function(pr, pk) { 1120 return function(k) { key = k; return k < "z" } 1121 } 1122})) 1123 1124 1125function TestInThrow(handler) { 1126 TestWithProxies(TestInThrow2, handler) 1127} 1128 1129function TestInThrow2(create, handler) { 1130 var p = create(handler) 1131 assertThrows(function(){ return "a" in o }, "myexn") 1132 assertThrows(function(){ return 99 in o }, "myexn") 1133 assertThrows(function(){ return !("a" in o) }, "myexn") 1134 assertThrows(function(){ return ("a" in o) ? 2 : 3 }, "myexn") 1135 assertThrows(function(){ if ("b" in o) {} }, "myexn") 1136 assertThrows(function(){ if (!("b" in o)) {} }, "myexn") 1137 assertThrows(function(){ if ("zzz" in o) {} }, "myexn") 1138} 1139 1140TestInThrow({ 1141 has: function(k) { throw "myexn" } 1142}) 1143 1144TestInThrow({ 1145 has: function(k) { return this.has2(k) }, 1146 has2: function(k) { throw "myexn" } 1147}) 1148 1149TestInThrow({ 1150 getPropertyDescriptor: function(k) { throw "myexn" } 1151}) 1152 1153TestInThrow({ 1154 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 1155 getPropertyDescriptor2: function(k) { throw "myexn" } 1156}) 1157 1158TestInThrow({ 1159 has: undefined, 1160 getPropertyDescriptor: function(k) { throw "myexn" } 1161}) 1162 1163TestInThrow(Proxy.create({ 1164 get: function(pr, pk) { throw "myexn" } 1165})) 1166 1167TestInThrow(Proxy.create({ 1168 get: function(pr, pk) { 1169 return function(k) { throw "myexn" } 1170 } 1171})) 1172 1173 1174function TestInForDerived(handler) { 1175 TestWithProxies(TestInForDerived2, handler) 1176} 1177 1178function TestInForDerived2(create, handler) { 1179 var p = create(handler) 1180 var o = Object.create(p) 1181 1182 assertTrue("a" in o) 1183 assertEquals("a", key) 1184 assertTrue(99 in o) 1185 assertEquals("99", key) 1186 assertFalse("z" in o) 1187 assertEquals("z", key) 1188 1189 assertEquals(2, ("a" in o) ? 2 : 0) 1190 assertEquals(0, !("a" in o) ? 2 : 0) 1191 assertEquals(0, ("zzz" in o) ? 2 : 0) 1192 assertEquals(2, !("zzz" in o) ? 2 : 0) 1193 1194 if ("b" in o) { 1195 } else { 1196 assertTrue(false) 1197 } 1198 assertEquals("b", key) 1199 1200 if ("zz" in o) { 1201 assertTrue(false) 1202 } 1203 assertEquals("zz", key) 1204 1205 if (!("c" in o)) { 1206 assertTrue(false) 1207 } 1208 assertEquals("c", key) 1209 1210 if (!("zzz" in o)) { 1211 } else { 1212 assertTrue(false) 1213 } 1214 assertEquals("zzz", key) 1215} 1216 1217TestInForDerived({ 1218 getPropertyDescriptor: function(k) { 1219 key = k; return k < "z" ? {value: 42, configurable: true} : void 0 1220 } 1221}) 1222 1223TestInForDerived({ 1224 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 1225 getPropertyDescriptor2: function(k) { 1226 key = k; return k < "z" ? {value: 42, configurable: true} : void 0 1227 } 1228}) 1229 1230TestInForDerived({ 1231 getPropertyDescriptor: function(k) { 1232 key = k; 1233 return k < "z" ? {get value() { return 42 }, configurable: true} : void 0 1234 } 1235}) 1236 1237/* TODO(rossberg): this will work once we implement the newest proposal 1238 * regarding default traps for getPropertyDescriptor. 1239TestInForDerived({ 1240 getOwnPropertyDescriptor: function(k) { 1241 key = k; return k < "z" ? {value: 42, configurable: true} : void 0 1242 } 1243}) 1244 1245TestInForDerived({ 1246 getOwnPropertyDescriptor: function(k) { 1247 return this.getOwnPropertyDescriptor2(k) 1248 }, 1249 getOwnPropertyDescriptor2: function(k) { 1250 key = k; return k < "z" ? {value: 42, configurable: true} : void 0 1251 } 1252}) 1253 1254TestInForDerived({ 1255 getOwnPropertyDescriptor: function(k) { 1256 key = k; 1257 return k < "z" ? {get value() { return 42 }, configurable: true} : void 0 1258 } 1259}) 1260*/ 1261 1262TestInForDerived(Proxy.create({ 1263 get: function(pr, pk) { 1264 return function(k) { 1265 key = k; return k < "z" ? {value: 42, configurable: true} : void 0 1266 } 1267 } 1268})) 1269 1270 1271 1272// Property descriptor conversion. 1273 1274var descget 1275 1276function TestDescriptorGetOrder(handler) { 1277 var p = Proxy.create(handler) 1278 var o = Object.create(p, {b: {value: 0}}) 1279 TestDescriptorGetOrder2(function(n) { return p[n] }, "vV") 1280 TestDescriptorGetOrder2(function(n) { return n in p }, "") 1281 TestDescriptorGetOrder2(function(n) { return o[n] }, "vV") 1282 TestDescriptorGetOrder2(function(n) { return n in o }, "eEcCvVwWgs") 1283} 1284 1285function TestDescriptorGetOrder2(f, access) { 1286 descget = "" 1287 assertTrue(f("a")) 1288 assertEquals(access, descget) 1289 descget = "" 1290 assertTrue(f(99)) 1291 assertEquals(access, descget) 1292 descget = "" 1293 assertFalse(!!f("z")) 1294 assertEquals("", descget) 1295} 1296 1297TestDescriptorGetOrder({ 1298 getPropertyDescriptor: function(k) { 1299 if (k >= "z") return void 0 1300 // Return a proxy as property descriptor, so that we can log accesses. 1301 return Proxy.create({ 1302 get: function(r, attr) { 1303 descget += attr[0].toUpperCase() 1304 return true 1305 }, 1306 has: function(attr) { 1307 descget += attr[0] 1308 switch (attr) { 1309 case "writable": 1310 case "enumerable": 1311 case "configurable": 1312 case "value": 1313 return true 1314 case "get": 1315 case "set": 1316 return false 1317 default: 1318 assertUnreachable() 1319 } 1320 } 1321 }) 1322 } 1323}) 1324 1325 1326 1327// Own Properties (Object.prototype.hasOwnProperty). 1328 1329var key 1330 1331function TestHasOwn(handler) { 1332 TestWithProxies(TestHasOwn2, handler) 1333} 1334 1335function TestHasOwn2(create, handler) { 1336 var p = create(handler) 1337 assertTrue(Object.prototype.hasOwnProperty.call(p, "a")) 1338 assertEquals("a", key) 1339 assertTrue(Object.prototype.hasOwnProperty.call(p, 99)) 1340 assertEquals("99", key) 1341 assertFalse(Object.prototype.hasOwnProperty.call(p, "z")) 1342 assertEquals("z", key) 1343} 1344 1345TestHasOwn({ 1346 hasOwn: function(k) { key = k; return k < "z" } 1347}) 1348 1349TestHasOwn({ 1350 hasOwn: function(k) { return this.hasOwn2(k) }, 1351 hasOwn2: function(k) { key = k; return k < "z" } 1352}) 1353 1354TestHasOwn({ 1355 getOwnPropertyDescriptor: function(k) { 1356 key = k; return k < "z" ? {value: 42} : void 0 1357 } 1358}) 1359 1360TestHasOwn({ 1361 getOwnPropertyDescriptor: function(k) { 1362 return this.getOwnPropertyDescriptor2(k) 1363 }, 1364 getOwnPropertyDescriptor2: function(k) { 1365 key = k; return k < "z" ? {value: 42} : void 0 1366 } 1367}) 1368 1369TestHasOwn({ 1370 getOwnPropertyDescriptor: function(k) { 1371 key = k; return k < "z" ? {get value() { return 42 }} : void 0 1372 } 1373}) 1374 1375TestHasOwn({ 1376 hasOwn: undefined, 1377 getOwnPropertyDescriptor: function(k) { 1378 key = k; return k < "z" ? {value: 42} : void 0 1379 } 1380}) 1381 1382TestHasOwn(Proxy.create({ 1383 get: function(pr, pk) { 1384 return function(k) { key = k; return k < "z" } 1385 } 1386})) 1387 1388 1389function TestHasOwnThrow(handler) { 1390 TestWithProxies(TestHasOwnThrow2, handler) 1391} 1392 1393function TestHasOwnThrow2(create, handler) { 1394 var p = create(handler) 1395 assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, "a")}, 1396 "myexn") 1397 assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, 99)}, 1398 "myexn") 1399} 1400 1401TestHasOwnThrow({ 1402 hasOwn: function(k) { throw "myexn" } 1403}) 1404 1405TestHasOwnThrow({ 1406 hasOwn: function(k) { return this.hasOwn2(k) }, 1407 hasOwn2: function(k) { throw "myexn" } 1408}) 1409 1410TestHasOwnThrow({ 1411 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1412}) 1413 1414TestHasOwnThrow({ 1415 getOwnPropertyDescriptor: function(k) { 1416 return this.getOwnPropertyDescriptor2(k) 1417 }, 1418 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 1419}) 1420 1421TestHasOwnThrow({ 1422 hasOwn: undefined, 1423 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1424}) 1425 1426TestHasOwnThrow(Proxy.create({ 1427 get: function(pr, pk) { throw "myexn" } 1428})) 1429 1430TestHasOwnThrow(Proxy.create({ 1431 get: function(pr, pk) { 1432 return function(k) { throw "myexn" } 1433 } 1434})) 1435 1436 1437 1438// Instanceof (instanceof) 1439 1440function TestProxyInstanceof() { 1441 var o1 = {} 1442 var p1 = Proxy.create({}) 1443 var p2 = Proxy.create({}, o1) 1444 var p3 = Proxy.create({}, p2) 1445 var o2 = Object.create(p2) 1446 1447 var f0 = function() {} 1448 f0.prototype = o1 1449 var f1 = function() {} 1450 f1.prototype = p1 1451 var f2 = function() {} 1452 f2.prototype = p2 1453 var f3 = function() {} 1454 f3.prototype = o2 1455 1456 assertTrue(o1 instanceof Object) 1457 assertFalse(o1 instanceof f0) 1458 assertFalse(o1 instanceof f1) 1459 assertFalse(o1 instanceof f2) 1460 assertFalse(o1 instanceof f3) 1461 assertFalse(p1 instanceof Object) 1462 assertFalse(p1 instanceof f0) 1463 assertFalse(p1 instanceof f1) 1464 assertFalse(p1 instanceof f2) 1465 assertFalse(p1 instanceof f3) 1466 assertTrue(p2 instanceof Object) 1467 assertTrue(p2 instanceof f0) 1468 assertFalse(p2 instanceof f1) 1469 assertFalse(p2 instanceof f2) 1470 assertFalse(p2 instanceof f3) 1471 assertTrue(p3 instanceof Object) 1472 assertTrue(p3 instanceof f0) 1473 assertFalse(p3 instanceof f1) 1474 assertTrue(p3 instanceof f2) 1475 assertFalse(p3 instanceof f3) 1476 assertTrue(o2 instanceof Object) 1477 assertTrue(o2 instanceof f0) 1478 assertFalse(o2 instanceof f1) 1479 assertTrue(o2 instanceof f2) 1480 assertFalse(o2 instanceof f3) 1481 1482 var f = Proxy.createFunction({}, function() {}) 1483 assertTrue(f instanceof Function) 1484} 1485 1486TestProxyInstanceof() 1487 1488 1489function TestInstanceofProxy() { 1490 var o0 = Object.create(null) 1491 var o1 = {} 1492 var o2 = Object.create(o0) 1493 var o3 = Object.create(o1) 1494 var o4 = Object.create(o2) 1495 var o5 = Object.create(o3) 1496 1497 function handler(o) { return {get: function() { return o } } } 1498 var f0 = Proxy.createFunction(handler(o0), function() {}) 1499 var f1 = Proxy.createFunction(handler(o1), function() {}) 1500 var f2 = Proxy.createFunction(handler(o2), function() {}) 1501 var f3 = Proxy.createFunction(handler(o3), function() {}) 1502 var f4 = Proxy.createFunction(handler(o4), function() {}) 1503 var f5 = Proxy.createFunction(handler(o4), function() {}) 1504 1505 assertFalse(null instanceof f0) 1506 assertFalse(o0 instanceof f0) 1507 assertFalse(o0 instanceof f1) 1508 assertFalse(o0 instanceof f2) 1509 assertFalse(o0 instanceof f3) 1510 assertFalse(o0 instanceof f4) 1511 assertFalse(o0 instanceof f5) 1512 assertFalse(o1 instanceof f0) 1513 assertFalse(o1 instanceof f1) 1514 assertFalse(o1 instanceof f2) 1515 assertFalse(o1 instanceof f3) 1516 assertFalse(o1 instanceof f4) 1517 assertFalse(o1 instanceof f5) 1518 assertTrue(o2 instanceof f0) 1519 assertFalse(o2 instanceof f1) 1520 assertFalse(o2 instanceof f2) 1521 assertFalse(o2 instanceof f3) 1522 assertFalse(o2 instanceof f4) 1523 assertFalse(o2 instanceof f5) 1524 assertFalse(o3 instanceof f0) 1525 assertTrue(o3 instanceof f1) 1526 assertFalse(o3 instanceof f2) 1527 assertFalse(o3 instanceof f3) 1528 assertFalse(o3 instanceof f4) 1529 assertFalse(o3 instanceof f5) 1530 assertTrue(o4 instanceof f0) 1531 assertFalse(o4 instanceof f1) 1532 assertTrue(o4 instanceof f2) 1533 assertFalse(o4 instanceof f3) 1534 assertFalse(o4 instanceof f4) 1535 assertFalse(o4 instanceof f5) 1536 assertFalse(o5 instanceof f0) 1537 assertTrue(o5 instanceof f1) 1538 assertFalse(o5 instanceof f2) 1539 assertTrue(o5 instanceof f3) 1540 assertFalse(o5 instanceof f4) 1541 assertFalse(o5 instanceof f5) 1542 1543 var f = Proxy.createFunction({}, function() {}) 1544 var ff = Proxy.createFunction(handler(Function), function() {}) 1545 assertTrue(f instanceof Function) 1546 assertFalse(f instanceof ff) 1547} 1548 1549TestInstanceofProxy() 1550 1551 1552 1553// Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). 1554 1555function TestPrototype() { 1556 var o1 = {} 1557 var p1 = Proxy.create({}) 1558 var p2 = Proxy.create({}, o1) 1559 var p3 = Proxy.create({}, p2) 1560 var p4 = Proxy.create({}, null) 1561 var o2 = Object.create(p3) 1562 1563 assertSame(Object.getPrototypeOf(o1), Object.prototype) 1564 assertSame(Object.getPrototypeOf(p1), null) 1565 assertSame(Object.getPrototypeOf(p2), o1) 1566 assertSame(Object.getPrototypeOf(p3), p2) 1567 assertSame(Object.getPrototypeOf(p4), null) 1568 assertSame(Object.getPrototypeOf(o2), p3) 1569 1570 assertTrue(Object.prototype.isPrototypeOf(o1)) 1571 assertFalse(Object.prototype.isPrototypeOf(p1)) 1572 assertTrue(Object.prototype.isPrototypeOf(p2)) 1573 assertTrue(Object.prototype.isPrototypeOf(p3)) 1574 assertFalse(Object.prototype.isPrototypeOf(p4)) 1575 assertTrue(Object.prototype.isPrototypeOf(o2)) 1576 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1)) 1577 assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p1)) 1578 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2)) 1579 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3)) 1580 assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p4)) 1581 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2)) 1582 assertFalse(Object.prototype.isPrototypeOf.call(o1, o1)) 1583 assertFalse(Object.prototype.isPrototypeOf.call(o1, p1)) 1584 assertTrue(Object.prototype.isPrototypeOf.call(o1, p2)) 1585 assertTrue(Object.prototype.isPrototypeOf.call(o1, p3)) 1586 assertFalse(Object.prototype.isPrototypeOf.call(o1, p4)) 1587 assertTrue(Object.prototype.isPrototypeOf.call(o1, o2)) 1588 assertFalse(Object.prototype.isPrototypeOf.call(p1, p1)) 1589 assertFalse(Object.prototype.isPrototypeOf.call(p1, o1)) 1590 assertFalse(Object.prototype.isPrototypeOf.call(p1, p2)) 1591 assertFalse(Object.prototype.isPrototypeOf.call(p1, p3)) 1592 assertFalse(Object.prototype.isPrototypeOf.call(p1, p4)) 1593 assertFalse(Object.prototype.isPrototypeOf.call(p1, o2)) 1594 assertFalse(Object.prototype.isPrototypeOf.call(p2, p1)) 1595 assertFalse(Object.prototype.isPrototypeOf.call(p2, p2)) 1596 assertTrue(Object.prototype.isPrototypeOf.call(p2, p3)) 1597 assertFalse(Object.prototype.isPrototypeOf.call(p2, p4)) 1598 assertTrue(Object.prototype.isPrototypeOf.call(p2, o2)) 1599 assertFalse(Object.prototype.isPrototypeOf.call(p3, p2)) 1600 assertTrue(Object.prototype.isPrototypeOf.call(p3, o2)) 1601 assertFalse(Object.prototype.isPrototypeOf.call(o2, o1)) 1602 assertFalse(Object.prototype.isPrototypeOf.call(o2, p1)) 1603 assertFalse(Object.prototype.isPrototypeOf.call(o2, p2)) 1604 assertFalse(Object.prototype.isPrototypeOf.call(o2, p3)) 1605 assertFalse(Object.prototype.isPrototypeOf.call(o2, p4)) 1606 assertFalse(Object.prototype.isPrototypeOf.call(o2, o2)) 1607 1608 var f = Proxy.createFunction({}, function() {}) 1609 assertSame(Object.getPrototypeOf(f), Function.prototype) 1610 assertTrue(Object.prototype.isPrototypeOf(f)) 1611 assertTrue(Object.prototype.isPrototypeOf.call(Function.prototype, f)) 1612} 1613 1614TestPrototype() 1615 1616 1617 1618// Property names (Object.getOwnPropertyNames, Object.keys). 1619 1620function TestPropertyNames(names, handler) { 1621 TestWithProxies(TestPropertyNames2, handler, names) 1622} 1623 1624function TestPropertyNames2(create, handler, names) { 1625 var p = create(handler) 1626 assertArrayEquals(names, Object.getOwnPropertyNames(p)) 1627} 1628 1629TestPropertyNames([], { 1630 getOwnPropertyNames: function() { return [] } 1631}) 1632 1633TestPropertyNames(["a", "zz", " ", "0"], { 1634 getOwnPropertyNames: function() { return ["a", "zz", " ", 0] } 1635}) 1636 1637TestPropertyNames(["throw", "function "], { 1638 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1639 getOwnPropertyNames2: function() { return ["throw", "function "] } 1640}) 1641 1642TestPropertyNames(["[object Object]"], { 1643 get getOwnPropertyNames() { 1644 return function() { return [{}] } 1645 } 1646}) 1647 1648 1649function TestPropertyNamesThrow(handler) { 1650 TestWithProxies(TestPropertyNamesThrow2, handler) 1651} 1652 1653function TestPropertyNamesThrow2(create, handler) { 1654 var p = create(handler) 1655 assertThrows(function(){ Object.getOwnPropertyNames(p) }, "myexn") 1656} 1657 1658TestPropertyNamesThrow({ 1659 getOwnPropertyNames: function() { throw "myexn" } 1660}) 1661 1662TestPropertyNamesThrow({ 1663 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1664 getOwnPropertyNames2: function() { throw "myexn" } 1665}) 1666 1667 1668function TestKeys(names, handler) { 1669 TestWithProxies(TestKeys2, handler, names) 1670} 1671 1672function TestKeys2(create, handler, names) { 1673 var p = create(handler) 1674 assertArrayEquals(names, Object.keys(p)) 1675} 1676 1677TestKeys([], { 1678 keys: function() { return [] } 1679}) 1680 1681TestKeys(["a", "zz", " ", "0"], { 1682 keys: function() { return ["a", "zz", " ", 0] } 1683}) 1684 1685TestKeys(["throw", "function "], { 1686 keys: function() { return this.keys2() }, 1687 keys2: function() { return ["throw", "function "] } 1688}) 1689 1690TestKeys(["[object Object]"], { 1691 get keys() { 1692 return function() { return [{}] } 1693 } 1694}) 1695 1696TestKeys(["a", "0"], { 1697 getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] }, 1698 getOwnPropertyDescriptor: function(k) { 1699 return k == "" ? undefined : {enumerable: k.length == 1} 1700 } 1701}) 1702 1703TestKeys(["23", "zz", ""], { 1704 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1705 getOwnPropertyNames2: function() { return ["a", 23, "zz", "", 0] }, 1706 getOwnPropertyDescriptor: function(k) { 1707 return this.getOwnPropertyDescriptor2(k) 1708 }, 1709 getOwnPropertyDescriptor2: function(k) { return {enumerable: k.length != 1} } 1710}) 1711 1712TestKeys(["a", "b", "c", "5"], { 1713 get getOwnPropertyNames() { 1714 return function() { return ["0", 4, "a", "b", "c", 5, "ety"] } 1715 }, 1716 get getOwnPropertyDescriptor() { 1717 return function(k) { 1718 return k == "ety" ? undefined : {enumerable: k >= "44"} 1719 } 1720 } 1721}) 1722 1723TestKeys([], { 1724 get getOwnPropertyNames() { 1725 return function() { return ["a", "b", "c"] } 1726 }, 1727 getOwnPropertyDescriptor: function(k) { return {} } 1728}) 1729 1730 1731function TestKeysThrow(handler) { 1732 TestWithProxies(TestKeysThrow2, handler) 1733} 1734 1735function TestKeysThrow2(create, handler) { 1736 var p = create(handler) 1737 assertThrows(function(){ Object.keys(p) }, "myexn") 1738} 1739 1740TestKeysThrow({ 1741 keys: function() { throw "myexn" } 1742}) 1743 1744TestKeysThrow({ 1745 keys: function() { return this.keys2() }, 1746 keys2: function() { throw "myexn" } 1747}) 1748 1749TestKeysThrow({ 1750 getOwnPropertyNames: function() { throw "myexn" }, 1751 getOwnPropertyDescriptor: function(k) { return true } 1752}) 1753 1754TestKeysThrow({ 1755 getOwnPropertyNames: function() { return [1, 2] }, 1756 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1757}) 1758 1759TestKeysThrow({ 1760 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1761 getOwnPropertyNames2: function() { throw "myexn" }, 1762}) 1763 1764TestKeysThrow({ 1765 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1766 getOwnPropertyNames2: function() { return [1, 2] }, 1767 getOwnPropertyDescriptor: function(k) { 1768 return this.getOwnPropertyDescriptor2(k) 1769 }, 1770 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 1771}) 1772 1773TestKeysThrow({ 1774 get getOwnPropertyNames() { throw "myexn" } 1775}) 1776 1777TestKeysThrow({ 1778 get getOwnPropertyNames() { 1779 return function() { throw "myexn" } 1780 }, 1781}) 1782 1783TestKeysThrow([], { 1784 get getOwnPropertyNames() { 1785 return function() { return [1, 2] } 1786 }, 1787 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1788}) 1789 1790 1791 1792// Fixing (Object.freeze, Object.seal, Object.preventExtensions, 1793// Object.isFrozen, Object.isSealed, Object.isExtensible) 1794 1795function TestFix(names, handler) { 1796 var proto = {p: 77} 1797 var assertFixing = function(o, s, f, e) { 1798 assertEquals(s, Object.isSealed(o)) 1799 assertEquals(f, Object.isFrozen(o)) 1800 assertEquals(e, Object.isExtensible(o)) 1801 } 1802 1803 var p1 = Proxy.create(handler, proto) 1804 assertFixing(p1, false, false, true) 1805 Object.seal(p1) 1806 assertFixing(p1, true, names.length === 0, false) 1807 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p1).sort()) 1808 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), 1809 Object.keys(p1).sort()) 1810 assertEquals(proto, Object.getPrototypeOf(p1)) 1811 assertEquals(77, p1.p) 1812 for (var n in p1) { 1813 var desc = Object.getOwnPropertyDescriptor(p1, n) 1814 if (desc !== undefined) assertFalse(desc.configurable) 1815 } 1816 1817 var p2 = Proxy.create(handler, proto) 1818 assertFixing(p2, false, false, true) 1819 Object.freeze(p2) 1820 assertFixing(p2, true, true, false) 1821 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p2).sort()) 1822 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), 1823 Object.keys(p2).sort()) 1824 assertEquals(proto, Object.getPrototypeOf(p2)) 1825 assertEquals(77, p2.p) 1826 for (var n in p2) { 1827 var desc = Object.getOwnPropertyDescriptor(p2, n) 1828 if (desc !== undefined) assertFalse(desc.writable) 1829 if (desc !== undefined) assertFalse(desc.configurable) 1830 } 1831 1832 var p3 = Proxy.create(handler, proto) 1833 assertFixing(p3, false, false, true) 1834 Object.preventExtensions(p3) 1835 assertFixing(p3, names.length === 0, names.length === 0, false) 1836 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p3).sort()) 1837 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(), 1838 Object.keys(p3).sort()) 1839 assertEquals(proto, Object.getPrototypeOf(p3)) 1840 assertEquals(77, p3.p) 1841 1842 var p = Proxy.create(handler, proto) 1843 var o = Object.create(p) 1844 assertFixing(p, false, false, true) 1845 assertFixing(o, false, false, true) 1846 Object.freeze(o) 1847 assertFixing(p, false, false, true) 1848 assertFixing(o, true, true, false) 1849} 1850 1851TestFix([], { 1852 fix: function() { return {} } 1853}) 1854 1855TestFix(["a", "b", "c", "3", "zz"], { 1856 fix: function() { 1857 return { 1858 a: {value: "a", writable: true, configurable: false, enumerable: true}, 1859 b: {value: 33, writable: false, configurable: false, enumerable: true}, 1860 c: {value: 0, writable: true, configurable: true, enumerable: true}, 1861 '3': {value: true, writable: false, configurable: true, enumerable: true}, 1862 zz: {value: 0, enumerable: false} 1863 } 1864 } 1865}) 1866 1867TestFix(["a"], { 1868 fix: function() { return this.fix2() }, 1869 fix2: function() { 1870 return {a: {value: 4, writable: true, configurable: true, enumerable: true}} 1871 } 1872}) 1873 1874TestFix(["b"], { 1875 get fix() { 1876 return function() { 1877 return {b: {configurable: true, writable: true, enumerable: true}} 1878 } 1879 } 1880}) 1881 1882 1883function TestFixFunction(fix) { 1884 var f1 = Proxy.createFunction({ 1885 fix: function() { return {} } 1886 }, function() {}) 1887 fix(f1) 1888 assertEquals(0, f1.length) 1889 1890 var f2 = Proxy.createFunction({ 1891 fix: function() { return {length: {value: 3}} } 1892 }, function() {}) 1893 fix(f2) 1894 assertEquals(3, f2.length) 1895 1896 var f3 = Proxy.createFunction({ 1897 fix: function() { return {length: {value: "huh"}} } 1898 }, function() {}) 1899 fix(f3) 1900 assertEquals(0, f1.length) 1901} 1902 1903TestFixFunction(Object.seal) 1904TestFixFunction(Object.freeze) 1905TestFixFunction(Object.preventExtensions) 1906 1907 1908function TestFixThrow(handler) { 1909 TestWithProxies(TestFixThrow2, handler) 1910} 1911 1912function TestFixThrow2(create, handler) { 1913 var p = create(handler, {}) 1914 assertThrows(function(){ Object.seal(p) }, "myexn") 1915 assertThrows(function(){ Object.freeze(p) }, "myexn") 1916 assertThrows(function(){ Object.preventExtensions(p) }, "myexn") 1917} 1918 1919TestFixThrow({ 1920 fix: function() { throw "myexn" } 1921}) 1922 1923TestFixThrow({ 1924 fix: function() { return this.fix2() }, 1925 fix2: function() { throw "myexn" } 1926}) 1927 1928TestFixThrow({ 1929 get fix() { throw "myexn" } 1930}) 1931 1932TestFixThrow({ 1933 get fix() { 1934 return function() { throw "myexn" } 1935 } 1936}) 1937 1938 1939// Freeze a proxy in the middle of operations on it. 1940// TODO(rossberg): actual behaviour not specified consistently at the moment, 1941// just make sure that we do not crash. 1942function TestReentrantFix(f) { 1943 TestWithProxies(f, Object.freeze) 1944 TestWithProxies(f, Object.seal) 1945 TestWithProxies(f, Object.preventExtensions) 1946} 1947 1948TestReentrantFix(function(create, freeze) { 1949 var handler = { 1950 get get() { freeze(p); return undefined }, 1951 fix: function() { return {} } 1952 } 1953 var p = create(handler) 1954 // Freeze while getting get trap. 1955 try { p.x } catch (e) { assertInstanceof(e, Error) } 1956}) 1957 1958TestReentrantFix(function(create, freeze) { 1959 var handler = { 1960 get: function() { freeze(p); return 3 }, 1961 fix: function() { return {} } 1962 } 1963 var p = create(handler) 1964 // Freeze while executing get trap. 1965 try { p.x } catch (e) { assertInstanceof(e, Error) } 1966}) 1967 1968TestReentrantFix(function(create, freeze) { 1969 var handler = { 1970 getPropertyDescriptor: function() { freeze(p); return undefined }, 1971 fix: function() { return {} } 1972 } 1973 var p = create(handler) 1974 // Freeze while executing default get trap. 1975 try { p.x } catch (e) { assertInstanceof(e, Error) } 1976}) 1977 1978TestReentrantFix(function(create, freeze) { 1979 var handler = { 1980 getPropertyDescriptor: function() { freeze(p); return {get: function(){}} }, 1981 fix: function() { return {} } 1982 } 1983 var p = create(handler) 1984 var o = Object.create(p) 1985 // Freeze while getting a property from prototype. 1986 try { o.x } catch (e) { assertInstanceof(e, Error) } 1987}) 1988 1989TestReentrantFix(function(create, freeze) { 1990 var handler = { 1991 get set() { freeze(p); return undefined }, 1992 fix: function() { return {} } 1993 } 1994 var p = create(handler) 1995 // Freeze while getting set trap. 1996 try { p.x = 4 } catch (e) { assertInstanceof(e, Error) } 1997}) 1998 1999TestReentrantFix(function(create, freeze) { 2000 var handler = { 2001 set: function() { freeze(p); return true }, 2002 fix: function() { return {} } 2003 } 2004 var p = create(handler) 2005 // Freeze while executing set trap. 2006 try { p.x = 4 } catch (e) { assertInstanceof(e, Error) } 2007}) 2008 2009TestReentrantFix(function(create, freeze) { 2010 var handler = { 2011 getOwnPropertyDescriptor: function() { freeze(p); return undefined }, 2012 fix: function() { return {} } 2013 } 2014 var p = create(handler) 2015 // Freeze while executing default set trap. 2016 try { p.x } catch (e) { assertInstanceof(e, Error) } 2017}) 2018 2019TestReentrantFix(function(create, freeze) { 2020 var handler = { 2021 getPropertyDescriptor: function() { freeze(p); return {set: function(){}} }, 2022 fix: function() { return {} } 2023 } 2024 var p = create(handler) 2025 var o = Object.create(p) 2026 // Freeze while setting a property in prototype, dropping the property! 2027 try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } 2028}) 2029 2030TestReentrantFix(function(create, freeze) { 2031 var handler = { 2032 getPropertyDescriptor: function() { freeze(p); return {set: function(){}} }, 2033 fix: function() { return {x: {get: function(){}}} } 2034 } 2035 var p = create(handler) 2036 var o = Object.create(p) 2037 // Freeze while setting a property in prototype, making it read-only! 2038 try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } 2039}) 2040 2041TestReentrantFix(function(create, freeze) { 2042 var handler = { 2043 get fix() { freeze(p); return function(){} } 2044 } 2045 var p = create(handler) 2046 // Freeze while getting fix trap. 2047 try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) } 2048 p = create(handler) 2049 try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) } 2050 p = create(handler) 2051 try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) } 2052}) 2053 2054TestReentrantFix(function(create, freeze) { 2055 var handler = { 2056 fix: function() { freeze(p); return {} } 2057 } 2058 var p = create(handler) 2059 // Freeze while executing fix trap. 2060 try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) } 2061 p = create(handler) 2062 try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) } 2063 p = create(handler) 2064 try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) } 2065}) 2066 2067 2068 2069// String conversion (Object.prototype.toString, 2070// Object.prototype.toLocaleString, 2071// Function.prototype.toString) 2072 2073var key 2074 2075function TestToString(handler) { 2076 var p = Proxy.create(handler) 2077 key = "" 2078 assertEquals("[object Object]", Object.prototype.toString.call(p)) 2079 assertEquals("", key) 2080 assertEquals("my_proxy", Object.prototype.toLocaleString.call(p)) 2081 assertEquals("toString", key) 2082 2083 var f = Proxy.createFunction(handler, function() {}) 2084 key = "" 2085 assertEquals("[object Function]", Object.prototype.toString.call(f)) 2086 assertEquals("", key) 2087 assertEquals("my_proxy", Object.prototype.toLocaleString.call(f)) 2088 assertEquals("toString", key) 2089 assertDoesNotThrow(function(){ Function.prototype.toString.call(f) }) 2090 2091 var o = Object.create(p) 2092 key = "" 2093 assertEquals("[object Object]", Object.prototype.toString.call(o)) 2094 assertEquals("", key) 2095 assertEquals("my_proxy", Object.prototype.toLocaleString.call(o)) 2096 assertEquals("toString", key) 2097} 2098 2099TestToString({ 2100 get: function(r, k) { key = k; return function() { return "my_proxy" } } 2101}) 2102 2103TestToString({ 2104 get: function(r, k) { return this.get2(r, k) }, 2105 get2: function(r, k) { key = k; return function() { return "my_proxy" } } 2106}) 2107 2108TestToString(Proxy.create({ 2109 get: function(pr, pk) { 2110 return function(r, k) { key = k; return function() { return "my_proxy" } } 2111 } 2112})) 2113 2114 2115function TestToStringThrow(handler) { 2116 var p = Proxy.create(handler) 2117 assertEquals("[object Object]", Object.prototype.toString.call(p)) 2118 assertThrows(function(){ Object.prototype.toLocaleString.call(p) }, "myexn") 2119 2120 var f = Proxy.createFunction(handler, function() {}) 2121 assertEquals("[object Function]", Object.prototype.toString.call(f)) 2122 assertThrows(function(){ Object.prototype.toLocaleString.call(f) }, "myexn") 2123 2124 var o = Object.create(p) 2125 assertEquals("[object Object]", Object.prototype.toString.call(o)) 2126 assertThrows(function(){ Object.prototype.toLocaleString.call(o) }, "myexn") 2127} 2128 2129TestToStringThrow({ 2130 get: function(r, k) { throw "myexn" } 2131}) 2132 2133TestToStringThrow({ 2134 get: function(r, k) { return function() { throw "myexn" } } 2135}) 2136 2137TestToStringThrow({ 2138 get: function(r, k) { return this.get2(r, k) }, 2139 get2: function(r, k) { throw "myexn" } 2140}) 2141 2142TestToStringThrow(Proxy.create({ 2143 get: function(pr, pk) { throw "myexn" } 2144})) 2145 2146TestToStringThrow(Proxy.create({ 2147 get: function(pr, pk) { 2148 return function(r, k) { throw "myexn" } 2149 } 2150})) 2151 2152 2153 2154// Value conversion (Object.prototype.toValue) 2155 2156function TestValueOf(handler) { 2157 TestWithProxies(TestValueOf2, handler) 2158} 2159 2160function TestValueOf2(create, handler) { 2161 var p = create(handler) 2162 assertSame(p, Object.prototype.valueOf.call(p)) 2163} 2164 2165TestValueOf({}) 2166 2167 2168 2169// Enumerability (Object.prototype.propertyIsEnumerable) 2170 2171var key 2172 2173function TestIsEnumerable(handler) { 2174 TestWithProxies(TestIsEnumerable2, handler) 2175} 2176 2177function TestIsEnumerable2(create, handler) { 2178 var p = create(handler) 2179 assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a")) 2180 assertEquals("a", key) 2181 assertTrue(Object.prototype.propertyIsEnumerable.call(p, 2)) 2182 assertEquals("2", key) 2183 assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z")) 2184 assertEquals("z", key) 2185 2186 var o = Object.create(p) 2187 key = "" 2188 assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a")) 2189 assertEquals("", key) // trap not invoked 2190} 2191 2192TestIsEnumerable({ 2193 getOwnPropertyDescriptor: function(k) { 2194 key = k; return {enumerable: k < "z", configurable: true} 2195 }, 2196}) 2197 2198TestIsEnumerable({ 2199 getOwnPropertyDescriptor: function(k) { 2200 return this.getOwnPropertyDescriptor2(k) 2201 }, 2202 getOwnPropertyDescriptor2: function(k) { 2203 key = k; return {enumerable: k < "z", configurable: true} 2204 }, 2205}) 2206 2207TestIsEnumerable({ 2208 getOwnPropertyDescriptor: function(k) { 2209 key = k; return {get enumerable() { return k < "z" }, configurable: true} 2210 }, 2211}) 2212 2213TestIsEnumerable(Proxy.create({ 2214 get: function(pr, pk) { 2215 return function(k) { 2216 key = k; return {enumerable: k < "z", configurable: true} 2217 } 2218 } 2219})) 2220 2221 2222function TestIsEnumerableThrow(handler) { 2223 TestWithProxies(TestIsEnumerableThrow2, handler) 2224} 2225 2226function TestIsEnumerableThrow2(create, handler) { 2227 var p = create(handler) 2228 assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, "a") }, 2229 "myexn") 2230 assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, 11) }, 2231 "myexn") 2232} 2233 2234TestIsEnumerableThrow({ 2235 getOwnPropertyDescriptor: function(k) { throw "myexn" } 2236}) 2237 2238TestIsEnumerableThrow({ 2239 getOwnPropertyDescriptor: function(k) { 2240 return this.getOwnPropertyDescriptor2(k) 2241 }, 2242 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 2243}) 2244 2245TestIsEnumerableThrow({ 2246 getOwnPropertyDescriptor: function(k) { 2247 return {get enumerable() { throw "myexn" }, configurable: true} 2248 }, 2249}) 2250 2251TestIsEnumerableThrow(Proxy.create({ 2252 get: function(pr, pk) { throw "myexn" } 2253})) 2254 2255TestIsEnumerableThrow(Proxy.create({ 2256 get: function(pr, pk) { 2257 return function(k) { throw "myexn" } 2258 } 2259})) 2260 2261 2262 2263// Constructor functions with proxy prototypes. 2264 2265function TestConstructorWithProxyPrototype() { 2266 TestWithProxies(TestConstructorWithProxyPrototype2, {}) 2267} 2268 2269function TestConstructorWithProxyPrototype2(create, handler) { 2270 function C() {}; 2271 C.prototype = create(handler); 2272 2273 var o = new C; 2274 assertSame(C.prototype, o.__proto__); 2275 assertSame(C.prototype, Object.getPrototypeOf(o)); 2276} 2277 2278TestConstructorWithProxyPrototype(); 2279