From f9a5add7a4471d0f5b53529769582d504288612b Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Tue, 21 Jan 2025 17:09:06 -0800 Subject: [PATCH] QuickJS: added support for QuickJS-NG library. --- auto/quickjs | 72 +++++++++++++++++++++++++++++++++++++--- external/qjs_fs_module.c | 22 ++++++------ nginx/config | 36 +++++++++++++++++--- nginx/config.make | 4 +-- src/qjs.h | 8 ++++- test/shell_test.exp | 12 +++---- 6 files changed, 124 insertions(+), 30 deletions(-) diff --git a/auto/quickjs b/auto/quickjs index 9aeb485ac..974321424 100644 --- a/auto/quickjs +++ b/auto/quickjs @@ -53,9 +53,19 @@ if [ $NJS_TRY_QUICKJS = YES ]; then . auto/feature fi + if [ $njs_found = no ]; then + njs_feature="QuickJS-NG library -lqjs" + njs_feature_incs="" + njs_feature_libs="-lqjs -lm -ldl -lpthread" + + . auto/feature + fi + + if [ $njs_found = yes ]; then njs_feature="QuickJS JS_GetClassID()" + njs_feature_name=NJS_HAVE_QUICKJS_GET_CLASS_ID njs_feature_test="#if defined(__GNUC__) && (__GNUC__ >= 8) #pragma GCC diagnostic push #pragma GCC diagnostic ignored \"-Wcast-function-type\" @@ -64,7 +74,7 @@ if [ $NJS_TRY_QUICKJS = YES ]; then #include int main() { - (void) JS_GetClassID; + (void) JS_GetClassID(JS_UNDEFINED); return 0; }" @@ -78,6 +88,7 @@ if [ $NJS_TRY_QUICKJS = YES ]; then fi njs_feature="QuickJS JS_NewTypedArray()" + njs_feature_name=NJS_HAVE_QUICKJS_NEW_TYPED_ARRAY njs_feature_test="#if defined(__GNUC__) && (__GNUC__ >= 8) #pragma GCC diagnostic push #pragma GCC diagnostic ignored \"-Wcast-function-type\" @@ -86,15 +97,66 @@ if [ $NJS_TRY_QUICKJS = YES ]; then #include int main() { - (void) JS_NewTypedArray; + JSValue ta, argv; + JSRuntime *rt; + JSContext *ctx; + + rt = JS_NewRuntime(); + ctx = JS_NewContext(rt); + argv = JS_NewInt64(ctx, 1); + ta = JS_NewTypedArray(ctx, 1, &argv, + JS_TYPED_ARRAY_UINT8); + JS_FreeValue(ctx, ta); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); return 0; }" . auto/feature - if [ $njs_found = yes ]; then - njs_define=NJS_HAVE_QUICKJS_NEW_TYPED_ARRAY . auto/define - fi + njs_feature="QuickJS JS_IsSameValue()" + njs_feature_name=NJS_HAVE_QUICKJS_IS_SAME_VALUE + njs_feature_test="#if defined(__GNUC__) && (__GNUC__ >= 8) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored \"-Wcast-function-type\" + #endif + + #include + + int main() { + JSRuntime *rt; + JSContext *ctx; + + rt = JS_NewRuntime(); + ctx = JS_NewContext(rt); + (void) JS_IsSameValue(ctx, JS_UNDEFINED, JS_UNDEFINED); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); + return 0; + }" + + . auto/feature + + njs_feature="QuickJS version" + njs_feature_name=NJS_QUICKJS_VERSION + njs_feature_run=value + njs_feature_test="#if defined(__GNUC__) && (__GNUC__ >= 8) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored \"-Wcast-function-type\" + #endif + + #include + + int main() { +#if defined(QJS_VERSION_MAJOR) + printf(\"\\\"%s\\\"\", JS_GetVersion()); +#else + printf(\"\\\"Unknown\\\"\"); +#endif + return 0; + }" + + . auto/feature NJS_HAVE_QUICKJS=YES NJS_QUICKJS_LIB="$njs_feature_libs" diff --git a/external/qjs_fs_module.c b/external/qjs_fs_module.c index fc2222ffd..2adeef201 100644 --- a/external/qjs_fs_module.c +++ b/external/qjs_fs_module.c @@ -397,7 +397,7 @@ qjs_fs_access(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, mode, callback)) { + if (qjs_is_same_value(cx, mode, callback)) { mode = JS_UNDEFINED; } } @@ -586,7 +586,7 @@ qjs_fs_mkdir(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, options, callback)) { + if (qjs_is_same_value(cx, options, callback)) { options = JS_UNDEFINED; } } @@ -894,7 +894,7 @@ qjs_fs_read_file(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, options, callback)) { + if (qjs_is_same_value(cx, options, callback)) { options = JS_UNDEFINED; } } @@ -955,7 +955,7 @@ qjs_fs_read_file(JSContext *cx, JSValueConst this_val, int argc, str.length = sb.st_size; v = qjs_fs_fd_read(cx, fd, &str); - if (!JS_SameValue(cx, v, JS_TRUE)) { + if (!qjs_is_same_value(cx, v, JS_TRUE)) { if (JS_IsException(v)) { result = JS_EXCEPTION; @@ -1012,7 +1012,7 @@ qjs_fs_readlink(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, options, callback)) { + if (qjs_is_same_value(cx, options, callback)) { options = JS_UNDEFINED; } } @@ -1150,7 +1150,7 @@ qjs_fs_readdir(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, options, callback)) { + if (qjs_is_same_value(cx, options, callback)) { options = JS_UNDEFINED; } } @@ -1309,7 +1309,7 @@ qjs_fs_realpath(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, options, callback)) { + if (qjs_is_same_value(cx, options, callback)) { options = JS_UNDEFINED; } } @@ -1655,7 +1655,7 @@ qjs_fs_rmdir(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, options, callback)) { + if (qjs_is_same_value(cx, options, callback)) { options = JS_UNDEFINED; } } @@ -1817,7 +1817,7 @@ qjs_fs_stat(JSContext *cx, JSValueConst this_val, int argc, JSValueConst *argv, return JS_EXCEPTION; } - if (JS_SameValue(cx, options, callback)) { + if (qjs_is_same_value(cx, options, callback)) { options = JS_UNDEFINED; } } @@ -1916,7 +1916,7 @@ qjs_fs_symlink(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, type, callback)) { + if (qjs_is_same_value(cx, type, callback)) { type = JS_UNDEFINED; } } @@ -2168,7 +2168,7 @@ qjs_fs_write_file(JSContext *cx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - if (JS_SameValue(cx, options, callback)) { + if (qjs_is_same_value(cx, options, callback)) { options = JS_UNDEFINED; } } diff --git a/nginx/config b/nginx/config index 436f06cbe..8e920477b 100644 --- a/nginx/config +++ b/nginx/config @@ -39,7 +39,6 @@ if [ $NJS_QUICKJS != NO ]; then ngx_feature_test="JSRuntime *rt; rt = JS_NewRuntime(); - (void) JS_GetClassID; JS_FreeRuntime(rt); return 0;" . auto/feature @@ -66,17 +65,44 @@ if [ $NJS_QUICKJS != NO ]; then . auto/feature fi + if [ $ngx_found = no ]; then + ngx_feature="QuickJS-NG library -lqjs" + ngx_feature_path="" + ngx_feature_libs="-lqjs -lm -ldl -lpthread" + + . auto/feature + fi + if [ $ngx_found = yes ]; then + ngx_feature="QuickJS JS_GetClassID()" + ngx_feature_name=NJS_HAVE_QUICKJS_GET_CLASS_ID + ngx_feature_run=no + ngx_feature_test="(void) JS_GetClassID(JS_UNDEFINED);" + + . auto/feature + + if [ $ngx_found = no ]; then + echo + echo $0: error: QuickJS library found, but JS_GetClassID\(\) is missing. + echo + exit 1; + fi + ngx_feature="QuickJS JS_NewTypedArray()" - ngx_feature_test="(void) JS_NewTypedArray; + ngx_feature_name=NJS_HAVE_QUICKJS_NEW_TYPED_ARRAY + ngx_feature_test="JSValue argv; + (void) JS_NewTypedArray(NULL, 1, &argv, + JS_TYPED_ARRAY_UINT8); return 0;" . auto/feature - if [ $ngx_found = yes ]; then - have=NJS_HAVE_QUICKJS_NEW_TYPED_ARRAY . auto/have - fi + ngx_feature="QuickJS JS_IsSameValue()" + ngx_feature_name=NJS_HAVE_QUICKJS_IS_SAME_VALUE + ngx_feature_test="(void) JS_IsSameValue(NULL, JS_UNDEFINED, JS_UNDEFINED);" + + . auto/feature NJS_HAVE_QUICKJS=YES NJS_QUICKJS_LIB="$ngx_feature_libs" diff --git a/nginx/config.make b/nginx/config.make index 2fa40063f..404a622b4 100644 --- a/nginx/config.make +++ b/nginx/config.make @@ -4,14 +4,14 @@ $ngx_addon_dir/../build/libnjs.a: $NGX_MAKEFILE cd $ngx_addon_dir/.. \\ && if [ -f build/Makefile ]; then \$(MAKE) clean; fi \\ && CFLAGS="\$(CFLAGS)" CC="\$(CC)" ./configure --no-openssl \\ - --no-libxml2 --no-zlib --no-pcre --no-quickjs \\ + --no-libxml2 --no-zlib --no-pcre --no-quickjs --ld-opt="$NGX_LD_OPT" \\ && \$(MAKE) libnjs $ngx_addon_dir/../build/libqjs.a: $NGX_MAKEFILE cd $ngx_addon_dir/.. \\ && if [ -f build/Makefile ]; then \$(MAKE) clean; fi \\ && CFLAGS="\$(CFLAGS)" CC="\$(CC)" ./configure --no-openssl \\ - --no-libxml2 --no-zlib --no-pcre \\ + --no-libxml2 --no-zlib --no-pcre --ld-opt="$NGX_LD_OPT" \\ && \$(MAKE) libnjs libqjs END diff --git a/src/qjs.h b/src/qjs.h index 76bf5c3df..71dd297e5 100644 --- a/src/qjs.h +++ b/src/qjs.h @@ -29,7 +29,6 @@ #if defined(__GNUC__) && (__GNUC__ >= 8) #pragma GCC diagnostic pop #endif -#define NJS_QUICKJS_VERSION "Unknown version" #include @@ -101,6 +100,13 @@ static inline JS_BOOL JS_IsNullOrUndefined(JSValueConst v) } +#ifdef NJS_HAVE_QUICKJS_IS_SAME_VALUE +#define qjs_is_same_value(cx, a, b) JS_IsSameValue(cx, a, b) +#else +#define qjs_is_same_value(cx, a, b) JS_SameValue(cx, a, b) +#endif + + extern qjs_module_t *qjs_modules[]; #endif /* _QJS_H_INCLUDED_ */ diff --git a/test/shell_test.exp b/test/shell_test.exp index b713ed09b..028282708 100644 --- a/test/shell_test.exp +++ b/test/shell_test.exp @@ -302,11 +302,11 @@ njs_test { njs_test { {"function f() { return ({}.a.a); }\r\n" - "undefined"} - {"var e; try {f()} catch (ee) {e = ee}\r\n" - "undefined"} + "undefined\r\n>> "} + {"var e; try {f()} catch (ee) {e = ee}; undefined\r\n" + "undefined\r\n>> "} {"Object.keys(null)\r\n" - "Thrown:\r\nTypeError: cannot convert*to object"} + "Thrown:\r\nTypeError: *annot convert*to object"} {"e\r\n" "TypeError: cannot * property *a* of undefined"} } @@ -382,11 +382,11 @@ njs_test { njs_run {"-c" "setTimeout(() => {console.log('A'.repeat(1024))}, 0); ref"} \ "^Thrown: -ReferenceError: \['\"\]ref\['\"\] is not defined.*" +ReferenceError: .* is not defined.*" njs_run {"-c" "setTimeout(() => {ref}, 0); setTimeout(() => {console.log('A'.repeat(1024))}, 0)"} \ "^Thrown: -ReferenceError: \['\"\]ref\['\"\] is not defined.*" +ReferenceError: .* is not defined.*" njs_test { {"setImmediate(() => { console.log('x'); return Promise.reject('xx'); })\r\n"