]> git.saurik.com Git - apple/javascriptcore.git/blob - API/JSObjectRef.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / API / JSObjectRef.cpp
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
63 using namespace JSC;
64
65 enum class ExceptionStatus {
66 DidThrow,
67 DidNotThrow
68 };
69
70 static 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
85 JSClassRef 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
95 JSClassRef JSClassRetain(JSClassRef jsClass)
96 {
97 jsClass->ref();
98 return jsClass;
99 }
100
101 void JSClassRelease(JSClassRef jsClass)
102 {
103 jsClass->deref();
104 }
105
106 JSObjectRef 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
125 JSObjectRef 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
136 JSObjectRef 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
154 JSObjectRef 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
177 JSObjectRef 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
202 JSObjectRef 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
222 JSObjectRef 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
241 JSObjectRef 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
261 JSValueRef 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
274 void 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
297 bool 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
311 JSValueRef 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
327 void 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
351 JSValueRef 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
368 void 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
384 bool 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
400 void* 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
420 bool 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
446 JSValueRef 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
469 bool 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
498 bool 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
526 bool 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
536 JSValueRef 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
565 bool 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
574 JSObjectRef 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
598 struct OpaqueJSPropertyNameArray {
599 WTF_MAKE_FAST_ALLOCATED;
600 public:
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
612 JSPropertyNameArrayRef 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
636 JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
637 {
638 ++array->refCount;
639 return array;
640 }
641
642 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
643 {
644 if (--array->refCount == 0) {
645 JSLockHolder locker(array->vm);
646 delete array;
647 }
648 }
649
650 size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
651 {
652 return array->array.size();
653 }
654
655 JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
656 {
657 return array->array[static_cast<unsigned>(index)].get();
658 }
659
660 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
661 {
662 PropertyNameArray* propertyNames = toJS(array);
663 JSLockHolder locker(propertyNames->vm());
664 propertyNames->add(propertyName->identifier(propertyNames->vm()));
665 }