21d6e59af83f753934186c6edc9dc009d5676440
[WebKit-https.git] / Source / JavaScriptCore / 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 "CallFrameInlines.h"
26 #include "CopiedSpaceInlines.h"
27 #include "Error.h"
28 #include "ExceptionHelpers.h"
29 #include "JSFunction.h"
30 #include "JSArray.h"
31 #include "JSGlobalObject.h"
32 #include "Lookup.h"
33 #include "ObjectPrototype.h"
34 #include "Operations.h"
35 #include "PropertyDescriptor.h"
36 #include "PropertyNameArray.h"
37 #include "StackIterator.h"
38
39 namespace JSC {
40
41 static EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*);
42 static EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*);
43 static EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState*);
44 static EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState*);
45 static EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*);
46 static EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*);
47 static EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState*);
48 static EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState*);
49 static EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState*);
50 static EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState*);
51 static EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState*);
52 static EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState*);
53 static EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState*);
54
55 }
56
57 #include "ObjectConstructor.lut.h"
58
59 namespace JSC {
60
61 ASSERT_HAS_TRIVIAL_DESTRUCTOR(ObjectConstructor);
62
63 const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::objectConstructorTable, CREATE_METHOD_TABLE(ObjectConstructor) };
64
65 /* Source for ObjectConstructor.lut.h
66 @begin objectConstructorTable
67   getPrototypeOf            objectConstructorGetPrototypeOf             DontEnum|Function 1
68   getOwnPropertyDescriptor  objectConstructorGetOwnPropertyDescriptor   DontEnum|Function 2
69   getOwnPropertyNames       objectConstructorGetOwnPropertyNames        DontEnum|Function 1
70   keys                      objectConstructorKeys                       DontEnum|Function 1
71   defineProperty            objectConstructorDefineProperty             DontEnum|Function 3
72   defineProperties          objectConstructorDefineProperties           DontEnum|Function 2
73   create                    objectConstructorCreate                     DontEnum|Function 2
74   seal                      objectConstructorSeal                       DontEnum|Function 1
75   freeze                    objectConstructorFreeze                     DontEnum|Function 1
76   preventExtensions         objectConstructorPreventExtensions          DontEnum|Function 1
77   isSealed                  objectConstructorIsSealed                   DontEnum|Function 1
78   isFrozen                  objectConstructorIsFrozen                   DontEnum|Function 1
79   isExtensible              objectConstructorIsExtensible               DontEnum|Function 1
80 @end
81 */
82
83 ObjectConstructor::ObjectConstructor(JSGlobalObject* globalObject, Structure* structure)
84     : InternalFunction(globalObject, structure)
85 {
86 }
87
88 void ObjectConstructor::finishCreation(ExecState* exec, ObjectPrototype* objectPrototype)
89 {
90     Base::finishCreation(exec->vm(), Identifier(exec, "Object").string());
91     // ECMA 15.2.3.1
92     putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
93     // no. of arguments for constructor
94     putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
95 }
96
97 bool ObjectConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
98 {
99     return getStaticFunctionSlot<JSObject>(exec, ExecState::objectConstructorTable(exec), jsCast<ObjectConstructor*>(object), propertyName, slot);
100 }
101
102 static ALWAYS_INLINE JSObject* constructObject(ExecState* exec)
103 {
104     JSGlobalObject* globalObject = exec->callee()->globalObject();
105     ArgList args(exec);
106     JSValue arg = args.at(0);
107     if (arg.isUndefinedOrNull())
108         return constructEmptyObject(exec, globalObject->objectPrototype());
109     return arg.toObject(exec, globalObject);
110 }
111
112 static EncodedJSValue JSC_HOST_CALL constructWithObjectConstructor(ExecState* exec)
113 {
114     return JSValue::encode(constructObject(exec));
115 }
116
117 ConstructType ObjectConstructor::getConstructData(JSCell*, ConstructData& constructData)
118 {
119     constructData.native.function = constructWithObjectConstructor;
120     return ConstructTypeHost;
121 }
122
123 static EncodedJSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec)
124 {
125     return JSValue::encode(constructObject(exec));
126 }
127
128 CallType ObjectConstructor::getCallData(JSCell*, CallData& callData)
129 {
130     callData.native.function = callObjectConstructor;
131     return CallTypeHost;
132 }
133
134 EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec)
135 {
136     if (!exec->argument(0).isObject())
137         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested prototype of a value that is not an object.")));
138     JSObject* object = asObject(exec->argument(0));
139     StackIterator iter = exec->begin();
140     ++iter;
141     if ((iter == exec->end()) || !object->allowsAccessFrom(iter->callFrame()))
142         return JSValue::encode(jsUndefined());
143     return JSValue::encode(object->prototype());
144 }
145
146 EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec)
147 {
148     if (!exec->argument(0).isObject())
149         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested property descriptor of a value that is not an object.")));
150     String propertyName = exec->argument(1).toString(exec)->value(exec);
151     if (exec->hadException())
152         return JSValue::encode(jsNull());
153     JSObject* object = asObject(exec->argument(0));
154     PropertyDescriptor descriptor;
155     if (!object->getOwnPropertyDescriptor(exec, Identifier(exec, propertyName), descriptor))
156         return JSValue::encode(jsUndefined());
157     if (exec->hadException())
158         return JSValue::encode(jsUndefined());
159
160     JSObject* description = constructEmptyObject(exec);
161     if (!descriptor.isAccessorDescriptor()) {
162         description->putDirect(exec->vm(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
163         description->putDirect(exec->vm(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
164     } else {
165         ASSERT(descriptor.getter());
166         ASSERT(descriptor.setter());
167         description->putDirect(exec->vm(), exec->propertyNames().get, descriptor.getter(), 0);
168         description->putDirect(exec->vm(), exec->propertyNames().set, descriptor.setter(), 0);
169     }
170     
171     description->putDirect(exec->vm(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
172     description->putDirect(exec->vm(), exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
173
174     return JSValue::encode(description);
175 }
176
177 // FIXME: Use the enumeration cache.
178 EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exec)
179 {
180     if (!exec->argument(0).isObject())
181         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested property names of a value that is not an object.")));
182     PropertyNameArray properties(exec);
183     asObject(exec->argument(0))->methodTable()->getOwnPropertyNames(asObject(exec->argument(0)), exec, properties, IncludeDontEnumProperties);
184     JSArray* names = constructEmptyArray(exec, 0);
185     size_t numProperties = properties.size();
186     for (size_t i = 0; i < numProperties; i++)
187         names->push(exec, jsOwnedString(exec, properties[i].string()));
188     return JSValue::encode(names);
189 }
190
191 // FIXME: Use the enumeration cache.
192 EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec)
193 {
194     if (!exec->argument(0).isObject())
195         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested keys of a value that is not an object.")));
196     PropertyNameArray properties(exec);
197     asObject(exec->argument(0))->methodTable()->getOwnPropertyNames(asObject(exec->argument(0)), exec, properties, ExcludeDontEnumProperties);
198     JSArray* keys = constructEmptyArray(exec, 0);
199     size_t numProperties = properties.size();
200     for (size_t i = 0; i < numProperties; i++)
201         keys->push(exec, jsOwnedString(exec, properties[i].string()));
202     return JSValue::encode(keys);
203 }
204
205 // ES5 8.10.5 ToPropertyDescriptor
206 static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
207 {
208     if (!in.isObject()) {
209         throwError(exec, createTypeError(exec, ASCIILiteral("Property description must be an object.")));
210         return false;
211     }
212     JSObject* description = asObject(in);
213
214     PropertySlot enumerableSlot(description);
215     if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) {
216         desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec));
217         if (exec->hadException())
218             return false;
219     }
220
221     PropertySlot configurableSlot(description);
222     if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) {
223         desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec));
224         if (exec->hadException())
225             return false;
226     }
227
228     JSValue value;
229     PropertySlot valueSlot(description);
230     if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) {
231         desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value));
232         if (exec->hadException())
233             return false;
234     }
235
236     PropertySlot writableSlot(description);
237     if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) {
238         desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec));
239         if (exec->hadException())
240             return false;
241     }
242
243     PropertySlot getSlot(description);
244     if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) {
245         JSValue get = getSlot.getValue(exec, exec->propertyNames().get);
246         if (exec->hadException())
247             return false;
248         if (!get.isUndefined()) {
249             CallData callData;
250             if (getCallData(get, callData) == CallTypeNone) {
251                 throwError(exec, createTypeError(exec, ASCIILiteral("Getter must be a function.")));
252                 return false;
253             }
254         }
255         desc.setGetter(get);
256     }
257
258     PropertySlot setSlot(description);
259     if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) {
260         JSValue set = setSlot.getValue(exec, exec->propertyNames().set);
261         if (exec->hadException())
262             return false;
263         if (!set.isUndefined()) {
264             CallData callData;
265             if (getCallData(set, callData) == CallTypeNone) {
266                 throwError(exec, createTypeError(exec, ASCIILiteral("Setter must be a function.")));
267                 return false;
268             }
269         }
270         desc.setSetter(set);
271     }
272
273     if (!desc.isAccessorDescriptor())
274         return true;
275
276     if (desc.value()) {
277         throwError(exec, createTypeError(exec, ASCIILiteral("Invalid property.  'value' present on property with getter or setter.")));
278         return false;
279     }
280
281     if (desc.writablePresent()) {
282         throwError(exec, createTypeError(exec, ASCIILiteral("Invalid property.  'writable' present on property with getter or setter.")));
283         return false;
284     }
285     return true;
286 }
287
288 EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
289 {
290     if (!exec->argument(0).isObject())
291         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Properties can only be defined on Objects.")));
292     JSObject* O = asObject(exec->argument(0));
293     String propertyName = exec->argument(1).toString(exec)->value(exec);
294     if (exec->hadException())
295         return JSValue::encode(jsNull());
296     PropertyDescriptor descriptor;
297     if (!toPropertyDescriptor(exec, exec->argument(2), descriptor))
298         return JSValue::encode(jsNull());
299     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
300     ASSERT(!exec->hadException());
301     O->methodTable()->defineOwnProperty(O, exec, Identifier(exec, propertyName), descriptor, true);
302     return JSValue::encode(O);
303 }
304
305 static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
306 {
307     PropertyNameArray propertyNames(exec);
308     asObject(properties)->methodTable()->getOwnPropertyNames(asObject(properties), exec, propertyNames, ExcludeDontEnumProperties);
309     size_t numProperties = propertyNames.size();
310     Vector<PropertyDescriptor> descriptors;
311     MarkedArgumentBuffer markBuffer;
312     for (size_t i = 0; i < numProperties; i++) {
313         JSValue prop = properties->get(exec, propertyNames[i]);
314         if (exec->hadException())
315             return jsNull();
316         PropertyDescriptor descriptor;
317         if (!toPropertyDescriptor(exec, prop, descriptor))
318             return jsNull();
319         descriptors.append(descriptor);
320         // Ensure we mark all the values that we're accumulating
321         if (descriptor.isDataDescriptor() && descriptor.value())
322             markBuffer.append(descriptor.value());
323         if (descriptor.isAccessorDescriptor()) {
324             if (descriptor.getter())
325                 markBuffer.append(descriptor.getter());
326             if (descriptor.setter())
327                 markBuffer.append(descriptor.setter());
328         }
329     }
330     for (size_t i = 0; i < numProperties; i++) {
331         object->methodTable()->defineOwnProperty(object, exec, propertyNames[i], descriptors[i], true);
332         if (exec->hadException())
333             return jsNull();
334     }
335     return object;
336 }
337
338 EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec)
339 {
340     if (!exec->argument(0).isObject())
341         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Properties can only be defined on Objects.")));
342     return JSValue::encode(defineProperties(exec, asObject(exec->argument(0)), exec->argument(1).toObject(exec)));
343 }
344
345 EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
346 {
347     if (!exec->argument(0).isObject() && !exec->argument(0).isNull())
348         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object prototype may only be an Object or null.")));
349     JSValue proto = exec->argument(0);
350     JSObject* newObject = proto.isObject()
351         ? constructEmptyObject(exec, asObject(proto))
352         : constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
353     if (exec->argument(1).isUndefined())
354         return JSValue::encode(newObject);
355     if (!exec->argument(1).isObject())
356         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Property descriptor list must be an Object.")));
357     return JSValue::encode(defineProperties(exec, newObject, asObject(exec->argument(1))));
358 }
359
360 EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
361 {
362     // 1. If Type(O) is not Object throw a TypeError exception.
363     JSValue obj = exec->argument(0);
364     if (!obj.isObject())
365         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.seal can only be called on Objects.")));
366     JSObject* object = asObject(obj);
367
368     if (isJSFinalObject(object)) {
369         object->seal(exec->vm());
370         return JSValue::encode(obj);
371     }
372
373     // 2. For each named own property name P of O,
374     PropertyNameArray properties(exec);
375     object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
376     PropertyNameArray::const_iterator end = properties.end();
377     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
378         // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
379         PropertyDescriptor desc;
380         if (!object->getOwnPropertyDescriptor(exec, *iter, desc))
381             continue;
382         // b. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
383         desc.setConfigurable(false);
384         // c. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
385         object->methodTable()->defineOwnProperty(object, exec, *iter, desc, true);
386         if (exec->hadException())
387             return JSValue::encode(obj);
388     }
389
390     // 3. Set the [[Extensible]] internal property of O to false.
391     object->preventExtensions(exec->vm());
392
393     // 4. Return O.
394     return JSValue::encode(obj);
395 }
396
397 EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
398 {
399     // 1. If Type(O) is not Object throw a TypeError exception.
400     JSValue obj = exec->argument(0);
401     if (!obj.isObject())
402         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.freeze can only be called on Objects.")));
403     JSObject* object = asObject(obj);
404
405     if (isJSFinalObject(object) && !hasIndexedProperties(object->structure()->indexingType())) {
406         object->freeze(exec->vm());
407         return JSValue::encode(obj);
408     }
409
410     // 2. For each named own property name P of O,
411     PropertyNameArray properties(exec);
412     object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
413     PropertyNameArray::const_iterator end = properties.end();
414     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
415         // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
416         PropertyDescriptor desc;
417         if (!object->getOwnPropertyDescriptor(exec, *iter, desc))
418             continue;
419         // b. If IsDataDescriptor(desc) is true, then
420         // i. If desc.[[Writable]] is true, set desc.[[Writable]] to false.
421         if (desc.isDataDescriptor())
422             desc.setWritable(false);
423         // c. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
424         desc.setConfigurable(false);
425         // d. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
426         object->methodTable()->defineOwnProperty(object, exec, *iter, desc, true);
427         if (exec->hadException())
428             return JSValue::encode(obj);
429     }
430
431     // 3. Set the [[Extensible]] internal property of O to false.
432     object->preventExtensions(exec->vm());
433
434     // 4. Return O.
435     return JSValue::encode(obj);
436 }
437
438 EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState* exec)
439 {
440     JSValue obj = exec->argument(0);
441     if (!obj.isObject())
442         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.preventExtensions can only be called on Objects.")));
443     asObject(obj)->preventExtensions(exec->vm());
444     return JSValue::encode(obj);
445 }
446
447 EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
448 {
449     // 1. If Type(O) is not Object throw a TypeError exception.
450     JSValue obj = exec->argument(0);
451     if (!obj.isObject())
452         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.isSealed can only be called on Objects.")));
453     JSObject* object = asObject(obj);
454
455     if (isJSFinalObject(object))
456         return JSValue::encode(jsBoolean(object->isSealed(exec->vm())));
457
458     // 2. For each named own property name P of O,
459     PropertyNameArray properties(exec);
460     object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
461     PropertyNameArray::const_iterator end = properties.end();
462     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
463         // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
464         PropertyDescriptor desc;
465         if (!object->getOwnPropertyDescriptor(exec, *iter, desc))
466             continue;
467         // b. If desc.[[Configurable]] is true, then return false.
468         if (desc.configurable())
469             return JSValue::encode(jsBoolean(false));
470     }
471
472     // 3. If the [[Extensible]] internal property of O is false, then return true.
473     // 4. Otherwise, return false.
474     return JSValue::encode(jsBoolean(!object->isExtensible()));
475 }
476
477 EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
478 {
479     // 1. If Type(O) is not Object throw a TypeError exception.
480     JSValue obj = exec->argument(0);
481     if (!obj.isObject())
482         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.isFrozen can only be called on Objects.")));
483     JSObject* object = asObject(obj);
484
485     if (isJSFinalObject(object))
486         return JSValue::encode(jsBoolean(object->isFrozen(exec->vm())));
487
488     // 2. For each named own property name P of O,
489     PropertyNameArray properties(exec);
490     object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
491     PropertyNameArray::const_iterator end = properties.end();
492     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
493         // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
494         PropertyDescriptor desc;
495         if (!object->getOwnPropertyDescriptor(exec, *iter, desc))
496             continue;
497         // b. If IsDataDescriptor(desc) is true then
498         // i. If desc.[[Writable]] is true, return false. c. If desc.[[Configurable]] is true, then return false.
499         if ((desc.isDataDescriptor() && desc.writable()) || desc.configurable())
500             return JSValue::encode(jsBoolean(false));
501     }
502
503     // 3. If the [[Extensible]] internal property of O is false, then return true.
504     // 4. Otherwise, return false.
505     return JSValue::encode(jsBoolean(!object->isExtensible()));
506 }
507
508 EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec)
509 {
510     JSValue obj = exec->argument(0);
511     if (!obj.isObject())
512         return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.isExtensible can only be called on Objects.")));
513     return JSValue::encode(jsBoolean(asObject(obj)->isExtensible()));
514 }
515
516 } // namespace JSC