a284c9fa099eb91b3d67e8bd1e590b4bebd2fe5e
[WebKit-https.git] / Source / JavaScriptCore / 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::fromString(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 ? sourceURL->string() : 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     if (JSProxy* proxy = jsDynamicCast<JSProxy*>(jsObject)) {
306         if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(proxy->target())) {
307             globalObject->resetPrototype(exec->vm(), jsValue.isObject() ? jsValue : jsNull());
308             return;
309         }
310         // Someday we might use proxies for something other than JSGlobalObjects, but today is not that day.
311         RELEASE_ASSERT_NOT_REACHED();
312     }
313     jsObject->setPrototypeWithCycleCheck(exec, jsValue.isObject() ? jsValue : jsNull());
314 }
315
316 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
317 {
318     if (!ctx) {
319         ASSERT_NOT_REACHED();
320         return false;
321     }
322     ExecState* exec = toJS(ctx);
323     JSLockHolder locker(exec);
324
325     JSObject* jsObject = toJS(object);
326     
327     return jsObject->hasProperty(exec, propertyName->identifier(&exec->vm()));
328 }
329
330 JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
331 {
332     if (!ctx) {
333         ASSERT_NOT_REACHED();
334         return 0;
335     }
336     ExecState* exec = toJS(ctx);
337     JSLockHolder locker(exec);
338
339     JSObject* jsObject = toJS(object);
340
341     JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->vm()));
342     if (exec->hadException()) {
343         JSValue exceptionValue = exec->exception();
344         if (exception)
345             *exception = toRef(exec, exceptionValue);
346         exec->clearException();
347 #if ENABLE(REMOTE_INSPECTOR)
348         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
349 #endif
350     }
351     return toRef(exec, jsValue);
352 }
353
354 void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
355 {
356     if (!ctx) {
357         ASSERT_NOT_REACHED();
358         return;
359     }
360     ExecState* exec = toJS(ctx);
361     JSLockHolder locker(exec);
362
363     JSObject* jsObject = toJS(object);
364     Identifier name(propertyName->identifier(&exec->vm()));
365     JSValue jsValue = toJS(exec, value);
366
367     if (attributes && !jsObject->hasProperty(exec, name)) {
368         PropertyDescriptor desc(jsValue, attributes);
369         jsObject->methodTable()->defineOwnProperty(jsObject, exec, name, desc, false);
370     } else {
371         PutPropertySlot slot(jsObject);
372         jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot);
373     }
374
375     if (exec->hadException()) {
376         JSValue exceptionValue = exec->exception();
377         if (exception)
378             *exception = toRef(exec, exceptionValue);
379         exec->clearException();
380 #if ENABLE(REMOTE_INSPECTOR)
381         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
382 #endif
383     }
384 }
385
386 JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
387 {
388     if (!ctx) {
389         ASSERT_NOT_REACHED();
390         return 0;
391     }
392     ExecState* exec = toJS(ctx);
393     JSLockHolder locker(exec);
394
395     JSObject* jsObject = toJS(object);
396
397     JSValue jsValue = jsObject->get(exec, propertyIndex);
398     if (exec->hadException()) {
399         JSValue exceptionValue = exec->exception();
400         if (exception)
401             *exception = toRef(exec, exceptionValue);
402         exec->clearException();
403 #if ENABLE(REMOTE_INSPECTOR)
404         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
405 #endif
406     }
407     return toRef(exec, jsValue);
408 }
409
410
411 void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
412 {
413     if (!ctx) {
414         ASSERT_NOT_REACHED();
415         return;
416     }
417     ExecState* exec = toJS(ctx);
418     JSLockHolder locker(exec);
419
420     JSObject* jsObject = toJS(object);
421     JSValue jsValue = toJS(exec, value);
422     
423     jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue, false);
424     if (exec->hadException()) {
425         JSValue exceptionValue = exec->exception();
426         if (exception)
427             *exception = toRef(exec, exceptionValue);
428         exec->clearException();
429 #if ENABLE(REMOTE_INSPECTOR)
430         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
431 #endif
432     }
433 }
434
435 bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
436 {
437     if (!ctx) {
438         ASSERT_NOT_REACHED();
439         return false;
440     }
441     ExecState* exec = toJS(ctx);
442     JSLockHolder locker(exec);
443
444     JSObject* jsObject = toJS(object);
445
446     bool result = jsObject->methodTable()->deleteProperty(jsObject, exec, propertyName->identifier(&exec->vm()));
447     if (exec->hadException()) {
448         JSValue exceptionValue = exec->exception();
449         if (exception)
450             *exception = toRef(exec, exceptionValue);
451         exec->clearException();
452 #if ENABLE(REMOTE_INSPECTOR)
453         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
454 #endif
455     }
456     return result;
457 }
458
459 void* JSObjectGetPrivate(JSObjectRef object)
460 {
461     JSObject* jsObject = uncheckedToJS(object);
462
463     // Get wrapped object if proxied
464     if (jsObject->inherits(JSProxy::info()))
465         jsObject = jsCast<JSProxy*>(jsObject)->target();
466
467     if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info()))
468         return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
469     if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info()))
470         return jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivate();
471 #if JSC_OBJC_API_ENABLED
472     if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info()))
473         return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivate();
474 #endif
475     
476     return 0;
477 }
478
479 bool JSObjectSetPrivate(JSObjectRef object, void* data)
480 {
481     JSObject* jsObject = uncheckedToJS(object);
482
483     // Get wrapped object if proxied
484     if (jsObject->inherits(JSProxy::info()))
485         jsObject = jsCast<JSProxy*>(jsObject)->target();
486
487     if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
488         jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
489         return true;
490     }
491     if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
492         jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivate(data);
493         return true;
494     }
495 #if JSC_OBJC_API_ENABLED
496     if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
497         jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivate(data);
498         return true;
499     }
500 #endif
501         
502     return false;
503 }
504
505 JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
506 {
507     ExecState* exec = toJS(ctx);
508     JSLockHolder locker(exec);
509     JSObject* jsObject = toJS(object);
510     JSValue result;
511     Identifier name(propertyName->identifier(&exec->vm()));
512
513     // Get wrapped object if proxied
514     if (jsObject->inherits(JSProxy::info()))
515         jsObject = jsCast<JSProxy*>(jsObject)->target();
516
517     if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info()))
518         result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
519     else if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info()))
520         result = jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivateProperty(name);
521 #if JSC_OBJC_API_ENABLED
522     else if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info()))
523         result = jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivateProperty(name);
524 #endif
525     return toRef(exec, result);
526 }
527
528 bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value)
529 {
530     ExecState* exec = toJS(ctx);
531     JSLockHolder locker(exec);
532     JSObject* jsObject = toJS(object);
533     JSValue jsValue = value ? toJS(exec, value) : JSValue();
534     Identifier name(propertyName->identifier(&exec->vm()));
535
536     // Get wrapped object if proxied
537     if (jsObject->inherits(JSProxy::info()))
538         jsObject = jsCast<JSProxy*>(jsObject)->target();
539
540     if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
541         jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
542         return true;
543     }
544     if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
545         jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
546         return true;
547     }
548 #if JSC_OBJC_API_ENABLED
549     if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
550         jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
551         return true;
552     }
553 #endif
554     return false;
555 }
556
557 bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
558 {
559     ExecState* exec = toJS(ctx);
560     JSLockHolder locker(exec);
561     JSObject* jsObject = toJS(object);
562     Identifier name(propertyName->identifier(&exec->vm()));
563
564     // Get wrapped object if proxied
565     if (jsObject->inherits(JSProxy::info()))
566         jsObject = jsCast<JSProxy*>(jsObject)->target();
567
568     if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) {
569         jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
570         return true;
571     }
572     if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) {
573         jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->deletePrivateProperty(name);
574         return true;
575     }
576 #if JSC_OBJC_API_ENABLED
577     if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) {
578         jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->deletePrivateProperty(name);
579         return true;
580     }
581 #endif
582     return false;
583 }
584
585 bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object)
586 {
587     if (!object)
588         return false;
589     JSLockHolder locker(toJS(ctx));
590     CallData callData;
591     JSCell* cell = toJS(object);
592     return cell->methodTable()->getCallData(cell, callData) != CallTypeNone;
593 }
594
595 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
596 {
597     ExecState* exec = toJS(ctx);
598     JSLockHolder locker(exec);
599
600     if (!object)
601         return 0;
602
603     JSObject* jsObject = toJS(object);
604     JSObject* jsThisObject = toJS(thisObject);
605
606     if (!jsThisObject)
607         jsThisObject = exec->globalThisValue();
608
609     MarkedArgumentBuffer argList;
610     for (size_t i = 0; i < argumentCount; i++)
611         argList.append(toJS(exec, arguments[i]));
612
613     CallData callData;
614     CallType callType = jsObject->methodTable()->getCallData(jsObject, callData);
615     if (callType == CallTypeNone)
616         return 0;
617
618     JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList));
619     if (exec->hadException()) {
620         JSValue exceptionValue = exec->exception();
621         if (exception)
622             *exception = toRef(exec, exceptionValue);
623         exec->clearException();
624 #if ENABLE(REMOTE_INSPECTOR)
625         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
626 #endif
627         result = 0;
628     }
629     return result;
630 }
631
632 bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
633 {
634     if (!object)
635         return false;
636     JSObject* jsObject = toJS(object);
637     ConstructData constructData;
638     return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructTypeNone;
639 }
640
641 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
642 {
643     ExecState* exec = toJS(ctx);
644     JSLockHolder locker(exec);
645
646     if (!object)
647         return 0;
648
649     JSObject* jsObject = toJS(object);
650
651     ConstructData constructData;
652     ConstructType constructType = jsObject->methodTable()->getConstructData(jsObject, constructData);
653     if (constructType == ConstructTypeNone)
654         return 0;
655
656     MarkedArgumentBuffer argList;
657     for (size_t i = 0; i < argumentCount; i++)
658         argList.append(toJS(exec, arguments[i]));
659     JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
660     if (exec->hadException()) {
661         JSValue exceptionValue = exec->exception();
662         if (exception)
663             *exception = toRef(exec, exceptionValue);
664         exec->clearException();
665 #if ENABLE(REMOTE_INSPECTOR)
666         exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue);
667 #endif
668         result = 0;
669     }
670     return result;
671 }
672
673 struct OpaqueJSPropertyNameArray {
674     WTF_MAKE_FAST_ALLOCATED;
675 public:
676     OpaqueJSPropertyNameArray(VM* vm)
677         : refCount(0)
678         , vm(vm)
679     {
680     }
681     
682     unsigned refCount;
683     VM* vm;
684     Vector<JSRetainPtr<JSStringRef>> array;
685 };
686
687 JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
688 {
689     if (!ctx) {
690         ASSERT_NOT_REACHED();
691         return 0;
692     }
693     ExecState* exec = toJS(ctx);
694     JSLockHolder locker(exec);
695
696     VM* vm = &exec->vm();
697
698     JSObject* jsObject = toJS(object);
699     JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(vm);
700     PropertyNameArray array(vm);
701     jsObject->methodTable()->getPropertyNames(jsObject, exec, array, EnumerationMode());
702
703     size_t size = array.size();
704     propertyNames->array.reserveInitialCapacity(size);
705     for (size_t i = 0; i < size; ++i)
706         propertyNames->array.uncheckedAppend(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].string()).leakRef()));
707     
708     return JSPropertyNameArrayRetain(propertyNames);
709 }
710
711 JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
712 {
713     ++array->refCount;
714     return array;
715 }
716
717 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
718 {
719     if (--array->refCount == 0) {
720         JSLockHolder locker(array->vm);
721         delete array;
722     }
723 }
724
725 size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
726 {
727     return array->array.size();
728 }
729
730 JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
731 {
732     return array->array[static_cast<unsigned>(index)].get();
733 }
734
735 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
736 {
737     PropertyNameArray* propertyNames = toJS(array);
738     JSLockHolder locker(propertyNames->vm());
739     propertyNames->add(propertyName->identifier(propertyNames->vm()));
740 }