Welcome! Log In Create A New Profile

Advanced

[njs] Refactored asynchronous events.

Dmitry Volyntsev
December 05, 2023 11:56AM
details: https://hg.nginx.org/njs/rev/bc80bcb3102c
branches:
changeset: 2245:bc80bcb3102c
user: Dmitry Volyntsev <xeioex@nginx.com>
date: Tue Dec 05 08:54:18 2023 -0800
description:
Refactored asynchronous events.

To align njs with other JS engines, async events are removed from njs
core. The following functions were removed: njs_vm_add_event(),
njs_vm_del_event(), njs_vm_waiting(). Instead the host is expected
to manage async events by itself.

In addition, the posted events are renamed to jobs, to better align with
the ECMA specs. The following methods are removed: njs_vm_run().
Instead, the host is expected to call njs_vm_execute_pending_job() in a
loop to execute pending jobs. The following functions were added:
njs_vm_enqueue_job().

diffstat:

auto/sources | 1 -
external/njs_fs_module.c | 17 +--
external/njs_shell.c | 16 ++-
external/njs_webcrypto_module.c | 8 +-
nginx/ngx_http_js_module.c | 99 +++++++-----------
nginx/ngx_js.c | 107 ++++++++++++--------
nginx/ngx_js.h | 33 ++++-
nginx/ngx_js_fetch.c | 59 ++++++----
nginx/ngx_stream_js_module.c | 133 +++++++++----------------
src/njs.h | 59 +----------
src/njs_event.c | 95 ------------------
src/njs_event.h | 24 ----
src/njs_promise.c | 39 +------
src/njs_vm.c | 208 ++++++++++-----------------------------
src/njs_vm.h | 4 +-
src/test/njs_externals_test.c | 35 ++++--
src/test/njs_externals_test.h | 2 +-
src/test/njs_unit_test.c | 24 ++-
18 files changed, 329 insertions(+), 634 deletions(-)

diffs (truncated from 1774 to 1000 lines):

