Home | History | Annotate | Download | only in js
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions
      6 // are met:
      7 // 1.  Redistributions of source code must retain the above copyright
      8 //     notice, this list of conditions and the following disclaimer.
      9 // 2.  Redistributions in binary form must reproduce the above copyright
     10 //     notice, this list of conditions and the following disclaimer in the
     11 //     documentation and/or other materials provided with the distribution.
     12 //
     13 // THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     14 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16 // DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20 // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 
     24 description("Test to ensure correct behaviour of Object.defineProperty");
     25 
     26 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {value:1}), 'foo'))",
     27          "JSON.stringify({value: 1, writable: false, enumerable: false, configurable: false})");
     28 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {}), 'foo'))",
     29          "JSON.stringify({writable: false, enumerable: false, configurable: false})");
     30 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {get:undefined}), 'foo'))",
     31          "JSON.stringify({enumerable: false, configurable: false})");
     32 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {value:1, writable: false}), 'foo'))",
     33          "JSON.stringify({value: 1, writable: false, enumerable: false, configurable: false})");
     34 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {value:1, writable: true}), 'foo'))",
     35          "JSON.stringify({value: 1, writable: true, enumerable: false, configurable: false})");
     36 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {value:1, enumerable: false}), 'foo'))",
     37          "JSON.stringify({value: 1, writable: false, enumerable: false, configurable: false})");
     38 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {value:1, enumerable: true}), 'foo'))",
     39          "JSON.stringify({value: 1, writable: false, enumerable: true, configurable: false})");
     40 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {value:1, configurable: false}), 'foo'))",
     41          "JSON.stringify({value: 1, writable: false, enumerable: false, configurable: false})");
     42 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty({}, 'foo', {value:1, configurable: true}), 'foo'))",
     43          "JSON.stringify({value: 1, writable: false, enumerable: false, configurable: true})");
     44 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty([1,2,3], 'foo', {value:1, configurable: true}), 'foo'))",
     45          "JSON.stringify({value: 1, writable: false, enumerable: false, configurable: true})");
     46 shouldBe("Object.getOwnPropertyDescriptor(Object.defineProperty([1,2,3], '1', {value:'foo', configurable: true}), '1').value", "'foo'");
     47 shouldBe("a=[1,2,3], Object.defineProperty(a, '1', {value:'foo', configurable: true}), a[1]", "'foo'");
     48 shouldBe("Object.getOwnPropertyDescriptor(Object.defineProperty([1,2,3], '1', {get:getter, configurable: true}), '1').get", "getter");
     49 shouldThrow("Object.defineProperty([1,2,3], '1', {get:getter, configurable: true})[1]", "'called getter'");
     50 
     51 shouldThrow("Object.defineProperty()");
     52 shouldThrow("Object.defineProperty(null)");
     53 shouldThrow("Object.defineProperty('foo')");
     54 shouldThrow("Object.defineProperty({})");
     55 shouldThrow("Object.defineProperty({}, 'foo')");
     56 shouldThrow("Object.defineProperty({}, 'foo', {get:undefined, value:true}).foo");
     57 shouldBeTrue("Object.defineProperty({get foo() { return true; } }, 'foo', {configurable:false}).foo");
     58 
     59 function createUnconfigurableProperty(o, prop, writable, enumerable) {
     60     writable = writable || false;
     61     enumerable = enumerable || false;
     62     return Object.defineProperty(o, prop, {value:1, configurable:false, writable: writable, enumerable: enumerable});
     63 }
     64 shouldThrow("Object.defineProperty(createUnconfigurableProperty({}, 'foo'), 'foo', {configurable: true})");
     65 shouldThrow("Object.defineProperty(createUnconfigurableProperty({}, 'foo'), 'foo', {writable: true})");
     66 shouldThrow("Object.defineProperty(createUnconfigurableProperty({}, 'foo'), 'foo', {enumerable: true})");
     67 shouldThrow("Object.defineProperty(createUnconfigurableProperty({}, 'foo', false, true), 'foo', {enumerable: false}), 'foo'");
     68 
     69 shouldBe("JSON.stringify(Object.getOwnPropertyDescriptor(Object.defineProperty(createUnconfigurableProperty({}, 'foo', true), 'foo', {writable: false}), 'foo'))",
     70          "JSON.stringify({value: 1, writable: false, enumerable: false, configurable: false})");
     71 
     72 shouldThrow("Object.defineProperty({}, 'foo', {value:1, get: function(){}})");
     73 shouldThrow("Object.defineProperty({}, 'foo', {value:1, set: function(){}})");
     74 shouldThrow("Object.defineProperty({}, 'foo', {writable:true, get: function(){}})");
     75 shouldThrow("Object.defineProperty({}, 'foo', {writable:true, set: function(){}})");
     76 shouldThrow("Object.defineProperty({}, 'foo', {get: null})");
     77 shouldThrow("Object.defineProperty({}, 'foo', {set: null})");
     78 function getter(){ throw "called getter"; }
     79 function getter1(){ throw "called getter1"; }
     80 function setter(){ throw "called setter"; }
     81 function setter1(){ throw "called setter1"; }
     82 shouldThrow("Object.defineProperty({}, 'foo', {set: setter}).foo='test'", "'called setter'");
     83 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {set: setter}), 'foo', {set: setter1})");
     84 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {set: setter}), 'foo', {get: getter1})");
     85 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {set: setter}), 'foo', {value: 1})");
     86 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {set: setter, configurable: true}), 'foo', {set: setter1}).foo='test'", "'called setter1'");
     87 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {set: setter, configurable: true}), 'foo', {get: getter1}).foo", "'called getter1'");
     88 shouldBeTrue("Object.defineProperty(Object.defineProperty({}, 'foo', {set: setter, configurable: true}), 'foo', {value: true}).foo");
     89 shouldBeTrue("'foo' in Object.defineProperty(Object.defineProperty({}, 'foo', {set: setter, configurable: true}), 'foo', {writable: true})");
     90 shouldBeUndefined("Object.defineProperty(Object.defineProperty({}, 'foo', {set: setter, configurable: true}), 'foo', {writable: true}).foo");
     91 shouldThrow("Object.defineProperty({}, 'foo', {get: getter}).foo", "'called getter'");
     92 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {get: getter}), 'foo', {get: getter1})");
     93 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {get: getter}), 'foo', {set: setter1})");
     94 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {get: getter, configurable: true}), 'foo', {get: getter1}).foo", "'called getter1'");
     95 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {get: getter, configurable: true}), 'foo', {set: setter1}).foo='test'", "'called setter1'");
     96 shouldBeTrue("Object.defineProperty(Object.defineProperty({}, 'foo', {get: getter, configurable: true}), 'foo', {value: true}).foo");
     97 shouldBeUndefined("Object.defineProperty(Object.defineProperty({}, 'foo', {get: getter, configurable: true}), 'foo', {writable: true}).foo");
     98 shouldBeTrue("'foo' in Object.defineProperty(Object.defineProperty({}, 'foo', {get: getter, configurable: true}), 'foo', {writable: true})");
     99 
    100 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1}), 'foo', {set: setter1})");
    101 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1, configurable: true}), 'foo', {set: setter1}).foo='test'", "'called setter1'");
    102 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1}), 'foo', {get: getter1})");
    103 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1}), 'foo', {set: setter1})");
    104 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1, configurable: true}), 'foo', {get: getter1}).foo", "'called getter1'");
    105 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1, configurable: true}), 'foo', {set: setter1}).foo='test'", "'called setter1'");
    106 
    107 // Should be able to redefine an non-writable property, if it is configurable.
    108 shouldBe("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1, configurable: true, writable: false}), 'foo', {value: 2, configurable: true, writable: true}).foo", "2");
    109 shouldBe("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1, configurable: true, writable: false}), 'foo', {value: 2, configurable: true, writable: false}).foo", "2");
    110 
    111 // Should be able to redefine an non-writable, non-configurable property, with the same value and attributes.
    112 shouldBe("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1, configurable: false, writable: false}), 'foo', {value: 1, configurable: false, writable: false}).foo", "1");
    113 
    114 // Should be able to redefine a configurable accessor, with the same or with different attributes.
    115 // Check the accessor function changed.
    116 shouldBe("Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: true, enumerable: true}), 'foo', {get: function() { return 2; }, configurable: true, enumerable: false}).foo", "2");
    117 shouldBe("Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: true, enumerable: false}), 'foo', {get: function() { return 2; }, configurable: true, enumerable: false}).foo", "2");
    118 // Check the attributes changed.
    119 shouldBeFalse("var result = false; var o = Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: true, enumerable: true}), 'foo', {get: function() { return 2; }, configurable: true, enumerable: false}); for (x in o) result = true; result");
    120 shouldBeTrue("var result = false; var o = Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: true, enumerable: false}), 'foo', {get: function() { return 2; }, configurable: true, enumerable: true}); for (x in o) result = true; result");
    121 
    122 // Should be able to define an non-configurable accessor.
    123 shouldBeUndefined("var o = Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: true}); delete o.foo; o.foo");
    124 shouldBe("var o = Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: false}); delete o.foo; o.foo", '1');
    125 shouldBe("Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: true}), 'foo', {value:2}).foo", "2");
    126 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: false}), 'foo', {value:2}).foo");
    127 
    128 // Defining a data descriptor over an accessor should result in a read only property.
    129 shouldBe("var o = Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return 1; }, configurable: true}), 'foo', {value:2}); o.foo = 3; o.foo", "2");
    130 
    131 // Trying to redefine a non-configurable property as configurable should throw.
    132 shouldThrow("Object.defineProperty(Object.defineProperty({}, 'foo', {value: 1}), 'foo', {value:2, configurable: true})");
    133 shouldThrow("Object.defineProperty(Object.defineProperty([], 'foo', {value: 1}), 'foo', {value:2, configurable: true})");
    134 
    135 // Test an object with a getter setter.
    136 // Either accessor may be omitted or replaced with undefined, or both may be replaced with undefined.
    137 shouldBe("var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}); o.foo", '42')
    138 shouldBe("var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}); o.foo = 42; o.result;", '42');
    139 shouldBe("var o = Object.defineProperty({}, 'foo', {get:undefined, set:function(x){this.result = x;}}); o.foo", 'undefined')
    140 shouldBe("var o = Object.defineProperty({}, 'foo', {get:undefined, set:function(x){this.result = x;}}); o.foo = 42; o.result;", '42');
    141 shouldBe("var o = Object.defineProperty({}, 'foo', {set:function(x){this.result = x;}}); o.foo", 'undefined')
    142 shouldBe("var o = Object.defineProperty({}, 'foo', {set:function(x){this.result = x;}}); o.foo = 42; o.result;", '42');
    143 shouldBe("var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}, set:undefined}); o.foo", '42')
    144 shouldBe("var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}, set:undefined}); o.foo = 42; o.result;", 'undefined');
    145 shouldBe("var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}}); o.foo", '42')
    146 shouldBe("var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}}); o.foo = 42; o.result;", 'undefined');
    147 shouldBe("var o = Object.defineProperty({}, 'foo', {get:undefined, set:undefined}); o.foo", 'undefined')
    148 shouldBe("var o = Object.defineProperty({}, 'foo', {get:undefined, set:undefined}); o.foo = 42; o.result;", 'undefined');
    149 // Test replacing or removing either the getter or setter individually.
    150 shouldBe("var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {get:function(){return 13;}}); o.foo", '13')
    151 shouldBe("var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {get:function(){return 13;}}); o.foo = 42; o.result;", '42')
    152 shouldBe("var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {get:undefined}); o.foo", 'undefined')
    153 shouldBe("var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {get:undefined}); o.foo = 42; o.result;", '42')
    154 shouldBe("var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {set:function(){this.result = 13;}}); o.foo", '42')
    155 shouldBe("var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {set:function(){this.result = 13;}}); o.foo = 42; o.result;", '13')
    156 shouldBe("var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {set:undefined}); o.foo", '42')
    157 shouldBe("var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {set:undefined}); o.foo = 42; o.result;", 'undefined')
    158 
    159 // Repeat of the above, in strict mode.
    160 // Either accessor may be omitted or replaced with undefined, or both may be replaced with undefined.
    161 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}); o.foo", '42')
    162 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}); o.foo = 42; o.result;", '42');
    163 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {get:undefined, set:function(x){this.result = x;}}); o.foo", 'undefined')
    164 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {get:undefined, set:function(x){this.result = x;}}); o.foo = 42; o.result;", '42');
    165 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {set:function(x){this.result = x;}}); o.foo", 'undefined')
    166 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {set:function(x){this.result = x;}}); o.foo = 42; o.result;", '42');
    167 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}, set:undefined}); o.foo", '42')
    168 shouldThrow("'use strict'; var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}, set:undefined}); o.foo = 42; o.result;");
    169 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}}); o.foo", '42')
    170 shouldThrow("'use strict'; var o = Object.defineProperty({}, 'foo', {get:function(){return 42;}}); o.foo = 42; o.result;");
    171 shouldBe("'use strict'; var o = Object.defineProperty({}, 'foo', {get:undefined, set:undefined}); o.foo", 'undefined')
    172 shouldThrow("'use strict'; var o = Object.defineProperty({}, 'foo', {get:undefined, set:undefined}); o.foo = 42; o.result;");
    173 // Test replacing or removing either the getter or setter individually.
    174 shouldBe("'use strict'; var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {get:function(){return 13;}}); o.foo", '13')
    175 shouldBe("'use strict'; var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {get:function(){return 13;}}); o.foo = 42; o.result;", '42')
    176 shouldBe("'use strict'; var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {get:undefined}); o.foo", 'undefined')
    177 shouldBe("'use strict'; var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {get:undefined}); o.foo = 42; o.result;", '42')
    178 shouldBe("'use strict'; var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {set:function(){this.result = 13;}}); o.foo", '42')
    179 shouldBe("'use strict'; var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {set:function(){this.result = 13;}}); o.foo = 42; o.result;", '13')
    180 shouldBe("'use strict'; var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {set:undefined}); o.foo", '42')
    181 shouldThrow("'use strict'; var o = Object.defineProperty(Object.defineProperty({foo:1}, 'foo', {get:function(){return 42;}, set:function(x){this.result = x;}}), 'foo', {set:undefined}); o.foo = 42; o.result;")
    182 
    183 Object.defineProperty(Object.prototype, 0, {get:function(){ return false; }, configurable:true})
    184 shouldBeTrue("0 in Object.prototype");
    185 shouldBeTrue("'0' in Object.prototype");
    186 delete Object.prototype[0];
    187 
    188 Object.defineProperty(Object.prototype, 'readOnly', {value:true, configurable:true, writable:false})
    189 shouldBeTrue("var o = {}; o.readOnly = false; o.readOnly");
    190 shouldThrow("'use strict'; var o = {}; o.readOnly = false; o.readOnly");
    191 delete Object.prototype.readOnly;
    192 
    193 // Check the writable attribute is set correctly when redefining an accessor as a data descriptor.
    194 shouldBeFalse("Object.getOwnPropertyDescriptor(Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return false; }, configurable: true}), 'foo', {value:false}), 'foo').writable");
    195 shouldBeFalse("Object.getOwnPropertyDescriptor(Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return false; }, configurable: true}), 'foo', {value:false, writable: false}), 'foo').writable");
    196 shouldBeTrue("Object.getOwnPropertyDescriptor(Object.defineProperty(Object.defineProperty({}, 'foo', {get: function() { return false; }, configurable: true}), 'foo', {value:false, writable: true}), 'foo').writable");
    197 
    198 // If array length is read-only, [[Put]] should fail.
    199 shouldBeFalse("var a = Object.defineProperty([], 'length', {writable: false}); a[0] = 42; 0 in a;");
    200 shouldThrow("'use strict'; var a = Object.defineProperty([], 'length', {writable: false}); a[0] = 42; 0 in a;");
    201 
    202 // If array property is read-only, [[Put]] should fail.
    203 shouldBe("var a = Object.defineProperty([42], '0', {writable: false}); a[0] = false; a[0];", '42');
    204 shouldThrow("'use strict'; var a = Object.defineProperty([42], '0', {writable: false}); a[0] = false; a[0];");
    205 
    206 // If array property is an undefined setter, [[Put]] should fail.
    207 shouldBeUndefined("var a = Object.defineProperty([], '0', {set: undefined}); a[0] = 42; a[0];");
    208 shouldThrow("'use strict'; var a = Object.defineProperty([], '0', {set: undefined}); a[0] = 42; a[0];");
    209 
    210 function testObject()
    211 {
    212     // Test case from https://bugs.webkit.org/show_bug.cgi?id=38636
    213     Object.defineProperty(anObj, 'slot1', {value: 'foo', enumerable: true});
    214     Object.defineProperty(anObj, 'slot2', {value: 'bar', writable: true});
    215     Object.defineProperty(anObj, 'slot3', {value: 'baz', enumerable: false});
    216     Object.defineProperty(anObj, 'slot4', {value: 'goo', configurable: false});
    217     shouldBe("anObj.slot1", '"foo"');
    218     shouldBe("anObj.slot2", '"bar"');
    219     anObj.slot2 = 'bad value';
    220     shouldBeTrue("anObj.propertyIsEnumerable('slot1')");
    221     shouldBeFalse("anObj.propertyIsEnumerable('slot2')");
    222     delete anObj.slot4;
    223     shouldBe("anObj.slot4", '"goo"');
    224 
    225     // Test case from https://bugs.webkit.org/show_bug.cgi?id=48911
    226     Object.defineProperty(Object.getPrototypeOf(anObj), 'slot5', {get: function() { return this._Slot5; }, set: function(v) { this._Slot5 = v; }, configurable: false});
    227     anObj.slot5 = 123;
    228     shouldBe("anObj.slot5", '123');
    229     shouldBe("anObj._Slot5", '123');
    230     shouldBeUndefined("Object.getOwnPropertyDescriptor(anObj, 'slot5')");
    231     Object.defineProperty(anObj, 'slot5', { value: 456 });
    232     shouldBe("anObj.slot5", '456');
    233     shouldBe("anObj._Slot5", '123');
    234     shouldBe("Object.getOwnPropertyDescriptor(anObj, 'slot5').value", '456');
    235 }
    236 var anObj = {};
    237 testObject();
    238 var anObj = this;
    239 testObject();
    240