1bbdf1ea587a303ab788cb4307586756ea505165
[WebKit-https.git] / JavaScriptGlue / JavaScriptGlue.cpp
1 /*
2         JSGlue.cpp
3 */
4
5 #include "JavaScriptGlue.h"
6 #include "JSUtils.h"
7 #include "JSBase.h"
8 #include "JSObject.h"
9 #include "JSRun.h"
10
11 static CFTypeRef sJSCFNullRef = NULL;
12
13 static void CFJSObjectDispose(void* data);
14 static JSObjectRef CFJSObjectCopyProperty(void* data, CFStringRef propertyName);
15 static void CFJSObjectSetProperty(void* data, CFStringRef propertyName, JSObjectRef jsValue);
16 static CFTypeRef CFJSObjectCopyCFValue(void* data);
17 static UInt8 CFJSObjectEqual(void* data1, void* data2);
18 static CFArrayRef CFJSObjectCopyPropertyNames(void* data);
19
20 void* JSCFRetain(CFAllocatorRef allocator, const void *value);
21 void JSCFRelease(CFAllocatorRef allocator, const void *value);
22
23
24 void JSSetCFNull(CFTypeRef nullRef)
25 {
26         ReleaseCFType(sJSCFNullRef);
27         sJSCFNullRef = RetainCFType(nullRef);
28 }
29
30 CFTypeRef JSGetCFNull(void)
31 {
32         return sJSCFNullRef;
33 }
34
35 /*
36         JSRetain
37 */
38 JSTypeRef JSRetain(JSTypeRef ref)
39 {
40         if (ref)
41         {
42                 JSBase* ptr = (JSBase*)ref;
43                 ptr->Retain();
44         }
45         return ref;
46 }
47
48 /*
49         JSRelease
50 */
51 void JSRelease(JSTypeRef ref)
52 {
53         if (ref)
54         {
55                 JSBase* ptr = (JSBase*)ref;
56                 ptr->Release();
57         }
58 }
59
60 /*
61         JSCopyDescription
62 */
63 CFStringRef     JSCopyDescription(JSTypeRef ref)
64 {
65         CFStringRef result = NULL;
66         if (ref)
67         {
68                 JSBase* ptr = (JSBase*)ref;
69                 ptr->CopyDescription();
70         }
71         return result;
72 }
73
74 /*
75         JSEqual
76 */
77 UInt8   JSEqual(JSTypeRef ref1, JSTypeRef ref2)
78 {
79         UInt8 result = false;
80         if (ref1 && ref2)
81         {
82                 JSBase* ptr = (JSBase*)ref1;
83                 result = ptr->Equal((JSBase*)ref2);
84         }
85         return result;
86 }
87
88
89 /*
90         JSGetTypeID
91 */
92 JSTypeID JSGetTypeID(JSTypeRef ref)
93 {
94         JSTypeID result = kJSInvalidTypeID;
95         if (ref)
96         {
97                 JSBase* ptr = (JSBase*)ref;
98                 result = ptr->GetTypeID();
99         }
100         return result;
101 }
102
103
104 /*
105         JSGetRetainCount
106 */
107 CFIndex JSGetRetainCount(JSTypeRef ref)
108 {
109         CFIndex result = -1;
110         if (ref)
111         {
112                 JSBase* ptr = (JSBase*)ref;
113                 result = ptr->RetainCount();
114         }
115         return result;
116 }
117
118
119
120 /*
121         JSObjectCreate
122 */
123 JSObjectRef JSObjectCreate(void* data, JSObjectCallBacksPtr callBacks)
124 {
125         JSObjectRef result = JSObjectCreateInternal(data, callBacks, NULL, kJSUserObjectDataTypeUnknown);
126         return result;
127 }
128
129 /*
130         JSObjectCreateInternal
131 */
132 JSObjectRef JSObjectCreateInternal(void* data, JSObjectCallBacksPtr callBacks, JSObjectMarkProcPtr markProc, int type)
133 {
134         JSObjectRef result = NULL;
135         JSUserObject* ptr = new JSUserObject(callBacks, markProc, data, type);
136         result = (JSObjectRef)ptr;
137         return result;
138 }
139
140 /*
141         JSObjectCopyCFValue
142 */
143 CFTypeRef JSObjectCopyCFValue(JSObjectRef ref)
144 {
145         CFTypeRef result = NULL;
146         JSUserObject* ptr = (JSUserObject*)ref;
147         if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
148         {
149                 result = ptr->CopyCFValue();
150         }
151         return result;
152 }
153
154 /*
155         JSObjectGetData
156 */
157 void* JSObjectGetData(JSObjectRef ref)
158 {
159         void* result = NULL;
160         JSUserObject* ptr = (JSUserObject*)ref;
161         if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
162         {
163                 result = ptr->GetData();
164         }
165         return result;
166 }
167
168
169 /*
170         JSObjectCopyProperty
171 */
172 JSObjectRef JSObjectCopyProperty(JSObjectRef ref, CFStringRef propertyName)
173 {
174         JSObjectRef result = NULL;
175         JSUserObject* ptr = (JSUserObject*)ref;
176         if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
177         {
178                 result = (JSObjectRef)ptr->CopyProperty(propertyName);
179         }
180         return result;
181 }
182
183
184 /*
185         JSObjectSetProperty
186 */
187 void JSObjectSetProperty(JSObjectRef ref, CFStringRef propertyName, JSObjectRef value)
188 {
189         JSUserObject* ptr = (JSUserObject*)ref;
190         if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
191         {
192                 ptr->SetProperty(propertyName, (JSUserObject*)value);
193         }
194 }
195
196
197 /*
198         JSObjectCallFunction
199 */
200 JSObjectRef JSObjectCallFunction(JSObjectRef ref, JSObjectRef thisObj, CFArrayRef args)
201 {
202         JSObjectRef result = NULL;
203         JSUserObject* ptr = (JSUserObject*)ref;
204         if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
205         {
206                 result = (JSObjectRef)ptr->CallFunction((JSUserObject*)thisObj, args);
207         }
208         return result;
209 }
210
211
212 /*
213         JSRunCreate
214 */
215 JSRunRef JSRunCreate(CFStringRef jsSource, JSFlags inFlags)
216 {
217         JSRunRef result = NULL;
218         if (jsSource)
219         {
220                 result = (JSRunRef) new JSRun(jsSource, inFlags);
221         }
222         return result;
223 }
224
225 /*
226         JSRunCopySource
227 */
228 CFStringRef JSRunCopySource(JSRunRef ref)
229 {
230         CFStringRef result = NULL;
231         JSRun* ptr = (JSRun*)ref;
232         if (ptr)
233         {
234                 result = UStringToCFString(ptr->GetSource());
235         }
236         return result;
237 }
238
239
240 /*
241         JSRunCopyGlobalObject
242 */
243 JSObjectRef JSRunCopyGlobalObject(JSRunRef ref)
244 {
245         JSObjectRef result = NULL;
246         JSRun* ptr = (JSRun*)ref;
247         if (ptr)
248         {
249                 ObjectImp *globalObject = ptr->GlobalObject();
250                 result = (JSObjectRef)KJSValueToJSObject(globalObject, ptr->GetInterpreter()->globalExec());
251         }
252         return result;
253 }
254
255 /*
256         JSRunEvaluate
257 */
258 JSObjectRef JSRunEvaluate(JSRunRef ref)
259 {
260         JSObjectRef result = NULL;
261         JSRun* ptr = (JSRun*)ref;
262         if (ptr)
263         {
264                 Completion completion = ptr->Evaluate();
265 #if JAG_PINK_OR_LATER
266
267                 if (completion.isValueCompletion())
268                 {
269                         result = (JSObjectRef)KJSValueToJSObject(completion.value(), ptr->GetInterpreter()->globalExec());
270                 }
271
272                 if (completion.complType() == Throw)    
273                 {
274                         JSFlags flags = ptr->Flags();
275                         if (flags & kJSFlagDebug)
276                         {
277                                 CFTypeRef error = JSObjectCopyCFValue(result);
278                                 if (error)
279                                 {
280                                         CFShow(error);
281                                         CFRelease(error);
282                                 }
283                         }
284                 }
285
286 #else
287                 result = (JSObjectRef)KJSValueToJSObject(completion, ptr->GetInterpreter()->globalExec());              
288 #endif
289         }
290         return result;
291 }
292
293 /*
294         JSRunCheckSyntax
295         Return true if no syntax error
296 */
297 bool JSRunCheckSyntax(JSRunRef ref)
298 {
299 #if JAG_PINK_OR_LATER
300         bool result = false;
301         JSRun* ptr = (JSRun*)ref;
302         if (ptr)
303         {
304             JSLockInterpreter();
305             result = ptr->CheckSyntax();
306             JSUnlockInterpreter();
307         }
308         return result;
309 #else
310         return true;
311 #endif
312 }
313
314 /*
315         JSCollect - trigger garbage collection
316 */
317 void JSCollect(void)
318 {
319 #if JAG_PINK_OR_LATER
320     InterpreterLock lock;
321         Collector::collect();
322 #endif
323 }
324
325 /*
326         JSTypeGetCFArrayCallBacks
327 */
328 void JSTypeGetCFArrayCallBacks(CFArrayCallBacks* outCallBacks)
329 {
330         if (outCallBacks)
331         {
332                 outCallBacks->version = 1;
333                 outCallBacks->retain = (CFArrayRetainCallBack)JSCFRetain;
334                 outCallBacks->release = (CFArrayReleaseCallBack)JSCFRelease;
335                 outCallBacks->copyDescription = (CFArrayCopyDescriptionCallBack)JSCopyDescription;
336                 outCallBacks->equal = (CFArrayEqualCallBack)JSEqual;
337         }
338 }
339
340
341 /*
342         JSCFRetain
343 */
344 void* JSCFRetain(CFAllocatorRef allocator, const void *value)
345 {
346         JSRetain((JSTypeRef)value);
347         return (void*)value;
348 }
349
350 /*
351         JSCFRelease
352 */
353 void JSCFRelease(CFAllocatorRef allocator, const void *value)
354 {
355         JSRelease((JSTypeRef)value);
356 }
357
358
359 /*
360         JSObjectCreateWithCFType
361 */
362 JSObjectRef JSObjectCreateWithCFType(CFTypeRef inRef)
363 {
364         JSObjectCallBacks callBacks;
365         JSObjectRef cfJSObject = nil;
366         if (inRef)
367         {
368                 callBacks.dispose = CFJSObjectDispose;
369                 callBacks.equal = CFJSObjectEqual;
370                 callBacks.copyCFValue = CFJSObjectCopyCFValue;
371                 callBacks.copyProperty = CFJSObjectCopyProperty;
372                 callBacks.setProperty = CFJSObjectSetProperty;
373                 callBacks.callFunction = NULL;
374                 callBacks.copyPropertyNames = CFJSObjectCopyPropertyNames;
375                 cfJSObject = JSObjectCreateInternal((void*)CFRetain(inRef), &callBacks, NULL, kJSUserObjectDataTypeCFType );
376         }
377         return cfJSObject;
378 }
379
380 /*
381         CFJSObjectDispose
382 */
383 void CFJSObjectDispose(void* data)
384 {
385         if (data)
386         {
387                 CFRelease((JSTypeRef)data);
388         }
389 }
390
391 CFArrayRef JSObjectCopyPropertyNames(JSObjectRef ref)
392 {
393         CFArrayRef result = NULL;
394         JSUserObject* ptr = (JSUserObject*)ref;
395         if (ptr && (ptr->GetTypeID() == kJSObjectTypeID))
396         {
397                 result = ptr->CopyPropertyNames();
398         }
399         return result;
400 }
401 /*
402         CFJSObjectCopyProperty
403 */
404 JSObjectRef CFJSObjectCopyProperty(void* data, CFStringRef propertyName)
405 {
406         JSObjectRef result = NULL;
407         if (data && propertyName)
408         {
409                 CFTypeRef cfResult = NULL;
410                 if (CFGetTypeID(data) == CFDictionaryGetTypeID())
411                 {
412                         if (CFStringCompare(propertyName, CFSTR("length"), 0) == kCFCompareEqualTo)
413                         {
414                                 int len = CFDictionaryGetCount((CFDictionaryRef)data);
415                                 cfResult = CFNumberCreate(NULL, kCFNumberIntType, &len);
416                         }
417                         else
418                         {
419                                 cfResult = RetainCFType(CFDictionaryGetValue((CFDictionaryRef)data, propertyName));
420                         }
421                 }
422                 else if (CFGetTypeID(data) == CFArrayGetTypeID())
423                 {
424                         if (CFStringCompare(propertyName, CFSTR("length"), 0) == kCFCompareEqualTo)
425                         {
426                                 int len = CFArrayGetCount((CFArrayRef)data);
427                                 cfResult = CFNumberCreate(NULL, kCFNumberIntType, &len);
428                         }
429                         else
430                         {
431                                 SInt32 index = CFStringGetIntValue(propertyName);       
432                                 CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
433                                 if (index >= 0 && index < arrayCount)
434                                 {
435                                         cfResult = RetainCFType(CFArrayGetValueAtIndex((CFArrayRef)data, index));
436                                 }
437                         }
438                 }
439                 else if (CFGetTypeID(data) == CFStringGetTypeID())
440                 {
441                         if (CFStringCompare(propertyName, CFSTR("length"), 0) == kCFCompareEqualTo)
442                         {
443                                 int len = CFStringGetLength((CFStringRef)data);
444                                 cfResult = CFNumberCreate(NULL, kCFNumberIntType, &len);
445                         }
446                 }
447                 if (cfResult)
448                 {
449                         result = JSObjectCreateWithCFType(cfResult);
450                         CFRelease(cfResult);
451                 }
452         }
453         return result;
454 }
455
456
457 /*
458         CFJSObjectSetProperty
459 */
460 void CFJSObjectSetProperty(void* data, CFStringRef propertyName, JSObjectRef jsValue)
461 {
462         if (data && propertyName)
463         {
464                 CFTypeRef cfValue = JSObjectCopyCFValue(jsValue);
465
466                 if (cfValue)
467                 {
468                         if (CFGetTypeID(data) == CFDictionaryGetTypeID())
469                         {
470                                 CFDictionarySetValue((CFMutableDictionaryRef)data, propertyName, cfValue);
471                         }
472                         else if (CFGetTypeID(data) == CFArrayGetTypeID())
473                         {
474                                 SInt32 index = CFStringGetIntValue(propertyName);       
475                                 CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
476                                 if (index >= 0)
477                                 {
478                                         for (; arrayCount < index; arrayCount++)
479                                         {
480                                                 CFArrayAppendValue((CFMutableArrayRef)data, GetCFNull());
481                                         }
482                                         CFArraySetValueAtIndex((CFMutableArrayRef)data, index, cfValue);                                        
483                                 }
484                         }               
485                         CFRelease(cfValue);
486                 }
487                 else
488                 {
489                         if (CFGetTypeID(data) == CFDictionaryGetTypeID())
490                         {
491                                 CFDictionaryRemoveValue((CFMutableDictionaryRef)data, propertyName);
492                         }
493                         else if (CFGetTypeID(data) == CFArrayGetTypeID())
494                         {
495                                 SInt32 index = CFStringGetIntValue(propertyName);                               
496                                 CFIndex arrayCount = CFArrayGetCount((CFArrayRef)data);
497                                 if (index >= 0)
498                                 {
499                                         for (; arrayCount < index; arrayCount++)
500                                         {
501                                                 CFArrayAppendValue((CFMutableArrayRef)data, GetCFNull());
502                                         }
503                                         CFArraySetValueAtIndex((CFMutableArrayRef)data, index, GetCFNull());                                    
504                                 }                               
505                         }
506                 }
507         }
508 }
509
510
511 /*
512         CFJSObjectCopyCFValue
513 */
514 CFTypeRef CFJSObjectCopyCFValue(void* data)
515 {
516         CFTypeRef result = NULL;
517         if (data)
518         {
519                 result = (CFTypeRef)CFRetain(data);
520         }
521         return result;
522 }
523
524 /*
525         CFJSObjectCopyCFValue
526 */
527 UInt8 CFJSObjectEqual(void* data1, void* data2)
528 {
529         UInt8 result = false;
530         if (data1 && data2)
531         {
532                 CFEqual((CFTypeRef)data1, (CFTypeRef)data2);
533         }
534         return result;
535 }
536
537
538 /*
539         CFJSObjectCopyPropertyNames
540 */
541 CFArrayRef CFJSObjectCopyPropertyNames(void* data)
542 {
543         CFMutableArrayRef result = NULL;
544         if (data)
545         {
546                 CFTypeID cfType = CFGetTypeID(data);
547                 if (cfType == CFDictionaryGetTypeID())
548                 {
549                         CFIndex count = CFDictionaryGetCount((CFDictionaryRef)data);
550                         if (count)
551                         {
552                                 CFTypeRef* keys = (CFTypeRef*)malloc(sizeof(CFTypeRef)*count);
553                                 if (keys)
554                                 {
555                                         int i;
556                                         CFDictionaryGetKeysAndValues((CFDictionaryRef)data, (const void **)keys, NULL);
557                                         for (i = 0; i < count; i++)
558                                         {
559                                                 CFStringRef key = (CFStringRef)keys[i];
560                                                 if (CFGetTypeID(key) != CFStringGetTypeID()) continue;
561
562                                                 if (!result) result = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
563                                                 if (!result) continue;
564                                                 
565                                                 CFArrayAppendValue(result, key);
566                                         }
567                                         free(keys);
568                                 }
569                         }
570                 }
571         }
572         return result;
573 }
574
575
576
577
578 CFMutableArrayRef JSCreateCFArrayFromJSArray(CFArrayRef array)
579 {
580         CFIndex count = array ? CFArrayGetCount(array) : 0;
581         CFMutableArrayRef cfArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
582         CFIndex i;
583
584         for (i = 0; cfArray && i <  count; i++)
585         {
586                 JSObjectRef jsValue = (JSObjectRef)CFArrayGetValueAtIndex(array, i);
587                 CFTypeRef cfvalue = JSObjectCopyCFValue(jsValue);
588                 if (cfvalue)
589                 {
590                         CFArrayAppendValue(cfArray, cfvalue);
591                         CFRelease(cfvalue);
592                 }
593                 else
594                 {
595                         CFArrayAppendValue(cfArray, GetCFNull());
596                 }
597         }
598         return cfArray;
599 }
600
601 CFMutableArrayRef JSCreateJSArrayFromCFArray(CFArrayRef array)
602 {
603         CFIndex count = array ? CFArrayGetCount(array) : 0;
604         CFArrayCallBacks arrayCallbacks;
605         CFMutableArrayRef jsArray;
606         CFIndex i;
607
608         JSTypeGetCFArrayCallBacks(&arrayCallbacks);
609         jsArray = CFArrayCreateMutable(NULL, 0, &arrayCallbacks);
610
611         for (i = 0; array && i <  count; i++)
612         {
613                 CFTypeRef cfValue = (CFTypeRef)CFArrayGetValueAtIndex(array, i);
614                 JSObjectRef jsValue = JSObjectCreateWithCFType(cfValue);
615                 
616                 if (!jsValue) jsValue = JSObjectCreateWithCFType(GetCFNull());
617                 if (jsValue)
618                 {
619                         CFArrayAppendValue(jsArray, jsValue);
620                         JSRelease(jsValue);
621                 }
622         }
623         return jsArray;
624 }
625
626
627 void JSLockInterpreter()
628 {
629 #if JAG_PINK_OR_LATER
630         Interpreter::lock();
631 #endif
632 }
633
634
635 void JSUnlockInterpreter()
636 {
637 #if JAG_PINK_OR_LATER
638         Interpreter::unlock();
639 #endif
640 }
641