diff -r 439ea33e531c -r bc80bcb3102c auto/sources
--- a/auto/sources Wed Nov 29 20:46:36 2023 -0800
+++ b/auto/sources Tue Dec 05 08:54:18 2023 -0800
@@ -34,7 +34,6 @@ NJS_LIB_SRCS=" \
src/njs_generator.c \
src/njs_disassembler.c \
src/njs_module.c \
- src/njs_event.c \
src/njs_extern.c \
src/njs_boolean.c \
src/njs_number.c \
diff -r 439ea33e531c -r bc80bcb3102c external/njs_fs_module.c
--- a/external/njs_fs_module.c Wed Nov 29 20:46:36 2023 -0800
+++ b/external/njs_fs_module.c Tue Dec 05 08:54:18 2023 -0800
@@ -3264,7 +3264,6 @@ njs_fs_result(njs_vm_t *vm, njs_opaque_v
const njs_value_t *callback, njs_uint_t nargs, njs_value_t *retval)
{
njs_int_t ret;
- njs_vm_event_t vm_event;
njs_function_t *cb;
njs_opaque_value_t promise, callbacks[2], arguments[2];

@@ -3290,16 +3289,11 @@ njs_fs_result(njs_vm_t *vm, njs_opaque_v
return NJS_ERROR;
}

- vm_event = njs_vm_add_event(vm, cb, 1, NULL, NULL);
- if (njs_slow_path(vm_event == NULL)) {
- return NJS_ERROR;
- }
-
njs_value_assign(&arguments[0],
&callbacks[njs_value_is_error(njs_value_arg(result))]);
njs_value_assign(&arguments[1], result);

- ret = njs_vm_post_event(vm, vm_event, njs_value_arg(&arguments), 2);
+ ret = njs_vm_enqueue_job(vm, cb, njs_value_arg(&arguments), 2);
if (njs_slow_path(ret == NJS_ERROR)) {
return NJS_ERROR;
}
@@ -3318,13 +3312,8 @@ njs_fs_result(njs_vm_t *vm, njs_opaque_v
njs_value_assign(&arguments[1], result);
}

- vm_event = njs_vm_add_event(vm, njs_value_function(callback), 1, NULL,
- NULL);
- if (njs_slow_path(vm_event == NULL)) {
- return NJS_ERROR;
- }
-
- ret = njs_vm_post_event(vm, vm_event, njs_value_arg(&arguments), 2);
+ ret = njs_vm_enqueue_job(vm, njs_value_function(callback),
+ njs_value_arg(&arguments), 2);
if (njs_slow_path(ret == NJS_ERROR)) {
return NJS_ERROR;
}
diff -r 439ea33e531c -r bc80bcb3102c external/njs_shell.c
--- a/external/njs_shell.c Wed Nov 29 20:46:36 2023 -0800
+++ b/external/njs_shell.c Tue Dec 05 08:54:18 2023 -0800
@@ -1096,12 +1096,18 @@ njs_process_script(njs_vm_t *vm, void *r
}

for ( ;; ) {
- ret = njs_vm_run(vm);
- if (ret == NJS_ERROR) {
- njs_process_output(vm, njs_value_arg(&retval), ret);
+ for ( ;; ) {
+ ret = njs_vm_execute_pending_job(vm);
+ if (ret <= NJS_OK) {
+ if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) {
+ njs_process_output(vm, NULL, ret);

- if (!njs_vm_options(vm)->interactive) {
- return NJS_ERROR;
+ if (!njs_vm_options(vm)->interactive) {
+ return NJS_ERROR;
+ }
+ }
+
+ break;
}
}

diff -r 439ea33e531c -r bc80bcb3102c external/njs_webcrypto_module.c
--- a/external/njs_webcrypto_module.c Wed Nov 29 20:46:36 2023 -0800
+++ b/external/njs_webcrypto_module.c Tue Dec 05 08:54:18 2023 -0800
@@ -4771,7 +4771,6 @@ njs_webcrypto_result(njs_vm_t *vm, njs_o
{
njs_int_t ret;
njs_function_t *callback;
- njs_vm_event_t vm_event;
njs_opaque_value_t promise, arguments[2];

ret = njs_vm_promise_create(vm, njs_value_arg(&promise),
@@ -4785,11 +4784,6 @@ njs_webcrypto_result(njs_vm_t *vm, njs_o
goto error;
}

- vm_event = njs_vm_add_event(vm, callback, 1, NULL, NULL);
- if (vm_event == NULL) {
- goto error;
- }
-
njs_value_assign(&arguments[0], &arguments[(rc != NJS_OK)]);

if (rc != NJS_OK) {
@@ -4799,7 +4793,7 @@ njs_webcrypto_result(njs_vm_t *vm, njs_o
njs_value_assign(&arguments[1], result);
}

- ret = njs_vm_post_event(vm, vm_event, njs_value_arg(&arguments), 2);
+ ret = njs_vm_enqueue_job(vm, callback, njs_value_arg(&arguments), 2);
if (ret == NJS_ERROR) {
goto error;
}
diff -r 439ea33e531c -r bc80bcb3102c nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Wed Nov 29 20:46:36 2023 -0800
+++ b/nginx/ngx_http_js_module.c Tue Dec 05 08:54:18 2023 -0800
@@ -266,9 +266,7 @@ static ngx_msec_t ngx_http_js_fetch_time
static size_t ngx_http_js_buffer_size(njs_vm_t *vm, ngx_http_request_t *r);
static size_t ngx_http_js_max_response_buffer_size(njs_vm_t *vm,
ngx_http_request_t *r);
-static void ngx_http_js_handle_vm_event(ngx_http_request_t *r,
- njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs);
-static void ngx_http_js_event_finalize(ngx_http_request_t *r, njs_int_t rc);
+static void ngx_http_js_event_finalize(ngx_http_request_t *r, ngx_int_t rc);
static ngx_js_ctx_t *ngx_http_js_ctx(njs_vm_t *vm, ngx_http_request_t *r);

static void ngx_http_js_periodic_handler(ngx_event_t *ev);
@@ -852,14 +850,13 @@ static uintptr_t ngx_http_js_uptr[] = {
(uintptr_t) ngx_http_js_pool,
(uintptr_t) ngx_http_js_resolver,
(uintptr_t) ngx_http_js_resolver_timeout,
- (uintptr_t) ngx_http_js_handle_vm_event,
+ (uintptr_t) ngx_http_js_event_finalize,
(uintptr_t) ngx_http_js_ssl,
(uintptr_t) ngx_http_js_ssl_verify,
(uintptr_t) ngx_http_js_fetch_timeout,
(uintptr_t) ngx_http_js_buffer_size,
(uintptr_t) ngx_http_js_max_response_buffer_size,
(uintptr_t) 0 /* main_conf ptr */,
- (uintptr_t) ngx_http_js_event_finalize,
(uintptr_t) ngx_http_js_ctx,
};

@@ -950,8 +947,8 @@ ngx_http_js_content_event_handler(ngx_ht

ctx->status = NGX_HTTP_INTERNAL_SERVER_ERROR;

- rc = ngx_js_call(ctx->vm, &jlcf->content, r->connection->log,
- &ctx->request, 1);
+ rc = ngx_js_name_call(ctx->vm, &jlcf->content, r->connection->log,
+ &ctx->request, 1);

if (rc == NGX_ERROR) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -1081,8 +1078,8 @@ ngx_http_js_header_filter(ngx_http_reque
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http js header call \"%V\"", &jlcf->header_filter);

- rc = ngx_js_call(ctx->vm, &jlcf->header_filter, r->connection->log,
- &ctx->request, 1);
+ rc = ngx_js_name_call(ctx->vm, &jlcf->header_filter, r->connection->log,
+ &ctx->request, 1);

if (rc == NGX_ERROR) {
return NGX_ERROR;
@@ -1184,8 +1181,8 @@ ngx_http_js_body_filter(ngx_http_request
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http js body call \"%V\"", &jlcf->body_filter);

- rc = ngx_js_call(ctx->vm, &jlcf->body_filter, c->log, &arguments[0],
- 3);
+ rc = ngx_js_name_call(ctx->vm, &jlcf->body_filter, c->log,
+ &arguments[0], 3);

if (rc == NGX_ERROR) {
return NGX_ERROR;
@@ -1260,8 +1257,8 @@ ngx_http_js_variable_set(ngx_http_reques

pending = ngx_vm_pending(ctx);

- rc = ngx_js_invoke(ctx->vm, fname, r->connection->log, &ctx->request, 1,
- &ctx->retval);
+ rc = ngx_js_name_invoke(ctx->vm, fname, r->connection->log, &ctx->request,
+ 1, &ctx->retval);

if (rc == NGX_ERROR) {
v->not_found = 1;
@@ -3389,7 +3386,7 @@ ngx_http_js_subrequest(ngx_http_request_
{
ngx_int_t flags;
ngx_str_t uri, args;
- njs_vm_event_t vm_event;
+ ngx_js_event_t *event;
ngx_http_js_ctx_t *ctx;
ngx_http_post_subrequest_t *ps;

@@ -3404,20 +3401,25 @@ ngx_http_js_subrequest(ngx_http_request_
return NJS_ERROR;
}

- vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL);
- if (vm_event == NULL) {
- njs_vm_error(ctx->vm, "internal error");
+ event = njs_mp_zalloc(njs_vm_memory_pool(ctx->vm),
+ sizeof(ngx_js_event_t));
+ if (njs_slow_path(event == NULL)) {
+ njs_vm_memory_error(ctx->vm);
return NJS_ERROR;
}

+ event->vm = ctx->vm;
+ event->function = callback;
+ event->fd = ctx->event_id++;
+
ps->handler = ngx_http_js_subrequest_done;
- ps->data = vm_event;
+ ps->data = event;

flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;

} else {
ps = NULL;
- vm_event = NULL;
+ event = NULL;
}

uri.len = uri_arg->length;
@@ -3429,14 +3431,14 @@ ngx_http_js_subrequest(ngx_http_request_
if (ngx_http_subrequest(r, &uri, args.len ? &args : NULL, sr, ps, flags)
!= NGX_OK)
{
- if (vm_event != NULL) {
- njs_vm_del_event(ctx->vm, vm_event);
- }
-
njs_vm_error(ctx->vm, "subrequest creation failed");
return NJS_ERROR;
}

+ if (event != NULL) {
+ ngx_js_add_event(ctx, event);
+ }
+
return NJS_OK;
}

@@ -3444,7 +3446,7 @@ ngx_http_js_subrequest(ngx_http_request_
static ngx_int_t
ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
{
- njs_vm_event_t vm_event = data;
+ ngx_js_event_t *event = data;

njs_int_t ret;
ngx_http_js_ctx_t *ctx;
@@ -3493,7 +3495,11 @@ ngx_http_js_subrequest_done(ngx_http_req
return NGX_ERROR;
}

- ngx_http_js_handle_vm_event(r->parent, vm_event, njs_value_arg(&reply), 1);
+ rc = ngx_js_call(ctx->vm, event->function, njs_value_arg(&reply), 1);
+
+ ngx_js_del_event(ctx, event);
+
+ ngx_http_js_event_finalize(r->parent, rc);

return NGX_OK;
}
@@ -4248,8 +4254,8 @@ ngx_http_js_periodic_handler(ngx_event_t

r->count++;

- rc = ngx_js_invoke(ctx->vm, &periodic->method, &periodic->log,
- &ctx->request, 1, &ctx->retval);
+ rc = ngx_js_name_invoke(ctx->vm, &periodic->method, &periodic->log,
+ &ctx->request, 1, &ctx->retval);

if (rc == NGX_AGAIN) {
rc = NGX_OK;
@@ -4440,41 +4446,12 @@ ngx_http_js_max_response_buffer_size(njs


static void
-ngx_http_js_handle_vm_event(ngx_http_request_t *r, njs_vm_event_t vm_event,
- njs_value_t *args, njs_uint_t nargs)
-{
- njs_int_t rc;
- ngx_str_t exception;
- ngx_http_js_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
-
- njs_vm_post_event(ctx->vm, vm_event, args, nargs);
-
- rc = njs_vm_run(ctx->vm);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http js post event handler rc: %i event: %p",
- (ngx_int_t) rc, vm_event);
-
- if (rc == NJS_ERROR) {
- ngx_js_exception(ctx->vm, &exception);
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "js exception: %V", &exception);
- }
-
- ngx_http_js_event_finalize(r, rc);
-}
-
-
-static void
-ngx_http_js_event_finalize(ngx_http_request_t *r, njs_int_t rc)
+ngx_http_js_event_finalize(ngx_http_request_t *r, ngx_int_t rc)
{
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http js event finalize rc: %i", (ngx_int_t) rc);
-
- if (rc == NJS_ERROR) {
+ "http js event finalize rc: %i", rc);
+
+ if (rc == NGX_ERROR) {
if (r->health_check) {
ngx_http_js_periodic_finalize(r, NGX_ERROR);
return;
@@ -4484,7 +4461,7 @@ ngx_http_js_event_finalize(ngx_http_requ
return;
}

- if (rc == NJS_OK) {
+ if (rc == NGX_OK) {
ngx_http_post_request(r, NULL);
}

diff -r 439ea33e531c -r bc80bcb3102c nginx/ngx_js.c
--- a/nginx/ngx_js.c Wed Nov 29 20:46:36 2023 -0800
+++ b/nginx/ngx_js.c Tue Dec 05 08:54:18 2023 -0800
@@ -334,17 +334,57 @@ static njs_int_t ngx_js_console_pro


ngx_int_t
-ngx_js_call(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log,
+ngx_js_call(njs_vm_t *vm, njs_function_t *func, njs_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, 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 || njs_vm_unhandled_rejection(vm)) {
+ 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_name_call(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 unused;

- return ngx_js_invoke(vm, fname, log, args, nargs, &unused);
+ return ngx_js_name_invoke(vm, fname, log, args, nargs, &unused);
}


ngx_int_t
-ngx_js_invoke(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log,
+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)
{
njs_int_t ret;
@@ -374,18 +414,19 @@ ngx_js_invoke(njs_vm_t *vm, ngx_str_t *f
return NGX_ERROR;
}

- ret = njs_vm_run(vm);
- if (ret == NJS_ERROR) {
- ngx_js_exception(vm, &exception);
+ for ( ;; ) {
+ ret = njs_vm_execute_pending_job(vm);
+ if (ret <= NJS_OK) {
+ if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) {
+ ngx_js_exception(vm, &exception);

- ngx_log_error(NGX_LOG_ERR, log, 0,
- "js exception: %V", &exception);
+ ngx_log_error(NGX_LOG_ERR, log, 0,
+ "js job exception: %V", &exception);
+ return NGX_ERROR;
+ }

- return NGX_ERROR;
- }
-
- if (ret == NJS_AGAIN) {
- return NGX_AGAIN;
+ break;
+ }
}

ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
@@ -966,34 +1007,21 @@ not_found:
static void
ngx_js_timer_handler(ngx_event_t *ev)
{
- njs_vm_t *vm;
- njs_int_t ret;
- ngx_str_t exception;
- ngx_js_ctx_t *ctx;
- ngx_js_event_t *event;
- ngx_connection_t *c;
- njs_external_ptr_t external;
+ njs_vm_t *vm;
+ ngx_int_t rc;
+ ngx_js_ctx_t *ctx;
+ ngx_js_event_t *event;

event = (ngx_js_event_t *) ((u_char *) ev - offsetof(ngx_js_event_t, ev));

vm = event->vm;

- ret = njs_vm_call(vm, event->function, event->args, event->nargs);
-
- external = njs_vm_external_ptr(vm);
- ctx = ngx_external_ctx(vm, external);
- njs_rbtree_delete(&ctx->waiting_events, &event->node);
+ rc = ngx_js_call(vm, event->function, event->args, event->nargs);

- if (ret == NJS_ERROR) {
- ngx_js_exception(vm, &exception);
-
- c = ngx_external_connection(vm, njs_vm_external_ptr(vm));
+ ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
+ ngx_js_del_event(ctx, event);

- ngx_log_error(NGX_LOG_ERR, c->log, 0,
- "js exception: %V", &exception);
- }
-
- ngx_external_event_finalize(vm)(external, ret);
+ ngx_external_event_finalize(vm)(njs_vm_external_ptr(vm), rc);
}


@@ -1065,7 +1093,7 @@ njs_set_timer(njs_vm_t *vm, njs_value_t
sizeof(njs_opaque_value_t) * event->nargs);
}

- njs_rbtree_insert(&ctx->waiting_events, &event->node);
+ ngx_js_add_event(ctx, event);

ngx_add_timer(&event->ev, delay);

@@ -1113,14 +1141,9 @@ njs_clear_timeout(njs_vm_t *vm, njs_valu
return NJS_ERROR;
}

- event = (ngx_js_event_t *) ((u_char *) rb
- - offsetof(ngx_js_event_t, node));
+ event = (ngx_js_event_t *) ((u_char *) rb - offsetof(ngx_js_event_t, node));

- if (event->ev.timer_set) {
- ngx_del_timer(&event->ev);
- }
-
- njs_rbtree_delete(&ctx->waiting_events, (njs_rbtree_part_t *) rb);
+ ngx_js_del_event(ctx, event);

njs_value_undefined_set(retval);

diff -r 439ea33e531c -r bc80bcb3102c nginx/ngx_js.h
--- a/nginx/ngx_js.h Wed Nov 29 20:46:36 2023 -0800
+++ b/nginx/ngx_js.h Tue Dec 05 08:54:18 2023 -0800
@@ -39,9 +39,7 @@ typedef struct ngx_js_ctx_s ngx_js_ctx_


typedef ngx_pool_t *(*ngx_external_pool_pt)(njs_vm_t *vm, njs_external_ptr_t e);
-typedef void (*ngx_js_event_handler_pt)(njs_external_ptr_t e,
- njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs);
-typedef void (*ngx_js_event_finalize_pt)(njs_external_ptr_t e, njs_int_t rc);
+typedef void (*ngx_js_event_finalize_pt)(njs_external_ptr_t e, ngx_int_t rc);
typedef ngx_resolver_t *(*ngx_external_resolver_pt)(njs_vm_t *vm,
njs_external_ptr_t e);
typedef ngx_msec_t (*ngx_external_timeout_pt)(njs_vm_t *vm,
@@ -73,6 +71,7 @@ struct ngx_js_event_s {
void (*destructor)(njs_external_ptr_t external,
ngx_js_event_t *event);
ngx_event_t ev;
+ void *data;
};


@@ -116,6 +115,20 @@ struct ngx_js_event_s {
ngx_socket_t event_id


+#define ngx_js_add_event(ctx, event) \
+ njs_rbtree_insert(&(ctx)->waiting_events, &(event)->node)
+
+
+#define ngx_js_del_event(ctx, event) \
+ do { \
+ if ((event)->destructor) { \
+ (event)->destructor(njs_vm_external_ptr((event)->vm), event); \
+ } \
+ \
+ njs_rbtree_delete(&(ctx)->waiting_events, &(event)->node); \
+ } while (0)
+
+
typedef struct {
NGX_JS_COMMON_MAIN_CONF;
} ngx_js_main_conf_t;
@@ -139,8 +152,8 @@ struct ngx_js_ctx_s {
((ngx_external_resolver_pt) njs_vm_meta(vm, 2))(vm, e)
#define ngx_external_resolver_timeout(vm, e) \
((ngx_external_timeout_pt) njs_vm_meta(vm, 3))(vm, e)
-#define ngx_external_event_handler(vm, e) \
- ((ngx_js_event_handler_pt) njs_vm_meta(vm, 4))
+#define ngx_external_event_finalize(vm) \
+ ((ngx_js_event_finalize_pt) njs_vm_meta(vm, 4))
#define ngx_external_ssl(vm, e) \
((ngx_external_ssl_pt) njs_vm_meta(vm, 5))(vm, e)
#define ngx_external_ssl_verify(vm, e) \
@@ -154,10 +167,8 @@ struct ngx_js_ctx_s {
#define NGX_JS_MAIN_CONF_INDEX 10
#define ngx_main_conf(vm) \
((ngx_js_main_conf_t *) njs_vm_meta(vm, NGX_JS_MAIN_CONF_INDEX))
-#define ngx_external_event_finalize(vm) \
- ((ngx_js_event_finalize_pt) njs_vm_meta(vm, 11))
#define ngx_external_ctx(vm, e) \
- ((ngx_js_external_ctx_pt) njs_vm_meta(vm, 12))(vm, e)
+ ((ngx_js_external_ctx_pt) njs_vm_meta(vm, 11))(vm, e)


#define ngx_js_prop(vm, type, value, start, len) \
@@ -171,9 +182,11 @@ struct ngx_js_ctx_s {

void ngx_js_ctx_init(ngx_js_ctx_t *ctx);
void ngx_js_ctx_destroy(ngx_js_ctx_t *ctx);
-ngx_int_t ngx_js_call(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log,
+ngx_int_t ngx_js_call(njs_vm_t *vm, njs_function_t *func, njs_value_t *args,
+ njs_uint_t nargs);
+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_int_t ngx_js_invoke(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log,
+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);
ngx_int_t ngx_js_exception(njs_vm_t *vm, ngx_str_t *s);

diff -r 439ea33e531c -r bc80bcb3102c nginx/ngx_js_fetch.c
--- a/nginx/ngx_js_fetch.c Wed Nov 29 20:46:36 2023 -0800
+++ b/nginx/ngx_js_fetch.c Tue Dec 05 08:54:18 2023 -0800
@@ -116,9 +116,7 @@ struct ngx_js_http_s {
ngx_pool_t *pool;

njs_vm_t *vm;
- njs_external_ptr_t external;
- njs_vm_event_t vm_event;
- ngx_js_event_handler_pt event_handler;
+ ngx_js_event_t *event;

ngx_resolver_ctx_t *ctx;
ngx_addr_t addr;
@@ -177,7 +175,7 @@ static njs_int_t ngx_js_headers_fill(njs
static ngx_js_http_t *ngx_js_http_alloc(njs_vm_t *vm, ngx_pool_t *pool,
ngx_log_t *log);
static void njs_js_http_destructor(njs_external_ptr_t external,
- njs_host_event_t host);
+ ngx_js_event_t *event);
static void ngx_js_resolve_handler(ngx_resolver_ctx_t *ctx);
static njs_int_t ngx_js_fetch_promissified_result(njs_vm_t *vm,
njs_value_t *result, njs_int_t rc, njs_value_t *retval);
@@ -695,9 +693,6 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value
return NJS_ERROR;
}

- http->external = external;
- http->event_handler = ngx_external_event_handler(vm, external);
-
ret = ngx_js_request_constructor(vm, &request, &u, external, args, nargs);
if (ret != NJS_OK) {
goto fail;
@@ -1273,8 +1268,9 @@ static ngx_js_http_t *
ngx_js_http_alloc(njs_vm_t *vm, ngx_pool_t *pool, ngx_log_t *log)
{
njs_int_t ret;
+ ngx_js_ctx_t *ctx;
ngx_js_http_t *http;
- njs_vm_event_t vm_event;
+ ngx_js_event_t *event;
njs_function_t *callback;

http = ngx_pcalloc(pool, sizeof(ngx_js_http_t));
@@ -1301,12 +1297,22 @@ ngx_js_http_alloc(njs_vm_t *vm, ngx_pool
goto failed;
}

- vm_event = njs_vm_add_event(vm, callback, 1, http, njs_js_http_destructor);
- if (vm_event == NULL) {
+ event = njs_mp_zalloc(njs_vm_memory_pool(vm), sizeof(ngx_js_event_t));
+ if (njs_slow_path(event == NULL)) {
goto failed;
}

- http->vm_event = vm_event;
+ ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
+
+ event->vm = vm;
+ event->function = callback;
+ event->destructor = njs_js_http_destructor;
+ event->fd = ctx->event_id++;
+ event->data = http;
+
+ ngx_js_add_event(ctx, event);
+
+ http->event = event;

ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "js fetch alloc:%p", http);

@@ -1428,11 +1434,11 @@ ngx_js_http_close_connection(ngx_connect


static void
-njs_js_http_destructor(njs_external_ptr_t external, njs_host_event_t host)
+njs_js_http_destructor(njs_external_ptr_t external, ngx_js_event_t *event)
{
ngx_js_http_t *http;

- http = host;
+ http = event->data;

ngx_log_debug1(NGX_LOG_DEBUG_EVENT, http->log, 0, "js fetch destructor:%p",
http);
@@ -1455,7 +1461,6 @@ ngx_js_fetch_promissified_result(njs_vm_
{
njs_int_t ret;
njs_function_t *callback;
- njs_vm_event_t vm_event;
njs_opaque_value_t promise, arguments[2];

ret = njs_vm_promise_create(vm, njs_value_arg(&promise),
@@ -1469,11 +1474,6 @@ ngx_js_fetch_promissified_result(njs_vm_
goto error;
}

- vm_event = njs_vm_add_event(vm, callback, 1, NULL, NULL);
- if (vm_event == NULL) {
- goto error;
- }
-
njs_value_assign(&arguments[0], &arguments[(rc != NJS_OK)]);

if (rc != NJS_OK) {
@@ -1483,7 +1483,7 @@ ngx_js_fetch_promissified_result(njs_vm_
njs_value_assign(&arguments[1], result);
}

- ret = njs_vm_post_event(vm, vm_event, njs_value_arg(&arguments), 2);
+ ret = njs_vm_enqueue_job(vm, callback, njs_value_arg(&arguments), 2);
if (ret == NJS_ERROR) {
goto error;
}
@@ -1504,7 +1504,10 @@ static void
ngx_js_http_fetch_done(ngx_js_http_t *http, njs_opaque_value_t *retval,
njs_int_t rc)
{
- njs_opaque_value_t arguments[2], *action;
+ njs_vm_t *vm;
+ ngx_js_ctx_t *ctx;
+ ngx_js_event_t *event;
+ njs_opaque_value_t arguments[2], *action;

ngx_log_debug2(NGX_LOG_DEBUG_EVENT, http->log, 0,
"js fetch done http:%p rc:%i", http, (ngx_int_t) rc);
@@ -1514,12 +1517,20 @@ ngx_js_http_fetch_done(ngx_js_http_t *ht
http->peer.connection = NULL;
}

- if (http->vm_event != NULL) {
+ if (http->event != NULL) {
action = &http->promise_callbacks[(rc != NJS_OK)];
njs_value_assign(&arguments[0], action);
njs_value_assign(&arguments[1], retval);
- http->event_handler(http->external, http->vm_event,
- njs_value_arg(&arguments), 2);
+
+ vm = http->vm;
+ event = http->event;
+
+ rc = ngx_js_call(vm, event->function, njs_value_arg(&arguments), 2);
+
+ ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
+ ngx_js_del_event(ctx, event);
+
+ ngx_external_event_finalize(vm)(njs_vm_external_ptr(vm), rc);
}
}

diff -r 439ea33e531c -r bc80bcb3102c nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c Wed Nov 29 20:46:36 2023 -0800
+++ b/nginx/ngx_stream_js_module.c Tue Dec 05 08:54:18 2023 -0800
@@ -22,7 +22,7 @@ typedef struct {


typedef struct {
- njs_vm_event_t ev;
+ njs_function_t *function;
ngx_uint_t data_type;
} ngx_stream_js_ev_t;

@@ -67,6 +67,12 @@ typedef struct {
} ngx_stream_js_ctx_t;


+#define ngx_stream_pending(ctx) \
+ (ngx_vm_pending(ctx) \
+ || (ctx)->events[NGX_JS_EVENT_UPLOAD].function != NULL \
+ || (ctx)->events[NGX_JS_EVENT_DOWNLOAD].function != NULL)
+
+
static ngx_int_t ngx_stream_js_access_handler(ngx_stream_session_t *s);
static ngx_int_t ngx_stream_js_preread_handler(ngx_stream_session_t *s);
static ngx_int_t ngx_stream_js_phase_handler(ngx_stream_session_t *s,
@@ -86,7 +92,7 @@ static void ngx_stream_js_cleanup(void *
static njs_int_t ngx_stream_js_run_event(ngx_stream_session_t *s,
ngx_stream_js_ctx_t *ctx, ngx_stream_js_ev_t *event,
ngx_uint_t from_upstream);
-static njs_vm_event_t *ngx_stream_js_event(ngx_stream_session_t *s,
+static njs_function_t **ngx_stream_js_event(ngx_stream_session_t *s,
njs_str_t *event);

static njs_int_t ngx_stream_js_ext_get_remote_address(njs_vm_t *vm,
@@ -123,9 +129,7 @@ static ngx_msec_t ngx_stream_js_fetch_ti
static size_t ngx_stream_js_buffer_size(njs_vm_t *vm, ngx_stream_session_t *s);
static size_t ngx_stream_js_max_response_buffer_size(njs_vm_t *vm,
ngx_stream_session_t *s);
-static void ngx_stream_js_handle_event(ngx_stream_session_t *s,
- njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs);
-static void ngx_stream_js_event_finalize(ngx_stream_session_t *s, njs_int_t rc);
+static void ngx_stream_js_event_finalize(ngx_stream_session_t *s, ngx_int_t rc);
static ngx_js_ctx_t *ngx_stream_js_ctx(njs_vm_t *vm, ngx_stream_session_t *s);

static void ngx_stream_js_periodic_handler(ngx_event_t *ev);
@@ -615,14 +619,13 @@ static uintptr_t ngx_stream_js_uptr[] =
(uintptr_t) ngx_stream_js_pool,
(uintptr_t) ngx_stream_js_resolver,
(uintptr_t) ngx_stream_js_resolver_timeout,
- (uintptr_t) ngx_stream_js_handle_event,
+ (uintptr_t) ngx_stream_js_event_finalize,
(uintptr_t) ngx_stream_js_ssl,
(uintptr_t) ngx_stream_js_ssl_verify,
(uintptr_t) ngx_stream_js_fetch_timeout,
(uintptr_t) ngx_stream_js_buffer_size,
(uintptr_t) ngx_stream_js_max_response_buffer_size,
(uintptr_t) 0 /* main_conf ptr */,
- (uintptr_t) ngx_stream_js_event_finalize,
(uintptr_t) ngx_stream_js_ctx,
};

@@ -734,7 +737,7 @@ ngx_stream_js_phase_handler(ngx_stream_s
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
"stream js phase call \"%V\"", name);

- rc = ngx_js_call(ctx->vm, name, c->log, &ctx->args[0], 1);
+ rc = ngx_js_name_call(ctx->vm, name, c->log, &ctx->args[0], 1);

if (rc == NGX_ERROR) {
return rc;
@@ -751,9 +754,9 @@ ngx_stream_js_phase_handler(ngx_stream_s
return NGX_ERROR;
}

- if (ngx_vm_pending(ctx)) {
+ if (ngx_stream_pending(ctx)) {
ctx->in_progress = 1;
- rc = ctx->events[NGX_JS_EVENT_UPLOAD].ev ? NGX_AGAIN : NGX_DONE;
+ rc = ctx->events[NGX_JS_EVENT_UPLOAD].function ? NGX_AGAIN : NGX_DONE;

} else {
ctx->in_progress = 0;
@@ -811,7 +814,7 @@ ngx_stream_js_body_filter(ngx_stream_ses
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
"stream js filter call \"%V\"" , &jscf->filter);

- rc = ngx_js_call(ctx->vm, &jscf->filter, c->log, &ctx->args[0], 1);
+ rc = ngx_js_name_call(ctx->vm, &jscf->filter, c->log, &ctx->args[0], 1);

if (rc == NGX_ERROR) {
return rc;
@@ -827,7 +830,7 @@ ngx_stream_js_body_filter(ngx_stream_ses

event = ngx_stream_event(from_upstream);

- if (event->ev != NULL) {
+ if (event->function != NULL) {
ret = ngx_stream_js_run_event(s, ctx, event, from_upstream);
if (ret != NJS_OK) {
ngx_js_exception(ctx->vm, &exception);
@@ -922,10 +925,10 @@ ngx_stream_js_variable_set(ngx_stream_se

ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module);

- pending = ngx_vm_pending(ctx);
-
- rc = ngx_js_invoke(ctx->vm, fname, s->connection->log, &ctx->args[0], 1,
- &ctx->retval);
+ pending = ngx_stream_pending(ctx);
+
+ rc = ngx_js_name_invoke(ctx->vm, fname, s->connection->log, &ctx->args[0],
+ 1, &ctx->retval);

if (rc == NGX_ERROR) {
v->not_found = 1;
@@ -1078,9 +1081,8 @@ ngx_stream_js_drop_events(ngx_stream_js_
ngx_uint_t i;

for (i = 0; i < NGX_JS_EVENT_MAX; i++) {
- if (ctx->events[i].ev != NULL) {
- njs_vm_del_event(ctx->vm, ctx->events[i].ev);
- ctx->events[i].ev = NULL;
+ if (ctx->events[i].function != NULL) {
+ ctx->events[i].function = NULL;
}
}
}
@@ -1119,7 +1121,7 @@ ngx_stream_js_run_event(ngx_stream_sessi
uintptr_t flags;
ngx_connection_t *c;

- if (event->ev == NULL) {
+ if (event->function == NULL) {
return NJS_OK;
}

@@ -1152,18 +1154,12 @@ ngx_stream_js_run_event(ngx_stream_sessi
return NGX_ERROR;
}

- njs_vm_post_event(ctx->vm, event->ev, njs_value_arg(&ctx->args[1]), 2);
-
- ret = njs_vm_run(ctx->vm);
- if (ret == NJS_ERROR) {
- return ret;
- }
-
- return NJS_OK;
+ return ngx_js_call(ctx->vm, event->function, njs_value_arg(&ctx->args[1]),
+ 2);
}


-static njs_vm_event_t *
+static njs_function_t **
ngx_stream_js_event(ngx_stream_session_t *s, njs_str_t *event)
{
ngx_uint_t i, n, type;
@@ -1231,7 +1227,7 @@ ngx_stream_js_event(ngx_stream_session_t
}
}

- return &ctx->events[events[i].id].ev;
+ return &ctx->events[events[i].id].function;
}


@@ -1317,10 +1313,10 @@ static njs_int_t
ngx_stream_js_ext_on(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused, njs_value_t *retval)
{
- njs_str_t name;
- njs_value_t *callback;
- njs_vm_event_t *event;
- ngx_stream_session_t *s;
+ njs_str_t name;
+ njs_value_t *callback;
+ njs_function_t **cb;
+ ngx_stream_session_t *s;

s = njs_vm_external(vm, ngx_stream_js_session_proto_id,
njs_argument(args, 0));
@@ -1340,21 +1336,17 @@ ngx_stream_js_ext_on(njs_vm_t *vm, njs_v
return NJS_ERROR;
}

- event = ngx_stream_js_event(s, &name);
- if (event == NULL) {
+ cb = ngx_stream_js_event(s, &name);
+ if (cb == NULL) {
return NJS_ERROR;
}

- if (*event != NULL) {
+ if (*cb != NULL) {
njs_vm_error(vm, "event handler \"%V\" is already set", &name);
return NJS_ERROR;
}

- *event = njs_vm_add_event(vm, njs_value_function(callback), 0, NULL, NULL);
- if (*event == NULL) {
- njs_vm_error(vm, "internal error");
- return NJS_ERROR;
- }
+ *cb = njs_value_function(callback);

njs_value_undefined_set(retval);

@@ -1366,9 +1358,9 @@ static njs_int_t
ngx_stream_js_ext_off(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused, njs_value_t *retval)
{
- njs_str_t name;
- njs_vm_event_t *event;
- ngx_stream_session_t *s;
+ njs_str_t name;
+ njs_function_t **callback;
+ ngx_stream_session_t *s;

s = njs_vm_external(vm, ngx_stream_js_session_proto_id,
njs_argument(args, 0));
@@ -1382,14 +1374,12 @@ ngx_stream_js_ext_off(njs_vm_t *vm, njs_
return NJS_ERROR;
}

- event = ngx_stream_js_event(s, &name);
- if (event == NULL) {
+ callback = ngx_stream_js_event(s, &name);
+ if (callback == NULL) {
return NJS_ERROR;
}

- njs_vm_del_event(vm, *event);
-
- *event = NULL;
+ *callback = NULL;

njs_value_undefined_set(retval);

@@ -1726,41 +1716,12 @@ ngx_stream_js_max_response_buffer_size(n


static void
-ngx_stream_js_handle_event(ngx_stream_session_t *s, njs_vm_event_t vm_event,
- njs_value_t *args, njs_uint_t nargs)
-{
- njs_int_t rc;
- ngx_str_t exception;
- ngx_stream_js_ctx_t *ctx;
-
- ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module);
-
- njs_vm_post_event(ctx->vm, vm_event, args, nargs);
-
- rc = njs_vm_run(ctx->vm);
-
- ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
- "stream js post event handler rc: %i event: %p",
- (ngx_int_t) rc, vm_event);
-
- if (rc == NJS_ERROR) {
- ngx_js_exception(ctx->vm, &exception);
-
- ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "js exception: %V", &exception);
- }
-
- ngx_stream_js_event_finalize(s, rc);
-}
-
-
-static void
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[njs] Refactored asynchronous events.

Dmitry Volyntsev 219 December 05, 2023 11:56AM



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

Online Users

Guests: 130
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