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