Rubber-stamped by Brady Eidson.
[webbrowser.git] / JavaScriptGlue / JavaScriptGlue.cpp
blobe552f19ca543c4b41418da805b5225b92d6524fb
1 /*
2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * 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 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "config.h"
30 #include "JavaScriptGlue.h"
31 #include "JSUtils.h"
32 #include "JSBase.h"
33 #include "JSObject.h"
34 #include "JSRun.h"
35 #include <JavaScriptCore/Completion.h>
36 #include <JavaScriptCore/InitializeThreading.h>
38 static CFTypeRef sJSCFNullRef = 0;
40 static void CFJSObjectDispose(void *data);
41 static JSObjectRef CFJSObjectCopyProperty(void *data, CFStringRef propertyName);
42 static void CFJSObjectSetProperty(void *data, CFStringRef propertyName, JSObjectRef jsValue);
43 static CFTypeRef CFJSObjectCopyCFValue(void *data);
44 static UInt8 CFJSObjectEqual(void *data1, void *data2);
45 static CFArrayRef CFJSObjectCopyPropertyNames(void *data);
47 void *JSCFRetain(CFAllocatorRef allocator, const void *value);
48 void JSCFRelease(CFAllocatorRef allocator, const void *value);
51 void JSSetCFNull(CFTypeRef nullRef)
53 ReleaseCFType(sJSCFNullRef);
54 sJSCFNullRef = RetainCFType(nullRef);
57 CFTypeRef JSGetCFNull(void)
59 return sJSCFNullRef;
63 JSRetain
65 JSTypeRef JSRetain(JSTypeRef ref)
67 if (ref)
69 JSBase* ptr = (JSBase*)ref;
70 ptr->Retain();
72 return ref;
76 JSRelease
78 void JSRelease(JSTypeRef ref)
80 if (ref)
82 JSBase* ptr = (JSBase*)ref;
83 ptr->Release();
88 JSCopyDescription
90 CFStringRef JSCopyDescription(JSTypeRef ref)
92 CFStringRef result = 0;
93 if (ref)
95 JSBase* ptr = (JSBase*)ref;
96 ptr->CopyDescription();
98 return result;
102 JSEqual
104 UInt8 JSEqual(JSTypeRef ref1, JSTypeRef ref2)
106 UInt8 result = false;
107 if (ref1 && ref2)
109 JSBase* ptr = (JSBase*)ref1;
110 result = ptr->Equal((JSBase*)ref2);
112 return result;
117 JSGetTypeID
119 JSTypeID JSGetTypeID(JSTypeRef ref)
121 JSTypeID result = kJSInvalidTypeID;
122 if (ref)
124 JSBase* ptr = (JSBase*)ref;
125 result = ptr->GetTypeID();
127 return result;
132 JSGetRetainCount
134 CFIndex JSGetRetainCount(JSTypeRef ref)
136 CFIndex result = -1;
137 if (ref)
139 JSBase* ptr = (JSBase*)ref;
140 result = ptr->RetainCount();
142 return result;
148 JSObjectCreate
150 JSObjectRef JSObjectCreate(void *data, JSObjectCallBacksPtr callBacks)
152 JSObjectRef result = JSObjectCreateInternal(data, callBacks, 0, kJSUserObjectDataTypeUnknown);
153 return result;
157 JSObjectCreateInternal
159 JSObjectRef JSObjectCreateInternal(void *data, JSObjectCallBacksPtr callBacks, JSObjectMarkProcPtr markProc, int type)
161 JSObjectRef result = 0;
162 JSUserObject* ptr = new JSUserObject(callBacks, markProc, data, type);
163 result = (JSObjectRef)ptr;
164 return result;
168 JSObjectCopyCFValue
170 CFTypeRef JSObjectCopyCFValue(JSObjectRef ref)
172 CFTypeRef result = 0;
173 JSUserObject* ptr = (JSUserObject*)ref;
174 if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
176 result = ptr->CopyCFValue();
178 return result;
182 JSObjectGetData
184 void *JSObjectGetData(JSObjectRef ref)
186 void *result = 0;
187 JSUserObject* ptr = (JSUserObject*)ref;
188 if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
190 result = ptr->GetData();
192 return result;
197 JSObjectCopyProperty
199 JSObjectRef JSObjectCopyProperty(JSObjectRef ref, CFStringRef propertyName)
201 JSObjectRef result = 0;
202 JSUserObject* ptr = (JSUserObject*)ref;
203 if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
205 result = (JSObjectRef)ptr->CopyProperty(propertyName);
207 return result;
212 JSObjectSetProperty
214 void JSObjectSetProperty(JSObjectRef ref, CFStringRef propertyName, JSObjectRef value)
216 JSUserObject* ptr = (JSUserObject*)ref;
217 if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
219 ptr->SetProperty(propertyName, (JSUserObject*)value);
225 JSObjectCallFunction
227 JSObjectRef JSObjectCallFunction(JSObjectRef ref, JSObjectRef thisObj, CFArrayRef args)
229 JSObjectRef result = 0;
230 JSUserObject* ptr = (JSUserObject*)ref;
231 if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
233 result = (JSObjectRef)ptr->CallFunction((JSUserObject*)thisObj, args);
235 return result;
240 JSRunCreate
242 JSRunRef JSRunCreate(CFStringRef jsSource, JSFlags inFlags)
244 initializeThreading();
246 JSRunRef result = 0;
247 if (jsSource)
249 JSLock lock(LockForReal);
250 result = (JSRunRef) new JSRun(jsSource, inFlags);
252 return result;
256 JSRunCopySource
258 CFStringRef JSRunCopySource(JSRunRef ref)
260 CFStringRef result = 0;
261 JSRun* ptr = (JSRun*)ref;
262 if (ptr)
264 result = UStringToCFString(ptr->GetSource());
266 return result;
271 JSRunCopyGlobalObject
273 JSObjectRef JSRunCopyGlobalObject(JSRunRef ref)
275 JSObjectRef result = 0;
276 JSRun* ptr = (JSRun*)ref;
277 if (ptr)
279 JSGlobalObject* globalObject = ptr->GlobalObject();
280 result = (JSObjectRef)KJSValueToJSObject(globalObject, globalObject->globalExec());
282 return result;
286 JSRunEvaluate
288 JSObjectRef JSRunEvaluate(JSRunRef ref)
290 JSObjectRef result = 0;
291 JSRun* ptr = (JSRun*)ref;
292 if (ptr)
294 JSLock lock(LockForReal);
295 Completion completion = ptr->Evaluate();
296 if (completion.isValueCompletion())
298 result = (JSObjectRef)KJSValueToJSObject(completion.value(), ptr->GlobalObject()->globalExec());
301 if (completion.complType() == Throw)
303 JSFlags flags = ptr->Flags();
304 if (flags & kJSFlagDebug)
306 CFTypeRef error = JSObjectCopyCFValue(result);
307 if (error)
309 CFShow(error);
310 CFRelease(error);
315 return result;
319 JSRunCheckSyntax
320 Return true if no syntax error
322 bool JSRunCheckSyntax(JSRunRef ref)
324 bool result = false;
325 JSRun* ptr = (JSRun*)ref;
326 if (ptr)
328 JSLock lock(LockForReal);
329 result = ptr->CheckSyntax();
331 return result;
335 JSCollect - trigger garbage collection
337 void JSCollect()
339 initializeThreading();
341 JSLock lock(LockForReal);
342 Heap* heap = getThreadGlobalExecState()->heap();
343 if (!heap->isBusy())
344 heap->collectAllGarbage();
348 JSTypeGetCFArrayCallBacks
350 void JSTypeGetCFArrayCallBacks(CFArrayCallBacks* outCallBacks)
352 if (outCallBacks)
354 outCallBacks->version = 1;
355 outCallBacks->retain = (CFArrayRetainCallBack)JSCFRetain;
356 outCallBacks->release = (CFArrayReleaseCallBack)JSCFRelease;
357 outCallBacks->copyDescription = (CFArrayCopyDescriptionCallBack)JSCopyDescription;
358 outCallBacks->equal = (CFArrayEqualCallBack)JSEqual;
364 JSCFRetain
366 void *JSCFRetain(CFAllocatorRef allocator, const void *value)
368 JSRetain((JSTypeRef)value);
369 return (void*)value;
373 JSCFRelease
375 void JSCFRelease(CFAllocatorRef allocator, const void *value)
377 JSRelease((JSTypeRef)value);
382 JSObjectCreateWithCFType
384 JSObjectRef JSObjectCreateWithCFType(CFTypeRef inRef)
386 JSObjectCallBacks callBacks;
387 JSObjectRef cfJSObject = nil;
388 if (inRef)
390 callBacks.dispose = CFJSObjectDispose;
391 callBacks.equal = CFJSObjectEqual;
392 callBacks.copyCFValue = CFJSObjectCopyCFValue;
393 callBacks.copyProperty = CFJSObjectCopyProperty;
394 callBacks.setProperty = CFJSObjectSetProperty;
395 callBacks.callFunction = 0;
396 callBacks.copyPropertyNames = CFJSObjectCopyPropertyNames;
397 cfJSObject = JSObjectCreateInternal((void*)CFRetain(inRef), &callBacks, 0, kJSUserObjectDataTypeCFType );
399 return cfJSObject;
403 CFJSObjectDispose
405 void CFJSObjectDispose(void *data)
407 if (data)
409 CFRelease((JSTypeRef)data);
413 CFArrayRef JSObjectCopyPropertyNames(JSObjectRef ref)
415 CFArrayRef result = 0;
416 JSUserObject* ptr = (JSUserObject*)ref;
417 if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
419 result = ptr->CopyPropertyNames();
421 return result;
424 CFJSObjectCopyProperty
426 JSObjectRef CFJSObjectCopyProperty(void *data, CFStringRef propertyName)
428 JSObjectRef result = 0;
429 if (data && propertyName)
431 CFTypeRef cfResult = 0;
432 if (CFGetTypeID(data) == CFDictionaryGetTypeID())
434 if (CFStringCompare(propertyName, CFSTR("length"), 0) == kCFCompareEqualTo)
436 int len = CFDictionaryGetCount((CFDictionaryRef)data);
437 cfResult = CFNumberCreate(0, kCFNumberIntType, &len);
439 else
441 cfResult = RetainCFType(CFDictionaryGetValue((CFDictionaryRef)data, propertyName));
444 else if (CFGetTypeID(data) == CFArrayGetTypeID())
446 if (CFStringCompare(propertyName, CFSTR("length"), 0) == kCFCompareEqualTo)
448 int len = CFArrayGetCount((CFArrayRef)data);
449 cfResult = CFNumberCreate(0, kCFNumberIntType, &len);
451 else
453 SInt32 index = CFStringGetIntValue(propertyName);
454 CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
455 if (index >= 0 && index < arrayCount)
457 cfResult = RetainCFType(CFArrayGetValueAtIndex((CFArrayRef)data, index));
461 else if (CFGetTypeID(data) == CFStringGetTypeID())
463 if (CFStringCompare(propertyName, CFSTR("length"), 0) == kCFCompareEqualTo)
465 int len = CFStringGetLength((CFStringRef)data);
466 cfResult = CFNumberCreate(0, kCFNumberIntType, &len);
469 if (cfResult)
471 result = JSObjectCreateWithCFType(cfResult);
472 CFRelease(cfResult);
475 return result;
480 CFJSObjectSetProperty
482 void CFJSObjectSetProperty(void *data, CFStringRef propertyName, JSObjectRef jsValue)
484 if (data && propertyName)
486 CFTypeRef cfValue = JSObjectCopyCFValue(jsValue);
488 if (cfValue)
490 if (CFGetTypeID(data) == CFDictionaryGetTypeID())
492 CFDictionarySetValue((CFMutableDictionaryRef)data, propertyName, cfValue);
494 else if (CFGetTypeID(data) == CFArrayGetTypeID())
496 SInt32 index = CFStringGetIntValue(propertyName);
497 CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
498 if (index >= 0)
500 for (; arrayCount < index; arrayCount++)
502 CFArrayAppendValue((CFMutableArrayRef)data, GetCFNull());
504 CFArraySetValueAtIndex((CFMutableArrayRef)data, index, cfValue);
507 CFRelease(cfValue);
509 else
511 if (CFGetTypeID(data) == CFDictionaryGetTypeID())
513 CFDictionaryRemoveValue((CFMutableDictionaryRef)data, propertyName);
515 else if (CFGetTypeID(data) == CFArrayGetTypeID())
517 SInt32 index = CFStringGetIntValue(propertyName);
518 CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
519 if (index >= 0)
521 for (; arrayCount < index; arrayCount++)
523 CFArrayAppendValue((CFMutableArrayRef)data, GetCFNull());
525 CFArraySetValueAtIndex((CFMutableArrayRef)data, index, GetCFNull());
534 CFJSObjectCopyCFValue
536 CFTypeRef CFJSObjectCopyCFValue(void *data)
538 CFTypeRef result = 0;
539 if (data)
541 result = (CFTypeRef)CFRetain(data);
543 return result;
547 CFJSObjectCopyCFValue
549 UInt8 CFJSObjectEqual(void *data1, void *data2)
551 UInt8 result = false;
552 if (data1 && data2)
554 CFEqual((CFTypeRef)data1, (CFTypeRef)data2);
556 return result;
561 CFJSObjectCopyPropertyNames
563 CFArrayRef CFJSObjectCopyPropertyNames(void *data)
565 CFMutableArrayRef result = 0;
566 if (data)
568 CFTypeID cfType = CFGetTypeID(data);
569 if (cfType == CFDictionaryGetTypeID())
571 CFIndex count = CFDictionaryGetCount((CFDictionaryRef)data);
572 if (count)
574 CFTypeRef* keys = (CFTypeRef*)malloc(sizeof(CFTypeRef)*count);
575 if (keys)
577 int i;
578 CFDictionaryGetKeysAndValues((CFDictionaryRef)data, (const void **)keys, 0);
579 for (i = 0; i < count; i++)
581 CFStringRef key = (CFStringRef)keys[i];
582 if (CFGetTypeID(key) != CFStringGetTypeID()) continue;
584 if (!result) result = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
585 if (!result) continue;
587 CFArrayAppendValue(result, key);
589 free(keys);
594 return result;
600 CFMutableArrayRef JSCreateCFArrayFromJSArray(CFArrayRef array)
602 CFIndex count = array ? CFArrayGetCount(array) : 0;
603 CFMutableArrayRef cfArray = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
604 CFIndex i;
606 for (i = 0; cfArray && i < count; i++)
608 JSObjectRef jsValue = (JSObjectRef)CFArrayGetValueAtIndex(array, i);
609 CFTypeRef cfvalue = JSObjectCopyCFValue(jsValue);
610 if (cfvalue)
612 CFArrayAppendValue(cfArray, cfvalue);
613 CFRelease(cfvalue);
615 else
617 CFArrayAppendValue(cfArray, GetCFNull());
620 return cfArray;
623 CFMutableArrayRef JSCreateJSArrayFromCFArray(CFArrayRef array)
625 initializeThreading();
627 CFIndex count = array ? CFArrayGetCount(array) : 0;
628 CFArrayCallBacks arrayCallbacks;
629 CFMutableArrayRef jsArray;
630 CFIndex i;
632 JSTypeGetCFArrayCallBacks(&arrayCallbacks);
633 jsArray = CFArrayCreateMutable(0, 0, &arrayCallbacks);
635 for (i = 0; array && i < count; i++)
637 CFTypeRef cfValue = (CFTypeRef)CFArrayGetValueAtIndex(array, i);
638 JSObjectRef jsValue = JSObjectCreateWithCFType(cfValue);
640 if (!jsValue) jsValue = JSObjectCreateWithCFType(GetCFNull());
641 if (jsValue)
643 CFArrayAppendValue(jsArray, jsValue);
644 JSRelease(jsValue);
647 return jsArray;
651 void JSLockInterpreter()
653 initializeThreading();
654 JSLock::lock(LockForReal);
658 void JSUnlockInterpreter()
660 JSLock::unlock(LockForReal);