From: Dmitry Volyntsev Date: Thu, 8 Jan 2026 02:09:20 +0000 (-0800) Subject: QuickJS: added native module support in CLI. X-Git-Tag: 0.9.5~1 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=9fc69ebab6974542187d41902905de8868a08f4b;p=njs.git QuickJS: added native module support in CLI. --- diff --git a/auto/feature b/auto/feature index 064c3fda..536df529 100644 --- a/auto/feature +++ b/auto/feature @@ -37,7 +37,7 @@ END njs_test="$CC $CFLAGS $NJS_CFLAGS $NJS_CC_OPT $NJS_TEST_CFLAGS \ $njs_feature_inc_path -o $NJS_AUTOTEST $NJS_AUTOTEST.c \ - $NJS_LD_OPT $NJS_TEST_LIBS $njs_feature_libs" + $NJS_LD_OPT $NJS_LINK $NJS_TEST_LIBS $njs_feature_libs" # /bin/sh -c "(...)" is to intercept "Killed", "Abort trap", # "Segmentation fault", or other shell messages. diff --git a/auto/make b/auto/make index 296ff5a8..2a07001d 100644 --- a/auto/make +++ b/auto/make @@ -88,7 +88,7 @@ cat << END > $NJS_MAKEFILE NJS_CC = ${CC} NJS_STATIC_LINK = ${AR} -r -c -NJS_LINK = ${CC} ${NJS_LD_OPT} +NJS_LINK = ${CC} ${NJS_LD_OPT} ${NJS_LINK} NJS_PIC = ${NJS_PIC} CFLAGS = ${NJS_CC_OPT} ${CFLAGS:-${NJS_CFLAGS}} NJS_LIB_AUX_CFLAGS = ${NJS_LIB_AUX_CFLAGS} diff --git a/auto/options b/auto/options index 49d98019..e99f9b97 100644 --- a/auto/options +++ b/auto/options @@ -5,6 +5,7 @@ NJS_CC_OPT= NJS_LD_OPT= +NJS_LINK="-Wl,-E" NJS_PIC=-fPIC NJS_DEBUG=NO diff --git a/external/njs_shell.c b/external/njs_shell.c index d72a3d98..d0f9e25f 100644 --- a/external/njs_shell.c +++ b/external/njs_shell.c @@ -14,6 +14,7 @@ #if (NJS_HAVE_QUICKJS) #include #include +#include #endif #if (!defined NJS_FUZZER_TARGET && defined NJS_HAVE_READLINE) @@ -2558,6 +2559,71 @@ njs_qjs_rejection_tracker(JSContext *ctx, JSValueConst promise, } +static njs_int_t +njs_has_suffix(const char *str, const char *suffix) +{ + size_t len, slen; + + len = njs_strlen(str); + slen = njs_strlen(suffix); + + return (len >= slen && memcmp(str + len - slen, suffix, slen) == 0); +} + + +static JSModuleDef * +njs_qjs_module_loader_so(JSContext *ctx, const char *module_name) +{ + void *handle; + char *filename; + JSModuleDef *m; + qjs_addon_init_pt init; + + if (!strchr(module_name, '/')) { + filename = js_malloc(ctx, njs_strlen(module_name) + 3); + if (filename == NULL) { + JS_ThrowOutOfMemory(ctx); + return NULL; + } + + strcpy(filename, "./"); + strcpy(filename + 2, module_name); + + } else { + filename = (char *) module_name; + } + + handle = dlopen(filename, RTLD_NOW | RTLD_LOCAL); + if (filename != module_name) { + js_free(ctx, filename); + } + + if (handle == NULL) { + JS_ThrowReferenceError(ctx, "could not load module filename '%s' as " + "shared library: %s", module_name, dlerror()); + return NULL; + } + + init = dlsym(handle, "js_init_module"); + if (init == NULL) { + JS_ThrowReferenceError(ctx, "could not load module filename '%s': " + "js_init_module not found", module_name); + dlclose(handle); + return NULL; + } + + m = init(ctx, module_name); + if (m == NULL) { + JS_ThrowReferenceError(ctx, "could not load module filename '%s': " + "initialization error", module_name); + dlclose(handle); + return NULL; + } + + return m; +} + + static JSModuleDef * njs_qjs_module_loader(JSContext *ctx, const char *module_name, void *opaque) { @@ -2572,6 +2638,10 @@ njs_qjs_module_loader(JSContext *ctx, const char *module_name, void *opaque) opts = opaque; console = JS_GetRuntimeOpaque(JS_GetRuntime(ctx)); + if (njs_has_suffix(module_name, ".so")) { + return njs_qjs_module_loader_so(ctx, module_name); + } + njs_memzero(&info, sizeof(njs_module_info_t)); info.name.start = (u_char *) module_name;