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
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.
30 #include "JavaScriptGlue.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)
65 JSTypeRef
JSRetain(JSTypeRef ref
)
69 JSBase
* ptr
= (JSBase
*)ref
;
78 void JSRelease(JSTypeRef ref
)
82 JSBase
* ptr
= (JSBase
*)ref
;
90 CFStringRef
JSCopyDescription(JSTypeRef ref
)
92 CFStringRef result
= 0;
95 JSBase
* ptr
= (JSBase
*)ref
;
96 ptr
->CopyDescription();
104 UInt8
JSEqual(JSTypeRef ref1
, JSTypeRef ref2
)
106 UInt8 result
= false;
109 JSBase
* ptr
= (JSBase
*)ref1
;
110 result
= ptr
->Equal((JSBase
*)ref2
);
119 JSTypeID
JSGetTypeID(JSTypeRef ref
)
121 JSTypeID result
= kJSInvalidTypeID
;
124 JSBase
* ptr
= (JSBase
*)ref
;
125 result
= ptr
->GetTypeID();
134 CFIndex
JSGetRetainCount(JSTypeRef ref
)
139 JSBase
* ptr
= (JSBase
*)ref
;
140 result
= ptr
->RetainCount();
150 JSObjectRef
JSObjectCreate(void *data
, JSObjectCallBacksPtr callBacks
)
152 JSObjectRef result
= JSObjectCreateInternal(data
, callBacks
, 0, kJSUserObjectDataTypeUnknown
);
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
;
170 CFTypeRef
JSObjectCopyCFValue(JSObjectRef ref
)
172 CFTypeRef result
= 0;
173 JSUserObject
* ptr
= (JSUserObject
*)ref
;
174 if (ptr
&& (ptr
->GetTypeID() == kJSObjectTypeID
))
176 result
= ptr
->CopyCFValue();
184 void *JSObjectGetData(JSObjectRef ref
)
187 JSUserObject
* ptr
= (JSUserObject
*)ref
;
188 if (ptr
&& (ptr
->GetTypeID() == kJSObjectTypeID
))
190 result
= ptr
->GetData();
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
);
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
);
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
);
242 JSRunRef
JSRunCreate(CFStringRef jsSource
, JSFlags inFlags
)
244 initializeThreading();
249 JSLock
lock(LockForReal
);
250 result
= (JSRunRef
) new JSRun(jsSource
, inFlags
);
258 CFStringRef
JSRunCopySource(JSRunRef ref
)
260 CFStringRef result
= 0;
261 JSRun
* ptr
= (JSRun
*)ref
;
264 result
= UStringToCFString(ptr
->GetSource());
271 JSRunCopyGlobalObject
273 JSObjectRef
JSRunCopyGlobalObject(JSRunRef ref
)
275 JSObjectRef result
= 0;
276 JSRun
* ptr
= (JSRun
*)ref
;
279 JSGlobalObject
* globalObject
= ptr
->GlobalObject();
280 result
= (JSObjectRef
)KJSValueToJSObject(globalObject
, globalObject
->globalExec());
288 JSObjectRef
JSRunEvaluate(JSRunRef ref
)
290 JSObjectRef result
= 0;
291 JSRun
* ptr
= (JSRun
*)ref
;
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
);
320 Return true if no syntax error
322 bool JSRunCheckSyntax(JSRunRef ref
)
325 JSRun
* ptr
= (JSRun
*)ref
;
328 JSLock
lock(LockForReal
);
329 result
= ptr
->CheckSyntax();
335 JSCollect - trigger garbage collection
339 initializeThreading();
341 JSLock
lock(LockForReal
);
342 Heap
* heap
= getThreadGlobalExecState()->heap();
344 heap
->collectAllGarbage();
348 JSTypeGetCFArrayCallBacks
350 void JSTypeGetCFArrayCallBacks(CFArrayCallBacks
* 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
;
366 void *JSCFRetain(CFAllocatorRef allocator
, const void *value
)
368 JSRetain((JSTypeRef
)value
);
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
;
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
);
405 void CFJSObjectDispose(void *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();
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
);
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
);
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
);
471 result
= JSObjectCreateWithCFType(cfResult
);
480 CFJSObjectSetProperty
482 void CFJSObjectSetProperty(void *data
, CFStringRef propertyName
, JSObjectRef jsValue
)
484 if (data
&& propertyName
)
486 CFTypeRef cfValue
= JSObjectCopyCFValue(jsValue
);
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
);
500 for (; arrayCount
< index
; arrayCount
++)
502 CFArrayAppendValue((CFMutableArrayRef
)data
, GetCFNull());
504 CFArraySetValueAtIndex((CFMutableArrayRef
)data
, index
, cfValue
);
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
);
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;
541 result
= (CFTypeRef
)CFRetain(data
);
547 CFJSObjectCopyCFValue
549 UInt8
CFJSObjectEqual(void *data1
, void *data2
)
551 UInt8 result
= false;
554 CFEqual((CFTypeRef
)data1
, (CFTypeRef
)data2
);
561 CFJSObjectCopyPropertyNames
563 CFArrayRef
CFJSObjectCopyPropertyNames(void *data
)
565 CFMutableArrayRef result
= 0;
568 CFTypeID cfType
= CFGetTypeID(data
);
569 if (cfType
== CFDictionaryGetTypeID())
571 CFIndex count
= CFDictionaryGetCount((CFDictionaryRef
)data
);
574 CFTypeRef
* keys
= (CFTypeRef
*)malloc(sizeof(CFTypeRef
)*count
);
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
);
600 CFMutableArrayRef
JSCreateCFArrayFromJSArray(CFArrayRef array
)
602 CFIndex count
= array
? CFArrayGetCount(array
) : 0;
603 CFMutableArrayRef cfArray
= CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks
);
606 for (i
= 0; cfArray
&& i
< count
; i
++)
608 JSObjectRef jsValue
= (JSObjectRef
)CFArrayGetValueAtIndex(array
, i
);
609 CFTypeRef cfvalue
= JSObjectCopyCFValue(jsValue
);
612 CFArrayAppendValue(cfArray
, cfvalue
);
617 CFArrayAppendValue(cfArray
, GetCFNull());
623 CFMutableArrayRef
JSCreateJSArrayFromCFArray(CFArrayRef array
)
625 initializeThreading();
627 CFIndex count
= array
? CFArrayGetCount(array
) : 0;
628 CFArrayCallBacks arrayCallbacks
;
629 CFMutableArrayRef jsArray
;
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());
643 CFArrayAppendValue(jsArray
, jsValue
);
651 void JSLockInterpreter()
653 initializeThreading();
654 JSLock::lock(LockForReal
);
658 void JSUnlockInterpreter()
660 JSLock::unlock(LockForReal
);