33#include <stdlib.h>
44#include <stdio.h>
55#include <string.h>
6+ #include <pthread.h>
67
78#include <dlfcn.h>
89#ifndef __APPLE__
@@ -59,7 +60,8 @@ typedef struct g_proxy_execute_jscore_s {
5960 void (* JSGarbageCollect )(JSContextRef ctx );
6061} g_proxy_execute_jscore_s ;
6162
62- g_proxy_execute_jscore_s g_proxy_execute_jscore ;
63+ static g_proxy_execute_jscore_s g_proxy_execute_jscore ;
64+ static pthread_once_t g_proxy_execute_jscore_init_flag = PTHREAD_ONCE_INIT ;
6365
6466typedef struct proxy_execute_jscore_s {
6567 // Execute error
@@ -139,6 +141,136 @@ static void js_print_exception(JSContextRef ctx, JSValueRef exception) {
139141 }
140142}
141143
144+ void proxy_execute_jscore_delayed_init (void ) {
145+ #ifdef __APPLE__
146+ g_proxy_execute_jscore .module = dlopen (
147+ "/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/JavaScriptCore" , RTLD_LAZY | RTLD_LOCAL );
148+ #else
149+ const char * library_names [] = {"libjavascriptcoregtk-4.1.so.0" , "libjavascriptcoregtk-4.0.so.18" ,
150+ "libjavascriptcoregtk-3.0.so.0" , "libjavascriptcoregtk-1.0.so.0" };
151+ const size_t library_names_size = sizeof (library_names ) / sizeof (library_names [0 ]);
152+
153+ // Use existing JavaScriptCoreGTK if already loaded
154+ struct link_map * map = NULL ;
155+ void * current_process = dlopen (0 , RTLD_LAZY );
156+ if (!current_process )
157+ return ;
158+ if (dlinfo (current_process , RTLD_DI_LINKMAP , & map ) == 0 ) {
159+ while (map && !g_proxy_execute_jscore .module ) {
160+ for (size_t i = 0 ; i < library_names_size ; i ++ ) {
161+ if (strstr (map -> l_name , library_names [i ])) {
162+ g_proxy_execute_jscore .module = dlopen (map -> l_name , RTLD_NOLOAD | RTLD_LAZY | RTLD_LOCAL );
163+ break ;
164+ }
165+ }
166+ map = map -> l_next ;
167+ }
168+ }
169+ dlclose (current_process );
170+
171+ // Load the first available version of the JavaScriptCoreGTK
172+ for (size_t i = 0 ; !g_proxy_execute_jscore .module && i < library_names_size ; i ++ ) {
173+ g_proxy_execute_jscore .module = dlopen (library_names [i ], RTLD_LAZY | RTLD_LOCAL );
174+ }
175+ #endif
176+
177+ if (!g_proxy_execute_jscore .module )
178+ return ;
179+
180+ // Class functions
181+ g_proxy_execute_jscore .JSClassCreate = dlsym (g_proxy_execute_jscore .module , "JSClassCreate" );
182+ if (!g_proxy_execute_jscore .JSClassCreate )
183+ goto jscore_init_error ;
184+ // Object functions
185+ g_proxy_execute_jscore .JSObjectMake = dlsym (g_proxy_execute_jscore .module , "JSObjectMake" );
186+ if (!g_proxy_execute_jscore .JSObjectMake )
187+ goto jscore_init_error ;
188+ g_proxy_execute_jscore .JSObjectMakeFunctionWithCallback =
189+ dlsym (g_proxy_execute_jscore .module , "JSObjectMakeFunctionWithCallback" );
190+ if (!g_proxy_execute_jscore .JSObjectMakeFunctionWithCallback )
191+ goto jscore_init_error ;
192+ g_proxy_execute_jscore .JSObjectGetProperty = dlsym (g_proxy_execute_jscore .module , "JSObjectGetProperty" );
193+ if (!g_proxy_execute_jscore .JSObjectGetProperty )
194+ goto jscore_init_error ;
195+ g_proxy_execute_jscore .JSObjectSetProperty = dlsym (g_proxy_execute_jscore .module , "JSObjectSetProperty" );
196+ if (!g_proxy_execute_jscore .JSObjectSetProperty )
197+ goto jscore_init_error ;
198+ g_proxy_execute_jscore .JSObjectGetPrivate = dlsym (g_proxy_execute_jscore .module , "JSObjectGetPrivate" );
199+ if (!g_proxy_execute_jscore .JSObjectGetPrivate )
200+ goto jscore_init_error ;
201+ g_proxy_execute_jscore .JSObjectSetPrivate = dlsym (g_proxy_execute_jscore .module , "JSObjectSetPrivate" );
202+ if (!g_proxy_execute_jscore .JSObjectSetPrivate )
203+ goto jscore_init_error ;
204+ // Context functions
205+ g_proxy_execute_jscore .JSContextGetGlobalObject = dlsym (g_proxy_execute_jscore .module , "JSContextGetGlobalObject" );
206+ if (!g_proxy_execute_jscore .JSContextGetGlobalObject )
207+ goto jscore_init_error ;
208+ // Value functions
209+ g_proxy_execute_jscore .JSValueIsString = dlsym (g_proxy_execute_jscore .module , "JSValueIsString" );
210+ if (!g_proxy_execute_jscore .JSValueIsString )
211+ goto jscore_init_error ;
212+ g_proxy_execute_jscore .JSValueIsNumber = dlsym (g_proxy_execute_jscore .module , "JSValueIsNumber" );
213+ if (!g_proxy_execute_jscore .JSValueIsNumber )
214+ goto jscore_init_error ;
215+ g_proxy_execute_jscore .JSValueToObject = dlsym (g_proxy_execute_jscore .module , "JSValueToObject" );
216+ if (!g_proxy_execute_jscore .JSValueToObject )
217+ goto jscore_init_error ;
218+ g_proxy_execute_jscore .JSValueToStringCopy = dlsym (g_proxy_execute_jscore .module , "JSValueToStringCopy" );
219+ if (!g_proxy_execute_jscore .JSValueToStringCopy )
220+ goto jscore_init_error ;
221+ g_proxy_execute_jscore .JSValueToNumber = dlsym (g_proxy_execute_jscore .module , "JSValueToNumber" );
222+ if (!g_proxy_execute_jscore .JSValueToNumber )
223+ goto jscore_init_error ;
224+ g_proxy_execute_jscore .JSValueMakeNull = dlsym (g_proxy_execute_jscore .module , "JSValueMakeNull" );
225+ if (!g_proxy_execute_jscore .JSValueMakeNull )
226+ goto jscore_init_error ;
227+ g_proxy_execute_jscore .JSValueMakeBoolean = dlsym (g_proxy_execute_jscore .module , "JSValueMakeBoolean" );
228+ if (!g_proxy_execute_jscore .JSValueMakeBoolean )
229+ goto jscore_init_error ;
230+ g_proxy_execute_jscore .JSValueMakeString = dlsym (g_proxy_execute_jscore .module , "JSValueMakeString" );
231+ if (!g_proxy_execute_jscore .JSValueMakeString )
232+ goto jscore_init_error ;
233+ // String functions
234+ g_proxy_execute_jscore .JSStringCreateWithUTF8CString =
235+ dlsym (g_proxy_execute_jscore .module , "JSStringCreateWithUTF8CString" );
236+ if (!g_proxy_execute_jscore .JSStringCreateWithUTF8CString )
237+ goto jscore_init_error ;
238+ g_proxy_execute_jscore .JSStringGetUTF8CString = dlsym (g_proxy_execute_jscore .module , "JSStringGetUTF8CString" );
239+ if (!g_proxy_execute_jscore .JSStringGetUTF8CString )
240+ goto jscore_init_error ;
241+ g_proxy_execute_jscore .JSStringGetMaximumUTF8CStringSize =
242+ dlsym (g_proxy_execute_jscore .module , "JSStringGetMaximumUTF8CStringSize" );
243+ if (!g_proxy_execute_jscore .JSStringGetMaximumUTF8CStringSize )
244+ goto jscore_init_error ;
245+ g_proxy_execute_jscore .JSStringGetMaximumUTF8CStringSize =
246+ dlsym (g_proxy_execute_jscore .module , "JSStringGetMaximumUTF8CStringSize" );
247+ if (!g_proxy_execute_jscore .JSStringGetMaximumUTF8CStringSize )
248+ goto jscore_init_error ;
249+ g_proxy_execute_jscore .JSStringRelease = dlsym (g_proxy_execute_jscore .module , "JSStringRelease" );
250+ if (!g_proxy_execute_jscore .JSStringRelease )
251+ goto jscore_init_error ;
252+ // Global context functions
253+ g_proxy_execute_jscore .JSGlobalContextCreate = dlsym (g_proxy_execute_jscore .module , "JSGlobalContextCreate" );
254+ if (!g_proxy_execute_jscore .JSGlobalContextCreate )
255+ goto jscore_init_error ;
256+ g_proxy_execute_jscore .JSGlobalContextRelease = dlsym (g_proxy_execute_jscore .module , "JSGlobalContextRelease" );
257+ if (!g_proxy_execute_jscore .JSGlobalContextRelease )
258+ goto jscore_init_error ;
259+ // Execute functions
260+ g_proxy_execute_jscore .JSEvaluateScript = dlsym (g_proxy_execute_jscore .module , "JSEvaluateScript" );
261+ if (!g_proxy_execute_jscore .JSEvaluateScript )
262+ goto jscore_init_error ;
263+ // Garbage collection functions
264+ g_proxy_execute_jscore .JSGarbageCollect = dlsym (g_proxy_execute_jscore .module , "JSGarbageCollect" );
265+ if (!g_proxy_execute_jscore .JSGarbageCollect )
266+ goto jscore_init_error ;
267+
268+ return ;
269+
270+ jscore_init_error :
271+ proxy_execute_jscore_global_cleanup ();
272+ }
273+
142274static JSValueRef proxy_execute_jscore_dns_resolve (JSContextRef ctx , JSObjectRef function , JSObjectRef object ,
143275 size_t argc , const JSValueRef argv [], JSValueRef * exception ) {
144276 if (argc != 1 )
@@ -354,6 +486,9 @@ int32_t proxy_execute_jscore_get_error(void *ctx) {
354486}
355487
356488void * proxy_execute_jscore_create (void ) {
489+ pthread_once (& g_proxy_execute_jscore_init_flag , proxy_execute_jscore_delayed_init );
490+ if (!g_proxy_execute_jscore .module )
491+ return NULL ;
357492 proxy_execute_jscore_s * proxy_execute = (proxy_execute_jscore_s * )calloc (1 , sizeof (proxy_execute_jscore_s ));
358493 return proxy_execute ;
359494}
@@ -373,136 +508,9 @@ bool proxy_execute_jscore_delete(void **ctx) {
373508/*********************************************************************/
374509
375510bool proxy_execute_jscore_global_init (void ) {
376- if (g_proxy_execute_jscore .module )
377- return true;
378- #ifdef __APPLE__
379- g_proxy_execute_jscore .module = dlopen (
380- "/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/JavaScriptCore" , RTLD_LAZY | RTLD_LOCAL );
381- #else
382- const char * library_names [] = {"libjavascriptcoregtk-4.1.so.0" , "libjavascriptcoregtk-4.0.so.18" ,
383- "libjavascriptcoregtk-3.0.so.0" , "libjavascriptcoregtk-1.0.so.0" };
384- const size_t library_names_size = sizeof (library_names ) / sizeof (library_names [0 ]);
385-
386- // Use existing JavaScriptCoreGTK if already loaded
387- struct link_map * map = NULL ;
388- void * current_process = dlopen (0 , RTLD_LAZY );
389- if (!current_process )
390- return false;
391- if (dlinfo (current_process , RTLD_DI_LINKMAP , & map ) == 0 ) {
392- while (map && !g_proxy_execute_jscore .module ) {
393- for (size_t i = 0 ; i < library_names_size ; i ++ ) {
394- if (strstr (map -> l_name , library_names [i ])) {
395- g_proxy_execute_jscore .module = dlopen (map -> l_name , RTLD_NOLOAD | RTLD_LAZY | RTLD_LOCAL );
396- break ;
397- }
398- }
399- map = map -> l_next ;
400- }
401- }
402- dlclose (current_process );
403-
404- // Load the first available version of the JavaScriptCoreGTK
405- for (size_t i = 0 ; !g_proxy_execute_jscore .module && i < library_names_size ; i ++ ) {
406- g_proxy_execute_jscore .module = dlopen (library_names [i ], RTLD_LAZY | RTLD_LOCAL );
407- }
408- #endif
409-
410- if (!g_proxy_execute_jscore .module )
411- return false;
412-
413- // Class functions
414- g_proxy_execute_jscore .JSClassCreate = dlsym (g_proxy_execute_jscore .module , "JSClassCreate" );
415- if (!g_proxy_execute_jscore .JSClassCreate )
416- goto jscore_init_error ;
417- // Object functions
418- g_proxy_execute_jscore .JSObjectMake = dlsym (g_proxy_execute_jscore .module , "JSObjectMake" );
419- if (!g_proxy_execute_jscore .JSObjectMake )
420- goto jscore_init_error ;
421- g_proxy_execute_jscore .JSObjectMakeFunctionWithCallback =
422- dlsym (g_proxy_execute_jscore .module , "JSObjectMakeFunctionWithCallback" );
423- if (!g_proxy_execute_jscore .JSObjectMakeFunctionWithCallback )
424- goto jscore_init_error ;
425- g_proxy_execute_jscore .JSObjectGetProperty = dlsym (g_proxy_execute_jscore .module , "JSObjectGetProperty" );
426- if (!g_proxy_execute_jscore .JSObjectGetProperty )
427- goto jscore_init_error ;
428- g_proxy_execute_jscore .JSObjectSetProperty = dlsym (g_proxy_execute_jscore .module , "JSObjectSetProperty" );
429- if (!g_proxy_execute_jscore .JSObjectSetProperty )
430- goto jscore_init_error ;
431- g_proxy_execute_jscore .JSObjectGetPrivate = dlsym (g_proxy_execute_jscore .module , "JSObjectGetPrivate" );
432- if (!g_proxy_execute_jscore .JSObjectGetPrivate )
433- goto jscore_init_error ;
434- g_proxy_execute_jscore .JSObjectSetPrivate = dlsym (g_proxy_execute_jscore .module , "JSObjectSetPrivate" );
435- if (!g_proxy_execute_jscore .JSObjectSetPrivate )
436- goto jscore_init_error ;
437- // Context functions
438- g_proxy_execute_jscore .JSContextGetGlobalObject = dlsym (g_proxy_execute_jscore .module , "JSContextGetGlobalObject" );
439- if (!g_proxy_execute_jscore .JSContextGetGlobalObject )
440- goto jscore_init_error ;
441- // Value functions
442- g_proxy_execute_jscore .JSValueIsString = dlsym (g_proxy_execute_jscore .module , "JSValueIsString" );
443- if (!g_proxy_execute_jscore .JSValueIsString )
444- goto jscore_init_error ;
445- g_proxy_execute_jscore .JSValueIsNumber = dlsym (g_proxy_execute_jscore .module , "JSValueIsNumber" );
446- if (!g_proxy_execute_jscore .JSValueIsNumber )
447- goto jscore_init_error ;
448- g_proxy_execute_jscore .JSValueToObject = dlsym (g_proxy_execute_jscore .module , "JSValueToObject" );
449- if (!g_proxy_execute_jscore .JSValueToObject )
450- goto jscore_init_error ;
451- g_proxy_execute_jscore .JSValueToStringCopy = dlsym (g_proxy_execute_jscore .module , "JSValueToStringCopy" );
452- if (!g_proxy_execute_jscore .JSValueToStringCopy )
453- goto jscore_init_error ;
454- g_proxy_execute_jscore .JSValueToNumber = dlsym (g_proxy_execute_jscore .module , "JSValueToNumber" );
455- if (!g_proxy_execute_jscore .JSValueToNumber )
456- goto jscore_init_error ;
457- g_proxy_execute_jscore .JSValueMakeNull = dlsym (g_proxy_execute_jscore .module , "JSValueMakeNull" );
458- if (!g_proxy_execute_jscore .JSValueMakeNull )
459- goto jscore_init_error ;
460- g_proxy_execute_jscore .JSValueMakeBoolean = dlsym (g_proxy_execute_jscore .module , "JSValueMakeBoolean" );
461- if (!g_proxy_execute_jscore .JSValueMakeBoolean )
462- goto jscore_init_error ;
463- g_proxy_execute_jscore .JSValueMakeString = dlsym (g_proxy_execute_jscore .module , "JSValueMakeString" );
464- if (!g_proxy_execute_jscore .JSValueMakeString )
465- goto jscore_init_error ;
466- // String functions
467- g_proxy_execute_jscore .JSStringCreateWithUTF8CString =
468- dlsym (g_proxy_execute_jscore .module , "JSStringCreateWithUTF8CString" );
469- if (!g_proxy_execute_jscore .JSStringCreateWithUTF8CString )
470- goto jscore_init_error ;
471- g_proxy_execute_jscore .JSStringGetUTF8CString = dlsym (g_proxy_execute_jscore .module , "JSStringGetUTF8CString" );
472- if (!g_proxy_execute_jscore .JSStringGetUTF8CString )
473- goto jscore_init_error ;
474- g_proxy_execute_jscore .JSStringGetMaximumUTF8CStringSize =
475- dlsym (g_proxy_execute_jscore .module , "JSStringGetMaximumUTF8CStringSize" );
476- if (!g_proxy_execute_jscore .JSStringGetMaximumUTF8CStringSize )
477- goto jscore_init_error ;
478- g_proxy_execute_jscore .JSStringGetMaximumUTF8CStringSize =
479- dlsym (g_proxy_execute_jscore .module , "JSStringGetMaximumUTF8CStringSize" );
480- if (!g_proxy_execute_jscore .JSStringGetMaximumUTF8CStringSize )
481- goto jscore_init_error ;
482- g_proxy_execute_jscore .JSStringRelease = dlsym (g_proxy_execute_jscore .module , "JSStringRelease" );
483- if (!g_proxy_execute_jscore .JSStringRelease )
484- goto jscore_init_error ;
485- // Global context functions
486- g_proxy_execute_jscore .JSGlobalContextCreate = dlsym (g_proxy_execute_jscore .module , "JSGlobalContextCreate" );
487- if (!g_proxy_execute_jscore .JSGlobalContextCreate )
488- goto jscore_init_error ;
489- g_proxy_execute_jscore .JSGlobalContextRelease = dlsym (g_proxy_execute_jscore .module , "JSGlobalContextRelease" );
490- if (!g_proxy_execute_jscore .JSGlobalContextRelease )
491- goto jscore_init_error ;
492- // Execute functions
493- g_proxy_execute_jscore .JSEvaluateScript = dlsym (g_proxy_execute_jscore .module , "JSEvaluateScript" );
494- if (!g_proxy_execute_jscore .JSEvaluateScript )
495- goto jscore_init_error ;
496- // Garbage collection functions
497- g_proxy_execute_jscore .JSGarbageCollect = dlsym (g_proxy_execute_jscore .module , "JSGarbageCollect" );
498- if (!g_proxy_execute_jscore .JSGarbageCollect )
499- goto jscore_init_error ;
500-
511+ // JSCoreGTK will be initialized with a delay to avoid conflicts with the
512+ // loaded JSCoreGTK in a user application after this function.
501513 return true;
502-
503- jscore_init_error :
504- proxy_execute_jscore_global_cleanup ();
505- return false;
506514}
507515
508516bool proxy_execute_jscore_global_cleanup (void ) {
0 commit comments