Home | History | Annotate | Download | only in es6
      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