diff options
author | Dmitry Volyntsev <xeioex@nginx.com> | 2024-06-10 22:58:24 -0700 |
---|---|---|
committer | Dmitry Volyntsev <xeioexception@gmail.com> | 2024-09-17 18:05:57 -0700 |
commit | 9b6744129ce4c18e74b5e41cd1da66f2cbadcf36 (patch) | |
tree | 27124eed44b9e938a1b971900c51a31f533c0ec1 /nginx/ngx_js.c | |
parent | 50e6a1141db346d1396ff7588a4f6e64327e5bdf (diff) | |
download | njs-9b6744129ce4c18e74b5e41cd1da66f2cbadcf36.tar.gz njs-9b6744129ce4c18e74b5e41cd1da66f2cbadcf36.zip |
Modules: introduced engine API.
No functional changes.
Diffstat (limited to 'nginx/ngx_js.c')
-rw-r--r-- | nginx/ngx_js.c | 533 |
1 files changed, 394 insertions, 139 deletions
diff --git a/nginx/ngx_js.c b/nginx/ngx_js.c index 4c1f29f3..ce4988f9 100644 --- a/nginx/ngx_js.c +++ b/nginx/ngx_js.c @@ -24,7 +24,8 @@ typedef struct { typedef struct { - void *promise; + void *promise_obj; + njs_opaque_value_t promise; njs_opaque_value_t message; } ngx_js_rejected_promise_t; @@ -43,6 +44,19 @@ typedef struct { } njs_module_info_t; +static ngx_int_t ngx_engine_njs_init(ngx_engine_t *engine, + ngx_engine_opts_t *opts); +static ngx_int_t ngx_engine_njs_compile(ngx_js_loc_conf_t *conf, ngx_log_t *log, + u_char *start, size_t size); +static ngx_int_t ngx_engine_njs_call(ngx_js_ctx_t *ctx, ngx_str_t *fname, + njs_opaque_value_t *args, njs_uint_t nargs); +static void *ngx_engine_njs_external(ngx_engine_t *engine); +static ngx_int_t ngx_engine_njs_pending(ngx_engine_t *engine); +static ngx_int_t ngx_engine_njs_string(ngx_engine_t *e, + njs_opaque_value_t *value, ngx_str_t *str); +static void ngx_engine_njs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx, + ngx_js_loc_conf_t *conf); + static njs_int_t ngx_js_ext_build(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_js_ext_conf_file_path(njs_vm_t *vm, @@ -70,6 +84,15 @@ static njs_int_t njs_set_immediate(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_clear_timeout(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static njs_int_t ngx_js_unhandled_rejection(ngx_js_ctx_t *ctx); +static void ngx_js_rejection_tracker(njs_vm_t *vm, njs_external_ptr_t unused, + njs_bool_t is_handled, njs_value_t *promise, njs_value_t *reason); +static njs_mod_t *ngx_js_module_loader(njs_vm_t *vm, + njs_external_ptr_t external, njs_str_t *name); +static njs_int_t ngx_js_module_lookup(ngx_js_loc_conf_t *conf, + njs_module_info_t *info); +static njs_int_t ngx_js_module_read(njs_mp_t *mp, int fd, njs_str_t *text); +static njs_int_t ngx_js_set_cwd(njs_mp_t *mp, ngx_js_loc_conf_t *conf, + njs_str_t *path); static void ngx_js_cleanup_vm(void *data); static njs_int_t ngx_js_core_init(njs_vm_t *vm); @@ -354,82 +377,234 @@ njs_module_t *njs_js_addon_modules_shared[] = { static njs_int_t ngx_js_console_proto_id; -ngx_int_t -ngx_js_call(njs_vm_t *vm, njs_function_t *func, njs_value_t *args, - njs_uint_t nargs) +static ngx_engine_t * +ngx_create_engine(ngx_engine_opts_t *opts) { - njs_int_t ret; - ngx_str_t exception; - ngx_connection_t *c; + njs_mp_t *mp; + ngx_int_t rc; + ngx_engine_t *engine; - ret = njs_vm_call(vm, func, args, nargs); - if (ret == NJS_ERROR) { - ngx_js_exception(vm, &exception); + mp = njs_mp_fast_create(2 * getpagesize(), 128, 512, 16); + if (mp == NULL) { + return NULL; + } - c = ngx_external_connection(vm, njs_vm_external_ptr(vm)); + engine = njs_mp_zalloc(mp, sizeof(ngx_engine_t)); + if (engine == NULL) { + return NULL; + } - ngx_log_error(NGX_LOG_ERR, c->log, 0, - "js exception: %V", &exception); + engine->pool = mp; + engine->clone = opts->clone; + + switch (opts->engine) { + case NGX_ENGINE_NJS: + rc = ngx_engine_njs_init(engine, opts); + if (rc != NGX_OK) { + return NULL; + } + + engine->name = "njs"; + engine->type = NGX_ENGINE_NJS; + engine->compile = ngx_engine_njs_compile; + engine->call = ngx_engine_njs_call; + engine->external = ngx_engine_njs_external; + engine->pending = ngx_engine_njs_pending; + engine->string = ngx_engine_njs_string; + engine->destroy = opts->destroy ? opts->destroy + : ngx_engine_njs_destroy; + break; + + default: + return NULL; + } + + return engine; +} + + +static ngx_int_t +ngx_engine_njs_init(ngx_engine_t *engine, ngx_engine_opts_t *opts) +{ + njs_vm_t *vm; + ngx_int_t rc; + njs_vm_opt_t vm_options; + + njs_vm_opt_init(&vm_options); + + vm_options.backtrace = 1; + vm_options.addons = opts->u.njs.addons; + vm_options.metas = opts->u.njs.metas; + vm_options.file = opts->file; + vm_options.argv = ngx_argv; + vm_options.argc = ngx_argc; + + vm = njs_vm_create(&vm_options); + if (vm == NULL) { return NGX_ERROR; } - for ( ;; ) { - ret = njs_vm_execute_pending_job(vm); - if (ret <= NJS_OK) { - c = ngx_external_connection(vm, njs_vm_external_ptr(vm)); + njs_vm_set_rejection_tracker(vm, ngx_js_rejection_tracker, NULL); - if (ret == NJS_ERROR) { - ngx_js_exception(vm, &exception); + rc = ngx_js_set_cwd(njs_vm_memory_pool(vm), opts->conf, &vm_options.file); + if (rc != NGX_OK) { + return NGX_ERROR; + } - ngx_log_error(NGX_LOG_ERR, c->log, 0, - "js job exception: %V", &exception); - return NGX_ERROR; - } + njs_vm_set_module_loader(vm, ngx_js_module_loader, opts->conf); - break; + engine->u.njs.vm = vm; + + return NJS_OK; +} + + +static ngx_int_t +ngx_engine_njs_compile(ngx_js_loc_conf_t *conf, ngx_log_t *log, u_char *start, + size_t size) +{ + u_char *end; + njs_vm_t *vm; + njs_int_t rc; + njs_str_t text; + ngx_uint_t i; + njs_value_t *value; + njs_opaque_value_t exception, lvalue; + ngx_js_named_path_t *import; + + static const njs_str_t line_number_key = njs_str("lineNumber"); + static const njs_str_t file_name_key = njs_str("fileName"); + + vm = conf->engine->u.njs.vm; + end = start + size; + + rc = njs_vm_compile(vm, &start, end); + + if (rc != NJS_OK) { + njs_vm_exception_get(vm, njs_value_arg(&exception)); + njs_vm_value_string(vm, &text, njs_value_arg(&exception)); + + value = njs_vm_object_prop(vm, njs_value_arg(&exception), + &file_name_key, &lvalue); + if (value == NULL) { + value = njs_vm_object_prop(vm, njs_value_arg(&exception), + &line_number_key, &lvalue); + + if (value != NULL) { + i = njs_value_number(value) - 1; + + if (i < conf->imports->nelts) { + import = conf->imports->elts; + ngx_log_error(NGX_LOG_EMERG, log, 0, + "%*s, included in %s:%ui", text.length, + text.start, import[i].file, import[i].line); + return NGX_ERROR; + } + } } + + ngx_log_error(NGX_LOG_EMERG, log, 0, "%*s", text.length, text.start); + return NGX_ERROR; + } + + if (start != end) { + ngx_log_error(NGX_LOG_EMERG, log, 0, + "extra characters in js script: \"%*s\"", + end - start, start); + return NGX_ERROR; } return NGX_OK; } -ngx_int_t -ngx_js_name_call(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, - njs_opaque_value_t *args, njs_uint_t nargs) +ngx_engine_t * +ngx_njs_clone(ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *cf, void *external) { - njs_opaque_value_t unused; + njs_vm_t *vm; + njs_int_t rc; + njs_str_t key; + ngx_str_t exception; + ngx_uint_t i; + ngx_engine_t *engine; + njs_opaque_value_t retval; + ngx_js_named_path_t *preload; + + vm = njs_vm_clone(cf->engine->u.njs.vm, external); + if (vm == NULL) { + return NULL; + } + + engine = njs_mp_alloc(njs_vm_memory_pool(vm), sizeof(ngx_engine_t)); + if (engine == NULL) { + return NULL; + } - return ngx_js_name_invoke(vm, fname, log, args, nargs, &unused); + memcpy(engine, cf->engine, sizeof(ngx_engine_t)); + engine->pool = njs_vm_memory_pool(vm); + engine->u.njs.vm = vm; + + /* bind objects from preload vm */ + + if (cf->preload_objects != NGX_CONF_UNSET_PTR) { + preload = cf->preload_objects->elts; + + for (i = 0; i < cf->preload_objects->nelts; i++) { + key.start = preload[i].name.data; + key.length = preload[i].name.len; + + rc = njs_vm_value(cf->preload_vm, &key, njs_value_arg(&retval)); + if (rc != NJS_OK) { + return NULL; + } + + rc = njs_vm_bind(vm, &key, njs_value_arg(&retval), 0); + if (rc != NJS_OK) { + return NULL; + } + } + } + + if (njs_vm_start(vm, njs_value_arg(&retval)) == NJS_ERROR) { + ngx_js_exception(vm, &exception); + + ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js exception: %V", &exception); + + return NULL; + } + + return engine; } -ngx_int_t -ngx_js_name_invoke(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, - njs_opaque_value_t *args, njs_uint_t nargs, njs_opaque_value_t *retval) +static ngx_int_t +ngx_engine_njs_call(ngx_js_ctx_t *ctx, ngx_str_t *fname, + njs_opaque_value_t *args, njs_uint_t nargs) { + njs_vm_t *vm; njs_int_t ret; njs_str_t name; ngx_str_t exception; - ngx_js_ctx_t *ctx; njs_function_t *func; name.start = fname->data; name.length = fname->len; + vm = ctx->engine->u.njs.vm; + func = njs_vm_function(vm, &name); if (func == NULL) { - ngx_log_error(NGX_LOG_ERR, log, 0, + ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js function \"%V\" not found", fname); return NGX_ERROR; } ret = njs_vm_invoke(vm, func, njs_value_arg(args), nargs, - njs_value_arg(retval)); + njs_value_arg(&ctx->retval)); if (ret == NJS_ERROR) { ngx_js_exception(vm, &exception); - ngx_log_error(NGX_LOG_ERR, log, 0, + ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js exception: %V", &exception); return NGX_ERROR; @@ -441,7 +616,7 @@ ngx_js_name_invoke(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, if (ret == NJS_ERROR) { ngx_js_exception(vm, &exception); - ngx_log_error(NGX_LOG_ERR, log, 0, + ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js job exception: %V", &exception); return NGX_ERROR; } @@ -450,12 +625,10 @@ ngx_js_name_invoke(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, } } - ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm)); - if (ngx_js_unhandled_rejection(ctx)) { ngx_js_exception(vm, &exception); - ngx_log_error(NGX_LOG_ERR, log, 0, "js exception: %V", &exception); + ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "js exception: %V", &exception); return NGX_ERROR; } @@ -463,6 +636,110 @@ ngx_js_name_invoke(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, } +static void * +ngx_engine_njs_external(ngx_engine_t *engine) +{ + return njs_vm_external_ptr(engine->u.njs.vm); +} + +static ngx_int_t +ngx_engine_njs_pending(ngx_engine_t *e) +{ + return njs_vm_pending(e->u.njs.vm); +} + + +static ngx_int_t +ngx_engine_njs_string(ngx_engine_t *e, njs_opaque_value_t *value, + ngx_str_t *str) +{ + ngx_int_t rc; + njs_str_t s; + + rc = ngx_js_string(e->u.njs.vm, njs_value_arg(value), &s); + + str->data = s.start; + str->len = s.length; + + return rc; +} + + +static void +ngx_engine_njs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx, + ngx_js_loc_conf_t *conf) +{ + ngx_js_event_t *event; + njs_rbtree_node_t *node; + + if (ctx != NULL) { + node = njs_rbtree_min(&ctx->waiting_events); + + while (njs_rbtree_is_there_successor(&ctx->waiting_events, node)) { + event = (ngx_js_event_t *) ((u_char *) node + - offsetof(ngx_js_event_t, node)); + + if (event->destructor != NULL) { + event->destructor(event); + } + + node = njs_rbtree_node_successor(&ctx->waiting_events, node); + } + } + + njs_vm_destroy(e->u.njs.vm); + + /* + * when ctx !=NULL e->pool is vm pool, in such case it is destroyed + * by njs_vm_destroy(). + */ + + if (ctx == NULL) { + njs_mp_destroy(e->pool); + } +} + + +ngx_int_t +ngx_js_call(njs_vm_t *vm, njs_function_t *func, njs_opaque_value_t *args, + njs_uint_t nargs) +{ + njs_int_t ret; + ngx_str_t exception; + ngx_connection_t *c; + + ret = njs_vm_call(vm, func, njs_value_arg(args), nargs); + if (ret == NJS_ERROR) { + ngx_js_exception(vm, &exception); + + c = ngx_external_connection(vm, njs_vm_external_ptr(vm)); + + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "js exception: %V", &exception); + return NGX_ERROR; + } + + for ( ;; ) { + ret = njs_vm_execute_pending_job(vm); + if (ret <= NJS_OK) { + c = ngx_external_connection(vm, njs_vm_external_ptr(vm)); + + if (ret == NJS_ERROR) { + ngx_js_exception(vm, &exception); + + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "js job exception: %V", &exception); + return NGX_ERROR; + } + + break; + } + } + + return NGX_OK; +} + + ngx_int_t ngx_js_exception(njs_vm_t *vm, ngx_str_t *s) { @@ -554,33 +831,18 @@ ngx_js_event_rbtree_compare(njs_rbtree_node_t *node1, njs_rbtree_node_t *node2) void -ngx_js_ctx_init(ngx_js_ctx_t *ctx) +ngx_js_ctx_init(ngx_js_ctx_t *ctx, ngx_log_t *log) { + ctx->log = log; ctx->event_id = 0; njs_rbtree_init(&ctx->waiting_events, ngx_js_event_rbtree_compare); } void -ngx_js_ctx_destroy(ngx_js_ctx_t *ctx) +ngx_js_ctx_destroy(ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *conf) { - ngx_js_event_t *event; - njs_rbtree_node_t *node; - - node = njs_rbtree_min(&ctx->waiting_events); - - while (njs_rbtree_is_there_successor(&ctx->waiting_events, node)) { - event = (ngx_js_event_t *) ((u_char *) node - - offsetof(ngx_js_event_t, node)); - - if (event->destructor != NULL) { - event->destructor(njs_vm_external_ptr(event->vm), event); - } - - node = njs_rbtree_node_successor(&ctx->waiting_events, node); - } - - njs_vm_destroy(ctx->vm); + ctx->engine->destroy(ctx->engine, ctx, conf); } @@ -1047,9 +1309,10 @@ ngx_js_timer_handler(ngx_event_t *ev) event = (ngx_js_event_t *) ((u_char *) ev - offsetof(ngx_js_event_t, ev)); - vm = event->vm; + vm = event->ctx; - rc = ngx_js_call(vm, event->function, event->args, event->nargs); + rc = ngx_js_call(vm, njs_value_function(njs_value_arg(&event->function)), + event->args, event->nargs); ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm)); ngx_js_del_event(ctx, event); @@ -1059,7 +1322,7 @@ ngx_js_timer_handler(ngx_event_t *ev) static void -ngx_js_clear_timer(njs_external_ptr_t external, ngx_js_event_t *event) +ngx_js_clear_timer(ngx_js_event_t *event) { if (event->ev.timer_set) { ngx_del_timer(&event->ev); @@ -1106,10 +1369,10 @@ njs_set_timer(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } - event->vm = vm; - event->function = njs_value_function(njs_argument(args, 1)); + event->ctx = vm; + njs_value_assign(&event->function, njs_argument(args, 1)); event->nargs = nargs; - event->args = (njs_value_t *) ((u_char *) event + sizeof(ngx_js_event_t)); + event->args = (njs_opaque_value_t *) &event[1]; event->destructor = ngx_js_clear_timer; ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm)); @@ -1344,6 +1607,47 @@ ngx_js_import(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) char * +ngx_js_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_uint_t *type, m; + ngx_conf_bitmask_t *mask; + + type = (size_t *) (p + cmd->offset); + if (*type != NGX_CONF_UNSET_UINT) { + return "is duplicate"; + } + + value = cf->args->elts; + mask = cmd->post; + + for (m = 0; mask[m].name.len != 0; m++) { + + if (mask[m].name.len != value[1].len + || ngx_strcasecmp(mask[m].name.data, value[1].data) != 0) + { + continue; + } + + *type = mask[m].mask; + + break; + } + + if (mask[m].name.len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%s\"", value[1].data); + + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +char * ngx_js_preload_object(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_js_loc_conf_t *jscf = conf; @@ -1552,14 +1856,16 @@ ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, ngx_js_named_path_t *import, *pi, *pij, *preload; if (conf->imports == NGX_CONF_UNSET_PTR + && conf->type == NGX_CONF_UNSET_UINT && conf->paths == NGX_CONF_UNSET_PTR && conf->preload_objects == NGX_CONF_UNSET_PTR) { - if (prev->vm != NULL) { + if (prev->engine != NULL) { conf->preload_objects = prev->preload_objects; conf->imports = prev->imports; + conf->type = prev->type; conf->paths = prev->paths; - conf->vm = prev->vm; + conf->engine = prev->engine; conf->preload_vm = prev->preload_vm; @@ -1703,9 +2009,10 @@ ngx_js_rejection_tracker(njs_vm_t *vm, njs_external_ptr_t unused, promise_obj = njs_value_ptr(promise); for (i = 0; i < length; i++) { - if (rejected_promise[i].promise == promise_obj) { - njs_arr_remove(ctx->rejected_promises, - &rejected_promise[i]); + if (njs_value_ptr(njs_value_arg(&rejected_promise[i].promise)) + == promise_obj) + { + njs_arr_remove(ctx->rejected_promises, &rejected_promise[i]); break; } @@ -1727,7 +2034,7 @@ ngx_js_rejection_tracker(njs_vm_t *vm, njs_external_ptr_t unused, return; } - rejected_promise->promise = njs_value_ptr(promise); + njs_value_assign(&rejected_promise->promise, promise); njs_value_assign(&rejected_promise->message, reason); } @@ -1918,13 +2225,13 @@ current_dir: static njs_int_t -ngx_js_set_cwd(njs_vm_t *vm, ngx_js_loc_conf_t *conf, njs_str_t *path) +ngx_js_set_cwd(njs_mp_t *mp, 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); + conf->cwd.data = njs_mp_alloc(mp, cwd.len); if (conf->cwd.data == NULL) { return NJS_ERROR; } @@ -1969,7 +2276,7 @@ ngx_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name) prev_cwd = conf->cwd; - ret = ngx_js_set_cwd(vm, conf, &info.file); + ret = ngx_js_set_cwd(njs_vm_memory_pool(vm), conf, &info.file); if (ret != NJS_OK) { njs_vm_internal_error(vm, "while setting cwd for \"%V\" module", &info.file); @@ -1992,22 +2299,15 @@ ngx_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name) ngx_int_t ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, - njs_vm_opt_t *options) + ngx_engine_opts_t *options) { + u_char *start, *p; size_t size; - u_char *start, *end, *p; ngx_str_t *m, file; - njs_int_t rc; - njs_str_t text; ngx_uint_t i; - njs_value_t *value; ngx_pool_cleanup_t *cln; - njs_opaque_value_t lvalue, exception; ngx_js_named_path_t *import; - static const njs_str_t line_number_key = njs_str("lineNumber"); - static const njs_str_t file_name_key = njs_str("fileName"); - if (conf->preload_objects != NGX_CONF_UNSET_PTR) { if (ngx_js_init_preload_vm(cf, (ngx_js_loc_conf_t *)conf) != NGX_OK) { return NGX_ERROR; @@ -2054,9 +2354,10 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, options->file.start = file.data; options->file.length = file.len; + options->conf = conf; - conf->vm = njs_vm_create(options); - if (conf->vm == NULL) { + conf->engine = ngx_create_engine(options); + if (conf->engine == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "failed to create js VM"); return NGX_ERROR; } @@ -2069,17 +2370,6 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, cln->handler = ngx_js_cleanup_vm; cln->data = conf; - 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) { m = conf->paths->elts; @@ -2090,52 +2380,14 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, } } - end = start + size; - - rc = njs_vm_compile(conf->vm, &start, end); - - if (rc != NJS_OK) { - njs_vm_exception_get(conf->vm, njs_value_arg(&exception)); - njs_vm_value_string(conf->vm, &text, njs_value_arg(&exception)); - - value = njs_vm_object_prop(conf->vm, njs_value_arg(&exception), - &file_name_key, &lvalue); - if (value == NULL) { - value = njs_vm_object_prop(conf->vm, njs_value_arg(&exception), - &line_number_key, &lvalue); - - if (value != NULL) { - i = njs_value_number(value) - 1; - - if (i < conf->imports->nelts) { - import = conf->imports->elts; - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "%*s, included in %s:%ui", text.length, - text.start, import[i].file, import[i].line); - return NGX_ERROR; - } - } - } - - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "%*s", text.length, - text.start); - return NGX_ERROR; - } - - if (start != end) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "extra characters in js script: \"%*s\"", - end - start, start); - return NGX_ERROR; - } - - return NGX_OK; + return conf->engine->compile(conf, cf->log, start, size); } static njs_int_t ngx_js_unhandled_rejection(ngx_js_ctx_t *ctx) { + njs_vm_t *vm; njs_int_t ret; njs_str_t message; ngx_js_rejected_promise_t *rejected_promise; @@ -2146,15 +2398,16 @@ ngx_js_unhandled_rejection(ngx_js_ctx_t *ctx) return 0; } + vm = ctx->engine->u.njs.vm; rejected_promise = ctx->rejected_promises->start; - ret = njs_vm_value_to_string(ctx->vm, &message, + ret = njs_vm_value_to_string(vm, &message, njs_value_arg(&rejected_promise->message)); if (njs_slow_path(ret != NJS_OK)) { return -1; } - njs_vm_error(ctx->vm, "unhandled promise rejection: %V", &message); + njs_vm_error(vm, "unhandled promise rejection: %V", &message); njs_arr_destroy(ctx->rejected_promises); ctx->rejected_promises = NULL; @@ -2168,7 +2421,7 @@ ngx_js_cleanup_vm(void *data) { ngx_js_loc_conf_t *jscf = data; - njs_vm_destroy(jscf->vm); + jscf->engine->destroy(jscf->engine, NULL, NULL); if (jscf->preload_objects != NGX_CONF_UNSET_PTR) { njs_vm_destroy(jscf->preload_vm); @@ -2187,6 +2440,7 @@ ngx_js_create_conf(ngx_conf_t *cf, size_t size) } conf->paths = NGX_CONF_UNSET_PTR; + conf->type = NGX_CONF_UNSET_UINT; conf->imports = NGX_CONF_UNSET_PTR; conf->preload_objects = NGX_CONF_UNSET_PTR; @@ -2251,6 +2505,7 @@ ngx_js_merge_conf(ngx_conf_t *cf, void *parent, void *child, ngx_js_loc_conf_t *prev = parent; ngx_js_loc_conf_t *conf = child; + ngx_conf_merge_uint_value(conf->type, prev->type, NGX_ENGINE_NJS); ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 16384); ngx_conf_merge_size_value(conf->max_response_body_size, |