]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/ObjectConstructor.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / ObjectConstructor.cpp
1 /*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include "config.h"
22 #include "ObjectConstructor.h"
23
24 #include "ButterflyInlines.h"
25 #include "CopiedSpaceInlines.h"
26 #include "Error.h"
27 #include "ExceptionHelpers.h"
28 #include "JSArray.h"
29 #include "JSCInlines.h"
30 #include "JSFunction.h"
31 #include "JSGlobalObject.h"
32 #include "JSGlobalObjectFunctions.h"
33 #include "Lookup.h"
34 #include "ObjectPrototype.h"
35 #include "PropertyDescriptor.h"
36 #include "PropertyNameArray.h"
37 #include "StackVisitor.h"
38 #include "Symbol.h"
39
40 namespace JSC {
41
42 EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*);
43 EncodedJSValue JSC_HOST_CALL objectConstructorSetPrototypeOf(ExecState*);
44 EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState*);
45 EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*);
46 EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*);
47 EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState*);
48 EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState*);
49 EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState*);
50 EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState*);
51 EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState*);
52 EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState*);
53 EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState*);
54 EncodedJSValue JSC_HOST_CALL objectConstructorIs(ExecState*);
55
56 }
57
58 #include "ObjectConstructor.lut.h"
59
60 namespace JSC {
61
62 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ObjectConstructor);
63
64 const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_info, &objectConstructorTable, CREATE_METHOD_TABLE(ObjectConstructor) };
65
66 /* Source for ObjectConstructor.lut.h
67 @begin objectConstructorTable
68 getPrototypeOf objectConstructorGetPrototypeOf DontEnum|Function 1
69 setPrototypeOf objectConstructorSetPrototypeOf DontEnum|Function 2
70 getOwnPropertyDescriptor objectConstructorGetOwnPropertyDescriptor DontEnum|Function 2
71 getOwnPropertyNames objectConstructorGetOwnPropertyNames DontEnum|Function 1
72 keys objectConstructorKeys DontEnum|Function 1
73 defineProperty objectConstructorDefineProperty DontEnum|Function 3
74 defineProperties objectConstructorDefineProperties DontEnum|Function 2
75 create objectConstructorCreate DontEnum|Function 2
76 seal objectConstructorSeal DontEnum|Function 1
77 freeze objectConstructorFreeze DontEnum|Function 1
78 preventExtensions objectConstructorPreventExtensions DontEnum|Function 1
79 isSealed objectConstructorIsSealed DontEnum|Function 1
80 isFrozen objectConstructorIsFrozen DontEnum|Function 1
81 isExtensible objectConstructorIsExtensible DontEnum|Function 1
82 is objectConstructorIs DontEnum|Function 2
83 assign objectConstructorAssign DontEnum|Function 2
84 @end
85 */
86
87 ObjectConstructor::ObjectConstructor(VM& vm, Structure* structure)
88 : InternalFunction(vm, structure)
89 {
90 }
91
92 void ObjectConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject, ObjectPrototype* objectPrototype)
93 {
94 Base::finishCreation(vm, objectPrototype->classInfo()->className);
95 // ECMA 15.2.3.1
96 putDirectWithoutTransition(vm, vm.propertyNames->prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
97 // no. of arguments for constructor
98 putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
99
100 if (!globalObject->runtimeFlags().isSymbolDisabled())
101 JSC_NATIVE_FUNCTION("getOwnPropertySymbols", objectConstructorGetOwnPropertySymbols, DontEnum, 1);
102
103 JSC_NATIVE_FUNCTION(vm.propertyNames->getPrototypeOfPrivateName, objectConstructorGetPrototypeOf, DontEnum, 1);
104 JSC_NATIVE_FUNCTION(vm.propertyNames->getOwnPropertyNamesPrivateName, objectConstructorGetOwnPropertyNames, DontEnum, 1);
105 }
106
107 JSFunction* ObjectConstructor::addDefineProperty(ExecState* exec, JSGlobalObject* globalObject)
108 {
109 VM& vm = exec->vm();
110 JSFunction* definePropertyFunction = JSFunction::create(vm, globalObject, 3, vm.propertyNames->defineProperty.string(), objectConstructorDefineProperty);
111 putDirectWithoutTransition(vm, vm.propertyNames->defineProperty, definePropertyFunction, DontEnum);
112 return definePropertyFunction;
113 }
114
115 bool ObjectConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
116 {
117 return getStaticFunctionSlot<JSObject>(exec, objectConstructorTable, jsCast<ObjectConstructor*>(object), propertyName, slot);
118 }
119
120 static ALWAYS_INLINE JSObject* constructObject(ExecState* exec)
121 {
122 JSGlobalObject* globalObject = exec->callee()->globalObject();
123 ArgList args(exec);
124 JSValue arg = args.at(0);
125 if (arg.isUndefinedOrNull())
126 return constructEmptyObject(exec, globalObject->objectPrototype());
127 return arg.toObject(exec, globalObject);
128 }
129
130 static EncodedJSValue JSC_HOST_CALL constructWithObjectConstructor(ExecState* exec)
131 {
132 return JSValue::encode(constructObject(exec));
133 }
134
135 ConstructType ObjectConstructor::getConstructData(JSCell*, ConstructData& constructData)
136 {
137 constructData.native.function = constructWithObjectConstructor;
138 return ConstructTypeHost;
139 }
140
141 static EncodedJSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec)
142 {
143 return JSValue::encode(constructObject(exec));
144 }
145
146 CallType ObjectConstructor::getCallData(JSCell*, CallData& callData)
147 {
148 callData.native.function = callObjectConstructor;
149 return CallTypeHost;
150 }
151
152 class ObjectConstructorGetPrototypeOfFunctor {
153 public:
154 ObjectConstructorGetPrototypeOfFunctor(JSObject* object)
155 : m_hasSkippedFirstFrame(false)
156 , m_object(object)
157 , m_result(JSValue::encode(jsUndefined()))
158 {
159 }
160
161 EncodedJSValue result() const { return m_result; }
162
163 StackVisitor::Status operator()(StackVisitor& visitor)
164 {
165 if (!m_hasSkippedFirstFrame) {
166 m_hasSkippedFirstFrame = true;
167 return StackVisitor::Continue;
168 }
169
170 if (m_object->allowsAccessFrom(visitor->callFrame()))
171 m_result = JSValue::encode(m_object->prototype());
172 return StackVisitor::Done;
173 }
174
175 private:
176 bool m_hasSkippedFirstFrame;
177 JSObject* m_object;
178 EncodedJSValue m_result;
179 };
180
181 EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec)
182 {
183 JSObject* object = exec->argument(0).toObject(exec);
184 if (exec->hadException())
185 return JSValue::encode(jsNull());
186 ObjectConstructorGetPrototypeOfFunctor functor(object);
187 exec->iterate(functor);
188 return functor.result();
189 }
190
191 EncodedJSValue JSC_HOST_CALL objectConstructorSetPrototypeOf(ExecState* exec)
192 {
193 JSValue objectValue = exec->argument(0);
194 if (objectValue.isUndefinedOrNull())
195 return throwVMTypeError(exec);
196
197 JSValue protoValue = exec->argument(1);
198 if (!protoValue.isObject() && !protoValue.isNull())
199 return throwVMTypeError(exec);
200
201 JSObject* object = objectValue.toObject(exec);
202 if (exec->hadException())
203 return JSValue::encode(objectValue);
204
205 if (!checkProtoSetterAccessAllowed(exec, object))
206 return JSValue::encode(objectValue);
207
208 if (!object->isExtensible())
209 return throwVMError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
210
211 if (!object->setPrototypeWithCycleCheck(exec, protoValue)) {
212 exec->vm().throwException(exec, createError(exec, ASCIILiteral("cyclic __proto__ value")));
213 return JSValue::encode(jsUndefined());
214 }
215
216 return JSValue::encode(objectValue);
217 }
218
219 EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec)
220 {
221 JSObject* object = exec->argument(0).toObject(exec);
222 if (exec->hadException())
223 return JSValue::encode(jsNull());
224 auto propertyName = exec->argument(1).toPropertyKey(exec);
225 if (exec->hadException())
226 return JSValue::encode(jsNull());
227 PropertyDescriptor descriptor;
228 if (!object->getOwnPropertyDescriptor(exec, propertyName, descriptor))
229 return JSValue::encode(jsUndefined());
230 if (exec->hadException())
231 return JSValue::encode(jsUndefined());
232
233 JSObject* description = constructEmptyObject(exec);
234 if (!descriptor.isAccessorDescriptor()) {
235 description->putDirect(exec->vm(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
236 description->putDirect(exec->vm(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
237 } else {
238 ASSERT(descriptor.getter());
239 ASSERT(descriptor.setter());
240 description->putDirect(exec->vm(), exec->propertyNames().get, descriptor.getter(), 0);
241 description->putDirect(exec->vm(), exec->propertyNames().set, descriptor.setter(), 0);
242 }
243
244 description->putDirect(exec->vm(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
245 description->putDirect(exec->vm(), exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
246
247 return JSValue::encode(description);
248 }
249
250 // FIXME: Use the enumeration cache.
251 EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exec)
252 {
253 JSObject* object = exec->argument(0).toObject(exec);
254 if (exec->hadException())
255 return JSValue::encode(jsNull());
256 PropertyNameArray properties(exec);
257 object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
258 JSArray* names = constructEmptyArray(exec, 0);
259 size_t numProperties = properties.size();
260 for (size_t i = 0; i < numProperties; i++)
261 names->push(exec, jsOwnedString(exec, properties[i].string()));
262 return JSValue::encode(names);
263 }
264
265 // FIXME: Use the enumeration cache.
266 EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertySymbols(ExecState* exec)
267 {
268 JSObject* object = exec->argument(0).toObject(exec);
269 if (exec->hadException())
270 return JSValue::encode(jsNull());
271 PropertyNameArray properties(exec);
272 object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
273 JSArray* names = constructEmptyArray(exec, 0);
274 size_t numProperties = properties.size();
275 for (size_t i = 0; i < numProperties; i++) {
276 auto impl = properties[i].impl();
277 if (impl->isSymbol() && !exec->propertyNames().isPrivateName(*impl))
278 names->push(exec, Symbol::create(exec->vm(), static_cast<SymbolImpl&>(*impl)));
279 }
280 return JSValue::encode(names);
281 }
282
283 // FIXME: Use the enumeration cache.
284 EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec)
285 {
286 JSObject* object = exec->argument(0).toObject(exec);
287 if (exec->hadException())
288 return JSValue::encode(jsNull());
289 PropertyNameArray properties(exec);
290 object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode());
291 JSArray* keys = constructEmptyArray(exec, 0);
292 size_t numProperties = properties.size();
293 for (size_t i = 0; i < numProperties; i++)
294 keys->push(exec, jsOwnedString(exec, properties[i].string()));
295 return JSValue::encode(keys);
296 }
297
298 // ES5 8.10.5 ToPropertyDescriptor
299 static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
300 {
301 if (!in.isObject()) {
302 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Property description must be an object.")));
303 return false;
304 }
305 JSObject* description = asObject(in);
306
307 PropertySlot enumerableSlot(description);
308 if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) {
309 desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec));
310 if (exec->hadException())
311 return false;
312 }
313
314 PropertySlot configurableSlot(description);
315 if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) {
316 desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec));
317 if (exec->hadException())
318 return false;
319 }
320
321 JSValue value;
322 PropertySlot valueSlot(description);
323 if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) {
324 desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value));
325 if (exec->hadException())
326 return false;
327 }
328
329 PropertySlot writableSlot(description);
330 if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) {
331 desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec));
332 if (exec->hadException())
333 return false;
334 }
335
336 PropertySlot getSlot(description);
337 if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) {
338 JSValue get = getSlot.getValue(exec, exec->propertyNames().get);
339 if (exec->hadException())
340 return false;
341 if (!get.isUndefined()) {
342 CallData callData;
343 if (getCallData(get, callData) == CallTypeNone) {
344 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Getter must be a function.")));
345 return false;
346 }
347 }
348 desc.setGetter(get);
349 }
350
351 PropertySlot setSlot(description);
352 if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) {
353 JSValue set = setSlot.getValue(exec, exec->propertyNames().set);
354 if (exec->hadException())
355 return false;
356 if (!set.isUndefined()) {
357 CallData callData;
358 if (getCallData(set, callData) == CallTypeNone) {
359 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Setter must be a function.")));
360 return false;
361 }
362 }
363 desc.setSetter(set);
364 }
365
366 if (!desc.isAccessorDescriptor())
367 return true;
368
369 if (desc.value()) {
370 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Invalid property. 'value' present on property with getter or setter.")));
371 return false;
372 }
373
374 if (desc.writablePresent()) {
375 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Invalid property. 'writable' present on property with getter or setter.")));
376 return false;
377 }
378 return true;
379 }
380
381 EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
382 {
383 if (!exec->argument(0).isObject())
384 return throwVMError(exec, createTypeError(exec, ASCIILiteral("Properties can only be defined on Objects.")));
385 JSObject* O = asObject(exec->argument(0));
386 auto propertyName = exec->argument(1).toPropertyKey(exec);
387 if (exec->hadException())
388 return JSValue::encode(jsNull());
389 PropertyDescriptor descriptor;
390 if (!toPropertyDescriptor(exec, exec->argument(2), descriptor))
391 return JSValue::encode(jsNull());
392 ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
393 ASSERT(!exec->hadException());
394 O->methodTable(exec->vm())->defineOwnProperty(O, exec, propertyName, descriptor, true);
395 return JSValue::encode(O);
396 }
397
398 static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
399 {
400 PropertyNameArray propertyNames(exec);
401 asObject(properties)->methodTable(exec->vm())->getOwnPropertyNames(asObject(properties), exec, propertyNames, EnumerationMode(DontEnumPropertiesMode::Exclude, SymbolPropertiesMode::Include));
402 size_t numProperties = propertyNames.size();
403 Vector<PropertyDescriptor> descriptors;
404 MarkedArgumentBuffer markBuffer;
405 for (size_t i = 0; i < numProperties; i++) {
406 JSValue prop = properties->get(exec, propertyNames[i]);
407 if (exec->hadException())
408 return jsNull();
409 PropertyDescriptor descriptor;
410 if (!toPropertyDescriptor(exec, prop, descriptor))
411 return jsNull();
412 descriptors.append(descriptor);
413 // Ensure we mark all the values that we're accumulating
414 if (descriptor.isDataDescriptor() && descriptor.value())
415 markBuffer.append(descriptor.value());
416 if (descriptor.isAccessorDescriptor()) {
417 if (descriptor.getter())
418 markBuffer.append(descriptor.getter());
419 if (descriptor.setter())
420 markBuffer.append(descriptor.setter());
421 }
422 }
423 for (size_t i = 0; i < numProperties; i++) {
424 Identifier propertyName = propertyNames[i];
425 if (exec->propertyNames().isPrivateName(propertyName))
426 continue;
427 object->methodTable(exec->vm())->defineOwnProperty(object, exec, propertyName, descriptors[i], true);
428 if (exec->hadException())
429 return jsNull();
430 }
431 return object;
432 }
433
434 EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec)
435 {
436 if (!exec->argument(0).isObject())
437 return throwVMError(exec, createTypeError(exec, ASCIILiteral("Properties can only be defined on Objects.")));
438 return JSValue::encode(defineProperties(exec, asObject(exec->argument(0)), exec->argument(1).toObject(exec)));
439 }
440
441 EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
442 {
443 JSValue proto = exec->argument(0);
444 if (!proto.isObject() && !proto.isNull())
445 return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object prototype may only be an Object or null.")));
446 JSObject* newObject = proto.isObject()
447 ? constructEmptyObject(exec, asObject(proto))
448 : constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
449 if (exec->argument(1).isUndefined())
450 return JSValue::encode(newObject);
451 if (!exec->argument(1).isObject())
452 return throwVMError(exec, createTypeError(exec, ASCIILiteral("Property descriptor list must be an Object.")));
453 return JSValue::encode(defineProperties(exec, newObject, asObject(exec->argument(1))));
454 }
455
456 EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
457 {
458 // 1. If Type(O) is not Object, return O.
459 JSValue obj = exec->argument(0);
460 if (!obj.isObject())
461 return JSValue::encode(obj);
462 JSObject* object = asObject(obj);
463
464 if (isJSFinalObject(object)) {
465 object->seal(exec->vm());
466 return JSValue::encode(obj);
467 }
468
469 // 2. For each named own property name P of O,
470 PropertyNameArray properties(exec);
471 object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
472 PropertyNameArray::const_iterator end = properties.end();
473 for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
474 Identifier propertyName = *iter;
475 if (exec->propertyNames().isPrivateName(propertyName))
476 continue;
477 // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
478 PropertyDescriptor desc;
479 if (!object->getOwnPropertyDescriptor(exec, propertyName, desc))
480 continue;
481 // b. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
482 desc.setConfigurable(false);
483 // c. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
484 object->methodTable(exec->vm())->defineOwnProperty(object, exec, propertyName, desc, true);
485 if (exec->hadException())
486 return JSValue::encode(obj);
487 }
488
489 // 3. Set the [[Extensible]] internal property of O to false.
490 object->preventExtensions(exec->vm());
491
492 // 4. Return O.
493 return JSValue::encode(obj);
494 }
495
496 JSObject* objectConstructorFreeze(ExecState* exec, JSObject* object)
497 {
498 if (isJSFinalObject(object) && !hasIndexedProperties(object->indexingType())) {
499 object->freeze(exec->vm());
500 return object;
501 }
502
503 // 2. For each named own property name P of O,
504 PropertyNameArray properties(exec);
505 object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
506 PropertyNameArray::const_iterator end = properties.end();
507 for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
508 Identifier propertyName = *iter;
509 if (exec->propertyNames().isPrivateName(propertyName))
510 continue;
511 // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
512 PropertyDescriptor desc;
513 if (!object->getOwnPropertyDescriptor(exec, propertyName, desc))
514 continue;
515 // b. If IsDataDescriptor(desc) is true, then
516 // i. If desc.[[Writable]] is true, set desc.[[Writable]] to false.
517 if (desc.isDataDescriptor())
518 desc.setWritable(false);
519 // c. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
520 desc.setConfigurable(false);
521 // d. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
522 object->methodTable(exec->vm())->defineOwnProperty(object, exec, propertyName, desc, true);
523 if (exec->hadException())
524 return object;
525 }
526
527 // 3. Set the [[Extensible]] internal property of O to false.
528 object->preventExtensions(exec->vm());
529
530 // 4. Return O.
531 return object;
532 }
533
534 EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
535 {
536 // 1. If Type(O) is not Object, return O.
537 JSValue obj = exec->argument(0);
538 if (!obj.isObject())
539 return JSValue::encode(obj);
540 return JSValue::encode(objectConstructorFreeze(exec, asObject(obj)));
541 }
542
543 EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState* exec)
544 {
545 JSValue obj = exec->argument(0);
546 if (!obj.isObject())
547 return JSValue::encode(obj);
548 asObject(obj)->preventExtensions(exec->vm());
549 return JSValue::encode(obj);
550 }
551
552 EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
553 {
554 // 1. If Type(O) is not Object, return true.
555 JSValue obj = exec->argument(0);
556 if (!obj.isObject())
557 return JSValue::encode(jsBoolean(true));
558 JSObject* object = asObject(obj);
559
560 if (isJSFinalObject(object))
561 return JSValue::encode(jsBoolean(object->isSealed(exec->vm())));
562
563 // 2. For each named own property name P of O,
564 PropertyNameArray properties(exec);
565 object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
566 PropertyNameArray::const_iterator end = properties.end();
567 for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
568 Identifier propertyName = *iter;
569 if (exec->propertyNames().isPrivateName(propertyName))
570 continue;
571 // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
572 PropertyDescriptor desc;
573 if (!object->getOwnPropertyDescriptor(exec, propertyName, desc))
574 continue;
575 // b. If desc.[[Configurable]] is true, then return false.
576 if (desc.configurable())
577 return JSValue::encode(jsBoolean(false));
578 }
579
580 // 3. If the [[Extensible]] internal property of O is false, then return true.
581 // 4. Otherwise, return false.
582 return JSValue::encode(jsBoolean(!object->isExtensible()));
583 }
584
585 EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
586 {
587 // 1. If Type(O) is not Object, return true.
588 JSValue obj = exec->argument(0);
589 if (!obj.isObject())
590 return JSValue::encode(jsBoolean(true));
591 JSObject* object = asObject(obj);
592
593 if (isJSFinalObject(object))
594 return JSValue::encode(jsBoolean(object->isFrozen(exec->vm())));
595
596 // 2. For each named own property name P of O,
597 PropertyNameArray properties(exec);
598 object->methodTable(exec->vm())->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include, SymbolPropertiesMode::Include));
599 PropertyNameArray::const_iterator end = properties.end();
600 for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
601 Identifier propertyName = *iter;
602 if (exec->propertyNames().isPrivateName(propertyName))
603 continue;
604 // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
605 PropertyDescriptor desc;
606 if (!object->getOwnPropertyDescriptor(exec, propertyName, desc))
607 continue;
608 // b. If IsDataDescriptor(desc) is true then
609 // i. If desc.[[Writable]] is true, return false. c. If desc.[[Configurable]] is true, then return false.
610 if ((desc.isDataDescriptor() && desc.writable()) || desc.configurable())
611 return JSValue::encode(jsBoolean(false));
612 }
613
614 // 3. If the [[Extensible]] internal property of O is false, then return true.
615 // 4. Otherwise, return false.
616 return JSValue::encode(jsBoolean(!object->isExtensible()));
617 }
618
619 EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec)
620 {
621 JSValue obj = exec->argument(0);
622 if (!obj.isObject())
623 return JSValue::encode(jsBoolean(false));
624 return JSValue::encode(jsBoolean(asObject(obj)->isExtensible()));
625 }
626
627 EncodedJSValue JSC_HOST_CALL objectConstructorIs(ExecState* exec)
628 {
629 return JSValue::encode(jsBoolean(sameValue(exec, exec->argument(0), exec->argument(1))));
630 }
631
632 } // namespace JSC