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