1// 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.seal and Object.isSealed methods - ES 15.2.3.9 and
29// ES 15.2.3.12
30
31
32// Test that we throw an error if an object is not passed as argument.
33var non_objects = new Array(undefined, null, 1, -1, 0, 42.43);
34for (var key in non_objects) {
35  var exception = false;
36  try {
37    Object.seal(non_objects[key]);
38  } catch(e) {
39    exception = true;
40    assertTrue(/Object.seal called on non-object/.test(e));
41  }
42  assertTrue(exception);
43}
44
45for (var key in non_objects) {
46  exception = false;
47  try {
48    Object.isSealed(non_objects[key]);
49  } catch(e) {
50    exception = true;
51    assertTrue(/Object.isSealed called on non-object/.test(e));
52  }
53  assertTrue(exception);
54}
55
56// Test normal data properties.
57var obj = { x: 42, z: 'foobar' };
58var desc = Object.getOwnPropertyDescriptor(obj, 'x');
59assertTrue(desc.writable);
60assertTrue(desc.configurable);
61assertEquals(42, desc.value);
62
63desc = Object.getOwnPropertyDescriptor(obj, 'z');
64assertTrue(desc.writable);
65assertTrue(desc.configurable);
66assertEquals('foobar', desc.value);
67
68assertTrue(Object.isExtensible(obj));
69assertFalse(Object.isSealed(obj));
70
71Object.seal(obj);
72
73// Make sure we are no longer extensible.
74assertFalse(Object.isExtensible(obj));
75assertTrue(Object.isSealed(obj));
76
77// We should not be frozen, since we are still able to
78// update values.
79assertFalse(Object.isFrozen(obj));
80
81// We should not allow new properties to be added.
82obj.foo = 42;
83assertEquals(obj.foo, undefined);
84
85desc = Object.getOwnPropertyDescriptor(obj, 'x');
86assertTrue(desc.writable);
87assertFalse(desc.configurable);
88assertEquals(42, desc.value);
89
90desc = Object.getOwnPropertyDescriptor(obj, 'z');
91assertTrue(desc.writable);
92assertFalse(desc.configurable);
93assertEquals("foobar", desc.value);
94
95// Since writable is not affected by seal we should still be able to
96// update the values.
97obj.x = "43";
98assertEquals("43", obj.x);
99
100// Test on accessors.
101var obj2 = {};
102function get() { return 43; };
103function set() {};
104Object.defineProperty(obj2, 'x', { get: get, set: set, configurable: true });
105
106desc = Object.getOwnPropertyDescriptor(obj2, 'x');
107assertTrue(desc.configurable);
108assertEquals(undefined, desc.value);
109assertEquals(set, desc.set);
110assertEquals(get, desc.get);
111
112assertTrue(Object.isExtensible(obj2));
113assertFalse(Object.isSealed(obj2));
114Object.seal(obj2);
115
116// Since this is an accessor property the object is now effectively both
117// sealed and frozen (accessors has no writable attribute).
118assertTrue(Object.isFrozen(obj2));
119assertFalse(Object.isExtensible(obj2));
120assertTrue(Object.isSealed(obj2));
121
122desc = Object.getOwnPropertyDescriptor(obj2, 'x');
123assertFalse(desc.configurable);
124assertEquals(undefined, desc.value);
125assertEquals(set, desc.set);
126assertEquals(get, desc.get);
127
128obj2.foo = 42;
129assertEquals(obj2.foo, undefined);
130
131// Test seal on arrays.
132var arr = new Array(42,43);
133
134desc = Object.getOwnPropertyDescriptor(arr, '0');
135assertTrue(desc.configurable);
136assertTrue(desc.writable);
137assertEquals(42, desc.value);
138
139desc = Object.getOwnPropertyDescriptor(arr, '1');
140assertTrue(desc.configurable);
141assertTrue(desc.writable);
142assertEquals(43, desc.value);
143
144assertTrue(Object.isExtensible(arr));
145assertFalse(Object.isSealed(arr));
146Object.seal(arr);
147assertTrue(Object.isSealed(arr));
148assertFalse(Object.isExtensible(arr));
149// Since the values in the array is still writable this object
150// is not frozen.
151assertFalse(Object.isFrozen(arr));
152
153desc = Object.getOwnPropertyDescriptor(arr, '0');
154assertFalse(desc.configurable);
155assertTrue(desc.writable);
156assertEquals(42, desc.value);
157
158desc = Object.getOwnPropertyDescriptor(arr, '1');
159assertFalse(desc.configurable);
160assertTrue(desc.writable);
161assertEquals(43, desc.value);
162
163arr[0] = 'foo';
164
165// We should be able to overwrite the existing value.
166assertEquals('foo', arr[0]);
167
168
169// Test that isSealed returns the correct value even if configurable
170// has been set to false on all properties manually and the extensible
171// flag has also been set to false manually.
172var obj3 = { x: 42, y: 'foo' };
173
174assertFalse(Object.isFrozen(obj3));
175
176Object.defineProperty(obj3, 'x', {configurable: false, writable: true});
177Object.defineProperty(obj3, 'y', {configurable: false, writable: false});
178Object.preventExtensions(obj3);
179
180assertTrue(Object.isSealed(obj3));
181
182
183// Make sure that an object that has a configurable property
184// is not classified as sealed.
185var obj4 = {};
186Object.defineProperty(obj4, 'x', {configurable: true, writable: false});
187Object.defineProperty(obj4, 'y', {configurable: false, writable: false});
188Object.preventExtensions(obj4);
189
190assertFalse(Object.isSealed(obj4));
191
192// Make sure that Object.seal returns the sealed object.
193var obj4 = {};
194assertTrue(obj4 === Object.seal(obj4));
195