]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - API/JSObjectRef.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / API / JSObjectRef.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Kelvin W Sherlock (ksherlock@gmail.com)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "JSObjectRef.h"
29#include "JSObjectRefPrivate.h"
30
31#include "APICast.h"
32#include "ButterflyInlines.h"
33#include "CodeBlock.h"
34#include "CopiedSpaceInlines.h"
35#include "DateConstructor.h"
36#include "ErrorConstructor.h"
37#include "Exception.h"
38#include "FunctionConstructor.h"
39#include "Identifier.h"
40#include "InitializeThreading.h"
41#include "JSAPIWrapperObject.h"
42#include "JSArray.h"
43#include "JSCallbackConstructor.h"
44#include "JSCallbackFunction.h"
45#include "JSCallbackObject.h"
46#include "JSClassRef.h"
47#include "JSFunction.h"
48#include "JSGlobalObject.h"
49#include "JSObject.h"
50#include "JSRetainPtr.h"
51#include "JSString.h"
52#include "JSValueRef.h"
53#include "ObjectConstructor.h"
54#include "ObjectPrototype.h"
55#include "JSCInlines.h"
56#include "PropertyNameArray.h"
57#include "RegExpConstructor.h"
58
59#if ENABLE(REMOTE_INSPECTOR)
60#include "JSGlobalObjectInspectorController.h"
61#endif
62
63using namespace JSC;
64
65enum class ExceptionStatus {
66 DidThrow,
67 DidNotThrow
68};
69
70static ExceptionStatus handleExceptionIfNeeded(ExecState* exec, JSValueRef* returnedExceptionRef)
71{
72 if (exec->hadException()) {
73 Exception* exception = exec->exception();
74 if (returnedExceptionRef)
75 *returnedExceptionRef = toRef(exec, exception->value());
76 exec->clearException();
77#if ENABLE(REMOTE_INSPECTOR)
78 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception);
79#endif
80 return ExceptionStatus::DidThrow;
81 }
82 return ExceptionStatus::DidNotThrow;
83}
84
85JSClassRef JSClassCreate(const JSClassDefinition* definition)
86{
87 initializeThreading();
88 RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
89 ? OpaqueJSClass::createNoAutomaticPrototype(definition)
90 : OpaqueJSClass::create(definition);
91
92 return jsClass.release().leakRef();
93}
94
95JSClassRef JSClassRetain(JSClassRef jsClass)
96{
97 jsClass->ref();
98 return jsClass;
99}
100
101void JSClassRelease(JSClassRef jsClass)
102{
103 jsClass->deref();
104}
105
106JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
107{
108 if (!ctx) {
109 ASSERT_NOT_REACHED();
110 return 0;
111 }
112 ExecState* exec = toJS(ctx);
113 JSLockHolder locker(exec);
114
115 if (!jsClass)
116 return toRef(constructEmptyObject(exec));
117
118 JSCallbackObject<JSDestructibleObject>* object = JSCallbackObject<JSDestructibleObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
119 if (JSObject* prototype = jsClass->prototype(exec))
120 object->setPrototype(exec->vm(), prototype);
121
122 return toRef(object);
123}
124
125JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
126{
127 if (!ctx) {
128 ASSERT_NOT_REACHED();
129 return 0;
130 }
131 ExecState* exec = toJS(ctx);
132 JSLockHolder locker(exec);
133 return toRef(JSCallbackFunction::create(exec->vm(), exec->lexicalGlobalObject(), callAsFunction, name ? name->string() : ASCIILiteral("anonymous")));
134}
135
136JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
137{
138 if (!ctx) {
139 ASSERT_NOT_REACHED();
140 return 0;
141 }
142 ExecState* exec = toJS(ctx);
143 JSLockHolder locker(exec);
144
145 JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0;
146 if (!jsPrototype)
147 jsPrototype = exec->lexicalGlobalObject()->objectPrototype();
148
149 JSCallbackConstructor* constructor = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
150 constructor->putDirect(exec->vm(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
151 return toRef(constructor);
152}
153
154JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
155{
156 if (!ctx) {
157 ASSERT_NOT_REACHED();
158 return 0;
159 }
160 ExecState* exec = toJS(ctx);
161 JSLockHolder locker(exec);
162
163 startingLineNumber = std::max(1, startingLineNumber);
164 Identifier nameID = name ? name->identifier(&exec->vm()) : Identifier::fromString(exec, "anonymous");
165
166 MarkedArgumentBuffer args;
167 for (unsigned i = 0; i < parameterCount; i++)
168 args.append(jsString(exec, parameterNames[i]->string()));
169 args.append(jsString(exec, body->string()));
170
171 JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL ? sourceURL->string() : String(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
172 if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
173 result = 0;
174 return toRef(result);
175}
176
177JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
178{
179 if (!ctx) {
180 ASSERT_NOT_REACHED();
181 return 0;
182 }
183 ExecState* exec = toJS(ctx);
184 JSLockHolder locker(exec);
185
186 JSObject* result;
187 if (argumentCount) {
188 MarkedArgumentBuffer argList;
189 for (size_t i = 0; i < argumentCount; ++i)
190 argList.append(toJS(exec, arguments[i]));
191
192 result = constructArray(exec, static_cast<ArrayAllocationProfile*>(0), argList);
193 } else
194 result = constructEmptyArray(exec, 0);
195
196 if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
197 result = 0;
198
199 return toRef(result);
200}
201
202JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
203{
204 if (!ctx) {
205 ASSERT_NOT_REACHED();
206 return 0;
207 }
208 ExecState* exec = toJS(ctx);
209 JSLockHolder locker(exec);
210
211 MarkedArgumentBuffer argList;
212 for (size_t i = 0; i < argumentCount; ++i)
213 argList.append(toJS(exec, arguments[i]));
214
215 JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList);
216 if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
217 result = 0;
218
219 return toRef(result);
220}
221
222JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
223{
224 if (!ctx) {
225 ASSERT_NOT_REACHED();
226 return 0;
227 }
228 ExecState* exec = toJS(ctx);
229 JSLockHolder locker(exec);
230
231 JSValue message = argumentCount ? toJS(exec, arguments[0]) : jsUndefined();
232 Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure();
233 JSObject* result = ErrorInstance::create(exec, errorStructure, message);
234
235 if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
236 result = 0;
237
238 return toRef(result);
239}
240
241JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
242{
243 if (!ctx) {
244 ASSERT_NOT_REACHED();
245 return 0;
246 }
247 ExecState* exec = toJS(ctx);
248 JSLockHolder locker(exec);
249
250 MarkedArgumentBuffer argList;
251 for (size_t i = 0; i < argumentCount; ++i)
252 argList.append(toJS(exec, arguments[i]));
253
254 JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(), argList);
255 if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
256 result = 0;
257
258 return toRef(result);
259}
260
261JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
262{
263 if (!ctx) {
264 ASSERT_NOT_REACHED();
265 return 0;
266 }
267 ExecState* exec = toJS(ctx);
268 JSLockHolder locker(exec);
269
270 JSObject* jsObject = toJS(object);
271 return toRef(exec, jsObject->prototype());
272}
273
274void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
275{
276 if (!ctx) {
277 ASSERT_NOT_REACHED();
278 return;
279 }
280 ExecState* exec = toJS(ctx);
281 JSLockHolder locker(exec);
282
283 JSObject* jsObject = toJS(object);
284 JSValue jsValue = toJS(exec, value);
285
286 if (JSProxy* proxy = jsDynamicCast<JSProxy*>(jsObject)) {
287 if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(proxy->target())) {
288 globalObject->resetPrototype(exec->vm(), jsValue.isObject() ? jsValue : jsNull());
289 return;
290 }
291 // Someday we might use proxies for something other than JSGlobalObjects, but today is not that day.
292 RELEASE_ASSERT_NOT_REACHED();
293 }
294 jsObject->setPrototypeWithCycleCheck(exec, jsValue.isObject() ? jsValue : jsNull());
295}
296
297bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
298{
299 if (!ctx) {
300 ASSERT_NOT_REACHED();
301 return false;
302 }
303 ExecState* exec = toJS(ctx);
304 JSLockHolder locker(exec);
305
306 JSObject* jsObject = toJS(object);
307
308 return jsObject->hasProperty(exec, propertyName->identifier(&exec->vm()));
309}
310
311JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
312{
313 if (!ctx) {
314 ASSERT_NOT_REACHED();
315 return 0;
316 }
317 ExecState* exec = toJS(ctx);
318 JSLockHolder locker(exec);
319
320 JSObject* jsObject = toJS(object);
321
322 JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->vm()));
323 handleExceptionIfNeeded(exec, exception);
324 return toRef(exec, jsValue);
325}
326
327void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
328{
329 if (!ctx) {
330 ASSERT_NOT_REACHED();
331 return;
332 }
333 ExecState* exec = toJS(ctx);
334 JSLockHolder locker(exec);
335
336 JSObject* jsObject = toJS(object);
337 Identifier name(propertyName->identifier(&exec->vm()));
338 JSValue jsValue = toJS(exec, value);
339
340 if (attributes && !jsObject->hasProperty(exec, name)) {
341 PropertyDescriptor desc(jsValue, attributes);
342 jsObject->methodTable()->defineOwnProperty(jsObject, exec, name, desc, false);
343 } else {
344 PutPropertySlot slot(jsObject);
345 jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot);
346 }
347
348 handleExceptionIfNeeded(exec, exception);
349}
350
351JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
352{
353 if (!ctx) {
354 ASSERT_NOT_REACHED();
355 return 0;
356 }
357 ExecState* exec = toJS(ctx);
358 JSLockHolder locker(exec);
359
360 JSObject* jsObject = toJS(object);
361
362 JSValue jsValue = jsObject->get(exec, propertyIndex);
363 handleExceptionIfNeeded(exec, exception);
364 return toRef(exec, jsValue);
365}
366
367
368void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
369{
370 if (!ctx) {
371 ASSERT_NOT_REACHED();
372 return;
373 }
374 ExecState* exec = toJS(ctx);
375 JSLockHolder locker(exec);
376
377 JSObject* jsObject = toJS(object);
378 JSValue jsValue = toJS(exec, value);
379
380 jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue, false);
381 handleExceptionIfNeeded(exec, exception);
382}
383
384bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
385{
386 if (!ctx) {
387 ASSERT_NOT_REACHED();
388 return false;
389 }
390 ExecState* exec = toJS(ctx);
391 JSLockHolder locker(exec);
392
393 JSObject* jsObject = toJS(object);
394
395 bool result = jsObject->methodTable()->deleteProperty(jsObject, exec, propertyName->identifier(&exec->vm()));
396 handleExceptionIfNeeded(exec, exception);
397 return result;
398}
399
400void* JSObjectGetPrivate(JSObjectRef object)
401{
402 JSObject* jsObject = uncheckedToJS(object);
403
404 // Get wrapped object if proxied
405 if (jsObject->inherits(JSProxy::info()))
406 jsObject = jsCast<JSProxy*>(jsObject)->target();
407
408 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info()))
409 return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
410 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info()))
411 return jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivate();
412#if JSC_OBJC_API_ENABLED
413 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info()))
414 return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivate();
415#endif
416
417 return 0;
418}
419
420bool JSObjectSetPrivate(JSObjectRef object, void* data)
421{
422 JSObject* jsObject = uncheckedToJS(object);
423
424 // Get wrapped object if proxied
425 if (jsObject->inherits(JSProxy::info()))
426 jsObject = jsCast<JSProxy*>(jsObject)->target();
427
428 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
429 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
430 return true;
431 }
432 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
433 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivate(data);
434 return true;
435 }
436#if JSC_OBJC_API_ENABLED
437 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
438 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivate(data);
439 return true;
440 }
441#endif
442
443 return false;
444}
445
446JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
447{
448 ExecState* exec = toJS(ctx);
449 JSLockHolder locker(exec);
450 JSObject* jsObject = toJS(object);
451 JSValue result;
452 Identifier name(propertyName->identifier(&exec->vm()));
453
454 // Get wrapped object if proxied
455 if (jsObject->inherits(JSProxy::info()))
456 jsObject = jsCast<JSProxy*>(jsObject)->target();
457
458 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info()))
459 result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
460 else if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info()))
461 result = jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivateProperty(name);
462#if JSC_OBJC_API_ENABLED
463 else if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info()))
464 result = jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivateProperty(name);
465#endif
466 return toRef(exec, result);
467}
468
469bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value)
470{
471 ExecState* exec = toJS(ctx);
472 JSLockHolder locker(exec);
473 JSObject* jsObject = toJS(object);
474 JSValue jsValue = value ? toJS(exec, value) : JSValue();
475 Identifier name(propertyName->identifier(&exec->vm()));
476
477 // Get wrapped object if proxied
478 if (jsObject->inherits(JSProxy::info()))
479 jsObject = jsCast<JSProxy*>(jsObject)->target();
480
481 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
482 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
483 return true;
484 }
485 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
486 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
487 return true;
488 }
489#if JSC_OBJC_API_ENABLED
490 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
491 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
492 return true;
493 }
494#endif
495 return false;
496}
497
498bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
499{
500 ExecState* exec = toJS(ctx);
501 JSLockHolder locker(exec);
502 JSObject* jsObject = toJS(object);
503 Identifier name(propertyName->identifier(&exec->vm()));
504
505 // Get wrapped object if proxied
506 if (jsObject->inherits(JSProxy::info()))
507 jsObject = jsCast<JSProxy*>(jsObject)->target();
508
509 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
510 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
511 return true;
512 }
513 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
514 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->deletePrivateProperty(name);
515 return true;
516 }
517#if JSC_OBJC_API_ENABLED
518 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
519 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->deletePrivateProperty(name);
520 return true;
521 }
522#endif
523 return false;
524}
525
526bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object)
527{
528 if (!object)
529 return false;
530 JSLockHolder locker(toJS(ctx));
531 CallData callData;
532 JSCell* cell = toJS(object);
533 return cell->methodTable()->getCallData(cell, callData) != CallTypeNone;
534}
535
536JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
537{
538 ExecState* exec = toJS(ctx);
539 JSLockHolder locker(exec);
540
541 if (!object)
542 return 0;
543
544 JSObject* jsObject = toJS(object);
545 JSObject* jsThisObject = toJS(thisObject);
546
547 if (!jsThisObject)
548 jsThisObject = exec->globalThisValue();
549
550 MarkedArgumentBuffer argList;
551 for (size_t i = 0; i < argumentCount; i++)
552 argList.append(toJS(exec, arguments[i]));
553
554 CallData callData;
555 CallType callType = jsObject->methodTable()->getCallData(jsObject, callData);
556 if (callType == CallTypeNone)
557 return 0;
558
559 JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList));
560 if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
561 result = 0;
562 return result;
563}
564
565bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
566{
567 if (!object)
568 return false;
569 JSObject* jsObject = toJS(object);
570 ConstructData constructData;
571 return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructTypeNone;
572}
573
574JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
575{
576 ExecState* exec = toJS(ctx);
577 JSLockHolder locker(exec);
578
579 if (!object)
580 return 0;
581
582 JSObject* jsObject = toJS(object);
583
584 ConstructData constructData;
585 ConstructType constructType = jsObject->methodTable()->getConstructData(jsObject, constructData);
586 if (constructType == ConstructTypeNone)
587 return 0;
588
589 MarkedArgumentBuffer argList;
590 for (size_t i = 0; i < argumentCount; i++)
591 argList.append(toJS(exec, arguments[i]));
592 JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
593 if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
594 result = 0;
595 return result;
596}
597
598struct OpaqueJSPropertyNameArray {
599 WTF_MAKE_FAST_ALLOCATED;
600public:
601 OpaqueJSPropertyNameArray(VM* vm)
602 : refCount(0)
603 , vm(vm)
604 {
605 }
606
607 unsigned refCount;
608 VM* vm;
609 Vector<JSRetainPtr<JSStringRef>> array;
610};
611
612JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
613{
614 if (!ctx) {
615 ASSERT_NOT_REACHED();
616 return 0;
617 }
618 ExecState* exec = toJS(ctx);
619 JSLockHolder locker(exec);
620
621 VM* vm = &exec->vm();
622
623 JSObject* jsObject = toJS(object);
624 JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(vm);
625 PropertyNameArray array(vm);
626 jsObject->methodTable()->getPropertyNames(jsObject, exec, array, EnumerationMode());
627
628 size_t size = array.size();
629 propertyNames->array.reserveInitialCapacity(size);
630 for (size_t i = 0; i < size; ++i)
631 propertyNames->array.uncheckedAppend(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].string()).leakRef()));
632
633 return JSPropertyNameArrayRetain(propertyNames);
634}
635
636JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
637{
638 ++array->refCount;
639 return array;
640}
641
642void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
643{
644 if (--array->refCount == 0) {
645 JSLockHolder locker(array->vm);
646 delete array;
647 }
648}
649
650size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
651{
652 return array->array.size();
653}
654
655JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
656{
657 return array->array[static_cast<unsigned>(index)].get();
658}
659
660void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
661{
662 PropertyNameArray* propertyNames = toJS(array);
663 JSLockHolder locker(propertyNames->vm());
664 propertyNames->add(propertyName->identifier(propertyNames->vm()));
665}