/* * QuickJS C library * * Copyright (c) 2017-2020 Fabrice Bellard * Copyright (c) 2017-2020 Charlie Gordon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <inttypes.h>#include <string.h>#include <assert.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <sys/time.h>#include <time.h>#include <signal.h>#include <limits.h>#include <sys/stat.h>#include <dirent.h>#if defined(_WIN32)#include <windows.h>#include <conio.h>#include <utime.h>#else#include <dlfcn.h>#include <termios.h>#include <sys/ioctl.h>#include <sys/wait.h> #if defined(__APPLE__)typedef sig_t sighandler_t;#if !defined(environ)#include <crt_externs.h>#define environ (*_NSGetEnviron())#endif#endif /* __APPLE__ */ #endif #if !defined(_WIN32) && !defined(__plan9__)/* enable the os.Worker API. IT relies on POSIX threads */#define USE_WORKER#endif #ifdef USE_WORKER#include <pthread.h>#include <stdatomic.h>#endif #include "cutils.h"#include "list.h"#include "quickjs-libc.h" /* TODO: - add socket calls*/ typedef struct { struct list_head link; int fd; JSValue rw_func[2];} JSOSRWHandler; typedef struct { struct list_head link; int sig_num; JSValue func;} JSOSSignalHandler; typedef struct { struct list_head link; BOOL has_object; int64_t timeout; JSValue func;} JSOSTimer; typedef struct { struct list_head link; uint8_t *data; size_t data_len; /* list of SharedArrayBuffers, necessary to free the message */ uint8_t **sab_tab; size_t sab_tab_len;} JSWorkerMessage; typedef struct { int ref_count;#ifdef USE_WORKER pthread_mutex_t mutex;#endif struct list_head msg_queue; /* list of JSWorkerMessage.link */ int read_fd; int write_fd;} JSWorkerMessagePipe; typedef struct { struct list_head link; JSWorkerMessagePipe *recv_pipe; JSValue on_message_func;} JSWorkerMessageHandler; typedef struct JSThreadState { struct list_head os_rw_handlers; /* list of JSOSRWHandler.link */ struct list_head os_signal_handlers; /* list JSOSSignalHandler.link */ struct list_head os_timers; /* list of JSOSTimer.link */ struct list_head port_list; /* list of JSWorkerMessageHandler.link */ int eval_script_recurse; /* only used in the main thread */ /* not used in the main thread */ JSWorkerMessagePipe *recv_pipe, *send_pipe;} JSThreadState; static uint64_t os_pending_signals;static int (*os_poll_func)(JSContext *ctx); static void js_std_dbuf_init(JSContext *ctx, DynBuf *s){ dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc *)js_realloc_rt);} static BOOL my_isdigit(int c){ return (c >= '0' && c <= '9');} static JSValue js_printf_internal(JSContext *ctx, int argc, JSValueConst *argv, FILE *fp){ char fmtbuf[32]; uint8_t cbuf[UTF8_CHAR_LEN_MAX+1]; JSValue res; DynBuf dbuf; const char *fmt_str; const uint8_t *fmt, *fmt_end; const uint8_t *p; char *q; int i, c, len, mod; size_t fmt_len; int32_t int32_arg; int64_t int64_arg; double double_arg; const char *string_arg; /* Use indirect call to dbuf_printf to prevent gcc warning */ int (*dbuf_printf_fun)(DynBuf *s, const char *fmt, ...) = (void*)dbuf_printf; js_std_dbuf_init(ctx, &dbuf); if (argc > 0) { fmt_str = JS_ToCStringLen(ctx, &fmt_len, argv[0]); if (!fmt_str) goto fail; i = 1; fmt = (const uint8_t *)fmt_str; fmt_end = fmt + fmt_len; while (fmt < fmt_end) { for (p = fmt; fmt < fmt_end && *fmt != '%'; fmt++) continue; dbuf_put(&dbuf, p, fmt - p); if (fmt >= fmt_end) break; q = fmtbuf; *q++ = *fmt++; /* copy '%' */ /* flags */ for(;;) { c = *fmt; if (c == '0' || c == '#' || c == '+' || c == '-' || c == ' ' || c == '\'') { if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = c; fmt++; } else { break; } } /* width */ if (*fmt == '*') { if (i >= argc) goto missing; if (JS_ToInt32(ctx, &int32_arg, argv[i++])) goto fail; q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg); fmt++; } else { while (my_isdigit(*fmt)) { if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = *fmt++; } } if (*fmt == '.') { if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = *fmt++; if (*fmt == '*') { if (i >= argc) goto missing; if (JS_ToInt32(ctx, &int32_arg, argv[i++])) goto fail; q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg); fmt++; } else { while (my_isdigit(*fmt)) { if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = *fmt++; } } } /* we only support the "l" modifier for 64 bit numbers */ mod = ' '; if (*fmt == 'l') { mod = *fmt++; } /* type */ c = *fmt++; if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = c; *q = '\0'; switch (c) { case 'c': if (i >= argc) goto missing; if (JS_IsString(argv[i])) { string_arg = JS_ToCString(ctx, argv[i++]); if (!string_arg) goto fail; int32_arg = unicode_from_utf8((uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p); JS_FreeCString(ctx, string_arg); } else { if (JS_ToInt32(ctx, &int32_arg, argv[i++])) goto fail; } /* handle utf-8 encoding explicitly */ if ((unsigned)int32_arg > 0x10FFFF) int32_arg = 0xFFFD; /* ignore conversion flags, width and precision */ len = unicode_to_utf8(cbuf, int32_arg); dbuf_put(&dbuf, cbuf, len); break; case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': if (i >= argc) goto missing; if (JS_ToInt64Ext(ctx, &int64_arg, argv[i++])) goto fail; if (mod == 'l') { /* 64 bit number */#if defined(_WIN32) if (q >= fmtbuf + sizeof(fmtbuf) - 3) goto invalid; q[2] = q[-1]; q[-1] = 'I'; q[0] = '6'; q[1] = '4'; q[3] = '\0'; dbuf_printf_fun(&dbuf, fmtbuf, (int64_t)int64_arg);#else if (q >= fmtbuf + sizeof(fmtbuf) - 2) goto invalid; q[1] = q[-1]; q[-1] = q[0] = 'l'; q[2] = '\0'; dbuf_printf_fun(&dbuf, fmtbuf, (long long)int64_arg);#endif } else { dbuf_printf_fun(&dbuf, fmtbuf, (int)int64_arg); } break; case 's': if (i >= argc) goto missing; /* XXX: handle strings containing null characters */ string_arg = JS_ToCString(ctx, argv[i++]); if (!string_arg) goto fail; dbuf_printf_fun(&dbuf, fmtbuf, string_arg); JS_FreeCString(ctx, string_arg); break; case 'e': case 'f': case 'g': case 'a': case 'E': case 'F': case 'G': case 'A': if (i >= argc) goto missing; if (JS_ToFloat64(ctx, &double_arg, argv[i++])) goto fail; dbuf_printf_fun(&dbuf, fmtbuf, double_arg); break; case '%': dbuf_putc(&dbuf, '%'); break; default: /* XXX: should support an extension mechanism */ invalid: JS_ThrowTypeError(ctx, "invalid conversion specifier in format string"); goto fail; missing: JS_ThrowReferenceError(ctx, "missing argument for conversion specifier"); goto fail; } } JS_FreeCString(ctx, fmt_str); } if (dbuf.error) { res = JS_ThrowOutOfMemory(ctx); } else { if (fp) { len = fwrite(dbuf.buf, 1, dbuf.size, fp); res = JS_NewInt32(ctx, len); } else { res = JS_NewStringLen(ctx, (char *)dbuf.buf, dbuf.size); } } dbuf_free(&dbuf); return res; fail: dbuf_free(&dbuf); return JS_EXCEPTION;} uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename){ FILE *f; uint8_t *buf; size_t buf_len; long lret; f = fopen(filename, "rb"); if (!f) return NULL; if (fseek(f, 0, SEEK_END) < 0) goto fail; lret = ftell(f); if (lret < 0) goto fail; /* XXX: on Linux, ftell() return LONG_MAX for directories */ if (lret == LONG_MAX) { errno = EISDIR; goto fail; } buf_len = lret; if (fseek(f, 0, SEEK_SET) < 0) goto fail; if (ctx) buf = js_malloc(ctx, buf_len + 1); else buf = malloc(buf_len + 1); if (!buf) goto fail; if (fread(buf, 1, buf_len, f) != buf_len) { errno = EIO; if (ctx) js_free(ctx, buf); else free(buf); fail: fclose(f); return NULL; } buf[buf_len] = '\0'; fclose(f); *pbuf_len = buf_len; return buf;} /* load and evaluate a file */static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){ uint8_t *buf; const char *filename; JSValue ret; size_t buf_len; filename = JS_ToCString(ctx, argv[0]); if (!filename) return JS_EXCEPTION; buf = js_load_file(ctx, &buf_len, filename); if (!buf) { JS_ThrowReferenceError(ctx, "could not load '%s'", filename); JS_FreeCString(ctx, filename); return JS_EXCEPTION; } ret = JS_Eval(ctx, (char *)buf, buf_len, filename, JS_EVAL_TYPE_GLOBAL); js_free(ctx, buf); JS_FreeCString(ctx, filename); return ret;} /* load a file as a UTF-8 encoded string */static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){ uint8_t *buf; const char *filename; JSValue ret; size_t buf_len; filename = JS_ToCString(ctx, argv[0]); if (!filename) return JS_EXCEPTION; buf = js_load_file(ctx, &buf_len, filename); JS_FreeCString(ctx, filename); if (!buf) return JS_NULL; ret = JS_NewStringLen(ctx, (char *)buf, buf_len); js_free(ctx, buf); return ret;} typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx, const char *module_name); #if defined(_WIN32) || defined(__plan9__)static JSModuleDef *js_module_loader_so(JSContext *ctx, const char *module_name){ JS_ThrowReferenceError(ctx, "shared library modules are not supported yet"); return NULL;}#elsestatic JSModuleDef *js_module_loader_so(JSContext *ctx, const char *module_name){ JSModuleDef *m; void *hd; JSInitModuleFunc *init; char *filename; if (!strchr(module_name, '/')) { /* must add a '/' so that the DLL is not searched in the system library paths */ filename = js_malloc(ctx, strlen(module_name) + 2 + 1); if (!filename) return NULL; strcpy(filename, "./"); strcpy(filename + 2, module_name); } else { filename = (char *)module_name; } /* C module */ hd = dlopen(filename, RTLD_NOW | RTLD_LOCAL); if (filename != module_name) js_free(ctx, filename); if (!hd) { JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library", module_name); goto fail; } init = dlsym(hd, "js_init_module"); if (!init) { JS_ThrowReferenceError(ctx, "could not load module filename '%s': js_init_module not found", module_name); goto fail; } Lines 1–500 of 3926. Load more
/* * QuickJS C library * * Copyright (c) 2017-2020 Fabrice Bellard * Copyright (c) 2017-2020 Charlie Gordon * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <inttypes.h> #include <string.h> #include <assert.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <sys/time.h> #include <time.h> #include <signal.h> #include <limits.h> #include <sys/stat.h> #include <dirent.h> #if defined(_WIN32) #include <windows.h> #include <conio.h> #include <utime.h> #else #include <dlfcn.h> #include <termios.h> #include <sys/ioctl.h> #include <sys/wait.h> #if defined(__APPLE__) typedef sig_t sighandler_t; #if !defined(environ) #include <crt_externs.h> #define environ (*_NSGetEnviron()) #endif #endif /* __APPLE__ */ #endif #if !defined(_WIN32) && !defined(__plan9__) /* enable the os.Worker API. IT relies on POSIX threads */ #define USE_WORKER #endif #ifdef USE_WORKER #include <pthread.h> #include <stdatomic.h> #endif #include "cutils.h" #include "list.h" #include "quickjs-libc.h" /* TODO: - add socket calls */ typedef struct { struct list_head link; int fd; JSValue rw_func[2]; } JSOSRWHandler; typedef struct { struct list_head link; int sig_num; JSValue func; } JSOSSignalHandler; typedef struct { struct list_head link; BOOL has_object; int64_t timeout; JSValue func; } JSOSTimer; typedef struct { struct list_head link; uint8_t *data; size_t data_len; /* list of SharedArrayBuffers, necessary to free the message */ uint8_t **sab_tab; size_t sab_tab_len; } JSWorkerMessage; typedef struct { int ref_count; #ifdef USE_WORKER pthread_mutex_t mutex; #endif struct list_head msg_queue; /* list of JSWorkerMessage.link */ int read_fd; int write_fd; } JSWorkerMessagePipe; typedef struct { struct list_head link; JSWorkerMessagePipe *recv_pipe; JSValue on_message_func; } JSWorkerMessageHandler; typedef struct JSThreadState { struct list_head os_rw_handlers; /* list of JSOSRWHandler.link */ struct list_head os_signal_handlers; /* list JSOSSignalHandler.link */ struct list_head os_timers; /* list of JSOSTimer.link */ struct list_head port_list; /* list of JSWorkerMessageHandler.link */ int eval_script_recurse; /* only used in the main thread */ /* not used in the main thread */ JSWorkerMessagePipe *recv_pipe, *send_pipe; } JSThreadState; static uint64_t os_pending_signals; static int (*os_poll_func)(JSContext *ctx); static void js_std_dbuf_init(JSContext *ctx, DynBuf *s) { dbuf_init2(s, JS_GetRuntime(ctx), (DynBufReallocFunc *)js_realloc_rt); } static BOOL my_isdigit(int c) { return (c >= '0' && c <= '9'); } static JSValue js_printf_internal(JSContext *ctx, int argc, JSValueConst *argv, FILE *fp) { char fmtbuf[32]; uint8_t cbuf[UTF8_CHAR_LEN_MAX+1]; JSValue res; DynBuf dbuf; const char *fmt_str; const uint8_t *fmt, *fmt_end; const uint8_t *p; char *q; int i, c, len, mod; size_t fmt_len; int32_t int32_arg; int64_t int64_arg; double double_arg; const char *string_arg; /* Use indirect call to dbuf_printf to prevent gcc warning */ int (*dbuf_printf_fun)(DynBuf *s, const char *fmt, ...) = (void*)dbuf_printf; js_std_dbuf_init(ctx, &dbuf); if (argc > 0) { fmt_str = JS_ToCStringLen(ctx, &fmt_len, argv[0]); if (!fmt_str) goto fail; i = 1; fmt = (const uint8_t *)fmt_str; fmt_end = fmt + fmt_len; while (fmt < fmt_end) { for (p = fmt; fmt < fmt_end && *fmt != '%'; fmt++) continue; dbuf_put(&dbuf, p, fmt - p); if (fmt >= fmt_end) break; q = fmtbuf; *q++ = *fmt++; /* copy '%' */ /* flags */ for(;;) { c = *fmt; if (c == '0' || c == '#' || c == '+' || c == '-' || c == ' ' || c == '\'') { if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = c; fmt++; } else { break; } } /* width */ if (*fmt == '*') { if (i >= argc) goto missing; if (JS_ToInt32(ctx, &int32_arg, argv[i++])) goto fail; q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg); fmt++; } else { while (my_isdigit(*fmt)) { if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = *fmt++; } } if (*fmt == '.') { if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = *fmt++; if (*fmt == '*') { if (i >= argc) goto missing; if (JS_ToInt32(ctx, &int32_arg, argv[i++])) goto fail; q += snprintf(q, fmtbuf + sizeof(fmtbuf) - q, "%d", int32_arg); fmt++; } else { while (my_isdigit(*fmt)) { if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = *fmt++; } } } /* we only support the "l" modifier for 64 bit numbers */ mod = ' '; if (*fmt == 'l') { mod = *fmt++; } /* type */ c = *fmt++; if (q >= fmtbuf + sizeof(fmtbuf) - 1) goto invalid; *q++ = c; *q = '\0'; switch (c) { case 'c': if (i >= argc) goto missing; if (JS_IsString(argv[i])) { string_arg = JS_ToCString(ctx, argv[i++]); if (!string_arg) goto fail; int32_arg = unicode_from_utf8((uint8_t *)string_arg, UTF8_CHAR_LEN_MAX, &p); JS_FreeCString(ctx, string_arg); } else { if (JS_ToInt32(ctx, &int32_arg, argv[i++])) goto fail; } /* handle utf-8 encoding explicitly */ if ((unsigned)int32_arg > 0x10FFFF) int32_arg = 0xFFFD; /* ignore conversion flags, width and precision */ len = unicode_to_utf8(cbuf, int32_arg); dbuf_put(&dbuf, cbuf, len); break; case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': if (i >= argc) goto missing; if (JS_ToInt64Ext(ctx, &int64_arg, argv[i++])) goto fail; if (mod == 'l') { /* 64 bit number */ #if defined(_WIN32) if (q >= fmtbuf + sizeof(fmtbuf) - 3) goto invalid; q[2] = q[-1]; q[-1] = 'I'; q[0] = '6'; q[1] = '4'; q[3] = '\0'; dbuf_printf_fun(&dbuf, fmtbuf, (int64_t)int64_arg); #else if (q >= fmtbuf + sizeof(fmtbuf) - 2) goto invalid; q[1] = q[-1]; q[-1] = q[0] = 'l'; q[2] = '\0'; dbuf_printf_fun(&dbuf, fmtbuf, (long long)int64_arg); #endif } else { dbuf_printf_fun(&dbuf, fmtbuf, (int)int64_arg); } break; case 's': if (i >= argc) goto missing; /* XXX: handle strings containing null characters */ string_arg = JS_ToCString(ctx, argv[i++]); if (!string_arg) goto fail; dbuf_printf_fun(&dbuf, fmtbuf, string_arg); JS_FreeCString(ctx, string_arg); break; case 'e': case 'f': case 'g': case 'a': case 'E': case 'F': case 'G': case 'A': if (i >= argc) goto missing; if (JS_ToFloat64(ctx, &double_arg, argv[i++])) goto fail; dbuf_printf_fun(&dbuf, fmtbuf, double_arg); break; case '%': dbuf_putc(&dbuf, '%'); break; default: /* XXX: should support an extension mechanism */ invalid: JS_ThrowTypeError(ctx, "invalid conversion specifier in format string"); goto fail; missing: JS_ThrowReferenceError(ctx, "missing argument for conversion specifier"); goto fail; } } JS_FreeCString(ctx, fmt_str); } if (dbuf.error) { res = JS_ThrowOutOfMemory(ctx); } else { if (fp) { len = fwrite(dbuf.buf, 1, dbuf.size, fp); res = JS_NewInt32(ctx, len); } else { res = JS_NewStringLen(ctx, (char *)dbuf.buf, dbuf.size); } } dbuf_free(&dbuf); return res; fail: dbuf_free(&dbuf); return JS_EXCEPTION; } uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) { FILE *f; uint8_t *buf; size_t buf_len; long lret; f = fopen(filename, "rb"); if (!f) return NULL; if (fseek(f, 0, SEEK_END) < 0) goto fail; lret = ftell(f); if (lret < 0) goto fail; /* XXX: on Linux, ftell() return LONG_MAX for directories */ if (lret == LONG_MAX) { errno = EISDIR; goto fail; } buf_len = lret; if (fseek(f, 0, SEEK_SET) < 0) goto fail; if (ctx) buf = js_malloc(ctx, buf_len + 1); else buf = malloc(buf_len + 1); if (!buf) goto fail; if (fread(buf, 1, buf_len, f) != buf_len) { errno = EIO; if (ctx) js_free(ctx, buf); else free(buf); fail: fclose(f); return NULL; } buf[buf_len] = '\0'; fclose(f); *pbuf_len = buf_len; return buf; } /* load and evaluate a file */ static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { uint8_t *buf; const char *filename; JSValue ret; size_t buf_len; filename = JS_ToCString(ctx, argv[0]); if (!filename) return JS_EXCEPTION; buf = js_load_file(ctx, &buf_len, filename); if (!buf) { JS_ThrowReferenceError(ctx, "could not load '%s'", filename); JS_FreeCString(ctx, filename); return JS_EXCEPTION; } ret = JS_Eval(ctx, (char *)buf, buf_len, filename, JS_EVAL_TYPE_GLOBAL); js_free(ctx, buf); JS_FreeCString(ctx, filename); return ret; } /* load a file as a UTF-8 encoded string */ static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { uint8_t *buf; const char *filename; JSValue ret; size_t buf_len; filename = JS_ToCString(ctx, argv[0]); if (!filename) return JS_EXCEPTION; buf = js_load_file(ctx, &buf_len, filename); JS_FreeCString(ctx, filename); if (!buf) return JS_NULL; ret = JS_NewStringLen(ctx, (char *)buf, buf_len); js_free(ctx, buf); return ret; } typedef JSModuleDef *(JSInitModuleFunc)(JSContext *ctx, const char *module_name); #if defined(_WIN32) || defined(__plan9__) static JSModuleDef *js_module_loader_so(JSContext *ctx, const char *module_name) { JS_ThrowReferenceError(ctx, "shared library modules are not supported yet"); return NULL; } #else static JSModuleDef *js_module_loader_so(JSContext *ctx, const char *module_name) { JSModuleDef *m; void *hd; JSInitModuleFunc *init; char *filename; if (!strchr(module_name, '/')) { /* must add a '/' so that the DLL is not searched in the system library paths */ filename = js_malloc(ctx, strlen(module_name) + 2 + 1); if (!filename) return NULL; strcpy(filename, "./"); strcpy(filename + 2, module_name); } else { filename = (char *)module_name; } /* C module */ hd = dlopen(filename, RTLD_NOW | RTLD_LOCAL); if (filename != module_name) js_free(ctx, filename); if (!hd) { JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library", module_name); goto fail; } init = dlsym(hd, "js_init_module"); if (!init) { JS_ThrowReferenceError(ctx, "could not load module filename '%s': js_init_module not found", module_name); goto fail; }