details: https://hg.nginx.org/njs/rev/25e548de3d61 branches: changeset: 2280:25e548de3d61 user: Dmitry Volyntsev <xei...@nginx.com> date: Tue Feb 06 19:32:08 2024 -0800 description: Reverted changes introduced in 7eaaa7d57636 (not released) back.
Relative importing is again supported. diffstat: external/njs_shell.c | 101 ++++++++++++++++++++++++++++++++++++- nginx/ngx_js.c | 88 ++++++++++++++++++++++++++++++++- nginx/ngx_js.h | 1 + nginx/t/js_import_relative.t | 100 +++++++++++++++++++++++++++++++++++++ test/js/import_relative_path.t.js | 9 +++ test/js/module/libs/hash.js | 1 + test/js/module/sub/sub3.js | 1 + 7 files changed, 296 insertions(+), 5 deletions(-) diffs (468 lines): diff -r 673d78618fc9 -r 25e548de3d61 external/njs_shell.c --- a/external/njs_shell.c Wed Jan 31 17:06:58 2024 -0800 +++ b/external/njs_shell.c Tue Feb 06 19:32:08 2024 -0800 @@ -115,6 +115,8 @@ typedef struct { njs_queue_t labels; + njs_str_t cwd; + njs_arr_t *rejected_promises; njs_bool_t suppress_stdout; @@ -693,6 +695,8 @@ njs_console_init(njs_vm_t *vm, njs_conso njs_queue_init(&console->posted_events); njs_queue_init(&console->labels); + njs_memzero(&console->cwd, sizeof(njs_str_t)); + console->rejected_promises = NULL; console->completion.completions = njs_vm_completions(vm, NULL); @@ -869,7 +873,7 @@ njs_module_path(const njs_str_t *dir, nj if (dir != NULL) { length += dir->length; - if (length == 0) { + if (length == 0 || dir->length == 0) { return NJS_DECLINED; } @@ -915,7 +919,8 @@ njs_module_path(const njs_str_t *dir, nj static njs_int_t -njs_module_lookup(njs_opts_t *opts, njs_module_info_t *info) +njs_module_lookup(njs_opts_t *opts, const njs_str_t *cwd, + njs_module_info_t *info) { njs_int_t ret; njs_str_t *path; @@ -925,6 +930,12 @@ njs_module_lookup(njs_opts_t *opts, njs_ return njs_module_path(NULL, info); } + ret = njs_module_path(cwd, info); + + if (ret != NJS_DECLINED) { + return ret; + } + path = opts->paths; for (i = 0; i < opts->n_paths; i++) { @@ -980,23 +991,86 @@ fail: } +static void +njs_file_dirname(const njs_str_t *path, njs_str_t *name) +{ + const u_char *p, *end; + + if (path->length == 0) { + goto current_dir; + } + + p = path->start + path->length - 1; + + /* Stripping basename. */ + + while (p >= path->start && *p != '/') { p--; } + + end = p + 1; + + if (end == path->start) { + goto current_dir; + } + + /* Stripping trailing slashes. */ + + while (p >= path->start && *p == '/') { p--; } + + p++; + + if (p == path->start) { + p = end; + } + + name->start = path->start; + name->length = p - path->start; + + return; + +current_dir: + + *name = njs_str_value("."); +} + + +static njs_int_t +njs_console_set_cwd(njs_vm_t *vm, njs_console_t *console, njs_str_t *file) +{ + njs_str_t cwd; + + njs_file_dirname(file, &cwd); + + console->cwd.start = njs_mp_alloc(njs_vm_memory_pool(vm), cwd.length); + if (njs_slow_path(console->cwd.start == NULL)) { + return NJS_ERROR; + } + + memcpy(console->cwd.start, cwd.start, cwd.length); + console->cwd.length = cwd.length; + + return NJS_OK; +} + + static njs_mod_t * njs_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name) { u_char *start; njs_int_t ret; - njs_str_t text; + njs_str_t text, prev_cwd; njs_mod_t *module; njs_opts_t *opts; + njs_console_t *console; njs_module_info_t info; opts = external; + console = njs_vm_external_ptr(vm); njs_memzero(&info, sizeof(njs_module_info_t)); info.name = *name; - ret = njs_module_lookup(opts, &info); + ret = njs_module_lookup(opts, &console->cwd, &info); if (njs_slow_path(ret != NJS_OK)) { return NULL; } @@ -1010,11 +1084,23 @@ njs_module_loader(njs_vm_t *vm, njs_exte return NULL; } + prev_cwd = console->cwd; + + ret = njs_console_set_cwd(vm, console, &info.file); + if (njs_slow_path(ret != NJS_OK)) { + njs_vm_internal_error(vm, "while setting cwd for \"%V\" module", + &info.file); + return NULL; + } + start = text.start; module = njs_vm_compile_module(vm, &info.file, &start, &text.start[text.length]); + njs_mp_free(njs_vm_memory_pool(vm), console->cwd.start); + console->cwd = prev_cwd; + njs_mp_free(njs_vm_memory_pool(vm), text.start); return module; @@ -1025,6 +1111,7 @@ static njs_vm_t * njs_create_vm(njs_opts_t *opts) { njs_vm_t *vm; + njs_int_t ret; njs_vm_opt_t vm_options; njs_vm_opt_init(&vm_options); @@ -1068,6 +1155,12 @@ njs_create_vm(njs_opts_t *opts) njs_vm_external_ptr(vm)); } + ret = njs_console_set_cwd(vm, njs_vm_external_ptr(vm), &vm_options.file); + if (njs_slow_path(ret != NJS_OK)) { + njs_stderror("failed to set cwd\n"); + return NULL; + } + njs_vm_set_module_loader(vm, njs_module_loader, opts); return vm; diff -r 673d78618fc9 -r 25e548de3d61 nginx/ngx_js.c --- a/nginx/ngx_js.c Wed Jan 31 17:06:58 2024 -0800 +++ b/nginx/ngx_js.c Tue Feb 06 19:32:08 2024 -0800 @@ -1743,7 +1743,7 @@ ngx_js_module_path(const ngx_str_t *dir, if (dir != NULL) { length += dir->len; - if (length == 0) { + if (length == 0 || dir->len == 0) { return NJS_DECLINED; } @@ -1799,6 +1799,12 @@ ngx_js_module_lookup(ngx_js_loc_conf_t * return ngx_js_module_path(NULL, info); } + ret = ngx_js_module_path(&conf->cwd, info); + + if (ret != NJS_DECLINED) { + return ret; + } + ret = ngx_js_module_path((const ngx_str_t *) &ngx_cycle->conf_prefix, info); if (ret != NJS_DECLINED) { @@ -1864,12 +1870,74 @@ fail: } +static void +ngx_js_file_dirname(const njs_str_t *path, ngx_str_t *name) +{ + const u_char *p, *end; + + if (path->length == 0) { + goto current_dir; + } + + p = path->start + path->length - 1; + + /* Stripping basename. */ + + while (p >= path->start && *p != '/') { p--; } + + end = p + 1; + + if (end == path->start) { + goto current_dir; + } + + /* Stripping trailing slashes. */ + + while (p >= path->start && *p == '/') { p--; } + + p++; + + if (p == path->start) { + p = end; + } + + name->data = path->start; + name->len = p - path->start; + + return; + +current_dir: + + ngx_str_set(name, "."); +} + + +static njs_int_t +ngx_js_set_cwd(njs_vm_t *vm, ngx_js_loc_conf_t *conf, njs_str_t *path) +{ + ngx_str_t cwd; + + ngx_js_file_dirname(path, &cwd); + + conf->cwd.data = njs_mp_alloc(njs_vm_memory_pool(vm), cwd.len); + if (conf->cwd.data == NULL) { + return NJS_ERROR; + } + + memcpy(conf->cwd.data, cwd.data, cwd.len); + conf->cwd.len = cwd.len; + + return NJS_OK; +} + + static njs_mod_t * ngx_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name) { u_char *start; njs_int_t ret; njs_str_t text; + ngx_str_t prev_cwd; njs_mod_t *module; ngx_js_loc_conf_t *conf; njs_module_info_t info; @@ -1894,11 +1962,23 @@ ngx_js_module_loader(njs_vm_t *vm, njs_e return NULL; } + prev_cwd = conf->cwd; + + ret = ngx_js_set_cwd(vm, conf, &info.file); + if (ret != NJS_OK) { + njs_vm_internal_error(vm, "while setting cwd for \"%V\" module", + &info.file); + return NULL; + } + start = text.start; module = njs_vm_compile_module(vm, &info.file, &start, &text.start[text.length]); + njs_mp_free(njs_vm_memory_pool(vm), conf->cwd.data); + conf->cwd = prev_cwd; + njs_mp_free(njs_vm_memory_pool(vm), text.start); return module; @@ -1985,6 +2065,12 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_ njs_vm_set_rejection_tracker(conf->vm, ngx_js_rejection_tracker, NULL); + rc = ngx_js_set_cwd(conf->vm, conf, &options->file); + if (rc != NJS_OK) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "failed to set cwd"); + return NGX_ERROR; + } + njs_vm_set_module_loader(conf->vm, ngx_js_module_loader, conf); if (conf->paths != NGX_CONF_UNSET_PTR) { diff -r 673d78618fc9 -r 25e548de3d61 nginx/ngx_js.h --- a/nginx/ngx_js.h Wed Jan 31 17:06:58 2024 -0800 +++ b/nginx/ngx_js.h Tue Feb 06 19:32:08 2024 -0800 @@ -83,6 +83,7 @@ struct ngx_js_event_s { #define _NGX_JS_COMMON_LOC_CONF \ njs_vm_t *vm; \ + ngx_str_t cwd; \ ngx_array_t *imports; \ ngx_array_t *paths; \ \ diff -r 673d78618fc9 -r 25e548de3d61 nginx/t/js_import_relative.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nginx/t/js_import_relative.t Tue Feb 06 19:32:08 2024 -0800 @@ -0,0 +1,100 @@ +#!/usr/bin/perl + +# (C) Dmitry Volyntsev +# (c) Nginx, Inc. + +# Tests for http njs module, js_import directive, importing relative paths. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +my $t = Test::Nginx->new()->has(qw/http/) + ->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +http { + %%TEST_GLOBALS_HTTP%% + + js_import main from lib/main.js; + + server { + listen 127.0.0.1:8080; + server_name localhost; + + location /local { + js_content main.test_local; + } + + location /top { + js_content main.test_top; + } + } +} + +EOF + +my $d = $t->testdir(); + +mkdir("$d/lib"); +mkdir("$d/lib/sub"); + +$t->write_file('lib/main.js', <<EOF); + import sub from './sub/foo.js'; + import local from './foo.js'; + import top from '../foo.js'; + + function test_local(r) { + r.return(200, local.test); + } + + function test_top(r) { + r.return(200, top.test); + } + + export default {test_local, test_top}; + +EOF + +$t->write_file('lib/sub/foo.js', <<EOF); + export default {test: "SUB"}; + +EOF + +$t->write_file('lib/foo.js', <<EOF); + export default {test: "LOCAL"}; + +EOF + +$t->write_file('foo.js', <<EOF); + export default {test: "TOP"}; + +EOF + +$t->try_run('no njs available')->plan(2); + +############################################################################### + +like(http_get('/local'), qr/LOCAL/s, 'local relative import'); +like(http_get('/top'), qr/TOP/s, 'local relative import 2'); + +############################################################################### diff -r 673d78618fc9 -r 25e548de3d61 test/js/import_relative_path.t.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/import_relative_path.t.js Tue Feb 06 19:32:08 2024 -0800 @@ -0,0 +1,9 @@ +/*--- +includes: [] +flags: [] +paths: [test/js/module/] +---*/ + +import hash from 'libs/hash.js'; + +assert.sameValue(hash.name, "libs.name"); diff -r 673d78618fc9 -r 25e548de3d61 test/js/module/libs/hash.js --- a/test/js/module/libs/hash.js Wed Jan 31 17:06:58 2024 -0800 +++ b/test/js/module/libs/hash.js Tue Feb 06 19:32:08 2024 -0800 @@ -4,6 +4,7 @@ function hash() { return v; } +import sub from 'sub/sub3.js'; import name from 'name.js'; import crypto from 'crypto'; diff -r 673d78618fc9 -r 25e548de3d61 test/js/module/sub/sub3.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/js/module/sub/sub3.js Tue Feb 06 19:32:08 2024 -0800 @@ -0,0 +1,1 @@ +export default { name: "SUB3" }; _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel