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 \
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];
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;
}
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;
}
}
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;
}
}
{
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),
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) {
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;
}
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);
(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,
};
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);
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;
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;
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;
{
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;
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;
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;
}
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;
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;
}
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;
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);
+ "http js event finalize rc: %i", rc);
- if (rc == NJS_ERROR) {
+ if (rc == NGX_ERROR) {
if (r->health_check) {
ngx_http_js_periodic_finalize(r, NGX_ERROR);
return;
return;
}
- if (rc == NJS_OK) {
+ if (rc == NGX_OK) {
ngx_http_post_request(r, NULL);
}
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;
return NGX_ERROR;
}
- ret = njs_vm_run(vm);
- if (ret == NJS_ERROR) {
- ngx_js_exception(vm, &exception);
-
- ngx_log_error(NGX_LOG_ERR, log, 0,
- "js exception: %V", &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);
- return NGX_ERROR;
- }
+ ngx_log_error(NGX_LOG_ERR, log, 0,
+ "js job exception: %V", &exception);
+ return NGX_ERROR;
+ }
- if (ret == NJS_AGAIN) {
- return NGX_AGAIN;
+ break;
+ }
}
ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
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);
+ rc = ngx_js_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);
-
- 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);
- }
+ ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
+ ngx_js_del_event(ctx, event);
- ngx_external_event_finalize(vm)(external, ret);
+ ngx_external_event_finalize(vm)(njs_vm_external_ptr(vm), rc);
}
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);
return NJS_ERROR;
}
- event = (ngx_js_event_t *) ((u_char *) rb
- - offsetof(ngx_js_event_t, node));
-
- if (event->ev.timer_set) {
- ngx_del_timer(&event->ev);
- }
+ event = (ngx_js_event_t *) ((u_char *) rb - offsetof(ngx_js_event_t, node));
- njs_rbtree_delete(&ctx->waiting_events, (njs_rbtree_part_t *) rb);
+ ngx_js_del_event(ctx, event);
njs_value_undefined_set(retval);
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,
void (*destructor)(njs_external_ptr_t external,
ngx_js_event_t *event);
ngx_event_t ev;
+ void *data;
};
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;
((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) \
#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) \
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);
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;
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);
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;
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));
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);
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);
{
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),
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) {
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;
}
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);
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);
}
}
typedef struct {
- njs_vm_event_t ev;
+ njs_function_t *function;
ngx_uint_t data_type;
} ngx_stream_js_ev_t;
} 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,
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,
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);
(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,
};
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;
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;
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;
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);
ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module);
- pending = ngx_vm_pending(ctx);
+ pending = ngx_stream_pending(ctx);
- rc = ngx_js_invoke(ctx->vm, fname, s->connection->log, &ctx->args[0], 1,
- &ctx->retval);
+ 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;
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;
}
}
}
uintptr_t flags;
ngx_connection_t *c;
- if (event->ev == NULL) {
+ if (event->function == NULL) {
return NJS_OK;
}
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;
}
}
- return &ctx->events[events[i].id].ev;
+ return &ctx->events[events[i].id].function;
}
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));
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);
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));
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);
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
-ngx_stream_js_event_finalize(ngx_stream_session_t *s, njs_int_t rc)
+ngx_stream_js_event_finalize(ngx_stream_session_t *s, ngx_int_t rc)
{
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
- "http js event finalize rc: %i", (ngx_int_t) rc);
+ "http js event finalize rc: %i", rc);
- if (rc == NJS_ERROR) {
+ if (rc == NGX_ERROR) {
if (s->health_check) {
ngx_stream_js_periodic_finalize(s, NGX_ERROR);
return;
return;
}
- if (rc == NJS_OK) {
+ if (rc == NGX_OK) {
ngx_post_event(s->connection->read, &ngx_posted_events);
}
}
s->received++;
- rc = ngx_js_invoke(ctx->vm, &periodic->method, &periodic->log,
- &ctx->args[0], 1, &ctx->retval);
+ rc = ngx_js_name_invoke(ctx->vm, &periodic->method, &periodic->log,
+ &ctx->args[0], 1, &ctx->retval);
if (rc == NGX_AGAIN) {
rc = NGX_OK;
};
-/*
- * NJS and event loops.
- *
- * njs_vm_ops_t callbacks are used to interact with the event loop environment.
- *
- * Functions get an external object as the first argument. The external
- * object is provided as the third argument to njs_vm_clone().
- *
- * The callbacks are expected to return to the VM the unique id of an
- * underlying event. This id will be passed as the second argument to
- * njs_event_destructor() at the moment the VM wants to destroy it.
- *
- * When an underlying events fires njs_vm_post_event() should be invoked with
- * the value provided as vm_event.
- *
- * The events posted by njs_vm_post_event() are processed as soon as
- * njs_vm_run() is invoked. njs_vm_run() returns NJS_AGAIN until pending events
- * are present.
- */
-
-typedef void * njs_vm_event_t;
-typedef void * njs_host_event_t;
typedef void * njs_external_ptr_t;
-typedef njs_host_event_t (*njs_set_timer_t)(njs_external_ptr_t external,
- 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 void (*njs_logger_t)(njs_vm_t *vm, njs_external_ptr_t external,
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,
- njs_function_t *function, njs_uint_t once, njs_host_event_t host_ev,
- njs_event_destructor_t destructor);
-NJS_EXPORT void njs_vm_del_event(njs_vm_t *vm, njs_vm_event_t vm_event);
-NJS_EXPORT njs_int_t njs_vm_post_event(njs_vm_t *vm, njs_vm_event_t vm_event,
+NJS_EXPORT njs_int_t njs_vm_enqueue_job(njs_vm_t *vm, njs_function_t *function,
const njs_value_t *args, njs_uint_t nargs);
-
/*
- * Returns 1 if async events are present.
- */
-NJS_EXPORT njs_int_t njs_vm_waiting(njs_vm_t *vm);
-
-/*
- * Returns 1 if posted events are ready to be executed.
+ * Executes a single pending job.
+ * 1 successful run.
+ * NJS_OK pending job was not found.
+ * NJS_ERROR some exception or internal error happens.
*/
-NJS_EXPORT njs_int_t njs_vm_posted(njs_vm_t *vm);
-
-#define njs_vm_pending(vm) (njs_vm_waiting(vm) || njs_vm_posted(vm))
-
+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_completions(njs_vm_t *vm, njs_str_t *expression);
NJS_EXPORT njs_int_t njs_vm_invoke(njs_vm_t *vm, njs_function_t *function,
const njs_value_t *args, njs_uint_t nargs, njs_value_t *retval);
-/*
- * Runs posted events.
- * NJS_OK successfully processed all posted events, no more events.
- * NJS_AGAIN successfully processed all events, some posted events are
- * still pending.
- * NJS_ERROR some exception or internal error happens.
- * njs_vm_exception_get(vm) can be used to get the exception value.
- */
-NJS_EXPORT njs_int_t njs_vm_run(njs_vm_t *vm);
-
/*
* Runs the global code.
* NJS_OK successful run.
+++ /dev/null
-
-/*
- * Copyright (C) Dmitry Volyntsev
- * Copyright (C) NGINX, Inc.
- */
-
-
-#include <njs_main.h>
-
-
-static njs_int_t njs_event_hash_test(njs_lvlhsh_query_t *lhq, void *data);
-
-
-const njs_lvlhsh_proto_t njs_event_hash_proto
- njs_aligned(64) =
-{
- NJS_LVLHSH_DEFAULT,
- njs_event_hash_test,
- njs_lvlhsh_alloc,
- njs_lvlhsh_free,
-};
-
-
-static njs_int_t
-njs_event_hash_test(njs_lvlhsh_query_t *lhq, void *data)
-{
- njs_str_t id;
- njs_event_t *event;
-
- event = data;
-
- njs_string_get(&event->id, &id);
-
- if (njs_strstr_eq(&lhq->key, &id)) {
- return NJS_OK;
- }
-
- return NJS_DECLINED;
-}
-
-
-njs_int_t
-njs_add_event(njs_vm_t *vm, njs_event_t *event)
-{
- njs_int_t ret;
- njs_lvlhsh_query_t lhq;
-
- njs_uint32_to_string(&event->id, vm->event_id++);
-
- njs_string_get(&event->id, &lhq.key);
- lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length);
- lhq.value = event;
- lhq.proto = &njs_event_hash_proto;
- lhq.pool = vm->mem_pool;
-
- ret = njs_lvlhsh_insert(&vm->events_hash, &lhq);
- if (njs_slow_path(ret != NJS_OK)) {
- njs_internal_error(vm, "Failed to add event with id: %s",
- njs_string_short_start(&event->id));
-
- njs_del_event(vm, event, NJS_EVENT_RELEASE | NJS_EVENT_DELETE);
- return NJS_ERROR;
- }
-
- return NJS_OK;
-}
-
-
-void
-njs_del_event(njs_vm_t *vm, njs_event_t *ev, njs_uint_t action)
-{
- njs_lvlhsh_query_t lhq;
-
- if (action & NJS_EVENT_RELEASE) {
- if (ev->destructor != NULL && ev->host_event != NULL) {
- ev->destructor(vm->external, ev->host_event);
- }
-
- ev->host_event = NULL;
- }
-
- if (action & NJS_EVENT_DELETE) {
- njs_string_get(&ev->id, &lhq.key);
- lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length);
- lhq.proto = &njs_event_hash_proto;
- lhq.pool = vm->mem_pool;
-
- if (ev->posted) {
- ev->posted = 0;
- njs_queue_remove(&ev->link);
- }
-
- (void) njs_lvlhsh_delete(&vm->events_hash, &lhq);
- }
-}
#define _NJS_EVENT_H_INCLUDED_
-#define NJS_EVENT_RELEASE 1
-#define NJS_EVENT_DELETE 2
-
-
-#define njs_waiting_events(vm) (!njs_lvlhsh_is_empty(&(vm)->events_hash))
-
-#define njs_posted_events(vm) (!njs_queue_is_empty(&(vm)->posted_events))
-
-#define njs_promise_events(vm) (!njs_queue_is_empty(&(vm)->promise_events))
-
-
typedef struct {
njs_function_t *function;
njs_value_t *args;
njs_uint_t nargs;
- njs_host_event_t host_event;
- njs_event_destructor_t destructor;
- njs_value_t id;
njs_queue_link_t link;
-
- unsigned posted:1;
- unsigned once:1;
} njs_event_t;
-njs_int_t njs_add_event(njs_vm_t *vm, njs_event_t *event);
-void njs_del_event(njs_vm_t *vm, njs_event_t *event, njs_uint_t action);
-
-
-extern const njs_lvlhsh_proto_t njs_event_hash_proto;
-
-
#endif /* _NJS_EVENT_H_INCLUDED_ */
}
-njs_inline njs_int_t
-njs_promise_add_event(njs_vm_t *vm, njs_function_t *function, njs_value_t *args,
- njs_uint_t nargs)
-{
- njs_event_t *event;
-
- event = njs_mp_zalloc(vm->mem_pool, sizeof(njs_event_t));
- if (njs_slow_path(event == NULL)) {
- njs_memory_error(vm);
- return NJS_ERROR;
- }
-
- event->function = function;
- event->once = 1;
-
- if (nargs != 0) {
- event->args = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t) * nargs);
- if (njs_slow_path(event->args == NULL)) {
- njs_memory_error(vm);
- return NJS_ERROR;
- }
-
- memcpy(event->args, args, sizeof(njs_value_t) * nargs);
-
- event->nargs = nargs;
- }
-
- njs_queue_insert_tail(&vm->promise_events, &event->link);
-
- return NJS_OK;
-}
-
-
njs_inline njs_value_t *
njs_promise_trigger_reactions(njs_vm_t *vm, njs_value_t *value,
njs_queue_t *queue)
njs_set_data(&arguments[0], reaction, 0);
arguments[1] = *value;
- ret = njs_promise_add_event(vm, function, arguments, 2);
+ ret = njs_vm_enqueue_job(vm, function, arguments, 2);
if (njs_slow_path(ret != NJS_OK)) {
return njs_value_arg(&njs_value_null);
}
function->u.native = njs_promise_resolve_thenable_job;
- ret = njs_promise_add_event(vm, function, arguments, 3);
+ ret = njs_vm_enqueue_job(vm, function, arguments, 3);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
arguments[1] = data->result;
- ret = njs_promise_add_event(vm, function, arguments, 2);
+ ret = njs_vm_enqueue_job(vm, function, arguments, 2);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
#include <njs_main.h>
-static njs_int_t njs_vm_handle_events(njs_vm_t *vm);
static njs_int_t njs_vm_protos_init(njs_vm_t *vm, njs_value_t *global);
void
njs_vm_destroy(njs_vm_t *vm)
{
- njs_event_t *event;
- njs_lvlhsh_each_t lhe;
-
if (vm->hooks[NJS_HOOK_EXIT] != NULL) {
(void) njs_vm_call(vm, vm->hooks[NJS_HOOK_EXIT], NULL, 0);
}
- if (njs_waiting_events(vm)) {
- njs_lvlhsh_each_init(&lhe, &njs_event_hash_proto);
-
- for ( ;; ) {
- event = njs_lvlhsh_each(&vm->events_hash, &lhe);
-
- if (event == NULL) {
- break;
- }
-
- njs_del_event(vm, event, NJS_EVENT_RELEASE);
- }
- }
-
njs_mp_destroy(vm->mem_pool);
}
njs_lvlhsh_init(&vm->values_hash);
njs_lvlhsh_init(&vm->keywords_hash);
njs_lvlhsh_init(&vm->modules_hash);
- njs_lvlhsh_init(&vm->events_hash);
njs_rbtree_init(&vm->global_symbols, njs_symbol_rbtree_cmp);
- njs_queue_init(&vm->posted_events);
- njs_queue_init(&vm->promise_events);
+ njs_queue_init(&vm->jobs);
return NJS_OK;
}
}
-njs_vm_event_t
-njs_vm_add_event(njs_vm_t *vm, njs_function_t *function, njs_uint_t once,
- njs_host_event_t host_ev, njs_event_destructor_t destructor)
-{
- njs_event_t *event;
-
- event = njs_mp_alloc(vm->mem_pool, sizeof(njs_event_t));
- if (njs_slow_path(event == NULL)) {
- return NULL;
- }
-
- event->host_event = host_ev;
- event->destructor = destructor;
- event->function = function;
- event->once = once;
- event->posted = 0;
- event->nargs = 0;
- event->args = NULL;
-
- if (njs_add_event(vm, event) != NJS_OK) {
- return NULL;
- }
-
- return event;
-}
-
-
-void
-njs_vm_del_event(njs_vm_t *vm, njs_vm_event_t vm_event)
+njs_int_t
+njs_vm_pending(njs_vm_t *vm)
{
- njs_event_t *event;
-
- event = (njs_event_t *) vm_event;
-
- njs_del_event(vm, event, NJS_EVENT_RELEASE | NJS_EVENT_DELETE);
+ return !njs_queue_is_empty(&(vm)->jobs);
}
njs_int_t
-njs_vm_waiting(njs_vm_t *vm)
+njs_vm_unhandled_rejection(njs_vm_t *vm)
{
- return njs_waiting_events(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_int_t
-njs_vm_posted(njs_vm_t *vm)
-{
- return njs_posted_events(vm) || njs_promise_events(vm);
-}
+ 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_int_t
-njs_vm_unhandled_rejection(njs_vm_t *vm)
-{
- return vm->options.unhandled_rejection
- == NJS_VM_OPT_UNHANDLED_REJECTION_THROW
- && vm->promise_reason != NULL
- && vm->promise_reason->length != 0;
+ njs_mp_free(vm->mem_pool, vm->promise_reason);
+ vm->promise_reason = NULL;
+
+ return 1;
}
njs_int_t
-njs_vm_post_event(njs_vm_t *vm, njs_vm_event_t vm_event,
+njs_vm_enqueue_job(njs_vm_t *vm, njs_function_t *function,
const njs_value_t *args, njs_uint_t nargs)
{
njs_event_t *event;
- event = (njs_event_t *) vm_event;
+ event = njs_mp_zalloc(vm->mem_pool, sizeof(njs_event_t));
+ if (njs_slow_path(event == NULL)) {
+ njs_memory_error(vm);
+ return NJS_ERROR;
+ }
- if (nargs != 0 && !event->posted) {
- event->nargs = nargs;
+ event->function = function;
+
+ if (nargs != 0) {
event->args = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t) * nargs);
if (njs_slow_path(event->args == NULL)) {
+ njs_memory_error(vm);
return NJS_ERROR;
}
memcpy(event->args, args, sizeof(njs_value_t) * nargs);
- }
- if (!event->posted) {
- event->posted = 1;
- njs_queue_insert_tail(&vm->posted_events, &event->link);
+ event->nargs = nargs;
}
- return NJS_OK;
-}
-
+ njs_queue_insert_tail(&vm->jobs, &event->link);
-njs_int_t
-njs_vm_run(njs_vm_t *vm)
-{
- return njs_vm_handle_events(vm);
+ return NJS_OK;
}
}
-static njs_int_t
-njs_vm_handle_events(njs_vm_t *vm)
+njs_int_t
+njs_vm_execute_pending_job(njs_vm_t *vm)
{
njs_int_t ret;
- njs_str_t str;
- njs_value_t string;
njs_event_t *ev;
- njs_queue_t *promise_events, *posted_events;
+ njs_queue_t *jobs;
njs_queue_link_t *link;
- promise_events = &vm->promise_events;
- posted_events = &vm->posted_events;
-
- do {
- for ( ;; ) {
- link = njs_queue_first(promise_events);
-
- if (link == njs_queue_tail(promise_events)) {
- break;
- }
+ jobs = &vm->jobs;
- ev = njs_queue_link_data(link, njs_event_t, link);
-
- njs_queue_remove(&ev->link);
-
- ret = njs_vm_call(vm, ev->function, ev->args, ev->nargs);
- if (njs_slow_path(ret == NJS_ERROR)) {
- return ret;
- }
- }
+ link = njs_queue_first(jobs);
- if (njs_vm_unhandled_rejection(vm)) {
- 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 NJS_ERROR;
- }
-
- for ( ;; ) {
- link = njs_queue_first(posted_events);
-
- if (link == njs_queue_tail(posted_events)) {
- break;
- }
-
- ev = njs_queue_link_data(link, njs_event_t, link);
-
- if (ev->once) {
- njs_del_event(vm, ev, NJS_EVENT_RELEASE | NJS_EVENT_DELETE);
+ if (link == njs_queue_tail(jobs)) {
+ return NJS_OK;
+ }
- } else {
- ev->posted = 0;
- njs_queue_remove(&ev->link);
- }
+ ev = njs_queue_link_data(link, njs_event_t, link);
- ret = njs_vm_call(vm, ev->function, ev->args, ev->nargs);
+ njs_queue_remove(&ev->link);
- if (ret == NJS_ERROR) {
- return ret;
- }
- }
-
- } while (!njs_queue_is_empty(promise_events));
+ ret = njs_vm_call(vm, ev->function, ev->args, ev->nargs);
+ if (ret == NJS_ERROR) {
+ return ret;
+ }
- return njs_vm_pending(vm) ? NJS_AGAIN : NJS_OK;
+ return 1;
}
njs_lvlhsh_t modules_hash;
uint32_t event_id;
- njs_lvlhsh_t events_hash;
- njs_queue_t posted_events;
- njs_queue_t promise_events;
+ njs_queue_t jobs;
njs_vm_opt_t options;
{
njs_int_t ret;
njs_value_t value, *argument, *select;
- njs_vm_event_t vm_event;
njs_function_t *callback;
njs_external_ev_t *ev;
njs_external_env_t *env;
return NJS_ERROR;
}
- vm_event = njs_vm_add_event(vm, callback, 1, NULL, NULL);
- if (vm_event == NULL) {
- njs_internal_error(vm, "njs_vm_add_event() failed");
- return NJS_ERROR;
- }
-
argument = njs_arg(args, nargs, 1);
select = njs_arg(args, nargs, 2);
- ev->vm_event = vm_event;
+ ev->function = callback;
ev->data = r;
ev->nargs = 2;
njs_value_assign(&ev->args[0], &ev->callbacks[!!njs_bool(select)]);
njs_int_t
njs_external_process_events(njs_vm_t *vm, njs_external_env_t *env)
{
+ njs_int_t ret;
njs_queue_t *events;
njs_queue_link_t *link;
njs_external_ev_t *ev;
+ if (env == NULL) {
+ return NJS_OK;
+ }
+
events = &env->events;
for ( ;; ) {
ev->link.prev = NULL;
ev->link.next = NULL;
- njs_vm_post_event(vm, ev->vm_event, njs_value_arg(&ev->args[0]),
- ev->nargs);
+ ret = njs_vm_call(vm, ev->function, njs_value_arg(ev->args), ev->nargs);
+ if (ret == NJS_ERROR) {
+ return NJS_ERROR;
+ }
}
- return NJS_OK;
+ return njs_vm_pending(vm) ? NJS_AGAIN: NJS_OK;
}
return NJS_ERROR;
}
- return njs_vm_run(vm);
+ for ( ;; ) {
+ ret = njs_vm_execute_pending_job(vm);
+ if (ret <= NJS_OK) {
+ if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) {
+ return NJS_ERROR;
+ }
+
+ break;
+ }
+ }
+
+ return NJS_OK;
}
typedef struct {
- njs_vm_event_t vm_event;
+ njs_function_t *function;
void *data;
njs_uint_t nargs;
njs_opaque_value_t args[3];
case sw_loop:
default:
for ( ;; ) {
- if (!njs_vm_pending(state->vm)) {
- break;
+ for ( ;; ) {
+ ret = njs_vm_execute_pending_job(state->vm);
+ if (ret <= NJS_OK) {
+ if (ret == NJS_ERROR
+ || njs_vm_unhandled_rejection(state->vm))
+ {
+ return NJS_ERROR;
+ }
+
+ break;
+ }
}
ret = njs_external_process_events(state->vm, state->env);
- if (ret != NJS_OK) {
+ if (ret == NJS_ERROR) {
njs_stderror("njs_external_process_events() failed\n");
return NJS_ERROR;
}
- if (njs_vm_waiting(state->vm) && !njs_vm_posted(state->vm)) {
- /*TODO: async events. */
-
- njs_stderror("njs_process_test(): async events unsupported\n");
- return NJS_ERROR;
+ if (ret == NJS_OK) {
+ break;
}
- (void) njs_vm_run(state->vm);
-
if (opts->async) {
return NJS_OK;
}