Welcome! Log In Create A New Profile

Advanced

[njs] Refactoring of user modules importing.

Dmitry Volyntsev
February 21, 2022 10:08AM
details: https://hg.nginx.org/njs/rev/77c398f26d7e
branches:
changeset: 1828:77c398f26d7e
user: Dmitry Volyntsev <xeioex@nginx.com>
date: Mon Feb 21 14:49:38 2022 +0000
description:
Refactoring of user modules importing.

Previously, user modules were compiled as as anonymous functions in a
global scope. This is incorrect, because modules should be compiled
in their own scope.

In addition, this patch introduces HostResolveImportedModule support.
When vm->options.ops->module_loader is provided, a module lookup
and compilation is delegated to this callback.

This closes #443 issue on Github.

diffstat:

external/njs_crypto_module.c | 2 +-
external/njs_fs_module.c | 2 +-
external/njs_query_string_module.c | 2 +-
nginx/ngx_http_js_module.c | 20 +-
nginx/ngx_stream_js_module.c | 19 +-
src/njs.h | 6 +
src/njs_buffer.c | 2 +-
src/njs_builtin.c | 4 +-
src/njs_disassembler.c | 22 +-
src/njs_function.c | 2 +-
src/njs_generator.c | 87 +---
src/njs_generator.h | 5 +-
src/njs_module.c | 481 +++++++---------------------
src/njs_module.h | 13 +-
src/njs_parser.c | 238 ++++---------
src/njs_parser.h | 31 +-
src/njs_shell.c | 21 +-
src/njs_variable.c | 2 +-
src/njs_vm.c | 84 ++++-
src/njs_vm.h | 1 +
src/njs_vmcode.c | 68 ++++
src/njs_vmcode.h | 8 +
test/js/import_cyclic.t.js | 11 +
test/js/import_expression.t.js | 1 +
test/js/import_global_ref.t.js | 13 +
test/js/import_global_ref_var.t.js | 10 +
test/js/import_order.t.js | 18 +
test/js/import_recursive.t.js | 6 +-
test/js/import_recursive_early_access.t.js | 9 +
test/js/import_recursive_relative.t.js | 9 +
test/js/import_sinking_export_default.t.js | 10 +
test/js/module/cyclic_a.js | 2 +
test/js/module/cyclic_b.js | 2 +
test/js/module/export_global_a.js | 5 +
test/js/module/http.js | 7 +
test/js/module/jwt.js | 7 +
test/js/module/lib1.js | 5 +
test/js/module/order.js | 7 +
test/js/module/order2.js | 7 +
test/js/module/recursive.js | 2 +
test/js/module/recursive_early_access.js | 5 +
test/js/module/recursive_relative.js | 2 +
test/js/module/sinking_export_default.js | 5 +
43 files changed, 598 insertions(+), 665 deletions(-)

diffs (truncated from 2098 to 1000 lines):

diff -r 7a08ed3e9cb8 -r 77c398f26d7e external/njs_crypto_module.c
--- a/external/njs_crypto_module.c Tue Feb 15 13:17:52 2022 +0000
+++ b/external/njs_crypto_module.c Mon Feb 21 14:49:38 2022 +0000
@@ -646,7 +646,7 @@ njs_crypto_init(njs_vm_t *vm)
return NJS_ERROR;
}

- module = njs_module_add(vm, &njs_str_value("crypto"), 1);
+ module = njs_module_add(vm, &njs_str_value("crypto"));
if (njs_slow_path(module == NULL)) {
return NJS_ERROR;
}
diff -r 7a08ed3e9cb8 -r 77c398f26d7e external/njs_fs_module.c
--- a/external/njs_fs_module.c Tue Feb 15 13:17:52 2022 +0000
+++ b/external/njs_fs_module.c Mon Feb 21 14:49:38 2022 +0000
@@ -3090,7 +3090,7 @@ njs_fs_init(njs_vm_t *vm)
return NJS_ERROR;
}

- module = njs_module_add(vm, &njs_str_value("fs"), 1);
+ module = njs_module_add(vm, &njs_str_value("fs"));
if (njs_slow_path(module == NULL)) {
return NJS_ERROR;
}
diff -r 7a08ed3e9cb8 -r 77c398f26d7e external/njs_query_string_module.c
--- a/external/njs_query_string_module.c Tue Feb 15 13:17:52 2022 +0000
+++ b/external/njs_query_string_module.c Mon Feb 21 14:49:38 2022 +0000
@@ -967,7 +967,7 @@ njs_query_string_init(njs_vm_t *vm)
return NJS_ERROR;
}

- module = njs_module_add(vm, &njs_str_value("querystring"), 1);
+ module = njs_module_add(vm, &njs_str_value("querystring"));
if (njs_slow_path(module == NULL)) {
return NJS_ERROR;
}
diff -r 7a08ed3e9cb8 -r 77c398f26d7e nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Tue Feb 15 13:17:52 2022 +0000
+++ b/nginx/ngx_http_js_module.c Mon Feb 21 14:49:38 2022 +0000
@@ -704,7 +704,8 @@ static njs_external_t ngx_http_js_ext_r

