blob: 46bfb34c931c813400528220fd71e8113b2f070b [file] [log] [blame]
Andrei Popescu402d9372010-02-26 13:31:12 +00001// Copyright 2010 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
31
32// Check that an exception is thrown when null is passed as object.
33try {
34 Object.defineProperty(null, null, null);
35 assertTrue(false);
36} catch (e) {
37 assertTrue(/called on non-object/.test(e));
38}
39
40// Check that an exception is thrown when undefined is passed as object.
41try {
42 Object.defineProperty(undefined, undefined, undefined);
43 assertTrue(false);
44} catch (e) {
45 assertTrue(/called on non-object/.test(e));
46}
47
48// Check that an exception is thrown when non-object is passed as object.
49try {
50 Object.defineProperty(0, "foo", undefined);
51 assertTrue(false);
52} catch (e) {
53 assertTrue(/called on non-object/.test(e));
54}
55
Leon Clarkef7060e22010-06-03 12:02:55 +010056// Object.
Andrei Popescu402d9372010-02-26 13:31:12 +000057var obj1 = {};
58
Leon Clarkef7060e22010-06-03 12:02:55 +010059// Values.
Andrei Popescu402d9372010-02-26 13:31:12 +000060var val1 = 0;
61var val2 = 0;
62var val3 = 0;
63
Leon Clarkef7060e22010-06-03 12:02:55 +010064function setter1() {val1++; }
65function getter1() {return val1; }
66
67function setter2() {val2++; }
68function getter2() {return val2; }
69
70function setter3() {val3++; }
71function getter3() {return val3; }
72
73
74// Descriptors.
Andrei Popescu402d9372010-02-26 13:31:12 +000075var emptyDesc = {};
76
77var accessorConfigurable = {
Leon Clarkef7060e22010-06-03 12:02:55 +010078 set: setter1,
79 get: getter1,
Andrei Popescu402d9372010-02-26 13:31:12 +000080 configurable: true
81};
82
83var accessorNoConfigurable = {
Leon Clarkef7060e22010-06-03 12:02:55 +010084 set: setter2,
85 get: getter2,
Andrei Popescu402d9372010-02-26 13:31:12 +000086 configurable: false
87};
88
89var accessorOnlySet = {
Leon Clarkef7060e22010-06-03 12:02:55 +010090 set: setter3,
Andrei Popescu402d9372010-02-26 13:31:12 +000091 configurable: true
92};
93
94var accessorOnlyGet = {
Leon Clarkef7060e22010-06-03 12:02:55 +010095 get: getter3,
Andrei Popescu402d9372010-02-26 13:31:12 +000096 configurable: true
97};
98
99var accessorDefault = {set: function(){} };
100
101var dataConfigurable = { value: 1000, configurable: true };
102
103var dataNoConfigurable = { value: 2000, configurable: false };
104
105var dataWritable = { value: 3000, writable: true};
106
107
108// Check that we can't add property with undefined attributes.
109try {
110 Object.defineProperty(obj1, "foo", undefined);
111 assertTrue(false);
112} catch (e) {
113 assertTrue(/must be an object/.test(e));
114}
115
116// Make sure that we can add a property with an empty descriptor and
117// that it has the default descriptor values.
118Object.defineProperty(obj1, "foo", emptyDesc);
119
120// foo should be undefined as it has no get, set or value
121assertEquals(undefined, obj1.foo);
122
123// We should, however, be able to retrieve the propertydescriptor which should
124// have all default values (according to 8.6.1).
125var desc = Object.getOwnPropertyDescriptor(obj1, "foo");
126assertFalse(desc.configurable);
127assertFalse(desc.enumerable);
128assertFalse(desc.writable);
129assertEquals(desc.get, undefined);
130assertEquals(desc.set, undefined);
131assertEquals(desc.value, undefined);
132
133// Make sure that getOwnPropertyDescriptor does not return a descriptor
134// with default values if called with non existing property (otherwise
135// the test above is invalid).
136desc = Object.getOwnPropertyDescriptor(obj1, "bar");
137assertEquals(desc, undefined);
138
139// Make sure that foo can't be reset (as configurable is false).
140try {
141 Object.defineProperty(obj1, "foo", accessorConfigurable);
142} catch (e) {
143 assertTrue(/Cannot redefine property/.test(e));
144}
145
146
147// Accessor properties
148
149Object.defineProperty(obj1, "bar", accessorConfigurable);
150desc = Object.getOwnPropertyDescriptor(obj1, "bar");
151assertTrue(desc.configurable);
152assertFalse(desc.enumerable);
153assertEquals(desc.writable, undefined);
154assertEquals(desc.get, accessorConfigurable.get);
155assertEquals(desc.set, accessorConfigurable.set);
156assertEquals(desc.value, undefined);
157assertEquals(1, obj1.bar = 1);
158assertEquals(1, val1);
159assertEquals(1, obj1.bar = 1);
160assertEquals(2, val1);
161assertEquals(2, obj1.bar);
162
163// Redefine bar with non configurable test
164Object.defineProperty(obj1, "bar", accessorNoConfigurable);
165desc = Object.getOwnPropertyDescriptor(obj1, "bar");
166assertFalse(desc.configurable);
167assertFalse(desc.enumerable);
168assertEquals(desc.writable, undefined);
169assertEquals(desc.get, accessorNoConfigurable.get);
170assertEquals(desc.set, accessorNoConfigurable.set);
171assertEquals(desc.value, undefined);
172assertEquals(1, obj1.bar = 1);
173assertEquals(2, val1);
174assertEquals(1, val2);
175assertEquals(1, obj1.bar = 1)
176assertEquals(2, val1);
177assertEquals(2, val2);
178assertEquals(2, obj1.bar);
179
180// Try to redefine bar again - should fail as configurable is false.
181try {
182 Object.defineProperty(obj1, "bar", accessorConfigurable);
183 assertTrue(false);
184} catch(e) {
185 assertTrue(/Cannot redefine property/.test(e));
186}
187
188// Try to redefine bar again using the data descriptor - should fail.
189try {
190 Object.defineProperty(obj1, "bar", dataConfigurable);
191 assertTrue(false);
192} catch(e) {
193 assertTrue(/Cannot redefine property/.test(e));
194}
195
196// Redefine using same descriptor - should succeed.
197Object.defineProperty(obj1, "bar", accessorNoConfigurable);
198desc = Object.getOwnPropertyDescriptor(obj1, "bar");
199assertFalse(desc.configurable);
200assertFalse(desc.enumerable);
201assertEquals(desc.writable, undefined);
202assertEquals(desc.get, accessorNoConfigurable.get);
203assertEquals(desc.set, accessorNoConfigurable.set);
204assertEquals(desc.value, undefined);
205assertEquals(1, obj1.bar = 1);
206assertEquals(2, val1);
207assertEquals(3, val2);
208assertEquals(1, obj1.bar = 1)
209assertEquals(2, val1);
210assertEquals(4, val2);
211assertEquals(4, obj1.bar);
212
Leon Clarkef7060e22010-06-03 12:02:55 +0100213// Define an accessor that has only a setter.
Andrei Popescu402d9372010-02-26 13:31:12 +0000214Object.defineProperty(obj1, "setOnly", accessorOnlySet);
215desc = Object.getOwnPropertyDescriptor(obj1, "setOnly");
216assertTrue(desc.configurable);
217assertFalse(desc.enumerable);
218assertEquals(desc.set, accessorOnlySet.set);
219assertEquals(desc.writable, undefined);
220assertEquals(desc.value, undefined);
221assertEquals(desc.get, undefined);
222assertEquals(1, obj1.setOnly = 1);
223assertEquals(1, val3);
224
Leon Clarkef7060e22010-06-03 12:02:55 +0100225// Add a getter - should not touch the setter.
Andrei Popescu402d9372010-02-26 13:31:12 +0000226Object.defineProperty(obj1, "setOnly", accessorOnlyGet);
227desc = Object.getOwnPropertyDescriptor(obj1, "setOnly");
228assertTrue(desc.configurable);
229assertFalse(desc.enumerable);
230assertEquals(desc.get, accessorOnlyGet.get);
231assertEquals(desc.set, accessorOnlySet.set);
232assertEquals(desc.writable, undefined);
233assertEquals(desc.value, undefined);
234assertEquals(1, obj1.setOnly = 1);
235assertEquals(2, val3);
236
237// The above should also work if redefining just a getter or setter on
238// an existing property with both a getter and a setter.
239Object.defineProperty(obj1, "both", accessorConfigurable);
240
241Object.defineProperty(obj1, "both", accessorOnlySet);
242desc = Object.getOwnPropertyDescriptor(obj1, "both");
243assertTrue(desc.configurable);
244assertFalse(desc.enumerable);
245assertEquals(desc.set, accessorOnlySet.set);
246assertEquals(desc.get, accessorConfigurable.get);
247assertEquals(desc.writable, undefined);
248assertEquals(desc.value, undefined);
249assertEquals(1, obj1.both = 1);
250assertEquals(3, val3);
251
252
253// Data properties
254
255Object.defineProperty(obj1, "foobar", dataConfigurable);
256desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
257assertEquals(obj1.foobar, 1000);
258assertEquals(desc.value, 1000);
259assertTrue(desc.configurable);
260assertFalse(desc.writable);
261assertFalse(desc.enumerable);
262assertEquals(desc.get, undefined);
263assertEquals(desc.set, undefined);
264//Try writing to non writable attribute - should remain 1000
265obj1.foobar = 1001;
266assertEquals(obj1.foobar, 1000);
267
268
Leon Clarkef7060e22010-06-03 12:02:55 +0100269// Redefine to writable descriptor - now writing to foobar should be allowed.
Andrei Popescu402d9372010-02-26 13:31:12 +0000270Object.defineProperty(obj1, "foobar", dataWritable);
271desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
272assertEquals(obj1.foobar, 3000);
273assertEquals(desc.value, 3000);
274// Note that since dataWritable does not define configurable the configurable
275// setting from the redefined property (in this case true) is used.
276assertTrue(desc.configurable);
277assertTrue(desc.writable);
278assertFalse(desc.enumerable);
279assertEquals(desc.get, undefined);
280assertEquals(desc.set, undefined);
281// Writing to the property should now be allowed
282obj1.foobar = 1001;
283assertEquals(obj1.foobar, 1001);
284
285
286// Redefine with non configurable data property.
287Object.defineProperty(obj1, "foobar", dataNoConfigurable);
288desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
289assertEquals(obj1.foobar, 2000);
290assertEquals(desc.value, 2000);
291assertFalse(desc.configurable);
Leon Clarkef7060e22010-06-03 12:02:55 +0100292assertTrue(desc.writable);
Andrei Popescu402d9372010-02-26 13:31:12 +0000293assertFalse(desc.enumerable);
294assertEquals(desc.get, undefined);
295assertEquals(desc.set, undefined);
296
297// Try redefine again - shold fail because configurable is now false.
298try {
299 Object.defineProperty(obj1, "foobar", dataConfigurable);
300 assertTrue(false);
301} catch (e) {
302 assertTrue(/Cannot redefine property/.test(e));
303}
304
305// Try redefine again with accessor property - shold also fail.
306try {
307 Object.defineProperty(obj1, "foobar", dataConfigurable);
308 assertTrue(false);
309} catch (e) {
310 assertTrue(/Cannot redefine property/.test(e));
311}
312
313
314// Redifine with the same descriptor - should succeed (step 6).
315Object.defineProperty(obj1, "foobar", dataNoConfigurable);
316desc = Object.getOwnPropertyDescriptor(obj1, "foobar");
317assertEquals(obj1.foobar, 2000);
318assertEquals(desc.value, 2000);
319assertFalse(desc.configurable);
Leon Clarkef7060e22010-06-03 12:02:55 +0100320assertTrue(desc.writable);
Andrei Popescu402d9372010-02-26 13:31:12 +0000321assertFalse(desc.enumerable);
322assertEquals(desc.get, undefined);
323assertEquals(desc.set, undefined);
324
325
326// New object
327var obj2 = {};
328
329// Make accessor - redefine to data
330Object.defineProperty(obj2, "foo", accessorConfigurable);
331
332// Redefine to data property
333Object.defineProperty(obj2, "foo", dataConfigurable);
334desc = Object.getOwnPropertyDescriptor(obj2, "foo");
335assertEquals(obj2.foo, 1000);
336assertEquals(desc.value, 1000);
337assertTrue(desc.configurable);
338assertFalse(desc.writable);
339assertFalse(desc.enumerable);
340assertEquals(desc.get, undefined);
341assertEquals(desc.set, undefined);
342
343
344// Redefine back to accessor
345Object.defineProperty(obj2, "foo", accessorConfigurable);
346desc = Object.getOwnPropertyDescriptor(obj2, "foo");
347assertTrue(desc.configurable);
348assertFalse(desc.enumerable);
349assertEquals(desc.writable, undefined);
350assertEquals(desc.get, accessorConfigurable.get);
351assertEquals(desc.set, accessorConfigurable.set);
352assertEquals(desc.value, undefined);
353assertEquals(1, obj2.foo = 1);
354assertEquals(3, val1);
355assertEquals(4, val2);
356assertEquals(3, obj2.foo);
357
358// Make data - redefine to accessor
359Object.defineProperty(obj2, "bar", dataConfigurable)
360
361// Redefine to accessor property
362Object.defineProperty(obj2, "bar", accessorConfigurable);
363desc = Object.getOwnPropertyDescriptor(obj2, "bar");
364assertTrue(desc.configurable);
365assertFalse(desc.enumerable);
366assertEquals(desc.writable, undefined);
367assertEquals(desc.get, accessorConfigurable.get);
368assertEquals(desc.set, accessorConfigurable.set);
369assertEquals(desc.value, undefined);
370assertEquals(1, obj2.bar = 1);
371assertEquals(4, val1);
372assertEquals(4, val2);
373assertEquals(4, obj2.foo);
374
375// Redefine back to data property
376Object.defineProperty(obj2, "bar", dataConfigurable);
377desc = Object.getOwnPropertyDescriptor(obj2, "bar");
378assertEquals(obj2.bar, 1000);
379assertEquals(desc.value, 1000);
380assertTrue(desc.configurable);
381assertFalse(desc.writable);
382assertFalse(desc.enumerable);
383assertEquals(desc.get, undefined);
384assertEquals(desc.set, undefined);
385
386
387// Redefinition of an accessor defined using __defineGetter__ and
Leon Clarkef7060e22010-06-03 12:02:55 +0100388// __defineSetter__.
Andrei Popescu402d9372010-02-26 13:31:12 +0000389function get(){return this.x}
390function set(x){this.x=x};
391
392var obj3 = {x:1000};
393obj3.__defineGetter__("foo", get);
394obj3.__defineSetter__("foo", set);
395
396desc = Object.getOwnPropertyDescriptor(obj3, "foo");
397assertTrue(desc.configurable);
398assertTrue(desc.enumerable);
399assertEquals(desc.writable, undefined);
400assertEquals(desc.get, get);
401assertEquals(desc.set, set);
402assertEquals(desc.value, undefined);
403assertEquals(1, obj3.foo = 1);
404assertEquals(1, obj3.x);
405assertEquals(1, obj3.foo);
406
407// Redefine to accessor property (non configurable) - note that enumerable
408// which we do not redefine should remain the same (true).
409Object.defineProperty(obj3, "foo", accessorNoConfigurable);
410desc = Object.getOwnPropertyDescriptor(obj3, "foo");
411assertFalse(desc.configurable);
412assertTrue(desc.enumerable);
413assertEquals(desc.writable, undefined);
414assertEquals(desc.get, accessorNoConfigurable.get);
415assertEquals(desc.set, accessorNoConfigurable.set);
416assertEquals(desc.value, undefined);
417assertEquals(1, obj3.foo = 1);
418assertEquals(5, val2);
419assertEquals(5, obj3.foo);
420
421
422obj3.__defineGetter__("bar", get);
423obj3.__defineSetter__("bar", set);
424
425
426// Redefine back to data property
427Object.defineProperty(obj3, "bar", dataConfigurable);
428desc = Object.getOwnPropertyDescriptor(obj3, "bar");
429assertEquals(obj3.bar, 1000);
430assertEquals(desc.value, 1000);
431assertTrue(desc.configurable);
432assertFalse(desc.writable);
433assertTrue(desc.enumerable);
434assertEquals(desc.get, undefined);
435assertEquals(desc.set, undefined);
436
437
438var obj4 = {};
439var func = function (){return 42;};
440obj4.bar = func;
441assertEquals(42, obj4.bar());
442
443Object.defineProperty(obj4, "bar", accessorConfigurable);
444desc = Object.getOwnPropertyDescriptor(obj4, "bar");
445assertTrue(desc.configurable);
446assertTrue(desc.enumerable);
447assertEquals(desc.writable, undefined);
448assertEquals(desc.get, accessorConfigurable.get);
449assertEquals(desc.set, accessorConfigurable.set);
450assertEquals(desc.value, undefined);
451assertEquals(1, obj4.bar = 1);
452assertEquals(5, val1);
453assertEquals(5, obj4.bar);
454
Leon Clarkef7060e22010-06-03 12:02:55 +0100455// Make sure an error is thrown when trying to access to redefined function.
Andrei Popescu402d9372010-02-26 13:31:12 +0000456try {
457 obj4.bar();
458 assertTrue(false);
459} catch (e) {
460 assertTrue(/is not a function/.test(e));
461}
462
463
464// Test runtime calls to DefineOrRedefineDataProperty and
465// DefineOrRedefineAccessorProperty - make sure we don't
Leon Clarkef7060e22010-06-03 12:02:55 +0100466// crash.
Andrei Popescu402d9372010-02-26 13:31:12 +0000467try {
468 %DefineOrRedefineAccessorProperty(0, 0, 0, 0, 0);
469} catch (e) {
470 assertTrue(/illegal access/.test(e));
471}
472
473try {
474 %DefineOrRedefineDataProperty(0, 0, 0, 0);
475} catch (e) {
476 assertTrue(/illegal access/.test(e));
477}
478
479try {
480 %DefineOrRedefineDataProperty(null, null, null, null);
481} catch (e) {
482 assertTrue(/illegal access/.test(e));
483}
484
485try {
486 %DefineOrRedefineAccessorProperty(null, null, null, null, null);
487} catch (e) {
488 assertTrue(/illegal access/.test(e));
489}
490
491try {
492 %DefineOrRedefineDataProperty({}, null, null, null);
493} catch (e) {
494 assertTrue(/illegal access/.test(e));
495}
496
497// Defining properties null should fail even when we have
498// other allowed values
499try {
500 %DefineOrRedefineAccessorProperty(null, 'foo', 0, func, 0);
501} catch (e) {
502 assertTrue(/illegal access/.test(e));
503}
504
505try {
506 %DefineOrRedefineDataProperty(null, 'foo', 0, 0);
507} catch (e) {
508 assertTrue(/illegal access/.test(e));
509}
Leon Clarkef7060e22010-06-03 12:02:55 +0100510
511// Test that all possible differences in step 6 in DefineOwnProperty are
512// exercised, i.e., any difference in the given property descriptor and the
513// existing properties should not return true, but throw an error if the
514// existing configurable property is false.
515
516var obj5 = {};
517// Enumerable will default to false.
518Object.defineProperty(obj5, 'foo', accessorNoConfigurable);
519desc = Object.getOwnPropertyDescriptor(obj5, 'foo');
520// First, test that we are actually allowed to set the accessor if all
521// values are of the descriptor are the same as the existing one.
522Object.defineProperty(obj5, 'foo', accessorNoConfigurable);
523
524// Different setter.
525var descDifferent = {
526 configurable:false,
527 enumerable:false,
528 set: setter1,
529 get: getter2
530};
531
532try {
533 Object.defineProperty(obj5, 'foo', descDifferent);
534 assertTrue(false);
535} catch (e) {
536 assertTrue(/Cannot redefine property/.test(e));
537}
538
539// Different getter.
540descDifferent = {
541 configurable:false,
542 enumerable:false,
543 set: setter2,
544 get: getter1
545};
546
547try {
548 Object.defineProperty(obj5, 'foo', descDifferent);
549 assertTrue(false);
550} catch (e) {
551 assertTrue(/Cannot redefine property/.test(e));
552}
553
554// Different enumerable.
555descDifferent = {
556 configurable:false,
557 enumerable:true,
558 set: setter2,
559 get: getter2
560};
561
562try {
563 Object.defineProperty(obj5, 'foo', descDifferent);
564 assertTrue(false);
565} catch (e) {
566 assertTrue(/Cannot redefine property/.test(e));
567}
568
569// Different configurable.
570descDifferent = {
571 configurable:false,
572 enumerable:true,
573 set: setter2,
574 get: getter2
575};
576
577try {
578 Object.defineProperty(obj5, 'foo', descDifferent);
579 assertTrue(false);
580} catch (e) {
581 assertTrue(/Cannot redefine property/.test(e));
582}
583
584// No difference.
585descDifferent = {
586 configurable:false,
587 enumerable:false,
588 set: setter2,
589 get: getter2
590};
591// Make sure we can still redefine if all properties are the same.
592Object.defineProperty(obj5, 'foo', descDifferent);
593
594// Make sure that obj5 still holds the original values.
595desc = Object.getOwnPropertyDescriptor(obj5, 'foo');
596assertEquals(desc.get, getter2);
597assertEquals(desc.set, setter2);
598assertFalse(desc.enumerable);
599assertFalse(desc.configurable);
600
601
602// Also exercise step 6 on data property, writable and enumerable
603// defaults to false.
604Object.defineProperty(obj5, 'bar', dataNoConfigurable);
605
606// Test that redefinition with the same property descriptor is possible
607Object.defineProperty(obj5, 'bar', dataNoConfigurable);
608
609// Different value.
610descDifferent = {
611 configurable:false,
612 enumerable:false,
613 writable: false,
614 value: 1999
615};
616
617try {
618 Object.defineProperty(obj5, 'bar', descDifferent);
619 assertTrue(false);
620} catch (e) {
621 assertTrue(/Cannot redefine property/.test(e));
622}
623
624// Different writable.
625descDifferent = {
626 configurable:false,
627 enumerable:false,
628 writable: true,
629 value: 2000
630};
631
632try {
633 Object.defineProperty(obj5, 'bar', descDifferent);
634 assertTrue(false);
635} catch (e) {
636 assertTrue(/Cannot redefine property/.test(e));
637}
638
639
640// Different enumerable.
641descDifferent = {
642 configurable:false,
643 enumerable:true ,
644 writable:false,
645 value: 2000
646};
647
648try {
649 Object.defineProperty(obj5, 'bar', descDifferent);
650 assertTrue(false);
651} catch (e) {
652 assertTrue(/Cannot redefine property/.test(e));
653}
654
655
656// Different configurable.
657descDifferent = {
658 configurable:true,
659 enumerable:false,
660 writable:false,
661 value: 2000
662};
663
664try {
665 Object.defineProperty(obj5, 'bar', descDifferent);
666 assertTrue(false);
667} catch (e) {
668 assertTrue(/Cannot redefine property/.test(e));
669}
670
671// No difference.
672descDifferent = {
673 configurable:false,
674 enumerable:false,
675 writable:false,
676 value:2000
677};
678// Make sure we can still redefine if all properties are the same.
679Object.defineProperty(obj5, 'bar', descDifferent);
680
681// Make sure that obj5 still holds the original values.
682desc = Object.getOwnPropertyDescriptor(obj5, 'bar');
683assertEquals(desc.value, 2000);
684assertFalse(desc.writable);
685assertFalse(desc.enumerable);
686assertFalse(desc.configurable);
687
688
689// Make sure that we can't overwrite +0 with -0 and vice versa.
690var descMinusZero = {value: -0, configurable: false};
691var descPlusZero = {value: +0, configurable: false};
692
693Object.defineProperty(obj5, 'minuszero', descMinusZero);
694
695// Make sure we can redefine with -0.
696Object.defineProperty(obj5, 'minuszero', descMinusZero);
697
698try {
699 Object.defineProperty(obj5, 'minuszero', descPlusZero);
700 assertUnreachable();
701} catch (e) {
702 assertTrue(/Cannot redefine property/.test(e));
703}
704
705
706Object.defineProperty(obj5, 'pluszero', descPlusZero);
707
708// Make sure we can redefine with +0.
709Object.defineProperty(obj5, 'pluszero', descPlusZero);
710
711try {
712 Object.defineProperty(obj5, 'pluszero', descMinusZero);
713 assertUnreachable();
714} catch (e) {
715 assertTrue(/Cannot redefine property/.test(e));
716}