Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 } | 46 } |
| 47 | 47 |
| 48 // Check that an exception is thrown when non-object is passed as object. | 48 // Check that an exception is thrown when non-object is passed as object. |
| 49 try { | 49 try { |
| 50 Object.defineProperty(0, "foo", undefined); | 50 Object.defineProperty(0, "foo", undefined); |
| 51 assertTrue(false); | 51 assertTrue(false); |
| 52 } catch (e) { | 52 } catch (e) { |
| 53 assertTrue(/called on non-object/.test(e)); | 53 assertTrue(/called on non-object/.test(e)); |
| 54 } | 54 } |
| 55 | 55 |
| 56 // Object | 56 // Object. |
| 57 var obj1 = {}; | 57 var obj1 = {}; |
| 58 | 58 |
| 59 // Values | 59 // Values. |
| 60 var val1 = 0; | 60 var val1 = 0; |
| 61 var val2 = 0; | 61 var val2 = 0; |
| 62 var val3 = 0; | 62 var val3 = 0; |
| 63 | 63 |
| 64 // Descriptors | 64 function setter1() {val1++; } |
| 65 function getter1() {return val1; } | |
| 66 | |
| 67 function setter2() {val2++; } | |
| 68 function getter2() {return val2; } | |
| 69 | |
| 70 function setter3() {val3++; } | |
| 71 function getter3() {return val3; } | |
| 72 | |
| 73 | |
| 74 // Descriptors. | |
| 65 var emptyDesc = {}; | 75 var emptyDesc = {}; |
| 66 | 76 |
| 67 var accessorConfigurable = { | 77 var accessorConfigurable = { |
| 68 set: function() { val1++; }, | 78 set: setter1, |
| 69 get: function() { return val1; }, | 79 get: getter1, |
| 70 configurable: true | 80 configurable: true |
| 71 }; | 81 }; |
| 72 | 82 |
| 73 var accessorNoConfigurable = { | 83 var accessorNoConfigurable = { |
| 74 set: function() { val2++; }, | 84 set: setter2, |
| 75 get: function() { return val2; }, | 85 get: getter2, |
| 76 configurable: false | 86 configurable: false |
| 77 }; | 87 }; |
| 78 | 88 |
| 79 var accessorOnlySet = { | 89 var accessorOnlySet = { |
| 80 set: function() { val3++; }, | 90 set: setter3, |
| 81 configurable: true | 91 configurable: true |
| 82 }; | 92 }; |
| 83 | 93 |
| 84 var accessorOnlyGet = { | 94 var accessorOnlyGet = { |
| 85 get: function() { return val3; }, | 95 get: getter3, |
| 86 configurable: true | 96 configurable: true |
| 87 }; | 97 }; |
| 88 | 98 |
| 89 var accessorDefault = {set: function(){} }; | 99 var accessorDefault = {set: function(){} }; |
| 90 | 100 |
| 91 var dataConfigurable = { value: 1000, configurable: true }; | 101 var dataConfigurable = { value: 1000, configurable: true }; |
| 92 | 102 |
| 93 var dataNoConfigurable = { value: 2000, configurable: false }; | 103 var dataNoConfigurable = { value: 2000, configurable: false }; |
| 94 | 104 |
| 95 var dataWritable = { value: 3000, writable: true}; | 105 var dataWritable = { value: 3000, writable: true}; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 assertEquals(desc.set, accessorNoConfigurable.set); | 203 assertEquals(desc.set, accessorNoConfigurable.set); |
| 194 assertEquals(desc.value, undefined); | 204 assertEquals(desc.value, undefined); |
| 195 assertEquals(1, obj1.bar = 1); | 205 assertEquals(1, obj1.bar = 1); |
| 196 assertEquals(2, val1); | 206 assertEquals(2, val1); |
| 197 assertEquals(3, val2); | 207 assertEquals(3, val2); |
| 198 assertEquals(1, obj1.bar = 1) | 208 assertEquals(1, obj1.bar = 1) |
| 199 assertEquals(2, val1); | 209 assertEquals(2, val1); |
| 200 assertEquals(4, val2); | 210 assertEquals(4, val2); |
| 201 assertEquals(4, obj1.bar); | 211 assertEquals(4, obj1.bar); |
| 202 | 212 |
| 203 // Define an accessor that has only a setter | 213 // Define an accessor that has only a setter. |
| 204 Object.defineProperty(obj1, "setOnly", accessorOnlySet); | 214 Object.defineProperty(obj1, "setOnly", accessorOnlySet); |
| 205 desc = Object.getOwnPropertyDescriptor(obj1, "setOnly"); | 215 desc = Object.getOwnPropertyDescriptor(obj1, "setOnly"); |
| 206 assertTrue(desc.configurable); | 216 assertTrue(desc.configurable); |
| 207 assertFalse(desc.enumerable); | 217 assertFalse(desc.enumerable); |
| 208 assertEquals(desc.set, accessorOnlySet.set); | 218 assertEquals(desc.set, accessorOnlySet.set); |
| 209 assertEquals(desc.writable, undefined); | 219 assertEquals(desc.writable, undefined); |
| 210 assertEquals(desc.value, undefined); | 220 assertEquals(desc.value, undefined); |
| 211 assertEquals(desc.get, undefined); | 221 assertEquals(desc.get, undefined); |
| 212 assertEquals(1, obj1.setOnly = 1); | 222 assertEquals(1, obj1.setOnly = 1); |
| 213 assertEquals(1, val3); | 223 assertEquals(1, val3); |
| 214 | 224 |
| 215 // Add a getter - should not touch the setter | 225 // Add a getter - should not touch the setter. |
| 216 Object.defineProperty(obj1, "setOnly", accessorOnlyGet); | 226 Object.defineProperty(obj1, "setOnly", accessorOnlyGet); |
| 217 desc = Object.getOwnPropertyDescriptor(obj1, "setOnly"); | 227 desc = Object.getOwnPropertyDescriptor(obj1, "setOnly"); |
| 218 assertTrue(desc.configurable); | 228 assertTrue(desc.configurable); |
| 219 assertFalse(desc.enumerable); | 229 assertFalse(desc.enumerable); |
| 220 assertEquals(desc.get, accessorOnlyGet.get); | 230 assertEquals(desc.get, accessorOnlyGet.get); |
| 221 assertEquals(desc.set, accessorOnlySet.set); | 231 assertEquals(desc.set, accessorOnlySet.set); |
| 222 assertEquals(desc.writable, undefined); | 232 assertEquals(desc.writable, undefined); |
| 223 assertEquals(desc.value, undefined); | 233 assertEquals(desc.value, undefined); |
| 224 assertEquals(1, obj1.setOnly = 1); | 234 assertEquals(1, obj1.setOnly = 1); |
| 225 assertEquals(2, val3); | 235 assertEquals(2, val3); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 249 assertTrue(desc.configurable); | 259 assertTrue(desc.configurable); |
| 250 assertFalse(desc.writable); | 260 assertFalse(desc.writable); |
| 251 assertFalse(desc.enumerable); | 261 assertFalse(desc.enumerable); |
| 252 assertEquals(desc.get, undefined); | 262 assertEquals(desc.get, undefined); |
| 253 assertEquals(desc.set, undefined); | 263 assertEquals(desc.set, undefined); |
| 254 //Try writing to non writable attribute - should remain 1000 | 264 //Try writing to non writable attribute - should remain 1000 |
| 255 obj1.foobar = 1001; | 265 obj1.foobar = 1001; |
| 256 assertEquals(obj1.foobar, 1000); | 266 assertEquals(obj1.foobar, 1000); |
| 257 | 267 |
| 258 | 268 |
| 259 // Redefine to writable descriptor - now writing to foobar should be allowed | 269 // Redefine to writable descriptor - now writing to foobar should be allowed. |
| 260 Object.defineProperty(obj1, "foobar", dataWritable); | 270 Object.defineProperty(obj1, "foobar", dataWritable); |
| 261 desc = Object.getOwnPropertyDescriptor(obj1, "foobar"); | 271 desc = Object.getOwnPropertyDescriptor(obj1, "foobar"); |
| 262 assertEquals(obj1.foobar, 3000); | 272 assertEquals(obj1.foobar, 3000); |
| 263 assertEquals(desc.value, 3000); | 273 assertEquals(desc.value, 3000); |
| 264 // Note that since dataWritable does not define configurable the configurable | 274 // Note that since dataWritable does not define configurable the configurable |
| 265 // setting from the redefined property (in this case true) is used. | 275 // setting from the redefined property (in this case true) is used. |
| 266 assertTrue(desc.configurable); | 276 assertTrue(desc.configurable); |
| 267 assertTrue(desc.writable); | 277 assertTrue(desc.writable); |
| 268 assertFalse(desc.enumerable); | 278 assertFalse(desc.enumerable); |
| 269 assertEquals(desc.get, undefined); | 279 assertEquals(desc.get, undefined); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 assertEquals(obj2.bar, 1000); | 378 assertEquals(obj2.bar, 1000); |
| 369 assertEquals(desc.value, 1000); | 379 assertEquals(desc.value, 1000); |
| 370 assertTrue(desc.configurable); | 380 assertTrue(desc.configurable); |
| 371 assertFalse(desc.writable); | 381 assertFalse(desc.writable); |
| 372 assertFalse(desc.enumerable); | 382 assertFalse(desc.enumerable); |
| 373 assertEquals(desc.get, undefined); | 383 assertEquals(desc.get, undefined); |
| 374 assertEquals(desc.set, undefined); | 384 assertEquals(desc.set, undefined); |
| 375 | 385 |
| 376 | 386 |
| 377 // Redefinition of an accessor defined using __defineGetter__ and | 387 // Redefinition of an accessor defined using __defineGetter__ and |
| 378 // __defineSetter__ | 388 // __defineSetter__. |
| 379 function get(){return this.x} | 389 function get(){return this.x} |
| 380 function set(x){this.x=x}; | 390 function set(x){this.x=x}; |
| 381 | 391 |
| 382 var obj3 = {x:1000}; | 392 var obj3 = {x:1000}; |
| 383 obj3.__defineGetter__("foo", get); | 393 obj3.__defineGetter__("foo", get); |
| 384 obj3.__defineSetter__("foo", set); | 394 obj3.__defineSetter__("foo", set); |
| 385 | 395 |
| 386 desc = Object.getOwnPropertyDescriptor(obj3, "foo"); | 396 desc = Object.getOwnPropertyDescriptor(obj3, "foo"); |
| 387 assertTrue(desc.configurable); | 397 assertTrue(desc.configurable); |
| 388 assertTrue(desc.enumerable); | 398 assertTrue(desc.enumerable); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 assertTrue(desc.configurable); | 445 assertTrue(desc.configurable); |
| 436 assertTrue(desc.enumerable); | 446 assertTrue(desc.enumerable); |
| 437 assertEquals(desc.writable, undefined); | 447 assertEquals(desc.writable, undefined); |
| 438 assertEquals(desc.get, accessorConfigurable.get); | 448 assertEquals(desc.get, accessorConfigurable.get); |
| 439 assertEquals(desc.set, accessorConfigurable.set); | 449 assertEquals(desc.set, accessorConfigurable.set); |
| 440 assertEquals(desc.value, undefined); | 450 assertEquals(desc.value, undefined); |
| 441 assertEquals(1, obj4.bar = 1); | 451 assertEquals(1, obj4.bar = 1); |
| 442 assertEquals(5, val1); | 452 assertEquals(5, val1); |
| 443 assertEquals(5, obj4.bar); | 453 assertEquals(5, obj4.bar); |
| 444 | 454 |
| 445 // Make sure an error is thrown when trying to access to redefined function | 455 // Make sure an error is thrown when trying to access to redefined function. |
| 446 try { | 456 try { |
| 447 obj4.bar(); | 457 obj4.bar(); |
| 448 assertTrue(false); | 458 assertTrue(false); |
| 449 } catch (e) { | 459 } catch (e) { |
| 450 assertTrue(/is not a function/.test(e)); | 460 assertTrue(/is not a function/.test(e)); |
| 451 } | 461 } |
| 452 | 462 |
| 453 | 463 |
| 454 // Test runtime calls to DefineOrRedefineDataProperty and | 464 // Test runtime calls to DefineOrRedefineDataProperty and |
| 455 // DefineOrRedefineAccessorProperty - make sure we don't | 465 // DefineOrRedefineAccessorProperty - make sure we don't |
| 456 // crash | 466 // crash. |
| 457 try { | 467 try { |
| 458 %DefineOrRedefineAccessorProperty(0, 0, 0, 0, 0); | 468 %DefineOrRedefineAccessorProperty(0, 0, 0, 0, 0); |
| 459 } catch (e) { | 469 } catch (e) { |
| 460 assertTrue(/illegal access/.test(e)); | 470 assertTrue(/illegal access/.test(e)); |
| 461 } | 471 } |
| 462 | 472 |
| 463 try { | 473 try { |
| 464 %DefineOrRedefineDataProperty(0, 0, 0, 0); | 474 %DefineOrRedefineDataProperty(0, 0, 0, 0); |
| 465 } catch (e) { | 475 } catch (e) { |
| 466 assertTrue(/illegal access/.test(e)); | 476 assertTrue(/illegal access/.test(e)); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 490 %DefineOrRedefineAccessorProperty(null, 'foo', 0, func, 0); | 500 %DefineOrRedefineAccessorProperty(null, 'foo', 0, func, 0); |
| 491 } catch (e) { | 501 } catch (e) { |
| 492 assertTrue(/illegal access/.test(e)); | 502 assertTrue(/illegal access/.test(e)); |
| 493 } | 503 } |
| 494 | 504 |
| 495 try { | 505 try { |
| 496 %DefineOrRedefineDataProperty(null, 'foo', 0, 0); | 506 %DefineOrRedefineDataProperty(null, 'foo', 0, 0); |
| 497 } catch (e) { | 507 } catch (e) { |
| 498 assertTrue(/illegal access/.test(e)); | 508 assertTrue(/illegal access/.test(e)); |
| 499 } | 509 } |
| 510 | |
| 511 // Test that all possible differences in step 6 in DefineOwnProperty is | |
|
Erik Corry
2010/05/21 13:21:57
differences ... is -> differences ... are
Rico
2010/05/25 06:24:50
Done.
| |
| 512 // exercised, i.e., any difference in the given property descriptor and the | |
| 513 // existing properties should not return true, but throw an error if the | |
| 514 // existing configurable property is false. | |
| 515 | |
| 516 var obj5 = {}; | |
| 517 // Enumerable will default to false. | |
| 518 Object.defineProperty(obj5, 'foo', accessorNoConfigurable); | |
| 519 desc = Object.getOwnPropertyDescriptor(obj5, 'foo'); | |
| 520 // First, test that we are actually allowed to set the accessor if all | |
| 521 // values are of the descriptor are the same as the existing one. | |
| 522 Object.defineProperty(obj5, 'foo', accessorNoConfigurable); | |
| 523 | |
| 524 // Different setter. | |
| 525 var descDifferent = { | |
| 526 configurable:false, | |
| 527 enumerable:false, | |
| 528 set: setter1, | |
| 529 get: getter2 | |
| 530 }; | |
| 531 | |
| 532 try { | |
| 533 Object.defineProperty(obj5, 'foo', descDifferent); | |
| 534 assertTrue(false); | |
| 535 } catch (e) { | |
| 536 assertTrue(/Cannot redefine property/.test(e)); | |
| 537 } | |
| 538 | |
| 539 // Different getter. | |
| 540 descDifferent = { | |
| 541 configurable:false, | |
| 542 enumerable:false, | |
| 543 set: setter2, | |
| 544 get: getter1 | |
| 545 }; | |
| 546 | |
| 547 try { | |
| 548 Object.defineProperty(obj5, 'foo', descDifferent); | |
| 549 assertTrue(false); | |
| 550 } catch (e) { | |
| 551 assertTrue(/Cannot redefine property/.test(e)); | |
| 552 } | |
| 553 | |
| 554 // Different enumerable. | |
| 555 descDifferent = { | |
| 556 configurable:false, | |
| 557 enumerable:true, | |
| 558 set: setter2, | |
| 559 get: getter2 | |
| 560 }; | |
| 561 | |
| 562 try { | |
| 563 Object.defineProperty(obj5, 'foo', descDifferent); | |
| 564 assertTrue(false); | |
| 565 } catch (e) { | |
| 566 assertTrue(/Cannot redefine property/.test(e)); | |
| 567 } | |
| 568 | |
| 569 // Different configurable. | |
| 570 descDifferent = { | |
| 571 configurable:false, | |
| 572 enumerable:true, | |
| 573 set: setter2, | |
| 574 get: getter2 | |
| 575 }; | |
| 576 | |
| 577 try { | |
| 578 Object.defineProperty(obj5, 'foo', descDifferent); | |
| 579 assertTrue(false); | |
| 580 } catch (e) { | |
| 581 assertTrue(/Cannot redefine property/.test(e)); | |
| 582 } | |
| 583 | |
| 584 // No difference. | |
| 585 descDifferent = { | |
| 586 configurable:false, | |
| 587 enumerable:false, | |
| 588 set: setter2, | |
| 589 get: getter2 | |
| 590 }; | |
| 591 // Make sure we can still redefine if all properties are the same. | |
| 592 Object.defineProperty(obj5, 'foo', descDifferent); | |
| 593 | |
| 594 // Make sure that obj5 still holds the original values. | |
| 595 desc = Object.getOwnPropertyDescriptor(obj5, 'foo'); | |
| 596 assertEquals(desc.get, getter2); | |
| 597 assertEquals(desc.set, setter2); | |
| 598 assertFalse(desc.enumerable); | |
| 599 assertFalse(desc.configurable); | |
| 600 | |
| 601 | |
| 602 // Also exercise step 6 on data property, writable and enumerable | |
| 603 // defaults to false. | |
| 604 Object.defineProperty(obj5, 'bar', dataNoConfigurable); | |
| 605 | |
| 606 // Test that redefinition with the same property descriptor is possible | |
| 607 Object.defineProperty(obj5, 'bar', dataNoConfigurable); | |
| 608 | |
| 609 // Different value. | |
| 610 descDifferent = { | |
| 611 configurable:false, | |
| 612 enumerable:false, | |
| 613 writable: false, | |
| 614 value: 1999 | |
| 615 }; | |
| 616 | |
| 617 try { | |
| 618 Object.defineProperty(obj5, 'bar', descDifferent); | |
| 619 assertTrue(false); | |
| 620 } catch (e) { | |
| 621 assertTrue(/Cannot redefine property/.test(e)); | |
| 622 } | |
| 623 | |
| 624 // Different writable. | |
| 625 descDifferent = { | |
| 626 configurable:false, | |
| 627 enumerable:false, | |
| 628 writable: true, | |
| 629 value: 2000 | |
| 630 }; | |
| 631 | |
| 632 try { | |
| 633 Object.defineProperty(obj5, 'bar', descDifferent); | |
| 634 assertTrue(false); | |
| 635 } catch (e) { | |
| 636 assertTrue(/Cannot redefine property/.test(e)); | |
| 637 } | |
| 638 | |
| 639 | |
| 640 // Different enumerable. | |
| 641 descDifferent = { | |
| 642 configurable:false, | |
| 643 enumerable:true , | |
| 644 writable:false, | |
| 645 value: 2000 | |
| 646 }; | |
| 647 | |
| 648 try { | |
| 649 Object.defineProperty(obj5, 'bar', descDifferent); | |
| 650 assertTrue(false); | |
| 651 } catch (e) { | |
| 652 assertTrue(/Cannot redefine property/.test(e)); | |
| 653 } | |
| 654 | |
| 655 | |
| 656 // Different configurable. | |
| 657 descDifferent = { | |
| 658 configurable:true, | |
| 659 enumerable:false, | |
| 660 writable:false, | |
| 661 value: 2000 | |
| 662 }; | |
| 663 | |
| 664 try { | |
| 665 Object.defineProperty(obj5, 'bar', descDifferent); | |
| 666 assertTrue(false); | |
| 667 } catch (e) { | |
| 668 assertTrue(/Cannot redefine property/.test(e)); | |
| 669 } | |
| 670 | |
| 671 // No difference. | |
| 672 descDifferent = { | |
| 673 configurable:false, | |
| 674 enumerable:false, | |
| 675 writable:false, | |
| 676 value:2000 | |
| 677 }; | |
| 678 // Make sure we can still redefine if all properties are the same. | |
| 679 Object.defineProperty(obj5, 'bar', descDifferent); | |
| 680 | |
| 681 // Make sure that obj5 still holds the original values. | |
| 682 desc = Object.getOwnPropertyDescriptor(obj5, 'bar'); | |
| 683 assertEquals(desc.value, 2000); | |
| 684 assertFalse(desc.writable); | |
| 685 assertFalse(desc.enumerable); | |
| 686 assertFalse(desc.configurable); | |
| 687 | |
| 688 | |
| 689 // Make sure that we can't overwrite +0 with -0 and vise verca. | |
|
Erik Corry
2010/05/21 13:21:57
vise verca -> vice versa
(or was that deliberate
Rico
2010/05/25 06:24:50
No :-) done
| |
| 690 var descMinusZero = {value: -0, configurable: false}; | |
| 691 var descPlusZero = {value: +0, configurable: false}; | |
| 692 | |
| 693 Object.defineProperty(obj5, 'minuszero', descMinusZero); | |
| 694 | |
| 695 // Make sure we can redefine with -0. | |
| 696 Object.defineProperty(obj5, 'minuszero', descMinusZero); | |
| 697 | |
| 698 try { | |
| 699 Object.defineProperty(obj5, 'minuszero', descPlusZero); | |
| 700 assertUnreachable(); | |
| 701 } catch (e) { | |
| 702 assertTrue(/Cannot redefine property/.test(e)); | |
| 703 } | |
| 704 | |
| 705 | |
| 706 Object.defineProperty(obj5, 'pluszero', descPlusZero); | |
| 707 | |
| 708 // Make sure we can redefine with +0. | |
| 709 Object.defineProperty(obj5, 'pluszero', descPlusZero); | |
| 710 | |
| 711 try { | |
| 712 Object.defineProperty(obj5, 'pluszero', descMinusZero); | |
| 713 assertUnreachable(); | |
| 714 } catch (e) { | |
| 715 assertTrue(/Cannot redefine property/.test(e)); | |
| 716 } | |
| OLD | NEW |