static njs_vm_ops_t ngx_http_js_ops = {
ngx_http_js_set_timer,
- ngx_http_js_clear_timer
+ ngx_http_js_clear_timer,
+ NULL,
};


@@ -3490,8 +3491,12 @@ ngx_http_js_init_main_conf(ngx_conf_t *c

import = jmcf->imports->elts;
for (i = 0; i < jmcf->imports->nelts; i++) {
- size += sizeof("import from '';\n") - 1 + import[i].name.len
- + import[i].path.len;
+
+ /* import <name> from '<path>'; globalThis.<name> = <name>; */
+
+ size += sizeof("import from '';") - 1 + import[i].name.len * 3
+ + import[i].path.len
+ + sizeof(" globalThis. = ;\n") - 1;
}

start = ngx_pnalloc(cf->pool, size);
@@ -3502,11 +3507,18 @@ ngx_http_js_init_main_conf(ngx_conf_t *c
p = start;
import = jmcf->imports->elts;
for (i = 0; i < jmcf->imports->nelts; i++) {
+
+ /* import <name> from '<path>'; globalThis.<name> = <name>; */
+
p = ngx_cpymem(p, "import ", sizeof("import ") - 1);
p = ngx_cpymem(p, import[i].name.data, import[i].name.len);
p = ngx_cpymem(p, " from '", sizeof(" from '") - 1);
p = ngx_cpymem(p, import[i].path.data, import[i].path.len);
- p = ngx_cpymem(p, "';\n", sizeof("';\n") - 1);
+ p = ngx_cpymem(p, "'; globalThis.", sizeof("'; globalThis.") - 1);
+ p = ngx_cpymem(p, import[i].name.data, import[i].name.len);
+ p = ngx_cpymem(p, " = ", sizeof(" = ") - 1);
+ p = ngx_cpymem(p, import[i].name.data, import[i].name.len);
+ p = ngx_cpymem(p, ";\n", sizeof(";\n") - 1);
}

njs_vm_opt_init(&options);
diff -r 7a08ed3e9cb8 -r 77c398f26d7e nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c Tue Feb 15 13:17:52 2022 +0000
+++ b/nginx/ngx_stream_js_module.c Mon Feb 21 14:49:38 2022 +0000
@@ -456,7 +456,8 @@ static njs_external_t ngx_stream_js_ext

static njs_vm_ops_t ngx_stream_js_ops = {
ngx_stream_js_set_timer,
- ngx_stream_js_clear_timer
+ ngx_stream_js_clear_timer,
+ NULL,
};


@@ -1512,8 +1513,11 @@ ngx_stream_js_init_main_conf(ngx_conf_t

import = jmcf->imports->elts;
for (i = 0; i < jmcf->imports->nelts; i++) {
- size += sizeof("import from '';\n") - 1 + import[i].name.len
- + import[i].path.len;
+ /* import <name> from '<path>'; globalThis.<name> = <name>; */
+
+ size += sizeof("import from '';") - 1 + import[i].name.len * 3
+ + import[i].path.len
+ + sizeof(" globalThis. = ;\n") - 1;
}

start = ngx_pnalloc(cf->pool, size);
@@ -1524,11 +1528,18 @@ ngx_stream_js_init_main_conf(ngx_conf_t
p = start;
import = jmcf->imports->elts;
for (i = 0; i < jmcf->imports->nelts; i++) {
+
+ /* import <name> from '<path>'; globalThis.<name> = <name>; */
+
p = ngx_cpymem(p, "import ", sizeof("import ") - 1);
p = ngx_cpymem(p, import[i].name.data, import[i].name.len);
p = ngx_cpymem(p, " from '", sizeof(" from '") - 1);
p = ngx_cpymem(p, import[i].path.data, import[i].path.len);
- p = ngx_cpymem(p, "';\n", sizeof("';\n") - 1);
+ p = ngx_cpymem(p, "'; globalThis.", sizeof("'; globalThis.") - 1);
+ p = ngx_cpymem(p, import[i].name.data, import[i].name.len);
+ p = ngx_cpymem(p, " = ", sizeof(" = ") - 1);
+ p = ngx_cpymem(p, import[i].name.data, import[i].name.len);
+ p = ngx_cpymem(p, ";\n", sizeof(";\n") - 1);
}

njs_vm_opt_init(&options);
diff -r 7a08ed3e9cb8 -r 77c398f26d7e src/njs.h
--- a/src/njs.h Tue Feb 15 13:17:52 2022 +0000
+++ b/src/njs.h Mon Feb 21 14:49:38 2022 +0000
@@ -28,6 +28,7 @@

typedef uintptr_t njs_index_t;
typedef struct njs_vm_s njs_vm_t;
+typedef struct njs_mod_s njs_mod_t;
typedef union njs_value_s njs_value_t;
typedef struct njs_function_s njs_function_t;
typedef struct njs_vm_shared_s njs_vm_shared_t;
@@ -183,11 +184,14 @@ typedef njs_host_event_t (*njs_set_timer
uint64_t delay, njs_vm_event_t vm_event);
typedef void (*njs_event_destructor_t)(njs_external_ptr_t external,
njs_host_event_t event);
+typedef njs_mod_t *(*njs_module_loader_t)(njs_vm_t *vm,
+ njs_external_ptr_t external, njs_str_t *name);


typedef struct {
njs_set_timer_t set_timer;
njs_event_destructor_t clear_timer;
+ njs_module_loader_t module_loader;
} njs_vm_ops_t;


@@ -254,6 +258,8 @@ NJS_EXPORT njs_vm_t *njs_vm_create(njs_v
NJS_EXPORT void njs_vm_destroy(njs_vm_t *vm);

NJS_EXPORT njs_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end);
+NJS_EXPORT njs_mod_t *njs_vm_compile_module(njs_vm_t *vm, njs_str_t *name,
+ u_char **start, u_char *end);
NJS_EXPORT njs_vm_t *njs_vm_clone(njs_vm_t *vm, njs_external_ptr_t external);

NJS_EXPORT njs_vm_event_t njs_vm_add_event(njs_vm_t *vm,
diff -r 7a08ed3e9cb8 -r 77c398f26d7e src/njs_buffer.c
--- a/src/njs_buffer.c Tue Feb 15 13:17:52 2022 +0000
+++ b/src/njs_buffer.c Mon Feb 21 14:49:38 2022 +0000
@@ -3015,7 +3015,7 @@ njs_buffer_init(njs_vm_t *vm)
return NJS_ERROR;
}

- module = njs_module_add(vm, &njs_str_value("buffer"), 1);
+ module = njs_module_add(vm, &njs_str_value("buffer"));
if (njs_slow_path(module == NULL)) {
return NJS_ERROR;
}
diff -r 7a08ed3e9cb8 -r 77c398f26d7e src/njs_builtin.c
--- a/src/njs_builtin.c Tue Feb 15 13:17:52 2022 +0000
+++ b/src/njs_builtin.c Mon Feb 21 14:49:38 2022 +0000
@@ -761,7 +761,9 @@ njs_builtin_match_native_function(njs_vm
break;
}

- if (njs_is_object(&module->value)) {
+ if (njs_is_object(&module->value)
+ && !njs_object(&module->value)->shared)
+ {
ctx.match = module->name;

ret = njs_object_traverse(vm, njs_object(&module->value), &ctx,
diff -r 7a08ed3e9cb8 -r 77c398f26d7e src/njs_disassembler.c
--- a/src/njs_disassembler.c Tue Feb 15 13:17:52 2022 +0000
+++ b/src/njs_disassembler.c Mon Feb 21 14:49:38 2022 +0000
@@ -172,15 +172,6 @@ njs_disassembler(njs_vm_t *vm)
n = vm->codes->items;

while (n != 0) {
- if (code->start == vm->start) {
- break;
- }
-
- code++;
- n--;
- }
-
- while (n != 0) {
njs_printf("%V:%V\n", &code->file, &code->name);
njs_disassemble(code);
code++;
@@ -207,6 +198,7 @@ njs_disassemble(njs_vm_code_t *code)
njs_vmcode_3addr_t *code3;
njs_vmcode_array_t *array;
njs_vmcode_catch_t *catch;
+ njs_vmcode_import_t *import;
njs_vmcode_finally_t *finally;
njs_vmcode_try_end_t *try_end;
njs_vmcode_move_arg_t *move_arg;
@@ -398,6 +390,18 @@ njs_disassemble(njs_vm_code_t *code)
continue;
}

+ if (operation == NJS_VMCODE_IMPORT) {
+ import = (njs_vmcode_import_t *) p;
+
+ njs_printf("%5uD | %05uz IMPORT %04Xz %V\n",
+ line, p - start, (size_t) import->retval,
+ &import->module->name);
+
+ p += sizeof(njs_vmcode_import_t);
+
+ continue;
+ }
+
if (operation == NJS_VMCODE_TRY_START) {
try_start = (njs_vmcode_try_start_t *) p;

diff -r 7a08ed3e9cb8 -r 77c398f26d7e src/njs_function.c
--- a/src/njs_function.c Tue Feb 15 13:17:52 2022 +0000
+++ b/src/njs_function.c Mon Feb 21 14:49:38 2022 +0000
@@ -1209,7 +1209,7 @@ njs_function_constructor(njs_vm_t *vm, n
}
}

- ret = njs_generator_init(&generator, 0, 1);
+ ret = njs_generator_init(&generator, &file, 0, 1);
if (njs_slow_path(ret != NJS_OK)) {
njs_internal_error(vm, "njs_generator_init() failed");
return NJS_ERROR;
diff -r 7a08ed3e9cb8 -r 77c398f26d7e src/njs_generator.c
--- a/src/njs_generator.c Tue Feb 15 13:17:52 2022 +0000
+++ b/src/njs_generator.c Mon Feb 21 14:49:38 2022 +0000
@@ -319,8 +319,6 @@ static njs_int_t njs_generate_throw_end(
njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_import_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
-static njs_int_t njs_generate_import_statement_end(njs_vm_t *vm,
- njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_export_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_export_statement_end(njs_vm_t *vm,
@@ -424,8 +422,8 @@ static njs_int_t njs_generate_index_rele
njs_code_offset_diff(generator, patch->jump_offset)


-#define njs_generate_syntax_error(vm, node, fmt, ...) \
- njs_parser_node_error(vm, node, NJS_OBJ_TYPE_SYNTAX_ERROR, fmt, \
+#define njs_generate_syntax_error(vm, node, file, fmt, ...) \
+ njs_parser_node_error(vm, NJS_OBJ_TYPE_SYNTAX_ERROR, node, file, fmt, \
##__VA_ARGS__)


@@ -436,13 +434,14 @@ static const njs_str_t undef_label = {


njs_int_t
-njs_generator_init(njs_generator_t *generator, njs_int_t depth,
- njs_bool_t runtime)
+njs_generator_init(njs_generator_t *generator, njs_str_t *file,
+ njs_int_t depth, njs_bool_t runtime)
{
njs_memzero(generator, sizeof(njs_generator_t));

njs_queue_init(&generator->stack);

+ generator->file = *file;
generator->depth = depth;
generator->runtime = runtime;

@@ -2312,7 +2311,8 @@ njs_generate_continue_statement(njs_vm_t

syntax_error:

- njs_generate_syntax_error(vm, node, "Illegal continue statement");
+ njs_generate_syntax_error(vm, node, &generator->file,
+ "Illegal continue statement");

return NJS_ERROR;
}
@@ -2357,7 +2357,8 @@ njs_generate_break_statement(njs_vm_t *v

syntax_error:

- njs_generate_syntax_error(vm, node, "Illegal break statement");
+ njs_generate_syntax_error(vm, node, &generator->file,
+ "Illegal break statement");

return NJS_ERROR;
}
@@ -3102,17 +3103,13 @@ njs_generate_function(njs_vm_t *vm, njs_
njs_parser_node_t *node)
{
njs_int_t ret;
- njs_bool_t module;
- const njs_str_t *name;
njs_function_lambda_t *lambda;
njs_vmcode_function_t *function;

lambda = node->u.value.data.u.lambda;
- module = node->right->scope->module;
-
- name = module ? &njs_entry_module : &njs_entry_anonymous;
-
- ret = njs_generate_function_scope(vm, generator, lambda, node, name);
+
+ ret = njs_generate_function_scope(vm, generator, lambda, node,
+ &njs_entry_anonymous);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
@@ -3641,13 +3638,11 @@ njs_generate_function_scope(njs_vm_t *vm
njs_function_lambda_t *lambda, njs_parser_node_t *node,
const njs_str_t *name)
{
- njs_int_t ret;
- njs_arr_t *arr;
- njs_bool_t module;
- njs_uint_t depth;
- njs_vm_code_t *code;
- njs_generator_t generator;
- njs_parser_node_t *file_node;
+ njs_int_t ret;
+ njs_arr_t *arr;
+ njs_uint_t depth;
+ njs_vm_code_t *code;
+ njs_generator_t generator;

depth = prev->depth;

@@ -3656,7 +3651,7 @@ njs_generate_function_scope(njs_vm_t *vm
return NJS_ERROR;
}

- ret = njs_generator_init(&generator, depth, prev->runtime);
+ ret = njs_generator_init(&generator, &prev->file, depth, prev->runtime);
if (njs_slow_path(ret != NJS_OK)) {
njs_internal_error(vm, "njs_generator_init() failed");
return NJS_ERROR;
@@ -3673,11 +3668,6 @@ njs_generate_function_scope(njs_vm_t *vm
return NJS_ERROR;
}

- module = node->right->scope->module;
- file_node = module ? node->right : node;
-
- code->file = file_node->scope->file;
-
lambda->start = generator.code_start;
lambda->closures = generator.closures->start;
lambda->nclosures = generator.closures->items;
@@ -3774,7 +3764,7 @@ njs_generate_scope(njs_vm_t *vm, njs_gen
code = njs_arr_item(vm->codes, index);
code->start = generator->code_start;
code->end = generator->code_end;
- code->file = scope->file;
+ code->file = generator->file;
code->name = *name;

generator->code_size = generator->code_end - generator->code_start;
@@ -4620,45 +4610,22 @@ static njs_int_t
njs_generate_import_statement(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- njs_variable_t *var;
- njs_parser_node_t *lvalue, *expr;
+ njs_variable_t *var;
+ njs_parser_node_t *lvalue;
+ njs_vmcode_import_t *import;

lvalue = node->left;
- expr = node->right;

var = njs_variable_reference(vm, lvalue);
if (njs_slow_path(var == NULL)) {
return NJS_ERROR;
}

- if (expr->left != NULL) {
- njs_generator_next(generator, njs_generate, expr->left);
-
- return njs_generator_after(vm, generator,
- njs_queue_first(&generator->stack), node,
- njs_generate_import_statement_end, NULL, 0);
- }
-
- return njs_generate_import_statement_end(vm, generator, node);
-}
-
-
-static njs_int_t
-njs_generate_import_statement_end(njs_vm_t *vm, njs_generator_t *generator,
- njs_parser_node_t *node)
-{
- njs_mod_t *module;
- njs_parser_node_t *expr;
- njs_vmcode_object_copy_t *copy;
-
- expr = node->right;
-
- module = (njs_mod_t *) expr->index;
-
- njs_generate_code(generator, njs_vmcode_object_copy_t, copy,
- NJS_VMCODE_OBJECT_COPY, 2, node);
- copy->retval = node->left->index;
- copy->object = module->index;
+ njs_generate_code(generator, njs_vmcode_import_t, import,
+ NJS_VMCODE_IMPORT, 1, node);
+
+ import->module = node->u.module;
+ import->retval = lvalue->index;

return njs_generator_stack_pop(vm, generator, NULL);
}
diff -r 7a08ed3e9cb8 -r 77c398f26d7e src/njs_generator.h
--- a/src/njs_generator.h Tue Feb 15 13:17:52 2022 +0000
+++ b/src/njs_generator.h Mon Feb 21 14:49:38 2022 +0000
@@ -27,6 +27,7 @@ struct njs_generator_s {
njs_arr_t *index_cache;
njs_arr_t *closures;

+ njs_str_t file;
njs_arr_t *lines;

size_t code_size;
@@ -40,8 +41,8 @@ struct njs_generator_s {
};


-njs_int_t njs_generator_init(njs_generator_t *generator, njs_int_t depth,
- njs_bool_t runtime);
+njs_int_t njs_generator_init(njs_generator_t *generator, njs_str_t *file,
+ njs_int_t depth, njs_bool_t runtime);
njs_vm_code_t *njs_generate_scope(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_scope_t *scope, const njs_str_t *name);
uint32_t njs_lookup_line(njs_vm_code_t *code, uint32_t offset);
diff -r 7a08ed3e9cb8 -r 77c398f26d7e src/njs_module.c
--- a/src/njs_module.c Tue Feb 15 13:17:52 2022 +0000
+++ b/src/njs_module.c Mon Feb 21 14:49:38 2022 +0000
@@ -12,286 +12,60 @@ typedef struct {
int fd;
njs_str_t name;
njs_str_t file;
+ char path[NJS_MAX_PATH + 1];
} njs_module_info_t;


-typedef struct {
- njs_str_t text;
- njs_module_info_t info;
- njs_lexer_t *prev;
- njs_lexer_t lexer;
-} njs_module_temp_t;
-
-
-static njs_int_t njs_parser_module_lambda_after(njs_parser_t *parser,
- njs_lexer_token_t *token, njs_queue_link_t *current);
-static njs_int_t njs_parser_module_after(njs_parser_t *parser,
- njs_lexer_token_t *token, njs_queue_link_t *current);
-
static njs_int_t njs_module_lookup(njs_vm_t *vm, const njs_str_t *cwd,
njs_module_info_t *info);
-static njs_int_t njs_module_relative_path(njs_vm_t *vm,
- const njs_str_t *dir, njs_module_info_t *info);
-static njs_int_t njs_module_absolute_path(njs_vm_t *vm,
+static njs_int_t njs_module_path(njs_vm_t *vm, const njs_str_t *dir,
njs_module_info_t *info);
-static njs_bool_t njs_module_realpath_equal(const njs_str_t *path1,
- const njs_str_t *path2);
static njs_int_t njs_module_read(njs_vm_t *vm, int fd, njs_str_t *body);
-static njs_mod_t *njs_module_find(njs_vm_t *vm, njs_str_t *name,
- njs_bool_t local);
-static njs_int_t njs_module_insert(njs_parser_t *parser, njs_mod_t *module);
-
-
-njs_int_t
-njs_module_load(njs_vm_t *vm)
-{
- njs_int_t ret;
- njs_mod_t **item, *module;
- njs_uint_t i;
- njs_value_t *value;
- njs_object_t *object;
-
- if (vm->modules == NULL) {
- return NJS_OK;
- }
-
- item = vm->modules->start;
-
- for (i = 0; i < vm->modules->items; i++) {
- module = *item;
-
- if (module->function.native) {
- value = njs_scope_valid_value(vm, module->index);
- njs_value_assign(value, &module->value);
-
- object = njs_object_value_copy(vm, value);
- if (njs_slow_path(object == NULL)) {
- return NJS_ERROR;
- }
-
- } else {
- ret = njs_vm_invoke(vm, &module->function, NULL, 0,
- njs_scope_valid_value(vm, module->index));
- if (ret == NJS_ERROR) {
- return ret;
- }
- }
-
- item++;
- }
-
- return NJS_OK;
-}
+static njs_mod_t *njs_default_module_loader(njs_vm_t *vm,
+ njs_external_ptr_t external, njs_str_t *name);


-void
-njs_module_reset(njs_vm_t *vm)
-{
- njs_mod_t **item, *module;
- njs_uint_t i;
- njs_lvlhsh_query_t lhq;
-
- if (vm->modules == NULL) {
- return;
- }
-
- item = vm->modules->start;
-
- for (i = 0; i < vm->modules->items; i++) {
- module = *item;
-
- if (!module->function.native) {
- lhq.key = module->name;
- lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length);
- lhq.proto = &njs_modules_hash_proto;
- lhq.pool = vm->mem_pool;
-
- (void) njs_lvlhsh_delete(&vm->modules_hash, &lhq);
- }
-
- item++;
- }
-
- njs_arr_reset(vm->modules);
-}
-
-
-njs_int_t
-njs_parser_module(njs_parser_t *parser, njs_lexer_token_t *token,
- njs_queue_link_t *current)
+njs_mod_t *
+njs_parser_module(njs_parser_t *parser, njs_str_t *name)
{
- njs_int_t ret;
- njs_str_t name, text;
- njs_mod_t *module;
- njs_module_temp_t *temp;
- njs_module_info_t info;
-
- name = token->text;
-
- parser->node = NULL;
-
- module = njs_module_find(parser->vm, &name, 1);
- if (module != NULL && module->function.native) {
- njs_lexer_consume_token(parser->lexer, 1);
-
- parser->target = (njs_parser_node_t *) module;
+ njs_mod_t *module;
+ njs_vm_t *vm;
+ njs_external_ptr_t external;
+ njs_module_loader_t loader;

- return njs_parser_module_after(parser, token, current);
- }
-
- njs_memzero(&text, sizeof(njs_str_t));
-
- if (parser->vm->options.sandbox || name.length == 0) {
- njs_parser_syntax_error(parser, "Cannot find module \"%V\"", &name);
- goto fail;
- }
+ vm = parser->vm;

- /* Non-native module. */
-
- njs_memzero(&info, sizeof(njs_module_info_t));
-
- info.name = name;
-
- ret = njs_module_lookup(parser->vm, &parser->scope->cwd, &info);
- if (njs_slow_path(ret != NJS_OK)) {
- njs_parser_syntax_error(parser, "Cannot find module \"%V\"", &name);
- goto fail;
+ if (name->length == 0) {
+ njs_parser_syntax_error(parser, "Cannot find module \"%V\"", name);
+ return NULL;
}

- module = njs_module_find(parser->vm, &info.file, 1);
+ module = njs_module_find(vm, name, 1);
if (module != NULL) {
- (void) close(info.fd);
- njs_lexer_consume_token(parser->lexer, 1);
-
- parser->target = (njs_parser_node_t *) module;
-
- return njs_parser_module_after(parser, token, current);
- }
-
- ret = njs_module_read(parser->vm, info.fd, &text);
-
- (void) close(info.fd);
-
- if (njs_slow_path(ret != NJS_OK)) {
- njs_internal_error(parser->vm, "while reading \"%V\" module",
- &info.file);
- goto fail;
- }
-
- if (njs_module_realpath_equal(&parser->lexer->file, &info.file)) {
- njs_parser_syntax_error(parser, "Cannot import itself \"%V\"",
- &info.file);
- goto fail;
+ goto done;
}

- temp = njs_mp_alloc(parser->vm->mem_pool, sizeof(njs_module_temp_t));
- if (njs_slow_path(temp == NULL)) {
- return NJS_ERROR;
- }
-
- ret = njs_lexer_init(parser->vm, &temp->lexer, &info.file, text.start,
- text.start + text.length, 0);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
-
- njs_lexer_consume_token(parser->lexer, 1);
+ external = parser;
+ loader = njs_default_module_loader;

- temp->prev = parser->lexer;
- temp->info = info;
- temp->text = text;
-
- parser->lexer = &temp->lexer;
-
- njs_parser_next(parser, njs_parser_module_lambda);
-
- return njs_parser_after(parser, current, temp, 0,
- njs_parser_module_lambda_after);
-
-fail:
-
- if (text.start != NULL) {
- njs_mp_free(parser->vm->mem_pool, text.start);
+ if (vm->options.ops != NULL && vm->options.ops->module_loader != NULL) {
+ loader = vm->options.ops->module_loader;
+ external = vm->external;
}

- return NJS_ERROR;
-}
-
-
-static njs_int_t
-njs_parser_module_lambda_after(njs_parser_t *parser, njs_lexer_token_t *token,
- njs_queue_link_t *current)
-{
- njs_mod_t *module;
- njs_module_temp_t *temp;
-
- temp = (njs_module_temp_t *) parser->target;
-
- if (parser->ret != NJS_OK) {
- njs_mp_free(parser->vm->mem_pool, temp->text.start);
- njs_mp_free(parser->vm->mem_pool, temp);
-
- if (token->type == NJS_TOKEN_END) {
- return njs_parser_stack_pop(parser);
- }
-
- return njs_parser_failed(parser);
- }
-
- module = njs_module_add(parser->vm, &temp->info.file, 0);
- if (njs_slow_path(module == NULL)) {
- parser->lexer = temp->prev;
-
- if (temp->text.start != NULL) {
- njs_mp_free(parser->vm->mem_pool, temp->text.start);
- }
-
- return njs_parser_failed(parser);
+ module = loader(vm, external, name);
+ if (module == NULL) {
+ njs_parser_syntax_error(parser, "Cannot find module \"%V\"", name);
+ return NULL;
}

- module->function.args_offset = 1;
- module->function.u.lambda = parser->node->u.value.data.u.lambda;
-
- njs_mp_free(parser->vm->mem_pool, temp->text.start);
-
- parser->lexer = temp->prev;
- parser->target = (njs_parser_node_t *) module;
-
- njs_mp_free(parser->vm->mem_pool, temp);
-
- return njs_parser_module_after(parser, token, current);
-}
+done:

-
-static njs_int_t
-njs_parser_module_after(njs_parser_t *parser, njs_lexer_token_t *token,
- njs_queue_link_t *current)
-{
- njs_int_t ret;
- njs_mod_t *module;
- njs_parser_node_t *node;
-
- node = njs_parser_node_new(parser, 0);
- if (njs_slow_path(node == NULL)) {
- return NJS_ERROR;
+ if (module->index == 0) {
+ module->index = vm->shared->module_items++;
}

- node->left = parser->node;
-
- module = (njs_mod_t *) parser->target;
-
- if (module->index == 0) {
- ret = njs_module_insert(parser, module);
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
- }
-
- node->index = (njs_index_t) module;
-
- parser->node = node;
-
- return njs_parser_stack_pop(parser);
+ return module;
}


@@ -303,10 +77,10 @@ njs_module_lookup(njs_vm_t *vm, const nj
njs_uint_t i;

if (info->name.start[0] == '/') {
- return njs_module_absolute_path(vm, info);
+ return njs_module_path(vm, NULL, info);
}

- ret = njs_module_relative_path(vm, cwd, info);
+ ret = njs_module_path(vm, cwd, info);

if (ret != NJS_DECLINED) {
return ret;
@@ -319,7 +93,7 @@ njs_module_lookup(njs_vm_t *vm, const nj
path = vm->paths->start;

for (i = 0; i < vm->paths->items; i++) {
- ret = njs_module_relative_path(vm, path, info);
+ ret = njs_module_path(vm, path, info);

if (ret != NJS_DECLINED) {
return ret;
@@ -333,74 +107,60 @@ njs_module_lookup(njs_vm_t *vm, const nj


static njs_int_t
-njs_module_absolute_path(njs_vm_t *vm, njs_module_info_t *info)
+njs_module_path(njs_vm_t *vm, const njs_str_t *dir, njs_module_info_t *info)
{
- njs_str_t file;
+ char *p;
+ size_t length;
+ njs_bool_t trail;
+ char src[NJS_MAX_PATH + 1];
+
+ trail = 0;
+ length = info->name.length;
+
+ if (dir != NULL) {
+ length = dir->length;

- file.length = info->name.length;
- file.start = njs_mp_alloc(vm->mem_pool, file.length + 1);
- if (njs_slow_path(file.start == NULL)) {
+ if (length == 0) {
+ return NJS_DECLINED;
+ }
+
+ trail = (dir->start[dir->length - 1] != '/');
+
+ if (trail) {
+ length++;
+ }
+ }
+
+ if (njs_slow_path(length > NJS_MAX_PATH)) {
return NJS_ERROR;
}

- memcpy(file.start, info->name.start, file.length);
- file.start[file.length] = '\0';
+ p = &src[0];
+
+ if (dir != NULL) {
+ p = (char *) njs_cpymem(p, dir->start, dir->length);

- info->fd = open((char *) file.start, O_RDONLY);
- if (info->fd < 0) {
- njs_mp_free(vm->mem_pool, file.start);
+ if (trail) {
+ *p++ = '/';
+ }
+ }
+
+ p = (char *) njs_cpymem(p, info->name.start, info->name.length);
+ *p = '\0';
+
+ p = realpath(&src[0], &info->path[0]);
+ if (p == NULL) {
return NJS_DECLINED;
}

- info->file = file;
-
- return NJS_OK;
-}
-
-
-static njs_int_t
-njs_module_relative_path(njs_vm_t *vm, const njs_str_t *dir,
- njs_module_info_t *info)
-{
- u_char *p;
- njs_str_t file;
- njs_bool_t trail;
-
- file.length = dir->length;
-
- if (file.length == 0) {
+ info->fd = open(&info->path[0], O_RDONLY);
+ if (info->fd < 0) {
return NJS_DECLINED;
}

- trail = (dir->start[dir->length - 1] != '/');

- if (trail) {
- file.length++;
- }
-
- file.length += info->name.length;
-
- file.start = njs_mp_alloc(vm->mem_pool, file.length + 1);
- if (njs_slow_path(file.start == NULL)) {
- return NJS_ERROR;
- }
-
- p = njs_cpymem(file.start, dir->start, dir->length);
-
- if (trail) {
- *p++ = '/';
- }
-
- p = njs_cpymem(p, info->name.start, info->name.length);
- *p = '\0';
-
- info->fd = open((char *) file.start, O_RDONLY);
- if (info->fd < 0) {
- njs_mp_free(vm->mem_pool, file.start);
- return NJS_DECLINED;
- }
-
- info->file = file;
+ info->file.start = (u_char *) &info->path[0];
+ info->file.length = njs_strlen(info->file.start);

return NJS_OK;
}
@@ -412,6 +172,8 @@ njs_module_read(njs_vm_t *vm, int fd, nj
ssize_t n;
struct stat sb;

+ text->start = NULL;
+
if (fstat(fd, &sb) == -1) {
goto fail;
}
@@ -445,18 +207,6 @@ fail:
}


-static njs_bool_t
-njs_module_realpath_equal(const njs_str_t *path1, const njs_str_t *path2)
-{
- char rpath1[MAXPATHLEN], rpath2[MAXPATHLEN];
-
- realpath((char *) path1->start, rpath1);
- realpath((char *) path2->start, rpath2);
-
- return (strcmp(rpath1, rpath2) == 0);
-}
-
-
static njs_int_t
njs_module_hash_test(njs_lvlhsh_query_t *lhq, void *data)
{
@@ -482,7 +232,7 @@ const njs_lvlhsh_proto_t njs_modules_ha
};


-static njs_mod_t *
+njs_mod_t *
njs_module_find(njs_vm_t *vm, njs_str_t *name, njs_bool_t shared)
{
njs_int_t ret;
@@ -533,11 +283,10 @@ njs_module_find(njs_vm_t *vm, njs_str_t


njs_mod_t *
-njs_module_add(njs_vm_t *vm, njs_str_t *name, njs_bool_t shared)
+njs_module_add(njs_vm_t *vm, njs_str_t *name)
{
njs_int_t ret;
njs_mod_t *module;
- njs_lvlhsh_t *hash;
njs_lvlhsh_query_t lhq;

module = njs_mp_zalloc(vm->mem_pool, sizeof(njs_mod_t));
@@ -559,9 +308,7 @@ njs_module_add(njs_vm_t *vm, njs_str_t *
lhq.pool = vm->mem_pool;
lhq.proto = &njs_modules_hash_proto;

- hash = shared ? &vm->shared->modules_hash : &vm->modules_hash;
-
- ret = njs_lvlhsh_insert(hash, &lhq);
+ ret = njs_lvlhsh_insert(&vm->shared->modules_hash, &lhq);
if (njs_fast_path(ret == NJS_OK)) {
return module;
}
@@ -575,38 +322,6 @@ njs_module_add(njs_vm_t *vm, njs_str_t *
}


-static njs_int_t
-njs_module_insert(njs_parser_t *parser, njs_mod_t *module)
-{
- njs_vm_t *vm;
- njs_mod_t **value;
- njs_parser_scope_t *scope;
-
- scope = njs_parser_global_scope(parser);
- vm = parser->vm;
-
- module->index = njs_scope_index(scope->type, scope->items, NJS_LEVEL_LOCAL,
- NJS_VARIABLE_VAR);
- scope->items++;
-
- if (vm->modules == NULL) {
- vm->modules = njs_arr_create(vm->mem_pool, 4, sizeof(njs_mod_t *));
- if (njs_slow_path(vm->modules == NULL)) {
- return NJS_ERROR;
- }
- }
-
- value = njs_arr_add(vm->modules);
_______________________________________________
nginx-devel mailing list -- nginx-devel@nginx.org
To unsubscribe send an email to nginx-devel-leave@nginx.org
Subject Author Views Posted

[njs] Refactoring of user modules importing.

Dmitry Volyntsev 548 February 21, 2022 10:08AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 136
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready