b67c40b5081a914dee732fdcf5e1bc1cde0b31d3
[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 "FunctionConstructor.h"
38 #include "Identifier.h"
39 #include "InitializeThreading.h"
40 #include "JSAPIWrapperObject.h"
41 #include "JSArray.h"
42 #include "JSCallbackConstructor.h"
43 #include "JSCallbackFunction.h"
44 #include "JSCallbackObject.h"
45 #include "JSClassRef.h"
46 #include "JSFunction.h"
47 #include "JSGlobalObject.h"
48 #include "JSObject.h"
49 #include "JSRetainPtr.h"
50 #include "JSString.h"
51 #include "JSValueRef.h"
52 #include "ObjectConstructor.h"
53 #include "ObjectPrototype.h"
54 #include "JSCInlines.h"
55 #include "PropertyNameArray.h"
56 #include "RegExpConstructor.h"
57
58 #if ENABLE(REMOTE_INSPECTOR)
59 #include "JSGlobalObjectInspectorController.h"
60 #endif
61
62 using namespace JSC;
63
64 JSClassRef JSClassCreate(const JSClassDefinition* definition)
65 {
66 initializeThreading();
67 RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
68 ? OpaqueJSClass::createNoAutomaticPrototype(definition)
69 : OpaqueJSClass::create(definition);
70
71 return jsClass.release().leakRef();
72 }
73
74 JSClassRef JSClassRetain(JSClassRef jsClass)
75 {
76 jsClass->ref();
77 return jsClass;
78 }
79
80 void JSClassRelease(JSClassRef jsClass)
81 {
82 jsClass->deref();
83 }
84
85 JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
86 {
87 if (!ctx) {
88 ASSERT_NOT_REACHED();
89 return 0;
90 }
91 ExecState* exec = toJS(ctx);
92 JSLockHolder locker(exec);
93
94 if (!jsClass)
95 return toRef(constructEmptyObject(exec));
96
97 JSCallbackObject<JSDestructibleObject>* object = JSCallbackObject<JSDestructibleObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
98 if (JSObject* prototype = jsClass->prototype(exec))
99 object->setPrototype(exec->vm(), prototype);
100
101 return toRef(object);
102 }
103
104 JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
105 {
106 if (!ctx) {
107 ASSERT_NOT_REACHED();
108 return 0;
109 }
110 ExecState* exec = toJS(ctx);
111 JSLockHolder locker(exec);
112 return toRef(JSCallbackFunction::create(exec->vm(), exec->lexicalGlobalObject(), callAsFunction, name ? name->string() : ASCIILiteral("anonymous")));
113 }
114
115 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
116 {
117 if (!ctx) {
118 ASSERT_NOT_REACHED();
119 return 0;
120 }
121 ExecState* exec = toJS(ctx);
122 JSLockHolder locker(exec);
123
124 JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0;
125 if (!jsPrototype)
126 jsPrototype = exec->lexicalGlobalObject()->objectPrototype();
127
128 JSCallbackConstructor* constructor = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
129 constructor->putDirect(exec->vm(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
130 return toRef(constructor);
131 }
132
133 JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
134 {
135 if (!ctx) {
136 ASSERT_NOT_REACHED();
137 return 0;
138 }
139 ExecState* exec = toJS(ctx);
140 JSLockHolder locker(exec);
141
142 startingLineNumber = std::max(1, startingLineNumber);
143 Identifier nameID = name ? name->identifier(&exec->vm()) : Identifier(exec, "anonymous");
144
145 MarkedArgumentBuffer args;
146 for (unsigned i = 0; i < parameterCount; i++)
147 args.append(jsString(exec, parameterNames[i]->string()));
148 args.append(jsString(exec, body->string()));
149
150 JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->string(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
151 if (exec->hadException()) {
152 JSValue exceptionValue = exec->exception();
153 if (exception)
154 *exception = toRef(exec, exceptionValue);
155 exec->clearException();
156 #if ENABLE(REMOTE_INSPECTOR)
157 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
158 #endif
159 result = 0;
160 }
161 return toRef(result);
162 }
163
164 JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
165 {
166 if (!ctx) {
167 ASSERT_NOT_REACHED();
168 return 0;
169 }
170 ExecState* exec = toJS(ctx);
171 JSLockHolder locker(exec);
172
173 JSObject* result;
174 if (argumentCount) {
175 MarkedArgumentBuffer argList;
176 for (size_t i = 0; i < argumentCount; ++i)
177 argList.append(toJS(exec, arguments[i]));
178
179 result = constructArray(exec, static_cast<ArrayAllocationProfile*>(0), argList);
180 } else
181 result = constructEmptyArray(exec, 0);
182
183 if (exec->hadException()) {
184 JSValue exceptionValue = exec->exception();
185 if (exception)
186 *exception = toRef(exec, exceptionValue);
187 exec->clearException();
188 #if ENABLE(REMOTE_INSPECTOR)
189 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
190 #endif
191 result = 0;
192 }
193
194 return toRef(result);
195 }
196
197 JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
198 {
199 if (!ctx) {
200 ASSERT_NOT_REACHED();
201 return 0;
202 }
203 ExecState* exec = toJS(ctx);
204 JSLockHolder locker(exec);
205
206 MarkedArgumentBuffer argList;
207 for (size_t i = 0; i < argumentCount; ++i)
208 argList.append(toJS(exec, arguments[i]));
209
210 JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList);
211 if (exec->hadException()) {
212 JSValue exceptionValue = exec->exception();
213 if (exception)
214 *exception = toRef(exec, exceptionValue);
215 exec->clearException();
216 #if ENABLE(REMOTE_INSPECTOR)
217 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
218 #endif
219 result = 0;
220 }
221
222 return toRef(result);
223 }
224
225 JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
226 {
227 if (!ctx) {
228 ASSERT_NOT_REACHED();
229 return 0;
230 }
231 ExecState* exec = toJS(ctx);
232 JSLockHolder locker(exec);
233
234 JSValue message = argumentCount ? toJS(exec, arguments[0]) : jsUndefined();
235 Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure();
236 JSObject* result = ErrorInstance::create(exec, errorStructure, message);
237
238 if (exec->hadException()) {
239 JSValue exceptionValue = exec->exception();
240 if (exception)
241 *exception = toRef(exec, exceptionValue);
242 exec->clearException();
243 #if ENABLE(REMOTE_INSPECTOR)
244 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
245 #endif
246 result = 0;
247 }
248
249 return toRef(result);
250 }
251
252 JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
253 {
254 if (!ctx) {
255 ASSERT_NOT_REACHED();
256 return 0;
257 }
258 ExecState* exec = toJS(ctx);
259 JSLockHolder locker(exec);
260
261 MarkedArgumentBuffer argList;
262 for (size_t i = 0; i < argumentCount; ++i)
263 argList.append(toJS(exec, arguments[i]));
264
265 JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(), argList);
266 if (exec->hadException()) {
267 JSValue exceptionValue = exec->exception();
268 if (exception)
269 *exception = toRef(exec, exceptionValue);
270 exec->clearException();
271 #if ENABLE(REMOTE_INSPECTOR)
272 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
273 #endif
274 result = 0;
275 }
276
277 return toRef(result);
278 }
279
280 JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
281 {
282 if (!ctx) {
283 ASSERT_NOT_REACHED();
284 return 0;
285 }
286 ExecState* exec = toJS(ctx);
287 JSLockHolder locker(exec);
288
289 JSObject* jsObject = toJS(object);
290 return toRef(exec, jsObject->prototype());
291 }
292
293 void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
294 {
295 if (!ctx) {
296 ASSERT_NOT_REACHED();
297 return;
298 }
299 ExecState* exec = toJS(ctx);
300 JSLockHolder locker(exec);
301
302 JSObject* jsObject = toJS(object);
303 JSValue jsValue = toJS(exec, value);
304
305 jsObject->setPrototypeWithCycleCheck(exec, jsValue.isObject() ? jsValue : jsNull());
306 }
307
308 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
309 {
310 if (!ctx) {
311 ASSERT_NOT_REACHED();
312 return false;
313 }
314 ExecState* exec = toJS(ctx);
315 JSLockHolder locker(exec);
316
317 JSObject* jsObject = toJS(object);
318
319 return jsObject->hasProperty(exec, propertyName->identifier(&exec->vm()));
320 }
321
322 JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
323 {
324 if (!ctx) {
325 ASSERT_NOT_REACHED();
326 return 0;
327 }
328 ExecState* exec = toJS(ctx);
329 JSLockHolder locker(exec);
330
331 JSObject* jsObject = toJS(object);
332
333 JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->vm()));
334 if (exec->hadException()) {
335 JSValue exceptionValue = exec->exception();
336 if (exception)
337 *exception = toRef(exec, exceptionValue);
338 exec->clearException();
339 #if ENABLE(REMOTE_INSPECTOR)
340 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
341 #endif
342 }
343 return toRef(exec, jsValue);
344 }
345
346 void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
347 {
348 if (!ctx) {
349 ASSERT_NOT_REACHED();
350 return;
351 }
352 ExecState* exec = toJS(ctx);
353 JSLockHolder locker(exec);
354
355 JSObject* jsObject = toJS(object);
356 Identifier name(propertyName->identifier(&exec->vm()));
357 JSValue jsValue = toJS(exec, value);
358
359 if (attributes && !jsObject->hasProperty(exec, name)) {
360 PropertyDescriptor desc(jsValue, attributes);
361 jsObject->methodTable()->defineOwnProperty(jsObject, exec, name, desc, false);
362 } else {
363 PutPropertySlot slot(jsObject);
364 jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot);
365 }
366
367 if (exec->hadException()) {
368 JSValue exceptionValue = exec->exception();
369 if (exception)
370 *exception = toRef(exec, exceptionValue);
371 exec->clearException();
372 #if ENABLE(REMOTE_INSPECTOR)
373 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
374 #endif
375 }
376 }
377
378 JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
379 {
380 if (!ctx) {
381 ASSERT_NOT_REACHED();
382 return 0;
383 }
384 ExecState* exec = toJS(ctx);
385 JSLockHolder locker(exec);
386
387 JSObject* jsObject = toJS(object);
388
389 JSValue jsValue = jsObject->get(exec, propertyIndex);
390 if (exec->hadException()) {
391 JSValue exceptionValue = exec->exception();
392 if (exception)
393 *exception = toRef(exec, exceptionValue);
394 exec->clearException();
395 #if ENABLE(REMOTE_INSPECTOR)
396 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
397 #endif
398 }
399 return toRef(exec, jsValue);
400 }
401
402
403 void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
404 {
405 if (!ctx) {
406 ASSERT_NOT_REACHED();
407 return;
408 }
409 ExecState* exec = toJS(ctx);
410 JSLockHolder locker(exec);
411
412 JSObject* jsObject = toJS(object);
413 JSValue jsValue = toJS(exec, value);
414
415 jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue, false);
416 if (exec->hadException()) {
417 JSValue exceptionValue = exec->exception();
418 if (exception)
419 *exception = toRef(exec, exceptionValue);
420 exec->clearException();
421 #if ENABLE(REMOTE_INSPECTOR)
422 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
423 #endif
424 }
425 }
426
427 bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
428 {
429 if (!ctx) {
430 ASSERT_NOT_REACHED();
431 return false;
432 }
433 ExecState* exec = toJS(ctx);
434 JSLockHolder locker(exec);
435
436 JSObject* jsObject = toJS(object);
437
438 bool result = jsObject->methodTable()->deleteProperty(jsObject, exec, propertyName->identifier(&exec->vm()));
439 if (exec->hadException()) {
440 JSValue exceptionValue = exec->exception();
441 if (exception)
442 *exception = toRef(exec, exceptionValue);
443 exec->clearException();
444 #if ENABLE(REMOTE_INSPECTOR)
445 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
446 #endif
447 }
448 return result;
449 }
450
451 void* JSObjectGetPrivate(JSObjectRef object)
452 {
453 JSObject* jsObject = uncheckedToJS(object);
454
455 // Get wrapped object if proxied
456 if (jsObject->inherits(JSProxy::info()))
457 jsObject = jsCast<JSProxy*>(jsObject)->target();
458
459 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info()))
460 return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
461 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info()))
462 return jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivate();
463 #if JSC_OBJC_API_ENABLED
464 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info()))
465 return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivate();
466 #endif
467
468 return 0;
469 }
470
471 bool JSObjectSetPrivate(JSObjectRef object, void* data)
472 {
473 JSObject* jsObject = uncheckedToJS(object);
474
475 // Get wrapped object if proxied
476 if (jsObject->inherits(JSProxy::info()))
477 jsObject = jsCast<JSProxy*>(jsObject)->target();
478
479 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
480 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
481 return true;
482 }
483 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
484 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivate(data);
485 return true;
486 }
487 #if JSC_OBJC_API_ENABLED
488 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
489 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivate(data);
490 return true;
491 }
492 #endif
493
494 return false;
495 }
496
497 JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
498 {
499 ExecState* exec = toJS(ctx);
500 JSLockHolder locker(exec);
501 JSObject* jsObject = toJS(object);
502 JSValue result;
503 Identifier name(propertyName->identifier(&exec->vm()));
504 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info()))
505 result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
506 else if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info()))
507 result = jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivateProperty(name);
508 #if JSC_OBJC_API_ENABLED
509 else if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info()))
510 result = jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivateProperty(name);
511 #endif
512 return toRef(exec, result);
513 }
514
515 bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value)
516 {
517 ExecState* exec = toJS(ctx);
518 JSLockHolder locker(exec);
519 JSObject* jsObject = toJS(object);
520 JSValue jsValue = value ? toJS(exec, value) : JSValue();
521 Identifier name(propertyName->identifier(&exec->vm()));
522 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
523 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
524 return true;
525 }
526 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
527 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
528 return true;
529 }
530 #if JSC_OBJC_API_ENABLED
531 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
532 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
533 return true;
534 }
535 #endif
536 return false;
537 }
538
539 bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
540 {
541 ExecState* exec = toJS(ctx);
542 JSLockHolder locker(exec);
543 JSObject* jsObject = toJS(object);
544 Identifier name(propertyName->identifier(&exec->vm()));
545 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
546 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
547 return true;
548 }
549 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
550 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->deletePrivateProperty(name);
551 return true;
552 }
553 #if JSC_OBJC_API_ENABLED
554 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
555 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->deletePrivateProperty(name);
556 return true;
557 }
558 #endif
559 return false;
560 }
561
562 bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object)
563 {
564 if (!object)
565 return false;
566 JSLockHolder locker(toJS(ctx));
567 CallData callData;
568 JSCell* cell = toJS(object);
569 return cell->methodTable()->getCallData(cell, callData) != CallTypeNone;
570 }
571
572 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
573 {
574 ExecState* exec = toJS(ctx);
575 JSLockHolder locker(exec);
576
577 if (!object)
578 return 0;
579
580 JSObject* jsObject = toJS(object);
581 JSObject* jsThisObject = toJS(thisObject);
582
583 if (!jsThisObject)
584 jsThisObject = exec->globalThisValue();
585
586 MarkedArgumentBuffer argList;
587 for (size_t i = 0; i < argumentCount; i++)
588 argList.append(toJS(exec, arguments[i]));
589
590 CallData callData;
591 CallType callType = jsObject->methodTable()->getCallData(jsObject, callData);
592 if (callType == CallTypeNone)
593 return 0;
594
595 JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList));
596 if (exec->hadException()) {
597 JSValue exceptionValue = exec->exception();
598 if (exception)
599 *exception = toRef(exec, exceptionValue);
600 exec->clearException();
601 #if ENABLE(REMOTE_INSPECTOR)
602 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
603 #endif
604 result = 0;
605 }
606 return result;
607 }
608
609 bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
610 {
611 if (!object)
612 return false;
613 JSObject* jsObject = toJS(object);
614 ConstructData constructData;
615 return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructTypeNone;
616 }
617
618 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
619 {
620 ExecState* exec = toJS(ctx);
621 JSLockHolder locker(exec);
622
623 if (!object)
624 return 0;
625
626 JSObject* jsObject = toJS(object);
627
628 ConstructData constructData;
629 ConstructType constructType = jsObject->methodTable()->getConstructData(jsObject, constructData);
630 if (constructType == ConstructTypeNone)
631 return 0;
632
633 MarkedArgumentBuffer argList;
634 for (size_t i = 0; i < argumentCount; i++)
635 argList.append(toJS(exec, arguments[i]));
636 JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
637 if (exec->hadException()) {
638 JSValue exceptionValue = exec->exception();
639 if (exception)
640 *exception = toRef(exec, exceptionValue);
641 exec->clearException();
642 #if ENABLE(REMOTE_INSPECTOR)
643 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
644 #endif
645 result = 0;
646 }
647 return result;
648 }
649
650 struct OpaqueJSPropertyNameArray {
651 WTF_MAKE_FAST_ALLOCATED;
652 public:
653 OpaqueJSPropertyNameArray(VM* vm)
654 : refCount(0)
655 , vm(vm)
656 {
657 }
658
659 unsigned refCount;
660 VM* vm;
661 Vector<JSRetainPtr<JSStringRef>> array;
662 };
663
664 JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
665 {
666 if (!ctx) {
667 ASSERT_NOT_REACHED();
668 return 0;
669 }
670 ExecState* exec = toJS(ctx);
671 JSLockHolder locker(exec);
672
673 VM* vm = &exec->vm();
674
675 JSObject* jsObject = toJS(object);
676 JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(vm);
677 PropertyNameArray array(vm);
678 jsObject->methodTable()->getPropertyNames(jsObject, exec, array, ExcludeDontEnumProperties);
679
680 size_t size = array.size();
681 propertyNames->array.reserveInitialCapacity(size);
682 for (size_t i = 0; i < size; ++i)
683 propertyNames->array.uncheckedAppend(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].string()).leakRef()));
684
685 return JSPropertyNameArrayRetain(propertyNames);
686 }
687
688 JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
689 {
690 ++array->refCount;
691 return array;
692 }
693
694 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
695 {
696 if (--array->refCount == 0) {
697 JSLockHolder locker(array->vm);
698 delete array;
699 }
700 }
701
702 size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
703 {
704 return array->array.size();
705 }
706
707 JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
708 {
709 return array->array[static_cast<unsigned>(index)].get();
710 }
711
712 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
713 {
714 PropertyNameArray* propertyNames = toJS(array);
715 JSLockHolder locker(propertyNames->vm());
716 propertyNames->add(propertyName->identifier(propertyNames->vm()));
717 }