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