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 33 function 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 42 var key 43 44 function TestGetOwnProperty(handler) { 45 TestWithProxies(TestGetOwnProperty2, handler) 46 } 47 48 function 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 56 TestGetOwnProperty({ 57 getOwnPropertyDescriptor: function(k) { 58 key = k 59 return {value: 42, configurable: true} 60 } 61 }) 62 63 TestGetOwnProperty({ 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 73 TestGetOwnProperty({ 74 getOwnPropertyDescriptor: function(k) { 75 key = k 76 return {get value() { return 42 }, get configurable() { return true }} 77 } 78 }) 79 80 TestGetOwnProperty(Proxy.create({ 81 get: function(pr, pk) { 82 return function(k) { key = k; return {value: 42, configurable: true} } 83 } 84 })) 85 86 87 function TestGetOwnPropertyThrow(handler) { 88 TestWithProxies(TestGetOwnPropertyThrow2, handler) 89 } 90 91 function 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 97 TestGetOwnPropertyThrow({ 98 getOwnPropertyDescriptor: function(k) { throw "myexn" } 99 }) 100 101 TestGetOwnPropertyThrow({ 102 getOwnPropertyDescriptor: function(k) { 103 return this.getPropertyDescriptor2(k) 104 }, 105 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 106 }) 107 108 TestGetOwnPropertyThrow({ 109 getOwnPropertyDescriptor: function(k) { 110 return {get value() { throw "myexn" }} 111 } 112 }) 113 114 TestGetOwnPropertyThrow(Proxy.create({ 115 get: function(pr, pk) { 116 return function(k) { throw "myexn" } 117 } 118 })) 119 120 121 122 // Getters (dot, brackets). 123 124 var key 125 126 function TestGet(handler) { 127 TestWithProxies(TestGet2, handler) 128 } 129 130 function 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 159 TestGet({ 160 get: function(r, k) { key = k; return 42 } 161 }) 162 163 TestGet({ 164 get: function(r, k) { return this.get2(r, k) }, 165 get2: function(r, k) { key = k; return 42 } 166 }) 167 168 TestGet({ 169 getPropertyDescriptor: function(k) { key = k; return {value: 42} } 170 }) 171 172 TestGet({ 173 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 174 getPropertyDescriptor2: function(k) { key = k; return {value: 42} } 175 }) 176 177 TestGet({ 178 getPropertyDescriptor: function(k) { 179 key = k; 180 return {get value() { return 42 }} 181 } 182 }) 183 184 TestGet({ 185 get: undefined, 186 getPropertyDescriptor: function(k) { key = k; return {value: 42} } 187 }) 188 189 TestGet(Proxy.create({ 190 get: function(pr, pk) { 191 return function(r, k) { key = k; return 42 } 192 } 193 })) 194 195 196 function TestGetCall(handler) { 197 TestWithProxies(TestGetCall2, handler) 198 } 199 200 function 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 239 TestGetCall({ 240 get: function(r, k) { return function() { return 55 } } 241 }) 242 243 TestGetCall({ 244 get: function(r, k) { return this.get2(r, k) }, 245 get2: function(r, k) { return function() { return 55 } } 246 }) 247 248 TestGetCall({ 249 getPropertyDescriptor: function(k) { 250 return {value: function() { return 55 }} 251 } 252 }) 253 254 TestGetCall({ 255 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 256 getPropertyDescriptor2: function(k) { 257 return {value: function() { return 55 }} 258 } 259 }) 260 261 TestGetCall({ 262 getPropertyDescriptor: function(k) { 263 return {get value() { return function() { return 55 } }} 264 } 265 }) 266 267 TestGetCall({ 268 get: undefined, 269 getPropertyDescriptor: function(k) { 270 return {value: function() { return 55 }} 271 } 272 }) 273 274 TestGetCall({ 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 286 TestGetCall(Proxy.create({ 287 get: function(pr, pk) { 288 return function(r, k) { return function() { return 55 } } 289 } 290 })) 291 292 293 function TestGetThrow(handler) { 294 TestWithProxies(TestGetThrow2, handler) 295 } 296 297 function 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 313 TestGetThrow({ 314 get: function(r, k) { throw "myexn" } 315 }) 316 317 TestGetThrow({ 318 get: function(r, k) { return this.get2(r, k) }, 319 get2: function(r, k) { throw "myexn" } 320 }) 321 322 TestGetThrow({ 323 getPropertyDescriptor: function(k) { throw "myexn" } 324 }) 325 326 TestGetThrow({ 327 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 328 getPropertyDescriptor2: function(k) { throw "myexn" } 329 }) 330 331 TestGetThrow({ 332 getPropertyDescriptor: function(k) { 333 return {get value() { throw "myexn" }} 334 } 335 }) 336 337 TestGetThrow({ 338 get: undefined, 339 getPropertyDescriptor: function(k) { throw "myexn" } 340 }) 341 342 TestGetThrow(Proxy.create({ 343 get: function(pr, pk) { throw "myexn" } 344 })) 345 346 TestGetThrow(Proxy.create({ 347 get: function(pr, pk) { 348 return function(r, k) { throw "myexn" } 349 } 350 })) 351 352 353 354 // Setters. 355 356 var key 357 var val 358 359 function TestSet(handler) { 360 TestWithProxies(TestSet2, handler) 361 } 362 363 function 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 383 TestSet({ 384 set: function(r, k, v) { key = k; val = v; return true } 385 }) 386 387 TestSet({ 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 392 TestSet({ 393 getOwnPropertyDescriptor: function(k) { return {writable: true} }, 394 defineProperty: function(k, desc) { key = k; val = desc.value } 395 }) 396 397 TestSet({ 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 406 TestSet({ 407 getOwnPropertyDescriptor: function(k) { 408 return {get writable() { return true }} 409 }, 410 defineProperty: function(k, desc) { key = k; val = desc.value } 411 }) 412 413 TestSet({ 414 getOwnPropertyDescriptor: function(k) { 415 return {set: function(v) { key = k; val = v }} 416 } 417 }) 418 419 TestSet({ 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 425 TestSet({ 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 433 TestSet({ 434 getOwnPropertyDescriptor: function(k) { return null }, 435 getPropertyDescriptor: function(k) { 436 return {set: function(v) { key = k; val = v }} 437 } 438 }) 439 440 TestSet({ 441 getOwnPropertyDescriptor: function(k) { return null }, 442 getPropertyDescriptor: function(k) { return null }, 443 defineProperty: function(k, desc) { key = k, val = desc.value } 444 }) 445 446 TestSet(Proxy.create({ 447 get: function(pr, pk) { 448 return function(r, k, v) { key = k; val = v; return true } 449 } 450 })) 451 452 453 function TestSetThrow(handler) { 454 TestWithProxies(TestSetThrow2, handler) 455 } 456 457 function 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 466 TestSetThrow({ 467 set: function(r, k, v) { throw "myexn" } 468 }) 469 470 TestSetThrow({ 471 set: function(r, k, v) { return this.set2(r, k, v) }, 472 set2: function(r, k, v) { throw "myexn" } 473 }) 474 475 TestSetThrow({ 476 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 477 defineProperty: function(k, desc) { key = k; val = desc.value } 478 }) 479 480 TestSetThrow({ 481 getOwnPropertyDescriptor: function(k) { return {writable: true} }, 482 defineProperty: function(k, desc) { throw "myexn" } 483 }) 484 485 TestSetThrow({ 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 494 TestSetThrow({ 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 503 TestSetThrow({ 504 getOwnPropertyDescriptor: function(k) { throw "myexn" }, 505 defineProperty: function(k, desc) { key = k; val = desc.value } 506 }) 507 508 TestSetThrow({ 509 getOwnPropertyDescriptor: function(k) { 510 return {get writable() { return true }} 511 }, 512 defineProperty: function(k, desc) { throw "myexn" } 513 }) 514 515 TestSetThrow({ 516 getOwnPropertyDescriptor: function(k) { throw "myexn" } 517 }) 518 519 TestSetThrow({ 520 getOwnPropertyDescriptor: function(k) { 521 return {set: function(v) { throw "myexn" }} 522 } 523 }) 524 525 TestSetThrow({ 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 531 TestSetThrow({ 532 getOwnPropertyDescriptor: function(k) { return null }, 533 getPropertyDescriptor: function(k) { throw "myexn" }, 534 defineProperty: function(k, desc) { key = k; val = desc.value } 535 }) 536 537 TestSetThrow({ 538 getOwnPropertyDescriptor: function(k) { return null }, 539 getPropertyDescriptor: function(k) { return {writable: true} }, 540 defineProperty: function(k, desc) { throw "myexn" } 541 }) 542 543 TestSetThrow({ 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 551 TestSetThrow({ 552 getOwnPropertyDescriptor: function(k) { return null }, 553 getPropertyDescriptor: function(k) { 554 return {set: function(v) { throw "myexn" }} 555 } 556 }) 557 558 TestSetThrow({ 559 getOwnPropertyDescriptor: function(k) { return null }, 560 getPropertyDescriptor: function(k) { return null }, 561 defineProperty: function(k, desc) { throw "myexn" } 562 }) 563 564 TestSetThrow(Proxy.create({ 565 get: function(pr, pk) { throw "myexn" } 566 })) 567 568 TestSetThrow(Proxy.create({ 569 get: function(pr, pk) { 570 return function(r, k, v) { throw "myexn" } 571 } 572 })) 573 574 575 var key 576 var val 577 578 function TestSetForDerived(handler) { 579 TestWithProxies(TestSetForDerived2, handler) 580 } 581 582 function 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 638 TestSetForDerived({ 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 658 TestWithProxies(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 674 TestWithProxies(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 696 var key 697 var desc 698 699 function TestDefine(handler) { 700 TestWithProxies(TestDefine2, handler) 701 } 702 703 function 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 779 TestDefine({ 780 defineProperty: function(k, d) { key = k; desc = d; return true } 781 }) 782 783 TestDefine({ 784 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, 785 defineProperty2: function(k, d) { key = k; desc = d; return true } 786 }) 787 788 TestDefine(Proxy.create({ 789 get: function(pr, pk) { 790 return function(k, d) { key = k; desc = d; return true } 791 } 792 })) 793 794 795 function TestDefineThrow(handler) { 796 TestWithProxies(TestDefineThrow2, handler) 797 } 798 799 function 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 819 TestDefineThrow({ 820 defineProperty: function(k, d) { throw "myexn" } 821 }) 822 823 TestDefineThrow({ 824 defineProperty: function(k, d) { return this.defineProperty2(k, d) }, 825 defineProperty2: function(k, d) { throw "myexn" } 826 }) 827 828 TestDefineThrow(Proxy.create({ 829 get: function(pr, pk) { throw "myexn" } 830 })) 831 832 TestDefineThrow(Proxy.create({ 833 get: function(pr, pk) { 834 return function(k, d) { throw "myexn" } 835 } 836 })) 837 838 839 840 // Property deletion (delete). 841 842 var key 843 844 function TestDelete(handler) { 845 TestWithProxies(TestDelete2, handler) 846 } 847 848 function 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 878 TestDelete({ 879 delete: function(k) { key = k; return k < "z" } 880 }) 881 882 TestDelete({ 883 delete: function(k) { return this.delete2(k) }, 884 delete2: function(k) { key = k; return k < "z" } 885 }) 886 887 TestDelete(Proxy.create({ 888 get: function(pr, pk) { 889 return function(k) { key = k; return k < "z" } 890 } 891 })) 892 893 894 function TestDeleteThrow(handler) { 895 TestWithProxies(TestDeleteThrow2, handler) 896 } 897 898 function 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 912 TestDeleteThrow({ 913 delete: function(k) { throw "myexn" } 914 }) 915 916 TestDeleteThrow({ 917 delete: function(k) { return this.delete2(k) }, 918 delete2: function(k) { throw "myexn" } 919 }) 920 921 TestDeleteThrow(Proxy.create({ 922 get: function(pr, pk) { throw "myexn" } 923 })) 924 925 TestDeleteThrow(Proxy.create({ 926 get: function(pr, pk) { 927 return function(k) { throw "myexn" } 928 } 929 })) 930 931 932 933 // Property descriptors (Object.getOwnPropertyDescriptor). 934 935 function TestDescriptor(handler) { 936 TestWithProxies(TestDescriptor2, handler) 937 } 938 939 function 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 960 TestDescriptor({ 961 defineProperty: function(k, d) { this["__" + k] = d; return true }, 962 getOwnPropertyDescriptor: function(k) { return this["__" + k] } 963 }) 964 965 TestDescriptor({ 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 974 function TestDescriptorThrow(handler) { 975 TestWithProxies(TestDescriptorThrow2, handler) 976 } 977 978 function TestDescriptorThrow2(create, handler) { 979 var p = create(handler) 980 assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn") 981 } 982 983 TestDescriptorThrow({ 984 getOwnPropertyDescriptor: function(k) { throw "myexn" } 985 }) 986 987 TestDescriptorThrow({ 988 getOwnPropertyDescriptor: function(k) { 989 return this.getOwnPropertyDescriptor2(k) 990 }, 991 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 992 }) 993 994 995 996 // Comparison. 997 998 function TestComparison(eq) { 999 TestWithProxies(TestComparison2, eq) 1000 } 1001 1002 function 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 1014 TestComparison(function(o1, o2) { return o1 == o2 }) 1015 TestComparison(function(o1, o2) { return o1 === o2 }) 1016 TestComparison(function(o1, o2) { return !(o1 != o2) }) 1017 TestComparison(function(o1, o2) { return !(o1 !== o2) }) 1018 1019 1020 1021 // Type (typeof). 1022 1023 function 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 1033 TestTypeof() 1034 1035 1036 1037 // Membership test (in). 1038 1039 var key 1040 1041 function TestIn(handler) { 1042 TestWithProxies(TestIn2, handler) 1043 } 1044 1045 function 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 1083 TestIn({ 1084 has: function(k) { key = k; return k < "z" } 1085 }) 1086 1087 TestIn({ 1088 has: function(k) { return this.has2(k) }, 1089 has2: function(k) { key = k; return k < "z" } 1090 }) 1091 1092 TestIn({ 1093 getPropertyDescriptor: function(k) { 1094 key = k; return k < "z" ? {value: 42} : void 0 1095 } 1096 }) 1097 1098 TestIn({ 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 1105 TestIn({ 1106 getPropertyDescriptor: function(k) { 1107 key = k; return k < "z" ? {get value() { return 42 }} : void 0 1108 } 1109 }) 1110 1111 TestIn({ 1112 has: undefined, 1113 getPropertyDescriptor: function(k) { 1114 key = k; return k < "z" ? {value: 42} : void 0 1115 } 1116 }) 1117 1118 TestIn(Proxy.create({ 1119 get: function(pr, pk) { 1120 return function(k) { key = k; return k < "z" } 1121 } 1122 })) 1123 1124 1125 function TestInThrow(handler) { 1126 TestWithProxies(TestInThrow2, handler) 1127 } 1128 1129 function 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 1140 TestInThrow({ 1141 has: function(k) { throw "myexn" } 1142 }) 1143 1144 TestInThrow({ 1145 has: function(k) { return this.has2(k) }, 1146 has2: function(k) { throw "myexn" } 1147 }) 1148 1149 TestInThrow({ 1150 getPropertyDescriptor: function(k) { throw "myexn" } 1151 }) 1152 1153 TestInThrow({ 1154 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, 1155 getPropertyDescriptor2: function(k) { throw "myexn" } 1156 }) 1157 1158 TestInThrow({ 1159 has: undefined, 1160 getPropertyDescriptor: function(k) { throw "myexn" } 1161 }) 1162 1163 TestInThrow(Proxy.create({ 1164 get: function(pr, pk) { throw "myexn" } 1165 })) 1166 1167 TestInThrow(Proxy.create({ 1168 get: function(pr, pk) { 1169 return function(k) { throw "myexn" } 1170 } 1171 })) 1172 1173 1174 function TestInForDerived(handler) { 1175 TestWithProxies(TestInForDerived2, handler) 1176 } 1177 1178 function 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 1217 TestInForDerived({ 1218 getPropertyDescriptor: function(k) { 1219 key = k; return k < "z" ? {value: 42, configurable: true} : void 0 1220 } 1221 }) 1222 1223 TestInForDerived({ 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 1230 TestInForDerived({ 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. 1239 TestInForDerived({ 1240 getOwnPropertyDescriptor: function(k) { 1241 key = k; return k < "z" ? {value: 42, configurable: true} : void 0 1242 } 1243 }) 1244 1245 TestInForDerived({ 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 1254 TestInForDerived({ 1255 getOwnPropertyDescriptor: function(k) { 1256 key = k; 1257 return k < "z" ? {get value() { return 42 }, configurable: true} : void 0 1258 } 1259 }) 1260 */ 1261 1262 TestInForDerived(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 1274 var descget 1275 1276 function 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 1285 function 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 1297 TestDescriptorGetOrder({ 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 1329 var key 1330 1331 function TestHasOwn(handler) { 1332 TestWithProxies(TestHasOwn2, handler) 1333 } 1334 1335 function 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 1345 TestHasOwn({ 1346 hasOwn: function(k) { key = k; return k < "z" } 1347 }) 1348 1349 TestHasOwn({ 1350 hasOwn: function(k) { return this.hasOwn2(k) }, 1351 hasOwn2: function(k) { key = k; return k < "z" } 1352 }) 1353 1354 TestHasOwn({ 1355 getOwnPropertyDescriptor: function(k) { 1356 key = k; return k < "z" ? {value: 42} : void 0 1357 } 1358 }) 1359 1360 TestHasOwn({ 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 1369 TestHasOwn({ 1370 getOwnPropertyDescriptor: function(k) { 1371 key = k; return k < "z" ? {get value() { return 42 }} : void 0 1372 } 1373 }) 1374 1375 TestHasOwn({ 1376 hasOwn: undefined, 1377 getOwnPropertyDescriptor: function(k) { 1378 key = k; return k < "z" ? {value: 42} : void 0 1379 } 1380 }) 1381 1382 TestHasOwn(Proxy.create({ 1383 get: function(pr, pk) { 1384 return function(k) { key = k; return k < "z" } 1385 } 1386 })) 1387 1388 1389 function TestHasOwnThrow(handler) { 1390 TestWithProxies(TestHasOwnThrow2, handler) 1391 } 1392 1393 function 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 1401 TestHasOwnThrow({ 1402 hasOwn: function(k) { throw "myexn" } 1403 }) 1404 1405 TestHasOwnThrow({ 1406 hasOwn: function(k) { return this.hasOwn2(k) }, 1407 hasOwn2: function(k) { throw "myexn" } 1408 }) 1409 1410 TestHasOwnThrow({ 1411 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1412 }) 1413 1414 TestHasOwnThrow({ 1415 getOwnPropertyDescriptor: function(k) { 1416 return this.getOwnPropertyDescriptor2(k) 1417 }, 1418 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 1419 }) 1420 1421 TestHasOwnThrow({ 1422 hasOwn: undefined, 1423 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1424 }) 1425 1426 TestHasOwnThrow(Proxy.create({ 1427 get: function(pr, pk) { throw "myexn" } 1428 })) 1429 1430 TestHasOwnThrow(Proxy.create({ 1431 get: function(pr, pk) { 1432 return function(k) { throw "myexn" } 1433 } 1434 })) 1435 1436 1437 1438 // Instanceof (instanceof) 1439 1440 function 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 1486 TestProxyInstanceof() 1487 1488 1489 function 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 1549 TestInstanceofProxy() 1550 1551 1552 1553 // Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). 1554 1555 function 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 1614 TestPrototype() 1615 1616 1617 1618 // Property names (Object.getOwnPropertyNames, Object.keys). 1619 1620 function TestPropertyNames(names, handler) { 1621 TestWithProxies(TestPropertyNames2, handler, names) 1622 } 1623 1624 function TestPropertyNames2(create, handler, names) { 1625 var p = create(handler) 1626 assertArrayEquals(names, Object.getOwnPropertyNames(p)) 1627 } 1628 1629 TestPropertyNames([], { 1630 getOwnPropertyNames: function() { return [] } 1631 }) 1632 1633 TestPropertyNames(["a", "zz", " ", "0"], { 1634 getOwnPropertyNames: function() { return ["a", "zz", " ", 0] } 1635 }) 1636 1637 TestPropertyNames(["throw", "function "], { 1638 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1639 getOwnPropertyNames2: function() { return ["throw", "function "] } 1640 }) 1641 1642 TestPropertyNames(["[object Object]"], { 1643 get getOwnPropertyNames() { 1644 return function() { return [{}] } 1645 } 1646 }) 1647 1648 1649 function TestPropertyNamesThrow(handler) { 1650 TestWithProxies(TestPropertyNamesThrow2, handler) 1651 } 1652 1653 function TestPropertyNamesThrow2(create, handler) { 1654 var p = create(handler) 1655 assertThrows(function(){ Object.getOwnPropertyNames(p) }, "myexn") 1656 } 1657 1658 TestPropertyNamesThrow({ 1659 getOwnPropertyNames: function() { throw "myexn" } 1660 }) 1661 1662 TestPropertyNamesThrow({ 1663 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1664 getOwnPropertyNames2: function() { throw "myexn" } 1665 }) 1666 1667 1668 function TestKeys(names, handler) { 1669 TestWithProxies(TestKeys2, handler, names) 1670 } 1671 1672 function TestKeys2(create, handler, names) { 1673 var p = create(handler) 1674 assertArrayEquals(names, Object.keys(p)) 1675 } 1676 1677 TestKeys([], { 1678 keys: function() { return [] } 1679 }) 1680 1681 TestKeys(["a", "zz", " ", "0"], { 1682 keys: function() { return ["a", "zz", " ", 0] } 1683 }) 1684 1685 TestKeys(["throw", "function "], { 1686 keys: function() { return this.keys2() }, 1687 keys2: function() { return ["throw", "function "] } 1688 }) 1689 1690 TestKeys(["[object Object]"], { 1691 get keys() { 1692 return function() { return [{}] } 1693 } 1694 }) 1695 1696 TestKeys(["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 1703 TestKeys(["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 1712 TestKeys(["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 1723 TestKeys([], { 1724 get getOwnPropertyNames() { 1725 return function() { return ["a", "b", "c"] } 1726 }, 1727 getOwnPropertyDescriptor: function(k) { return {} } 1728 }) 1729 1730 1731 function TestKeysThrow(handler) { 1732 TestWithProxies(TestKeysThrow2, handler) 1733 } 1734 1735 function TestKeysThrow2(create, handler) { 1736 var p = create(handler) 1737 assertThrows(function(){ Object.keys(p) }, "myexn") 1738 } 1739 1740 TestKeysThrow({ 1741 keys: function() { throw "myexn" } 1742 }) 1743 1744 TestKeysThrow({ 1745 keys: function() { return this.keys2() }, 1746 keys2: function() { throw "myexn" } 1747 }) 1748 1749 TestKeysThrow({ 1750 getOwnPropertyNames: function() { throw "myexn" }, 1751 getOwnPropertyDescriptor: function(k) { return true } 1752 }) 1753 1754 TestKeysThrow({ 1755 getOwnPropertyNames: function() { return [1, 2] }, 1756 getOwnPropertyDescriptor: function(k) { throw "myexn" } 1757 }) 1758 1759 TestKeysThrow({ 1760 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() }, 1761 getOwnPropertyNames2: function() { throw "myexn" }, 1762 }) 1763 1764 TestKeysThrow({ 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 1773 TestKeysThrow({ 1774 get getOwnPropertyNames() { throw "myexn" } 1775 }) 1776 1777 TestKeysThrow({ 1778 get getOwnPropertyNames() { 1779 return function() { throw "myexn" } 1780 }, 1781 }) 1782 1783 TestKeysThrow([], { 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 1795 function 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 1851 TestFix([], { 1852 fix: function() { return {} } 1853 }) 1854 1855 TestFix(["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 1867 TestFix(["a"], { 1868 fix: function() { return this.fix2() }, 1869 fix2: function() { 1870 return {a: {value: 4, writable: true, configurable: true, enumerable: true}} 1871 } 1872 }) 1873 1874 TestFix(["b"], { 1875 get fix() { 1876 return function() { 1877 return {b: {configurable: true, writable: true, enumerable: true}} 1878 } 1879 } 1880 }) 1881 1882 1883 function 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 1903 TestFixFunction(Object.seal) 1904 TestFixFunction(Object.freeze) 1905 TestFixFunction(Object.preventExtensions) 1906 1907 1908 function TestFixThrow(handler) { 1909 TestWithProxies(TestFixThrow2, handler) 1910 } 1911 1912 function 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 1919 TestFixThrow({ 1920 fix: function() { throw "myexn" } 1921 }) 1922 1923 TestFixThrow({ 1924 fix: function() { return this.fix2() }, 1925 fix2: function() { throw "myexn" } 1926 }) 1927 1928 TestFixThrow({ 1929 get fix() { throw "myexn" } 1930 }) 1931 1932 TestFixThrow({ 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. 1942 function TestReentrantFix(f) { 1943 TestWithProxies(f, Object.freeze) 1944 TestWithProxies(f, Object.seal) 1945 TestWithProxies(f, Object.preventExtensions) 1946 } 1947 1948 TestReentrantFix(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 1958 TestReentrantFix(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 1968 TestReentrantFix(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 1978 TestReentrantFix(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 1989 TestReentrantFix(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 1999 TestReentrantFix(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 2009 TestReentrantFix(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 2019 TestReentrantFix(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 2030 TestReentrantFix(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 2041 TestReentrantFix(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 2054 TestReentrantFix(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 2073 var key 2074 2075 function 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 2099 TestToString({ 2100 get: function(r, k) { key = k; return function() { return "my_proxy" } } 2101 }) 2102 2103 TestToString({ 2104 get: function(r, k) { return this.get2(r, k) }, 2105 get2: function(r, k) { key = k; return function() { return "my_proxy" } } 2106 }) 2107 2108 TestToString(Proxy.create({ 2109 get: function(pr, pk) { 2110 return function(r, k) { key = k; return function() { return "my_proxy" } } 2111 } 2112 })) 2113 2114 2115 function 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 2129 TestToStringThrow({ 2130 get: function(r, k) { throw "myexn" } 2131 }) 2132 2133 TestToStringThrow({ 2134 get: function(r, k) { return function() { throw "myexn" } } 2135 }) 2136 2137 TestToStringThrow({ 2138 get: function(r, k) { return this.get2(r, k) }, 2139 get2: function(r, k) { throw "myexn" } 2140 }) 2141 2142 TestToStringThrow(Proxy.create({ 2143 get: function(pr, pk) { throw "myexn" } 2144 })) 2145 2146 TestToStringThrow(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 2156 function TestValueOf(handler) { 2157 TestWithProxies(TestValueOf2, handler) 2158 } 2159 2160 function TestValueOf2(create, handler) { 2161 var p = create(handler) 2162 assertSame(p, Object.prototype.valueOf.call(p)) 2163 } 2164 2165 TestValueOf({}) 2166 2167 2168 2169 // Enumerability (Object.prototype.propertyIsEnumerable) 2170 2171 var key 2172 2173 function TestIsEnumerable(handler) { 2174 TestWithProxies(TestIsEnumerable2, handler) 2175 } 2176 2177 function 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 2192 TestIsEnumerable({ 2193 getOwnPropertyDescriptor: function(k) { 2194 key = k; return {enumerable: k < "z", configurable: true} 2195 }, 2196 }) 2197 2198 TestIsEnumerable({ 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 2207 TestIsEnumerable({ 2208 getOwnPropertyDescriptor: function(k) { 2209 key = k; return {get enumerable() { return k < "z" }, configurable: true} 2210 }, 2211 }) 2212 2213 TestIsEnumerable(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 2222 function TestIsEnumerableThrow(handler) { 2223 TestWithProxies(TestIsEnumerableThrow2, handler) 2224 } 2225 2226 function 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 2234 TestIsEnumerableThrow({ 2235 getOwnPropertyDescriptor: function(k) { throw "myexn" } 2236 }) 2237 2238 TestIsEnumerableThrow({ 2239 getOwnPropertyDescriptor: function(k) { 2240 return this.getOwnPropertyDescriptor2(k) 2241 }, 2242 getOwnPropertyDescriptor2: function(k) { throw "myexn" } 2243 }) 2244 2245 TestIsEnumerableThrow({ 2246 getOwnPropertyDescriptor: function(k) { 2247 return {get enumerable() { throw "myexn" }, configurable: true} 2248 }, 2249 }) 2250 2251 TestIsEnumerableThrow(Proxy.create({ 2252 get: function(pr, pk) { throw "myexn" } 2253 })) 2254 2255 TestIsEnumerableThrow(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 2265 function TestConstructorWithProxyPrototype() { 2266 TestWithProxies(TestConstructorWithProxyPrototype2, {}) 2267 } 2268 2269 function 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 2278 TestConstructorWithProxyPrototype(); 2279