1 // Copyright 2012-2015 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 // Tests the Reflect.defineProperty method - ES6 26.1.3 29 // This is adapted from mjsunit/object-define-property.js. 30 31 // Flags: --allow-natives-syntax 32 33 34 // Check that an exception is thrown when null is passed as object. 35 var exception = false; 36 try { 37 Reflect.defineProperty(null, null, null); 38 } catch (e) { 39 exception = true; 40 assertTrue(/called on non-object/.test(e)); 41 } 42 assertTrue(exception); 43 44 // Check that an exception is thrown when undefined is passed as object. 45 exception = false; 46 try { 47 Reflect.defineProperty(undefined, undefined, undefined); 48 } catch (e) { 49 exception = true; 50 assertTrue(/called on non-object/.test(e)); 51 } 52 assertTrue(exception); 53 54 // Check that an exception is thrown when non-object is passed as object. 55 exception = false; 56 try { 57 Reflect.defineProperty(0, "foo", undefined); 58 } catch (e) { 59 exception = true; 60 assertTrue(/called on non-object/.test(e)); 61 } 62 assertTrue(exception); 63 64 // Object. 65 var obj1 = {}; 66 67 // Values. 68 var val1 = 0; 69 var val2 = 0; 70 var val3 = 0; 71 72 function setter1() {val1++; } 73 function getter1() {return val1; } 74 75 function setter2() {val2++; } 76 function getter2() {return val2; } 77 78 function setter3() {val3++; } 79 function getter3() {return val3; } 80 81 82 // Descriptors. 83 var emptyDesc = {}; 84 85 var accessorConfigurable = { 86 set: setter1, 87 get: getter1, 88 configurable: true 89 }; 90 91 var accessorNoConfigurable = { 92 set: setter2, 93 get: getter2, 94 configurable: false 95 }; 96 97 var accessorOnlySet = { 98 set: setter3, 99 configurable: true 100 }; 101 102 var accessorOnlyGet = { 103 get: getter3, 104 configurable: true 105 }; 106 107 var accessorDefault = {set: function(){} }; 108 109 var dataConfigurable = { value: 1000, configurable: true }; 110 111 var dataNoConfigurable = { value: 2000, configurable: false }; 112 113 var dataWritable = { value: 3000, writable: true}; 114 115 116 // Check that we can't add property with undefined attributes. 117 assertThrows(function() { Reflect.defineProperty(obj1, "foo", undefined) }, 118 TypeError); 119 120 // Make sure that we can add a property with an empty descriptor and 121 // that it has the default descriptor values. 122 assertTrue(Reflect.defineProperty(obj1, "foo", emptyDesc)); 123 124 // foo should be undefined as it has no get, set or value 125 assertEquals(undefined, obj1.foo); 126 127 // We should, however, be able to retrieve the propertydescriptor which should 128 // have all default values (according to 8.6.1). 129 var desc = Object.getOwnPropertyDescriptor(obj1, "foo"); 130 assertFalse(desc.configurable); 131 assertFalse(desc.enumerable); 132 assertFalse(desc.writable); 133 assertEquals(desc.get, undefined); 134 assertEquals(desc.set, undefined); 135 assertEquals(desc.value, undefined); 136 137 // Make sure that getOwnPropertyDescriptor does not return a descriptor 138 // with default values if called with non existing property (otherwise 139 // the test above is invalid). 140 desc = Object.getOwnPropertyDescriptor(obj1, "bar"); 141 assertEquals(desc, undefined); 142 143 // Make sure that foo can't be reset (as configurable is false). 144 assertFalse(Reflect.defineProperty(obj1, "foo", accessorConfigurable)); 145 146 147 // Accessor properties 148 149 assertTrue(Reflect.defineProperty(obj1, "bar", accessorConfigurable)); 150 desc = Object.getOwnPropertyDescriptor(obj1, "bar"); 151 assertTrue(desc.configurable); 152 assertFalse(desc.enumerable); 153 assertEquals(desc.writable, undefined); 154 assertEquals(desc.get, accessorConfigurable.get); 155 assertEquals(desc.set, accessorConfigurable.set); 156 assertEquals(desc.value, undefined); 157 assertEquals(1, obj1.bar = 1); 158 assertEquals(1, val1); 159 assertEquals(1, obj1.bar = 1); 160 assertEquals(2, val1); 161 assertEquals(2, obj1.bar); 162 163 // Redefine bar with non configurable test 164 assertTrue(Reflect.defineProperty(obj1, "bar", accessorNoConfigurable)); 165 desc = Object.getOwnPropertyDescriptor(obj1, "bar"); 166 assertFalse(desc.configurable); 167 assertFalse(desc.enumerable); 168 assertEquals(desc.writable, undefined); 169 assertEquals(desc.get, accessorNoConfigurable.get); 170 assertEquals(desc.set, accessorNoConfigurable.set); 171 assertEquals(desc.value, undefined); 172 assertEquals(1, obj1.bar = 1); 173 assertEquals(2, val1); 174 assertEquals(1, val2); 175 assertEquals(1, obj1.bar = 1) 176 assertEquals(2, val1); 177 assertEquals(2, val2); 178 assertEquals(2, obj1.bar); 179 180 // Try to redefine bar again - should fail as configurable is false. 181 assertFalse(Reflect.defineProperty(obj1, "bar", accessorConfigurable)); 182 183 // Try to redefine bar again using the data descriptor - should fail. 184 assertFalse(Reflect.defineProperty(obj1, "bar", dataConfigurable)); 185 186 // Redefine using same descriptor - should succeed. 187 assertTrue(Reflect.defineProperty(obj1, "bar", accessorNoConfigurable)); 188 desc = Object.getOwnPropertyDescriptor(obj1, "bar"); 189 assertFalse(desc.configurable); 190 assertFalse(desc.enumerable); 191 assertEquals(desc.writable, undefined); 192 assertEquals(desc.get, accessorNoConfigurable.get); 193 assertEquals(desc.set, accessorNoConfigurable.set); 194 assertEquals(desc.value, undefined); 195 assertEquals(1, obj1.bar = 1); 196 assertEquals(2, val1); 197 assertEquals(3, val2); 198 assertEquals(1, obj1.bar = 1) 199 assertEquals(2, val1); 200 assertEquals(4, val2); 201 assertEquals(4, obj1.bar); 202 203 // Define an accessor that has only a setter. 204 assertTrue(Reflect.defineProperty(obj1, "setOnly", accessorOnlySet)); 205 desc = Object.getOwnPropertyDescriptor(obj1, "setOnly"); 206 assertTrue(desc.configurable); 207 assertFalse(desc.enumerable); 208 assertEquals(desc.set, accessorOnlySet.set); 209 assertEquals(desc.writable, undefined); 210 assertEquals(desc.value, undefined); 211 assertEquals(desc.get, undefined); 212 assertEquals(1, obj1.setOnly = 1); 213 assertEquals(1, val3); 214 215 // Add a getter - should not touch the setter. 216 assertTrue(Reflect.defineProperty(obj1, "setOnly", accessorOnlyGet)); 217 desc = Object.getOwnPropertyDescriptor(obj1, "setOnly"); 218 assertTrue(desc.configurable); 219 assertFalse(desc.enumerable); 220 assertEquals(desc.get, accessorOnlyGet.get); 221 assertEquals(desc.set, accessorOnlySet.set); 222 assertEquals(desc.writable, undefined); 223 assertEquals(desc.value, undefined); 224 assertEquals(1, obj1.setOnly = 1); 225 assertEquals(2, val3); 226 227 // The above should also work if redefining just a getter or setter on 228 // an existing property with both a getter and a setter. 229 assertTrue(Reflect.defineProperty(obj1, "both", accessorConfigurable)); 230 231 assertTrue(Reflect.defineProperty(obj1, "both", accessorOnlySet)); 232 desc = Object.getOwnPropertyDescriptor(obj1, "both"); 233 assertTrue(desc.configurable); 234 assertFalse(desc.enumerable); 235 assertEquals(desc.set, accessorOnlySet.set); 236 assertEquals(desc.get, accessorConfigurable.get); 237 assertEquals(desc.writable, undefined); 238 assertEquals(desc.value, undefined); 239 assertEquals(1, obj1.both = 1); 240 assertEquals(3, val3); 241 242 243 // Data properties 244 245 assertTrue(Reflect.defineProperty(obj1, "foobar", dataConfigurable)); 246 desc = Object.getOwnPropertyDescriptor(obj1, "foobar"); 247 assertEquals(obj1.foobar, 1000); 248 assertEquals(desc.value, 1000); 249 assertTrue(desc.configurable); 250 assertFalse(desc.writable); 251 assertFalse(desc.enumerable); 252 assertEquals(desc.get, undefined); 253 assertEquals(desc.set, undefined); 254 //Try writing to non writable attribute - should remain 1000 255 obj1.foobar = 1001; 256 assertEquals(obj1.foobar, 1000); 257 258 259 // Redefine to writable descriptor - now writing to foobar should be allowed. 260 assertTrue(Reflect.defineProperty(obj1, "foobar", dataWritable)); 261 desc = Object.getOwnPropertyDescriptor(obj1, "foobar"); 262 assertEquals(obj1.foobar, 3000); 263 assertEquals(desc.value, 3000); 264 // Note that since dataWritable does not define configurable the configurable 265 // setting from the redefined property (in this case true) is used. 266 assertTrue(desc.configurable); 267 assertTrue(desc.writable); 268 assertFalse(desc.enumerable); 269 assertEquals(desc.get, undefined); 270 assertEquals(desc.set, undefined); 271 // Writing to the property should now be allowed 272 obj1.foobar = 1001; 273 assertEquals(obj1.foobar, 1001); 274 275 276 // Redefine with non configurable data property. 277 assertTrue(Reflect.defineProperty(obj1, "foobar", dataNoConfigurable)); 278 desc = Object.getOwnPropertyDescriptor(obj1, "foobar"); 279 assertEquals(obj1.foobar, 2000); 280 assertEquals(desc.value, 2000); 281 assertFalse(desc.configurable); 282 assertTrue(desc.writable); 283 assertFalse(desc.enumerable); 284 assertEquals(desc.get, undefined); 285 assertEquals(desc.set, undefined); 286 287 // Try redefine again - shold fail because configurable is now false. 288 assertFalse(Reflect.defineProperty(obj1, "foobar", dataConfigurable)); 289 290 // Try redefine again with accessor property - shold also fail. 291 assertFalse(Reflect.defineProperty(obj1, "foobar", dataConfigurable)); 292 293 294 // Redifine with the same descriptor - should succeed (step 6). 295 assertTrue(Reflect.defineProperty(obj1, "foobar", dataNoConfigurable)); 296 desc = Object.getOwnPropertyDescriptor(obj1, "foobar"); 297 assertEquals(obj1.foobar, 2000); 298 assertEquals(desc.value, 2000); 299 assertFalse(desc.configurable); 300 assertTrue(desc.writable); 301 assertFalse(desc.enumerable); 302 assertEquals(desc.get, undefined); 303 assertEquals(desc.set, undefined); 304 305 306 // New object 307 var obj2 = {}; 308 309 // Make accessor - redefine to data 310 assertTrue(Reflect.defineProperty(obj2, "foo", accessorConfigurable)); 311 312 // Redefine to data property 313 assertTrue(Reflect.defineProperty(obj2, "foo", dataConfigurable)); 314 desc = Object.getOwnPropertyDescriptor(obj2, "foo"); 315 assertEquals(obj2.foo, 1000); 316 assertEquals(desc.value, 1000); 317 assertTrue(desc.configurable); 318 assertFalse(desc.writable); 319 assertFalse(desc.enumerable); 320 assertEquals(desc.get, undefined); 321 assertEquals(desc.set, undefined); 322 323 324 // Redefine back to accessor 325 assertTrue(Reflect.defineProperty(obj2, "foo", accessorConfigurable)); 326 desc = Object.getOwnPropertyDescriptor(obj2, "foo"); 327 assertTrue(desc.configurable); 328 assertFalse(desc.enumerable); 329 assertEquals(desc.writable, undefined); 330 assertEquals(desc.get, accessorConfigurable.get); 331 assertEquals(desc.set, accessorConfigurable.set); 332 assertEquals(desc.value, undefined); 333 assertEquals(1, obj2.foo = 1); 334 assertEquals(3, val1); 335 assertEquals(4, val2); 336 assertEquals(3, obj2.foo); 337 338 // Make data - redefine to accessor 339 assertTrue(Reflect.defineProperty(obj2, "bar", dataConfigurable)) 340 341 // Redefine to accessor property 342 assertTrue(Reflect.defineProperty(obj2, "bar", accessorConfigurable)); 343 desc = Object.getOwnPropertyDescriptor(obj2, "bar"); 344 assertTrue(desc.configurable); 345 assertFalse(desc.enumerable); 346 assertEquals(desc.writable, undefined); 347 assertEquals(desc.get, accessorConfigurable.get); 348 assertEquals(desc.set, accessorConfigurable.set); 349 assertEquals(desc.value, undefined); 350 assertEquals(1, obj2.bar = 1); 351 assertEquals(4, val1); 352 assertEquals(4, val2); 353 assertEquals(4, obj2.foo); 354 355 // Redefine back to data property 356 assertTrue(Reflect.defineProperty(obj2, "bar", dataConfigurable)); 357 desc = Object.getOwnPropertyDescriptor(obj2, "bar"); 358 assertEquals(obj2.bar, 1000); 359 assertEquals(desc.value, 1000); 360 assertTrue(desc.configurable); 361 assertFalse(desc.writable); 362 assertFalse(desc.enumerable); 363 assertEquals(desc.get, undefined); 364 assertEquals(desc.set, undefined); 365 366 367 // Redefinition of an accessor defined using __defineGetter__ and 368 // __defineSetter__. 369 function get(){return this.x} 370 function set(x){this.x=x}; 371 372 var obj3 = {x:1000}; 373 obj3.__defineGetter__("foo", get); 374 obj3.__defineSetter__("foo", set); 375 376 desc = Object.getOwnPropertyDescriptor(obj3, "foo"); 377 assertTrue(desc.configurable); 378 assertTrue(desc.enumerable); 379 assertEquals(desc.writable, undefined); 380 assertEquals(desc.get, get); 381 assertEquals(desc.set, set); 382 assertEquals(desc.value, undefined); 383 assertEquals(1, obj3.foo = 1); 384 assertEquals(1, obj3.x); 385 assertEquals(1, obj3.foo); 386 387 // Redefine to accessor property (non configurable) - note that enumerable 388 // which we do not redefine should remain the same (true). 389 assertTrue(Reflect.defineProperty(obj3, "foo", accessorNoConfigurable)); 390 desc = Object.getOwnPropertyDescriptor(obj3, "foo"); 391 assertFalse(desc.configurable); 392 assertTrue(desc.enumerable); 393 assertEquals(desc.writable, undefined); 394 assertEquals(desc.get, accessorNoConfigurable.get); 395 assertEquals(desc.set, accessorNoConfigurable.set); 396 assertEquals(desc.value, undefined); 397 assertEquals(1, obj3.foo = 1); 398 assertEquals(5, val2); 399 assertEquals(5, obj3.foo); 400 401 402 obj3.__defineGetter__("bar", get); 403 obj3.__defineSetter__("bar", set); 404 405 406 // Redefine back to data property 407 assertTrue(Reflect.defineProperty(obj3, "bar", dataConfigurable)); 408 desc = Object.getOwnPropertyDescriptor(obj3, "bar"); 409 assertEquals(obj3.bar, 1000); 410 assertEquals(desc.value, 1000); 411 assertTrue(desc.configurable); 412 assertFalse(desc.writable); 413 assertTrue(desc.enumerable); 414 assertEquals(desc.get, undefined); 415 assertEquals(desc.set, undefined); 416 417 418 var obj4 = {}; 419 var func = function (){return 42;}; 420 obj4.bar = func; 421 assertEquals(42, obj4.bar()); 422 423 assertTrue(Reflect.defineProperty(obj4, "bar", accessorConfigurable)); 424 desc = Object.getOwnPropertyDescriptor(obj4, "bar"); 425 assertTrue(desc.configurable); 426 assertTrue(desc.enumerable); 427 assertEquals(desc.writable, undefined); 428 assertEquals(desc.get, accessorConfigurable.get); 429 assertEquals(desc.set, accessorConfigurable.set); 430 assertEquals(desc.value, undefined); 431 assertEquals(1, obj4.bar = 1); 432 assertEquals(5, val1); 433 assertEquals(5, obj4.bar); 434 435 // Make sure an error is thrown when trying to access to redefined function. 436 try { 437 obj4.bar(); 438 assertTrue(false); 439 } catch (e) { 440 assertTrue(/is not a function/.test(e)); 441 } 442 443 444 // Test runtime calls to DefineAccessorPropertyUnchecked - make sure we don't 445 // crash. 446 try { 447 %DefineAccessorPropertyUnchecked(0, 0, 0, 0, 0); 448 } catch (e) { 449 assertTrue(/illegal access/.test(e)); 450 } 451 452 try { 453 %DefineAccessorPropertyUnchecked(null, null, null, null, null); 454 } catch (e) { 455 assertTrue(/illegal access/.test(e)); 456 } 457 458 // Defining properties null should fail even when we have 459 // other allowed values 460 try { 461 %DefineAccessorPropertyUnchecked(null, 'foo', func, null, 0); 462 } catch (e) { 463 assertTrue(/illegal access/.test(e)); 464 } 465 466 // Test that all possible differences in step 6 in DefineOwnProperty are 467 // exercised, i.e., any difference in the given property descriptor and the 468 // existing properties should not return true, but throw an error if the 469 // existing configurable property is false. 470 471 var obj5 = {}; 472 // Enumerable will default to false. 473 assertTrue(Reflect.defineProperty(obj5, 'foo', accessorNoConfigurable)); 474 desc = Object.getOwnPropertyDescriptor(obj5, 'foo'); 475 // First, test that we are actually allowed to set the accessor if all 476 // values are of the descriptor are the same as the existing one. 477 assertTrue(Reflect.defineProperty(obj5, 'foo', accessorNoConfigurable)); 478 479 // Different setter. 480 var descDifferent = { 481 configurable:false, 482 enumerable:false, 483 set: setter1, 484 get: getter2 485 }; 486 487 assertFalse(Reflect.defineProperty(obj5, 'foo', descDifferent)); 488 489 // Different getter. 490 descDifferent = { 491 configurable:false, 492 enumerable:false, 493 set: setter2, 494 get: getter1 495 }; 496 497 assertFalse(Reflect.defineProperty(obj5, 'foo', descDifferent)); 498 499 // Different enumerable. 500 descDifferent = { 501 configurable:false, 502 enumerable:true, 503 set: setter2, 504 get: getter2 505 }; 506 507 assertFalse(Reflect.defineProperty(obj5, 'foo', descDifferent)); 508 509 // Different configurable. 510 descDifferent = { 511 configurable:false, 512 enumerable:true, 513 set: setter2, 514 get: getter2 515 }; 516 517 assertFalse(Reflect.defineProperty(obj5, 'foo', descDifferent)); 518 519 // No difference. 520 descDifferent = { 521 configurable:false, 522 enumerable:false, 523 set: setter2, 524 get: getter2 525 }; 526 // Make sure we can still redefine if all properties are the same. 527 assertTrue(Reflect.defineProperty(obj5, 'foo', descDifferent)); 528 529 // Make sure that obj5 still holds the original values. 530 desc = Object.getOwnPropertyDescriptor(obj5, 'foo'); 531 assertEquals(desc.get, getter2); 532 assertEquals(desc.set, setter2); 533 assertFalse(desc.enumerable); 534 assertFalse(desc.configurable); 535 536 537 // Also exercise step 6 on data property, writable and enumerable 538 // defaults to false. 539 assertTrue(Reflect.defineProperty(obj5, 'bar', dataNoConfigurable)); 540 541 // Test that redefinition with the same property descriptor is possible 542 assertTrue(Reflect.defineProperty(obj5, 'bar', dataNoConfigurable)); 543 544 // Different value. 545 descDifferent = { 546 configurable:false, 547 enumerable:false, 548 writable: false, 549 value: 1999 550 }; 551 552 assertFalse(Reflect.defineProperty(obj5, 'bar', descDifferent)); 553 554 // Different writable. 555 descDifferent = { 556 configurable:false, 557 enumerable:false, 558 writable: true, 559 value: 2000 560 }; 561 562 assertFalse(Reflect.defineProperty(obj5, 'bar', descDifferent)); 563 564 565 // Different enumerable. 566 descDifferent = { 567 configurable:false, 568 enumerable:true , 569 writable:false, 570 value: 2000 571 }; 572 573 assertFalse(Reflect.defineProperty(obj5, 'bar', descDifferent)); 574 575 576 // Different configurable. 577 descDifferent = { 578 configurable:true, 579 enumerable:false, 580 writable:false, 581 value: 2000 582 }; 583 584 assertFalse(Reflect.defineProperty(obj5, 'bar', descDifferent)); 585 586 // No difference. 587 descDifferent = { 588 configurable:false, 589 enumerable:false, 590 writable:false, 591 value:2000 592 }; 593 // Make sure we can still redefine if all properties are the same. 594 assertTrue(Reflect.defineProperty(obj5, 'bar', descDifferent)); 595 596 // Make sure that obj5 still holds the original values. 597 desc = Object.getOwnPropertyDescriptor(obj5, 'bar'); 598 assertEquals(desc.value, 2000); 599 assertFalse(desc.writable); 600 assertFalse(desc.enumerable); 601 assertFalse(desc.configurable); 602 603 604 // Make sure that we can't overwrite +0 with -0 and vice versa. 605 var descMinusZero = {value: -0, configurable: false}; 606 var descPlusZero = {value: +0, configurable: false}; 607 608 assertTrue(Reflect.defineProperty(obj5, 'minuszero', descMinusZero)); 609 610 // Make sure we can redefine with -0. 611 assertTrue(Reflect.defineProperty(obj5, 'minuszero', descMinusZero)); 612 613 assertFalse(Reflect.defineProperty(obj5, 'minuszero', descPlusZero)); 614 615 616 assertTrue(Reflect.defineProperty(obj5, 'pluszero', descPlusZero)); 617 618 // Make sure we can redefine with +0. 619 assertTrue(Reflect.defineProperty(obj5, 'pluszero', descPlusZero)); 620 621 assertFalse(Reflect.defineProperty(obj5, 'pluszero', descMinusZero)); 622 623 624 var obj6 = {}; 625 obj6[1] = 'foo'; 626 obj6[2] = 'bar'; 627 obj6[3] = '42'; 628 obj6[4] = '43'; 629 obj6[5] = '44'; 630 631 var descElement = { value: 'foobar' }; 632 var descElementNonConfigurable = { value: 'barfoo', configurable: false }; 633 var descElementNonWritable = { value: 'foofoo', writable: false }; 634 var descElementNonEnumerable = { value: 'barbar', enumerable: false }; 635 var descElementAllFalse = { value: 'foofalse', 636 configurable: false, 637 writable: false, 638 enumerable: false }; 639 640 641 // Redefine existing property. 642 assertTrue(Reflect.defineProperty(obj6, '1', descElement)); 643 desc = Object.getOwnPropertyDescriptor(obj6, '1'); 644 assertEquals(desc.value, 'foobar'); 645 assertTrue(desc.writable); 646 assertTrue(desc.enumerable); 647 assertTrue(desc.configurable); 648 649 // Redefine existing property with configurable: false. 650 assertTrue(Reflect.defineProperty(obj6, '2', descElementNonConfigurable)); 651 desc = Object.getOwnPropertyDescriptor(obj6, '2'); 652 assertEquals(desc.value, 'barfoo'); 653 assertTrue(desc.writable); 654 assertTrue(desc.enumerable); 655 assertFalse(desc.configurable); 656 657 // Can use defineProperty to change the value of a non 658 // configurable property. 659 try { 660 assertTrue(Reflect.defineProperty(obj6, '2', descElement)); 661 desc = Object.getOwnPropertyDescriptor(obj6, '2'); 662 assertEquals(desc.value, 'foobar'); 663 } catch (e) { 664 assertUnreachable(); 665 } 666 667 // Ensure that we can't change the descriptor of a 668 // non configurable property. 669 var descAccessor = { get: function() { return 0; } }; 670 assertFalse(Reflect.defineProperty(obj6, '2', descAccessor)); 671 672 assertTrue(Reflect.defineProperty(obj6, '2', descElementNonWritable)); 673 desc = Object.getOwnPropertyDescriptor(obj6, '2'); 674 assertEquals(desc.value, 'foofoo'); 675 assertFalse(desc.writable); 676 assertTrue(desc.enumerable); 677 assertFalse(desc.configurable); 678 679 assertTrue(Reflect.defineProperty(obj6, '3', descElementNonWritable)); 680 desc = Object.getOwnPropertyDescriptor(obj6, '3'); 681 assertEquals(desc.value, 'foofoo'); 682 assertFalse(desc.writable); 683 assertTrue(desc.enumerable); 684 assertTrue(desc.configurable); 685 686 // Redefine existing property with configurable: false. 687 assertTrue(Reflect.defineProperty(obj6, '4', descElementNonEnumerable)); 688 desc = Object.getOwnPropertyDescriptor(obj6, '4'); 689 assertEquals(desc.value, 'barbar'); 690 assertTrue(desc.writable); 691 assertFalse(desc.enumerable); 692 assertTrue(desc.configurable); 693 694 // Redefine existing property with configurable: false. 695 assertTrue(Reflect.defineProperty(obj6, '5', descElementAllFalse)); 696 desc = Object.getOwnPropertyDescriptor(obj6, '5'); 697 assertEquals(desc.value, 'foofalse'); 698 assertFalse(desc.writable); 699 assertFalse(desc.enumerable); 700 assertFalse(desc.configurable); 701 702 // Define non existing property - all attributes should default to false. 703 assertTrue(Reflect.defineProperty(obj6, '15', descElement)); 704 desc = Object.getOwnPropertyDescriptor(obj6, '15'); 705 assertEquals(desc.value, 'foobar'); 706 assertFalse(desc.writable); 707 assertFalse(desc.enumerable); 708 assertFalse(desc.configurable); 709 710 // Make sure that we can't redefine using direct access. 711 obj6[15] ='overwrite'; 712 assertEquals(obj6[15],'foobar'); 713 714 715 // Repeat the above tests on an array. 716 var arr = new Array(); 717 arr[1] = 'foo'; 718 arr[2] = 'bar'; 719 arr[3] = '42'; 720 arr[4] = '43'; 721 arr[5] = '44'; 722 723 var descElement = { value: 'foobar' }; 724 var descElementNonConfigurable = { value: 'barfoo', configurable: false }; 725 var descElementNonWritable = { value: 'foofoo', writable: false }; 726 var descElementNonEnumerable = { value: 'barbar', enumerable: false }; 727 var descElementAllFalse = { value: 'foofalse', 728 configurable: false, 729 writable: false, 730 enumerable: false }; 731 732 733 // Redefine existing property. 734 assertTrue(Reflect.defineProperty(arr, '1', descElement)); 735 desc = Object.getOwnPropertyDescriptor(arr, '1'); 736 assertEquals(desc.value, 'foobar'); 737 assertTrue(desc.writable); 738 assertTrue(desc.enumerable); 739 assertTrue(desc.configurable); 740 741 // Redefine existing property with configurable: false. 742 assertTrue(Reflect.defineProperty(arr, '2', descElementNonConfigurable)); 743 desc = Object.getOwnPropertyDescriptor(arr, '2'); 744 assertEquals(desc.value, 'barfoo'); 745 assertTrue(desc.writable); 746 assertTrue(desc.enumerable); 747 assertFalse(desc.configurable); 748 749 // Can use defineProperty to change the value of a non 750 // configurable property of an array. 751 try { 752 assertTrue(Reflect.defineProperty(arr, '2', descElement)); 753 desc = Object.getOwnPropertyDescriptor(arr, '2'); 754 assertEquals(desc.value, 'foobar'); 755 } catch (e) { 756 assertUnreachable(); 757 } 758 759 // Ensure that we can't change the descriptor of a 760 // non configurable property. 761 var descAccessor = { get: function() { return 0; } }; 762 assertFalse(Reflect.defineProperty(arr, '2', descAccessor)); 763 764 assertTrue(Reflect.defineProperty(arr, '2', descElementNonWritable)); 765 desc = Object.getOwnPropertyDescriptor(arr, '2'); 766 assertEquals(desc.value, 'foofoo'); 767 assertFalse(desc.writable); 768 assertTrue(desc.enumerable); 769 assertFalse(desc.configurable); 770 771 assertTrue(Reflect.defineProperty(arr, '3', descElementNonWritable)); 772 desc = Object.getOwnPropertyDescriptor(arr, '3'); 773 assertEquals(desc.value, 'foofoo'); 774 assertFalse(desc.writable); 775 assertTrue(desc.enumerable); 776 assertTrue(desc.configurable); 777 778 // Redefine existing property with configurable: false. 779 assertTrue(Reflect.defineProperty(arr, '4', descElementNonEnumerable)); 780 desc = Object.getOwnPropertyDescriptor(arr, '4'); 781 assertEquals(desc.value, 'barbar'); 782 assertTrue(desc.writable); 783 assertFalse(desc.enumerable); 784 assertTrue(desc.configurable); 785 786 // Redefine existing property with configurable: false. 787 assertTrue(Reflect.defineProperty(arr, '5', descElementAllFalse)); 788 desc = Object.getOwnPropertyDescriptor(arr, '5'); 789 assertEquals(desc.value, 'foofalse'); 790 assertFalse(desc.writable); 791 assertFalse(desc.enumerable); 792 assertFalse(desc.configurable); 793 794 // Define non existing property - all attributes should default to false. 795 assertTrue(Reflect.defineProperty(arr, '15', descElement)); 796 desc = Object.getOwnPropertyDescriptor(arr, '15'); 797 assertEquals(desc.value, 'foobar'); 798 assertFalse(desc.writable); 799 assertFalse(desc.enumerable); 800 assertFalse(desc.configurable); 801 802 // Define non-array property, check that .length is unaffected. 803 assertEquals(16, arr.length); 804 assertTrue(Reflect.defineProperty(arr, '0x20', descElement)); 805 assertEquals(16, arr.length); 806 807 // See issue 968: http://code.google.com/p/v8/issues/detail?id=968 808 var o = { x : 42 }; 809 assertTrue(Reflect.defineProperty(o, "x", { writable: false })); 810 assertEquals(42, o.x); 811 o.x = 37; 812 assertEquals(42, o.x); 813 814 o = { x : 42 }; 815 assertTrue(Reflect.defineProperty(o, "x", {})); 816 assertEquals(42, o.x); 817 o.x = 37; 818 // Writability is preserved. 819 assertEquals(37, o.x); 820 821 var o = { }; 822 assertTrue(Reflect.defineProperty(o, "x", { writable: false })); 823 assertEquals(undefined, o.x); 824 o.x = 37; 825 assertEquals(undefined, o.x); 826 827 o = { get x() { return 87; } }; 828 assertTrue(Reflect.defineProperty(o, "x", { writable: false })); 829 assertEquals(undefined, o.x); 830 o.x = 37; 831 assertEquals(undefined, o.x); 832 833 // Ignore inherited properties. 834 o = { __proto__ : { x : 87 } }; 835 assertTrue(Reflect.defineProperty(o, "x", { writable: false })); 836 assertEquals(undefined, o.x); 837 o.x = 37; 838 assertEquals(undefined, o.x); 839 840 function testDefineProperty(obj, propertyName, desc, resultDesc) { 841 assertTrue(Reflect.defineProperty(obj, propertyName, desc)); 842 var actualDesc = Object.getOwnPropertyDescriptor(obj, propertyName); 843 assertEquals(resultDesc.enumerable, actualDesc.enumerable); 844 assertEquals(resultDesc.configurable, actualDesc.configurable); 845 if (resultDesc.hasOwnProperty('value')) { 846 assertEquals(resultDesc.value, actualDesc.value); 847 assertEquals(resultDesc.writable, actualDesc.writable); 848 assertFalse(resultDesc.hasOwnProperty('get')); 849 assertFalse(resultDesc.hasOwnProperty('set')); 850 } else { 851 assertEquals(resultDesc.get, actualDesc.get); 852 assertEquals(resultDesc.set, actualDesc.set); 853 assertFalse(resultDesc.hasOwnProperty('value')); 854 assertFalse(resultDesc.hasOwnProperty('writable')); 855 } 856 } 857 858 // tests redefining existing property with a generic descriptor 859 o = { p : 42 }; 860 testDefineProperty(o, 'p', 861 { }, 862 { value : 42, writable : true, enumerable : true, configurable : true }); 863 864 o = { p : 42 }; 865 testDefineProperty(o, 'p', 866 { enumerable : true }, 867 { value : 42, writable : true, enumerable : true, configurable : true }); 868 869 o = { p : 42 }; 870 testDefineProperty(o, 'p', 871 { configurable : true }, 872 { value : 42, writable : true, enumerable : true, configurable : true }); 873 874 o = { p : 42 }; 875 testDefineProperty(o, 'p', 876 { enumerable : false }, 877 { value : 42, writable : true, enumerable : false, configurable : true }); 878 879 o = { p : 42 }; 880 testDefineProperty(o, 'p', 881 { configurable : false }, 882 { value : 42, writable : true, enumerable : true, configurable : false }); 883 884 o = { p : 42 }; 885 testDefineProperty(o, 'p', 886 { enumerable : true, configurable : true }, 887 { value : 42, writable : true, enumerable : true, configurable : true }); 888 889 o = { p : 42 }; 890 testDefineProperty(o, 'p', 891 { enumerable : false, configurable : true }, 892 { value : 42, writable : true, enumerable : false, configurable : true }); 893 894 o = { p : 42 }; 895 testDefineProperty(o, 'p', 896 { enumerable : true, configurable : false }, 897 { value : 42, writable : true, enumerable : true, configurable : false }); 898 899 o = { p : 42 }; 900 testDefineProperty(o, 'p', 901 { enumerable : false, configurable : false }, 902 { value : 42, writable : true, enumerable : false, configurable : false }); 903 904 // can make a writable, non-configurable field non-writable 905 o = { p : 42 }; 906 assertTrue(Reflect.defineProperty(o, 'p', { configurable: false })); 907 testDefineProperty(o, 'p', 908 { writable: false }, 909 { value : 42, writable : false, enumerable : true, configurable : false }); 910 911 // redefine of get only property with generic descriptor 912 o = {}; 913 assertTrue(Reflect.defineProperty(o, 'p', 914 { get : getter1, enumerable: true, configurable: true })); 915 testDefineProperty(o, 'p', 916 { enumerable : false, configurable : false }, 917 { get: getter1, set: undefined, enumerable : false, configurable : false }); 918 919 // redefine of get/set only property with generic descriptor 920 o = {}; 921 assertTrue(Reflect.defineProperty(o, 'p', 922 { get: getter1, set: setter1, enumerable: true, configurable: true })); 923 testDefineProperty(o, 'p', 924 { enumerable : false, configurable : false }, 925 { get: getter1, set: setter1, enumerable : false, configurable : false }); 926 927 // redefine of set only property with generic descriptor 928 o = {}; 929 assertTrue(Reflect.defineProperty(o, 'p', 930 { set : setter1, enumerable: true, configurable: true })); 931 testDefineProperty(o, 'p', 932 { enumerable : false, configurable : false }, 933 { get: undefined, set: setter1, enumerable : false, configurable : false }); 934 935 936 // Regression test: Ensure that growing dictionaries are not ignored. 937 o = {}; 938 for (var i = 0; i < 1000; i++) { 939 // Non-enumerable property forces dictionary mode. 940 assertTrue(Reflect.defineProperty(o, i, {value: i, enumerable: false})); 941 } 942 assertEquals(999, o[999]); 943 944 945 // Regression test: Bizzare behavior on non-strict arguments object. 946 // TODO(yangguo): Tests disabled, needs investigation! 947 /* 948 (function test(arg0) { 949 // Here arguments[0] is a fast alias on arg0. 950 Reflect.defineProperty(arguments, "0", { 951 value:1, 952 enumerable:false 953 }); 954 // Here arguments[0] is a slow alias on arg0. 955 Reflect.defineProperty(arguments, "0", { 956 value:2, 957 writable:false 958 }); 959 // Here arguments[0] is no alias at all. 960 Reflect.defineProperty(arguments, "0", { 961 value:3 962 }); 963 assertEquals(2, arg0); 964 assertEquals(3, arguments[0]); 965 })(0); 966 */ 967 968 // Regression test: We should never observe the hole value. 969 var objectWithGetter = {}; 970 objectWithGetter.__defineGetter__('foo', function() {}); 971 assertEquals(undefined, objectWithGetter.__lookupSetter__('foo')); 972 973 var objectWithSetter = {}; 974 objectWithSetter.__defineSetter__('foo', function(x) {}); 975 assertEquals(undefined, objectWithSetter.__lookupGetter__('foo')); 976 977 // An object with a getter on the prototype chain. 978 function getter() { return 111; } 979 function anotherGetter() { return 222; } 980 981 function testGetterOnProto(expected, o) { 982 assertEquals(expected, o.quebec); 983 } 984 985 obj1 = {}; 986 assertTrue( 987 Reflect.defineProperty(obj1, "quebec", { get: getter, configurable: true })); 988 obj2 = Object.create(obj1); 989 obj3 = Object.create(obj2); 990 991 testGetterOnProto(111, obj3); 992 testGetterOnProto(111, obj3); 993 %OptimizeFunctionOnNextCall(testGetterOnProto); 994 testGetterOnProto(111, obj3); 995 testGetterOnProto(111, obj3); 996 997 assertTrue(Reflect.defineProperty(obj1, "quebec", { get: anotherGetter })); 998 999 testGetterOnProto(222, obj3); 1000 testGetterOnProto(222, obj3); 1001 %OptimizeFunctionOnNextCall(testGetterOnProto); 1002 testGetterOnProto(222, obj3); 1003 testGetterOnProto(222, obj3); 1004 1005 // An object with a setter on the prototype chain. 1006 var modifyMe; 1007 function setter(x) { modifyMe = x+1; } 1008 function anotherSetter(x) { modifyMe = x+2; } 1009 1010 function testSetterOnProto(expected, o) { 1011 modifyMe = 333; 1012 o.romeo = 444; 1013 assertEquals(expected, modifyMe); 1014 } 1015 1016 obj1 = {}; 1017 assertTrue( 1018 Reflect.defineProperty(obj1, "romeo", { set: setter, configurable: true })); 1019 obj2 = Object.create(obj1); 1020 obj3 = Object.create(obj2); 1021 1022 testSetterOnProto(445, obj3); 1023 testSetterOnProto(445, obj3); 1024 %OptimizeFunctionOnNextCall(testSetterOnProto); 1025 testSetterOnProto(445, obj3); 1026 testSetterOnProto(445, obj3); 1027 1028 assertTrue(Reflect.defineProperty(obj1, "romeo", { set: anotherSetter })); 1029 1030 testSetterOnProto(446, obj3); 1031 testSetterOnProto(446, obj3); 1032 %OptimizeFunctionOnNextCall(testSetterOnProto); 1033 testSetterOnProto(446, obj3); 1034 testSetterOnProto(446, obj3); 1035 1036 // Removing a setter on the prototype chain. 1037 function testSetterOnProtoStrict(o) { 1038 "use strict"; 1039 o.sierra = 12345; 1040 } 1041 1042 obj1 = {}; 1043 assertTrue(Reflect.defineProperty(obj1, "sierra", 1044 { get: getter, set: setter, configurable: true })); 1045 obj2 = Object.create(obj1); 1046 obj3 = Object.create(obj2); 1047 1048 testSetterOnProtoStrict(obj3); 1049 testSetterOnProtoStrict(obj3); 1050 %OptimizeFunctionOnNextCall(testSetterOnProtoStrict); 1051 testSetterOnProtoStrict(obj3); 1052 testSetterOnProtoStrict(obj3); 1053 1054 assertTrue(Reflect.defineProperty(obj1, "sierra", 1055 { get: getter, set: undefined, configurable: true })); 1056 1057 exception = false; 1058 try { 1059 testSetterOnProtoStrict(obj3); 1060 } catch (e) { 1061 exception = true; 1062 assertTrue(/which has only a getter/.test(e)); 1063 } 1064 assertTrue(exception); 1065 1066 // Test assignment to a getter-only property on the prototype chain. This makes 1067 // sure that crankshaft re-checks its assumptions and doesn't rely only on type 1068 // feedback (which would be monomorphic here). 1069 1070 function Assign(o) { 1071 o.blubb = 123; 1072 } 1073 1074 function C() {} 1075 1076 Assign(new C); 1077 Assign(new C); 1078 %OptimizeFunctionOnNextCall(Assign); 1079 assertTrue( 1080 Reflect.defineProperty(C.prototype, "blubb", {get: function() {return -42}})); 1081 Assign(new C); 1082 1083 // Test that changes to the prototype of a simple constructor are not ignored, 1084 // even after creating initial instances. 1085 function C() { 1086 this.x = 23; 1087 } 1088 assertEquals(23, new C().x); 1089 C.prototype.__defineSetter__('x', function(value) { this.y = 23; }); 1090 assertEquals(void 0, new C().x); 1091