[njs] Moving out HostPromiseRejectionTracker from njs core.
Dmitry Volyntsev
xeioex at nginx.com
Sat Jan 20 02:16:49 UTC 2024
details: https://hg.nginx.org/njs/rev/8aad26845b18
branches:
changeset: 2269:8aad26845b18
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Jan 18 18:03:35 2024 -0800
description:
Moving out HostPromiseRejectionTracker from njs core.
HostPromiseRejectionTracker should be implemented by host
environment according to ECMAScript specs.
The following method was removed: njs_vm_unhandled_rejection().
The following method was introduced: njs_vm_set_rejection_tracker().
diffstat:
external/njs_shell.c | 103 +++++++++++++++++++++++++++++++++++++++++-
nginx/ngx_http_js_module.c | 1 -
nginx/ngx_js.c | 101 +++++++++++++++++++++++++++++++++++++++--
nginx/ngx_js.h | 2 +
nginx/ngx_stream_js_module.c | 1 -
src/njs.h | 15 ++---
src/njs_promise.c | 74 ++++--------------------------
src/njs_value.c | 7 ++
src/njs_vm.c | 40 +++------------
src/njs_vm.h | 4 +-
10 files changed, 230 insertions(+), 118 deletions(-)
diffs (651 lines):
diff -r da8b044e1c61 -r 8aad26845b18 external/njs_shell.c
--- a/external/njs_shell.c Thu Jan 18 18:03:24 2024 -0800
+++ b/external/njs_shell.c Thu Jan 18 18:03:35 2024 -0800
@@ -93,6 +93,12 @@ typedef struct {
typedef struct {
+ void *promise;
+ njs_opaque_value_t message;
+} njs_rejected_promise_t;
+
+
+typedef struct {
njs_vm_t *vm;
uint32_t event_id;
@@ -101,6 +107,8 @@ typedef struct {
njs_queue_t labels;
+ njs_arr_t *rejected_promises;
+
njs_bool_t suppress_stdout;
njs_completion_t completion;
@@ -422,7 +430,7 @@ njs_options_parse(njs_opts_t *opts, int
opts->denormals = 1;
opts->exit_code = EXIT_FAILURE;
- opts->unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW;
+ opts->unhandled_rejection = 1;
p = getenv("NJS_EXIT_CODE");
if (p != NULL) {
@@ -528,7 +536,7 @@ njs_options_parse(njs_opts_t *opts, int
break;
case 'r':
- opts->unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_IGNORE;
+ opts->unhandled_rejection = 0;
break;
case 's':
@@ -636,6 +644,8 @@ njs_console_init(njs_vm_t *vm, njs_conso
njs_queue_init(&console->posted_events);
njs_queue_init(&console->labels);
+ console->rejected_promises = NULL;
+
console->completion.completions = njs_vm_completions(vm, NULL);
if (console->completion.completions == NULL) {
return NJS_ERROR;
@@ -749,6 +759,53 @@ njs_externals_init(njs_vm_t *vm)
}
+static void
+njs_rejection_tracker(njs_vm_t *vm, njs_external_ptr_t external,
+ njs_bool_t is_handled, njs_value_t *promise, njs_value_t *reason)
+{
+ void *promise_obj;
+ uint32_t i, length;
+ njs_console_t *console;
+ njs_rejected_promise_t *rejected_promise;
+
+ console = external;
+
+ if (is_handled && console->rejected_promises != NULL) {
+ rejected_promise = console->rejected_promises->start;
+ length = console->rejected_promises->items;
+
+ promise_obj = njs_value_ptr(promise);
+
+ for (i = 0; i < length; i++) {
+ if (rejected_promise[i].promise == promise_obj) {
+ njs_arr_remove(console->rejected_promises,
+ &rejected_promise[i]);
+
+ break;
+ }
+ }
+
+ return;
+ }
+
+ if (console->rejected_promises == NULL) {
+ console->rejected_promises = njs_arr_create(njs_vm_memory_pool(vm), 4,
+ sizeof(njs_rejected_promise_t));
+ if (njs_slow_path(console->rejected_promises == NULL)) {
+ return;
+ }
+ }
+
+ rejected_promise = njs_arr_add(console->rejected_promises);
+ if (njs_slow_path(rejected_promise == NULL)) {
+ return;
+ }
+
+ rejected_promise->promise = njs_value_ptr(promise);
+ njs_value_assign(&rejected_promise->message, reason);
+}
+
+
static njs_vm_t *
njs_create_vm(njs_opts_t *opts)
{
@@ -784,7 +841,6 @@ njs_create_vm(njs_opts_t *opts)
vm_options.argv = opts->argv;
vm_options.argc = opts->argc;
vm_options.ast = opts->ast;
- vm_options.unhandled_rejection = opts->unhandled_rejection;
if (opts->stack_size != 0) {
vm_options.max_stack_size = opts->stack_size;
@@ -796,6 +852,11 @@ njs_create_vm(njs_opts_t *opts)
return NULL;
}
+ if (opts->unhandled_rejection) {
+ njs_vm_set_rejection_tracker(vm, njs_rejection_tracker,
+ njs_vm_external_ptr(vm));
+ }
+
for (i = 0; i < opts->n_paths; i++) {
path.start = (u_char *) opts->paths[i];
path.length = njs_strlen(opts->paths[i]);
@@ -914,6 +975,40 @@ njs_process_events(void *runtime)
static njs_int_t
+njs_unhandled_rejection(void *runtime)
+{
+ njs_int_t ret;
+ njs_str_t message;
+ njs_console_t *console;
+ njs_rejected_promise_t *rejected_promise;
+
+ console = runtime;
+
+ if (console->rejected_promises == NULL
+ || console->rejected_promises->items == 0)
+ {
+ return 0;
+ }
+
+ rejected_promise = console->rejected_promises->start;
+
+ ret = njs_vm_value_to_string(console->vm, &message,
+ njs_value_arg(&rejected_promise->message));
+ if (njs_slow_path(ret != NJS_OK)) {
+ return -1;
+ }
+
+ njs_vm_error(console->vm, "unhandled promise rejection: %V",
+ &message);
+
+ njs_arr_destroy(console->rejected_promises);
+ console->rejected_promises = NULL;
+
+ return 1;
+}
+
+
+static njs_int_t
njs_read_file(njs_opts_t *opts, njs_str_t *content)
{
int fd;
@@ -1112,7 +1207,7 @@ njs_process_script(njs_vm_t *vm, void *r
}
}
- if (njs_vm_unhandled_rejection(vm)) {
+ if (njs_unhandled_rejection(runtime)) {
njs_process_output(vm, NULL, NJS_ERROR);
if (!njs_vm_options(vm)->interactive) {
diff -r da8b044e1c61 -r 8aad26845b18 nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Thu Jan 18 18:03:24 2024 -0800
+++ b/nginx/ngx_http_js_module.c Thu Jan 18 18:03:35 2024 -0800
@@ -4505,7 +4505,6 @@ ngx_http_js_init_conf_vm(ngx_conf_t *cf,
ngx_http_js_uptr[NGX_JS_MAIN_CONF_INDEX] = (uintptr_t) jmcf;
options.backtrace = 1;
- options.unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW;
options.metas = &ngx_http_js_metas;
options.addons = njs_http_js_addon_modules;
options.argv = ngx_argv;
diff -r da8b044e1c61 -r 8aad26845b18 nginx/ngx_js.c
--- a/nginx/ngx_js.c Thu Jan 18 18:03:24 2024 -0800
+++ b/nginx/ngx_js.c Thu Jan 18 18:03:35 2024 -0800
@@ -12,17 +12,23 @@
typedef struct {
- ngx_queue_t labels;
+ ngx_queue_t labels;
} ngx_js_console_t;
typedef struct {
- njs_str_t name;
- uint64_t time;
- ngx_queue_t queue;
+ njs_str_t name;
+ uint64_t time;
+ ngx_queue_t queue;
} ngx_js_timelabel_t;
+typedef struct {
+ void *promise;
+ njs_opaque_value_t message;
+} ngx_js_rejected_promise_t;
+
+
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,
@@ -49,6 +55,7 @@ static njs_int_t njs_set_immediate(njs_v
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
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_cleanup_vm(void *data);
static njs_int_t ngx_js_core_init(njs_vm_t *vm);
@@ -429,15 +436,15 @@ ngx_js_name_invoke(njs_vm_t *vm, ngx_str
}
}
- if (njs_vm_unhandled_rejection(vm)) {
+ 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);
return NGX_ERROR;
}
- ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
-
return njs_rbtree_is_empty(&ctx->waiting_events) ? NGX_OK : NGX_AGAIN;
}
@@ -1661,6 +1668,53 @@ ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_l
}
+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)
+{
+ void *promise_obj;
+ uint32_t i, length;
+ ngx_js_ctx_t *ctx;
+ ngx_js_rejected_promise_t *rejected_promise;
+
+ ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
+
+ if (is_handled && ctx->rejected_promises != NULL) {
+ rejected_promise = ctx->rejected_promises->start;
+ length = ctx->rejected_promises->items;
+
+ 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]);
+
+ break;
+ }
+ }
+
+ return;
+ }
+
+ if (ctx->rejected_promises == NULL) {
+ ctx->rejected_promises = njs_arr_create(njs_vm_memory_pool(vm), 4,
+ sizeof(ngx_js_rejected_promise_t));
+ if (njs_slow_path(ctx->rejected_promises == NULL)) {
+ return;
+ }
+ }
+
+ rejected_promise = njs_arr_add(ctx->rejected_promises);
+ if (njs_slow_path(rejected_promise == NULL)) {
+ return;
+ }
+
+ rejected_promise->promise = njs_value_ptr(promise);
+ njs_value_assign(&rejected_promise->message, reason);
+}
+
+
ngx_int_t
ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf,
njs_vm_opt_t *options)
@@ -1738,6 +1792,9 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_
cln->handler = ngx_js_cleanup_vm;
cln->data = conf;
+ njs_vm_set_rejection_tracker(conf->vm, ngx_js_rejection_tracker,
+ NULL);
+
path.start = ngx_cycle->conf_prefix.data;
path.length = ngx_cycle->conf_prefix.len;
@@ -1810,6 +1867,36 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_
}
+static njs_int_t
+ngx_js_unhandled_rejection(ngx_js_ctx_t *ctx)
+{
+ njs_int_t ret;
+ njs_str_t message;
+ ngx_js_rejected_promise_t *rejected_promise;
+
+ if (ctx->rejected_promises == NULL
+ || ctx->rejected_promises->items == 0)
+ {
+ return 0;
+ }
+
+ rejected_promise = ctx->rejected_promises->start;
+
+ ret = njs_vm_value_to_string(ctx->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_arr_destroy(ctx->rejected_promises);
+ ctx->rejected_promises = NULL;
+
+ return 1;
+}
+
+
static void
ngx_js_cleanup_vm(void *data)
{
diff -r da8b044e1c61 -r 8aad26845b18 nginx/ngx_js.h
--- a/nginx/ngx_js.h Thu Jan 18 18:03:24 2024 -0800
+++ b/nginx/ngx_js.h Thu Jan 18 18:03:35 2024 -0800
@@ -15,6 +15,7 @@
#include <ngx_event.h>
#include <njs.h>
#include <njs_rbtree.h>
+#include <njs_arr.h>
#include "ngx_js_fetch.h"
#include "ngx_js_shared_dict.h"
@@ -111,6 +112,7 @@ struct ngx_js_event_s {
#define NGX_JS_COMMON_CTX \
njs_vm_t *vm; \
+ njs_arr_t *rejected_promises; \
njs_rbtree_t waiting_events; \
ngx_socket_t event_id
diff -r da8b044e1c61 -r 8aad26845b18 nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c Thu Jan 18 18:03:24 2024 -0800
+++ b/nginx/ngx_stream_js_module.c Thu Jan 18 18:03:35 2024 -0800
@@ -1778,7 +1778,6 @@ ngx_stream_js_init_conf_vm(ngx_conf_t *c
ngx_stream_js_uptr[NGX_JS_MAIN_CONF_INDEX] = (uintptr_t) jmcf;
options.backtrace = 1;
- options.unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW;
options.metas = &ngx_stream_js_metas;
options.addons = njs_stream_js_addon_modules;
options.argv = ngx_argv;
diff -r da8b044e1c61 -r 8aad26845b18 src/njs.h
--- a/src/njs.h Thu Jan 18 18:03:24 2024 -0800
+++ b/src/njs.h Thu Jan 18 18:03:35 2024 -0800
@@ -196,6 +196,9 @@ typedef void * njs_
typedef njs_mod_t *(*njs_module_loader_t)(njs_vm_t *vm,
njs_external_ptr_t external, njs_str_t *name);
+typedef void (*njs_rejection_tracker_t)(njs_vm_t *vm,
+ njs_external_ptr_t external, njs_bool_t is_handled, njs_value_t *promise,
+ njs_value_t *reason);
typedef struct {
@@ -225,9 +228,6 @@ typedef struct {
njs_uint_t max_stack_size;
-#define NJS_VM_OPT_UNHANDLED_REJECTION_IGNORE 0
-#define NJS_VM_OPT_UNHANDLED_REJECTION_THROW 1
-
/*
* interactive - enables "interactive" mode.
* (REPL). Allows starting parent VM without cloning.
@@ -240,9 +240,6 @@ typedef struct {
* - Function constructors.
* module - ES6 "module" mode. Script mode is default.
* ast - print AST.
- * unhandled_rejection IGNORE | THROW - tracks unhandled promise rejections:
- * - throwing inside a Promise without a catch block.
- * - throwing inside in a finally or catch block.
*/
uint8_t interactive; /* 1 bit */
uint8_t trailer; /* 1 bit */
@@ -260,7 +257,6 @@ typedef struct {
#ifdef NJS_DEBUG_GENERATOR
uint8_t generator_debug; /* 1 bit */
#endif
- uint8_t unhandled_rejection;
} njs_vm_opt_t;
@@ -304,7 +300,9 @@ NJS_EXPORT njs_int_t njs_vm_enqueue_job(
*/
NJS_EXPORT njs_int_t njs_vm_execute_pending_job(njs_vm_t *vm);
NJS_EXPORT njs_int_t njs_vm_pending(njs_vm_t *vm);
-NJS_EXPORT njs_int_t njs_vm_unhandled_rejection(njs_vm_t *vm);
+
+NJS_EXPORT void njs_vm_set_rejection_tracker(njs_vm_t *vm,
+ njs_rejection_tracker_t rejection_tracker, void *opaque);
NJS_EXPORT void *njs_vm_completions(njs_vm_t *vm, njs_str_t *expression);
@@ -468,6 +466,7 @@ NJS_EXPORT double njs_value_number(const
NJS_EXPORT njs_function_t *njs_value_function(const njs_value_t *value);
NJS_EXPORT njs_function_native_t njs_value_native_function(
const njs_value_t *value);
+NJS_EXPORT void *njs_value_ptr(const njs_value_t *value);
njs_external_ptr_t njs_value_external(const njs_value_t *value);
NJS_EXPORT njs_int_t njs_value_external_tag(const njs_value_t *value);
diff -r da8b044e1c61 -r 8aad26845b18 src/njs_promise.c
--- a/src/njs_promise.c Thu Jan 18 18:03:24 2024 -0800
+++ b/src/njs_promise.c Thu Jan 18 18:03:35 2024 -0800
@@ -61,8 +61,6 @@ static njs_int_t njs_promise_value_const
static njs_int_t njs_promise_capability_executor(njs_vm_t *vm,
njs_value_t *args, njs_uint_t nargs, njs_index_t unused,
njs_value_t *retval);
-static njs_int_t njs_promise_host_rejection_tracker(njs_vm_t *vm,
- njs_promise_t *promise, njs_promise_rejection_type_t operation);
static njs_int_t njs_promise_resolve_function(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
static njs_int_t njs_promise_reject_function(njs_vm_t *vm, njs_value_t *args,
@@ -513,8 +511,8 @@ njs_promise_fulfill(njs_vm_t *vm, njs_pr
njs_inline njs_value_t *
njs_promise_reject(njs_vm_t *vm, njs_promise_t *promise, njs_value_t *reason)
{
- njs_int_t ret;
njs_queue_t queue;
+ njs_value_t promise_value;
njs_promise_data_t *data;
data = njs_data(&promise->value);
@@ -523,10 +521,10 @@ njs_promise_reject(njs_vm_t *vm, njs_pro
data->state = NJS_PROMISE_REJECTED;
if (!data->is_handled) {
- ret = njs_promise_host_rejection_tracker(vm, promise,
- NJS_PROMISE_REJECT);
- if (njs_slow_path(ret != NJS_OK)) {
- return njs_value_arg(&njs_value_null);
+ if (vm->rejection_tracker != NULL) {
+ njs_set_promise(&promise_value, promise);
+ vm->rejection_tracker(vm, vm->rejection_tracker_opaque, 0,
+ &promise_value, reason);
}
}
@@ -548,58 +546,6 @@ njs_promise_reject(njs_vm_t *vm, njs_pro
static njs_int_t
-njs_promise_host_rejection_tracker(njs_vm_t *vm, njs_promise_t *promise,
- njs_promise_rejection_type_t operation)
-{
- uint32_t i, length;
- njs_value_t *value;
- njs_promise_data_t *data;
-
- if (vm->options.unhandled_rejection
- == NJS_VM_OPT_UNHANDLED_REJECTION_IGNORE)
- {
- return NJS_OK;
- }
-
- if (vm->promise_reason == NULL) {
- vm->promise_reason = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
- if (njs_slow_path(vm->promise_reason == NULL)) {
- return NJS_ERROR;
- }
- }
-
- data = njs_data(&promise->value);
-
- if (operation == NJS_PROMISE_REJECT) {
- if (vm->promise_reason != NULL) {
- return njs_array_add(vm, vm->promise_reason, &data->result);
- }
-
- } else {
- value = vm->promise_reason->start;
- length = vm->promise_reason->length;
-
- for (i = 0; i < length; i++) {
- if (njs_values_same(&value[i], &data->result)) {
- length--;
-
- if (i < length) {
- memmove(&value[i], &value[i + 1],
- sizeof(njs_value_t) * (length - i));
- }
-
- break;
- }
- }
-
- vm->promise_reason->length = length;
- }
-
- return NJS_OK;
-}
-
-
-static njs_int_t
njs_promise_invoke_then(njs_vm_t *vm, njs_value_t *promise, njs_value_t *args,
njs_int_t nargs, njs_value_t *retval)
{
@@ -896,7 +842,7 @@ njs_promise_perform_then(njs_vm_t *vm, n
njs_promise_capability_t *capability, njs_value_t *retval)
{
njs_int_t ret;
- njs_value_t arguments[2];
+ njs_value_t arguments[2], promise_value;
njs_promise_t *promise;
njs_function_t *function;
njs_promise_data_t *data;
@@ -949,10 +895,10 @@ njs_promise_perform_then(njs_vm_t *vm, n
if (data->state == NJS_PROMISE_REJECTED) {
njs_set_data(&arguments[0], rejected_reaction, 0);
- ret = njs_promise_host_rejection_tracker(vm, promise,
- NJS_PROMISE_HANDLE);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
+ if (vm->rejection_tracker != NULL) {
+ njs_set_promise(&promise_value, promise);
+ vm->rejection_tracker(vm, vm->rejection_tracker_opaque, 1,
+ &promise_value, &data->result);
}
} else {
diff -r da8b044e1c61 -r 8aad26845b18 src/njs_value.c
--- a/src/njs_value.c Thu Jan 18 18:03:24 2024 -0800
+++ b/src/njs_value.c Thu Jan 18 18:03:35 2024 -0800
@@ -457,6 +457,13 @@ njs_value_native_function(const njs_valu
}
+void *
+njs_value_ptr(const njs_value_t *value)
+{
+ return njs_data(value);
+}
+
+
njs_external_ptr_t
njs_value_external(const njs_value_t *value)
{
diff -r da8b044e1c61 -r 8aad26845b18 src/njs_vm.c
--- a/src/njs_vm.c Thu Jan 18 18:03:24 2024 -0800
+++ b/src/njs_vm.c Thu Jan 18 18:03:35 2024 -0800
@@ -627,37 +627,6 @@ njs_vm_pending(njs_vm_t *vm)
njs_int_t
-njs_vm_unhandled_rejection(njs_vm_t *vm)
-{
- njs_int_t ret;
- njs_str_t str;
- njs_value_t string;
-
- if (!(vm->options.unhandled_rejection
- == NJS_VM_OPT_UNHANDLED_REJECTION_THROW
- && vm->promise_reason != NULL
- && vm->promise_reason->length != 0))
- {
- return 0;
- }
-
- njs_value_assign(&string, &vm->promise_reason->start[0]);
- ret = njs_value_to_string(vm, &string, &string);
- if (njs_slow_path(ret != NJS_OK)) {
- return ret;
- }
-
- njs_string_get(&string, &str);
- njs_vm_error(vm, "unhandled promise rejection: %V", &str);
-
- njs_mp_free(vm->mem_pool, vm->promise_reason);
- vm->promise_reason = NULL;
-
- return 1;
-}
-
-
-njs_int_t
njs_vm_enqueue_job(njs_vm_t *vm, njs_function_t *function,
const njs_value_t *args, njs_uint_t nargs)
{
@@ -738,6 +707,15 @@ njs_vm_set_module_loader(njs_vm_t *vm, n
}
+void
+njs_vm_set_rejection_tracker(njs_vm_t *vm,
+ njs_rejection_tracker_t rejection_tracker, void *opaque)
+{
+ vm->rejection_tracker = rejection_tracker;
+ vm->rejection_tracker_opaque = opaque;
+}
+
+
njs_int_t
njs_vm_add_path(njs_vm_t *vm, const njs_str_t *path)
{
diff -r da8b044e1c61 -r 8aad26845b18 src/njs_vm.h
--- a/src/njs_vm.h Thu Jan 18 18:03:24 2024 -0800
+++ b/src/njs_vm.h Thu Jan 18 18:03:35 2024 -0800
@@ -160,8 +160,6 @@ struct njs_vm_s {
njs_regex_compile_ctx_t *regex_compile_ctx;
njs_regex_match_data_t *single_match_data;
- njs_array_t *promise_reason;
-
njs_parser_scope_t *global_scope;
/*
@@ -185,6 +183,8 @@ struct njs_vm_s {
njs_module_loader_t module_loader;
void *module_loader_opaque;
+ njs_rejection_tracker_t rejection_tracker;
+ void *rejection_tracker_opaque;
};
More information about the nginx-devel
mailing list