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

Reply via email to