From 9de301351c28f1506f9fc4e20cfd40e121fb7b2e Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Tue, 21 Nov 2023 09:00:52 -0800 Subject: [PATCH] Moving out setTimeout() and clearTimeout() from njs core. This functions are not part of the ECMAScript and should be implemented by host environment. --- auto/sources | 1 - external/njs_shell.c | 308 +++++++++++++++++++++-------------- nginx/ngx_http_js_module.c | 119 ++++---------- nginx/ngx_js.c | 273 ++++++++++++++++++++++++++++++- nginx/ngx_js.h | 46 +++++- nginx/ngx_stream_js_module.c | 116 ++++--------- src/njs.h | 2 - src/njs_builtin.c | 6 - src/njs_main.h | 1 - src/test/njs_unit_test.c | 24 --- test/shell_test.exp | 2 +- 11 files changed, 573 insertions(+), 325 deletions(-) diff --git a/auto/sources b/auto/sources index fa80724d..9f5d9d5a 100644 --- a/auto/sources +++ b/auto/sources @@ -33,7 +33,6 @@ NJS_LIB_SRCS=" \ src/njs_scope.c \ src/njs_generator.c \ src/njs_disassembler.c \ - src/njs_timer.c \ src/njs_module.c \ src/njs_event.c \ src/njs_extern.c \ diff --git a/external/njs_shell.c b/external/njs_shell.c index 9633c165..eaabbb07 100644 --- a/external/njs_shell.c +++ b/external/njs_shell.c @@ -11,8 +11,6 @@ #include #include #include -#include -#include #if (!defined NJS_FUZZER_TARGET && defined NJS_HAVE_READLINE) @@ -70,7 +68,12 @@ typedef struct { typedef struct { - njs_vm_event_t vm_event; + NJS_RBTREE_NODE (node); + njs_function_t *function; + njs_value_t *args; + njs_uint_t nargs; + uint32_t id; + njs_queue_link_t link; } njs_ev_t; @@ -85,7 +88,8 @@ typedef struct { typedef struct { njs_vm_t *vm; - njs_lvlhsh_t events; /* njs_ev_t * */ + uint32_t event_id; + njs_rbtree_t events; /* njs_ev_t * */ njs_queue_t posted_events; njs_queue_t labels; @@ -120,6 +124,12 @@ static char *njs_completion_generator(const char *text, int state); #endif +static njs_int_t njs_set_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 njs_set_immediate(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_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 njs_ext_console_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t magic, njs_value_t *retval); static njs_int_t njs_ext_console_time(njs_vm_t *vm, njs_value_t *args, @@ -127,17 +137,11 @@ static njs_int_t njs_ext_console_time(njs_vm_t *vm, njs_value_t *args, static njs_int_t njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); -static njs_host_event_t njs_console_set_timer(njs_external_ptr_t external, - uint64_t delay, njs_vm_event_t vm_event); - -static void njs_console_clear_timer(njs_external_ptr_t external, - njs_host_event_t event); static void njs_console_log(njs_vm_t *vm, njs_external_ptr_t external, njs_log_level_t level, const u_char *start, size_t length); -static njs_int_t lvlhsh_key_test(njs_lvlhsh_query_t *lhq, void *data); -static void *lvlhsh_pool_alloc(void *pool, size_t size); -static void lvlhsh_pool_free(void *pool, void *p, size_t size); +static intptr_t njs_event_rbtree_compare(njs_rbtree_node_t *node1, + njs_rbtree_node_t *node2); njs_int_t njs_array_buffer_detach(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -264,17 +268,7 @@ static njs_external_t njs_ext_262[] = { }; -static const njs_lvlhsh_proto_t lvlhsh_proto njs_aligned(64) = { - NJS_LVLHSH_LARGE_SLAB, - lvlhsh_key_test, - lvlhsh_pool_alloc, - lvlhsh_pool_free, -}; - - static njs_vm_ops_t njs_console_ops = { - njs_console_set_timer, - njs_console_clear_timer, NULL, njs_console_log, }; @@ -635,7 +629,8 @@ njs_console_init(njs_vm_t *vm, njs_console_t *console) { console->vm = vm; - njs_lvlhsh_init(&console->events); + console->event_id = 0; + njs_rbtree_init(&console->events, njs_event_rbtree_compare); njs_queue_init(&console->posted_events); njs_queue_init(&console->labels); @@ -648,6 +643,24 @@ njs_console_init(njs_vm_t *vm, njs_console_t *console) } +static njs_int_t +njs_function_bind(njs_vm_t *vm, const njs_str_t *name, + njs_function_native_t native, njs_bool_t ctor) +{ + njs_function_t *f; + njs_opaque_value_t value; + + f = njs_vm_function_alloc(vm, native, 1, ctor); + if (f == NULL) { + return NJS_ERROR; + } + + njs_value_function_set(njs_value_arg(&value), f); + + return njs_vm_bind(vm, name, njs_value_arg(&value), 1); +} + + static njs_int_t njs_externals_init(njs_vm_t *vm) { @@ -659,6 +672,9 @@ njs_externals_init(njs_vm_t *vm) static const njs_str_t dollar_262 = njs_str("$262"); static const njs_str_t print_name = njs_str("print"); static const njs_str_t console_log = njs_str("console.log"); + static const njs_str_t set_timeout = njs_str("setTimeout"); + static const njs_str_t set_immediate = njs_str("setImmediate"); + static const njs_str_t clear_timeout = njs_str("clearTimeout"); console = njs_vm_options(vm)->external; @@ -690,8 +706,18 @@ njs_externals_init(njs_vm_t *vm) return NJS_ERROR; } - ret = njs_console_init(vm, console); - if (njs_slow_path(ret != NJS_OK)) { + ret = njs_function_bind(vm, &set_timeout, njs_set_timeout, 0); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_function_bind(vm, &set_immediate, njs_set_immediate, 0); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_function_bind(vm, &clear_timeout, njs_clear_timeout, 0); + if (ret != NJS_OK) { return NJS_ERROR; } @@ -712,6 +738,11 @@ njs_externals_init(njs_vm_t *vm) return NJS_ERROR; } + ret = njs_console_init(vm, console); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + return NJS_OK; } @@ -829,10 +860,13 @@ njs_console_output(njs_vm_t *vm, njs_value_t *value, njs_int_t ret) static njs_int_t njs_process_events(void *runtime) { - njs_ev_t *ev; - njs_queue_t *events; - njs_console_t *console; - njs_queue_link_t *link; + njs_ev_t *ev; + njs_vm_t *vm; + njs_int_t ret; + njs_queue_t *events; + njs_console_t *console; + njs_queue_link_t *link; + njs_opaque_value_t retval; if (runtime == NULL) { njs_stderror("njs_process_events(): no runtime\n"); @@ -840,6 +874,7 @@ njs_process_events(void *runtime) } console = runtime; + vm = console->vm; events = &console->posted_events; @@ -856,10 +891,24 @@ njs_process_events(void *runtime) ev->link.prev = NULL; ev->link.next = NULL; - njs_vm_post_event(console->vm, ev->vm_event, NULL, 0); + njs_rbtree_delete(&console->events, &ev->node); + + ret = njs_vm_invoke(vm, ev->function, ev->args, ev->nargs, + njs_value_arg(&retval)); + if (ret == NJS_ERROR) { + njs_process_output(vm, njs_value_arg(&retval), ret); + + if (!njs_vm_options(vm)->interactive) { + return NJS_ERROR; + } + } } - return NJS_OK; + if (!njs_rbtree_is_empty(&console->events)) { + return NJS_AGAIN; + } + + return njs_vm_pending(vm) ? NJS_AGAIN: NJS_OK; } @@ -1047,28 +1096,7 @@ njs_process_script(njs_vm_t *vm, void *runtime, const njs_str_t *script) } for ( ;; ) { - if (!njs_vm_pending(vm) && !njs_vm_unhandled_rejection(vm)) { - ret = NJS_OK; - break; - } - - ret = njs_process_events(runtime); - if (njs_slow_path(ret != NJS_OK)) { - njs_stderror("njs_process_events() failed\n"); - ret = NJS_ERROR; - break; - } - - if (njs_vm_waiting(vm) && !njs_vm_posted(vm)) { - /*TODO: async events. */ - - njs_stderror("njs_process_script(): async events unsupported\n"); - ret = NJS_ERROR; - break; - } - ret = njs_vm_run(vm); - if (ret == NJS_ERROR) { njs_process_output(vm, njs_value_arg(&retval), ret); @@ -1076,6 +1104,15 @@ njs_process_script(njs_vm_t *vm, void *runtime, const njs_str_t *script) return NJS_ERROR; } } + + ret = njs_process_events(runtime); + if (njs_slow_path(ret == NJS_ERROR)) { + break; + } + + if (ret == NJS_OK) { + break; + } } return ret; @@ -1534,81 +1571,119 @@ njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } -static njs_host_event_t -njs_console_set_timer(njs_external_ptr_t external, uint64_t delay, - njs_vm_event_t vm_event) +static njs_int_t +njs_set_timer(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused, njs_bool_t immediate, njs_value_t *retval) { - njs_ev_t *ev; - njs_vm_t *vm; - njs_int_t ret; - njs_console_t *console; - njs_lvlhsh_query_t lhq; + njs_ev_t *ev; + uint64_t delay; + njs_uint_t n; + njs_console_t *console; - console = external; - vm = console->vm; + console = njs_vm_external_ptr(vm); - if (delay != 0) { - njs_vm_err(vm, "njs_console_set_timer(): async timers unsupported\n"); - return NULL; + if (njs_slow_path(nargs < 2)) { + njs_vm_type_error(vm, "too few arguments"); + return NJS_ERROR; } - ev = njs_mp_alloc(njs_vm_memory_pool(vm), sizeof(njs_ev_t)); - if (njs_slow_path(ev == NULL)) { - return NULL; + if (njs_slow_path(!njs_value_is_function(njs_argument(args, 1)))) { + njs_vm_type_error(vm, "first arg must be a function"); + return NJS_ERROR; + } + + delay = 0; + + if (!immediate && nargs >= 3 + && njs_value_is_number(njs_argument(args, 2))) + { + delay = njs_value_number(njs_argument(args, 2)); } - ev->vm_event = vm_event; + if (delay != 0) { + njs_vm_internal_error(vm, "njs_set_timer(): async timers unsupported"); + return NJS_ERROR; + } - lhq.key.start = (u_char *) &ev->vm_event; - lhq.key.length = sizeof(njs_vm_event_t); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); + n = immediate ? 2 : 3; + nargs = (nargs >= n) ? nargs - n : 0; - lhq.replace = 0; - lhq.value = ev; - lhq.proto = &lvlhsh_proto; - lhq.pool = njs_vm_memory_pool(vm); + ev = njs_mp_alloc(njs_vm_memory_pool(vm), + sizeof(njs_ev_t) + sizeof(njs_opaque_value_t) * nargs); + if (njs_slow_path(ev == NULL)) { + njs_vm_memory_error(vm); + return NJS_ERROR; + } - ret = njs_lvlhsh_insert(&console->events, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - return NULL; + ev->function = njs_value_function(njs_argument(args, 1)); + ev->nargs = nargs; + ev->args = (njs_value_t *) ((u_char *) ev + sizeof(njs_ev_t)); + ev->id = console->event_id++; + + if (ev->nargs != 0) { + memcpy(ev->args, njs_argument(args, n), + sizeof(njs_opaque_value_t) * ev->nargs); } + njs_rbtree_insert(&console->events, &ev->node); + njs_queue_insert_tail(&console->posted_events, &ev->link); - return (njs_host_event_t) ev; + njs_value_number_set(retval, ev->id); + + return NJS_OK; } -static void -njs_console_clear_timer(njs_external_ptr_t external, njs_host_event_t event) +static njs_int_t +njs_set_timeout(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused, njs_value_t *retval) { - njs_vm_t *vm; - njs_ev_t *ev; - njs_int_t ret; - njs_console_t *console; - njs_lvlhsh_query_t lhq; + return njs_set_timer(vm, args, nargs, unused, 0, retval); +} - ev = event; - console = external; - vm = console->vm; - lhq.key.start = (u_char *) &ev->vm_event; - lhq.key.length = sizeof(njs_vm_event_t); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); +static njs_int_t +njs_set_immediate(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused, njs_value_t *retval) +{ + return njs_set_timer(vm, args, nargs, unused, 1, retval); +} + - lhq.proto = &lvlhsh_proto; - lhq.pool = njs_vm_memory_pool(vm); +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) +{ + njs_ev_t ev_lookup, *ev; + njs_console_t *console; + njs_rbtree_node_t *rb; - if (ev->link.prev != NULL) { - njs_queue_remove(&ev->link); + if (nargs < 2 || !njs_value_is_number(njs_argument(args, 1))) { + njs_value_undefined_set(retval); + return NJS_OK; } - ret = njs_lvlhsh_delete(&console->events, &lhq); - if (ret != NJS_OK) { - njs_vm_err(vm, "njs_lvlhsh_delete() failed\n"); + console = njs_vm_external_ptr(vm); + + ev_lookup.id = njs_value_number(njs_argument(args, 1)); + + rb = njs_rbtree_find(&console->events, &ev_lookup.node); + if (njs_slow_path(rb == NULL)) { + njs_vm_internal_error(vm, "failed to find timer"); + return NJS_ERROR; } - njs_mp_free(njs_vm_memory_pool(vm), ev); + njs_rbtree_delete(&console->events, (njs_rbtree_part_t *) rb); + + ev = (njs_ev_t *) rb; + njs_queue_remove(&ev->link); + ev->link.prev = NULL; + ev->link.next = NULL; + + njs_value_undefined_set(retval); + + return NJS_OK; } @@ -1630,30 +1705,21 @@ njs_console_log(njs_vm_t *vm, njs_external_ptr_t external, } -static njs_int_t -lvlhsh_key_test(njs_lvlhsh_query_t *lhq, void *data) +static intptr_t +njs_event_rbtree_compare(njs_rbtree_node_t *node1, njs_rbtree_node_t *node2) { - njs_ev_t *ev; + njs_ev_t *ev1, *ev2; - ev = data; + ev1 = (njs_ev_t *) node1; + ev2 = (njs_ev_t *) node2; - if (memcmp(&ev->vm_event, lhq->key.start, sizeof(njs_vm_event_t)) == 0) { - return NJS_OK; + if (ev1->id < ev2->id) { + return -1; } - return NJS_DECLINED; -} - - -static void * -lvlhsh_pool_alloc(void *pool, size_t size) -{ - return njs_mp_align(pool, NJS_MAX_ALIGNMENT, size); -} - + if (ev1->id > ev2->id) { + return 1; + } -static void -lvlhsh_pool_free(void *pool, void *p, size_t size) -{ - njs_mp_free(pool, p); + return 0; } diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 5500cc04..3d27f7fb 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -49,7 +49,7 @@ typedef struct { typedef struct { - njs_vm_t *vm; + NGX_JS_COMMON_CTX; ngx_log_t *log; ngx_uint_t done; ngx_int_t status; @@ -77,14 +77,6 @@ typedef struct { } ngx_http_js_cb_t; -typedef struct { - ngx_http_request_t *request; - njs_vm_event_t vm_event; - void *unused; - ngx_int_t ident; -} ngx_http_js_event_t; - - typedef struct { njs_str_t name; #if defined(nginx_version) && (nginx_version >= 1023000) @@ -264,11 +256,6 @@ static njs_int_t ngx_http_js_location(njs_vm_t *vm, ngx_http_request_t *r, unsigned flags, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); -static njs_host_event_t ngx_http_js_set_timer(njs_external_ptr_t external, - uint64_t delay, njs_vm_event_t vm_event); -static void ngx_http_js_clear_timer(njs_external_ptr_t external, - njs_host_event_t event); -static void ngx_http_js_timer_handler(ngx_event_t *ev); static ngx_pool_t *ngx_http_js_pool(njs_vm_t *vm, ngx_http_request_t *r); static ngx_resolver_t *ngx_http_js_resolver(njs_vm_t *vm, ngx_http_request_t *r); @@ -281,6 +268,8 @@ 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 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); static void ngx_http_js_periodic_write_event_handler(ngx_http_request_t *r); @@ -853,8 +842,6 @@ static njs_external_t ngx_http_js_ext_periodic_session[] = { static njs_vm_ops_t ngx_http_js_ops = { - ngx_http_js_set_timer, - ngx_http_js_clear_timer, NULL, ngx_js_logger, }; @@ -872,6 +859,8 @@ static uintptr_t ngx_http_js_uptr[] = { (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, }; @@ -991,7 +980,7 @@ ngx_http_js_content_write_event_handler(ngx_http_request_t *r) ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); - if (!njs_vm_pending(ctx->vm)) { + if (!ngx_vm_pending(ctx)) { ngx_http_js_content_finalize(r, ctx); return; } @@ -1087,7 +1076,7 @@ ngx_http_js_header_filter(ngx_http_request_t *r) ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); ctx->filter = 1; - pending = njs_vm_pending(ctx->vm); + pending = ngx_vm_pending(ctx); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http js header call \"%V\"", &jlcf->header_filter); @@ -1190,7 +1179,7 @@ ngx_http_js_body_filter(ngx_http_request_t *r, ngx_chain_t *in) return ret; } - pending = njs_vm_pending(ctx->vm); + pending = ngx_vm_pending(ctx); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http js body call \"%V\"", &jlcf->body_filter); @@ -1269,7 +1258,7 @@ ngx_http_js_variable_set(ngx_http_request_t *r, ngx_http_variable_value_t *v, ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); - pending = njs_vm_pending(ctx->vm); + pending = ngx_vm_pending(ctx); rc = ngx_js_invoke(ctx->vm, fname, r->connection->log, &ctx->request, 1, &ctx->retval); @@ -1352,6 +1341,8 @@ ngx_http_js_init_vm(ngx_http_request_t *r, njs_int_t proto_id) return NGX_ERROR; } + ngx_js_ctx_init((ngx_js_ctx_t *) ctx); + njs_value_invalid_set(njs_value_arg(&ctx->retval)); ngx_http_set_ctx(r, ctx, ngx_http_js_module); @@ -1424,14 +1415,14 @@ ngx_http_js_cleanup_ctx(void *data) { ngx_http_js_ctx_t *ctx = data; - if (njs_vm_pending(ctx->vm)) { + if (ngx_vm_pending(ctx)) { ngx_log_error(NGX_LOG_ERR, ctx->log, 0, "pending events"); } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "http js vm destroy: %p", ctx->vm); - njs_vm_destroy(ctx->vm); + ngx_js_ctx_destroy((ngx_js_ctx_t *) ctx); } @@ -4280,7 +4271,7 @@ ngx_http_js_periodic_write_event_handler(ngx_http_request_t *r) ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); - if (!njs_vm_pending(ctx->vm)) { + if (!ngx_vm_pending(ctx)) { ngx_http_js_periodic_finalize(r, NGX_OK); return; } @@ -4317,9 +4308,9 @@ ngx_http_js_periodic_finalize(ngx_http_request_t *r, ngx_int_t rc) ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http js periodic finalize: \"%V\" rc: %i c: %i pending: %i", &ctx->periodic->method, rc, r->count, - njs_vm_pending(ctx->vm)); + ngx_vm_pending(ctx)); - if (r->count > 1 || (rc == NGX_OK && njs_vm_pending(ctx->vm))) { + if (r->count > 1 || (rc == NGX_OK && ngx_vm_pending(ctx))) { return; } @@ -4386,65 +4377,6 @@ ngx_http_js_periodic_init(ngx_js_periodic_t *periodic) } -static njs_host_event_t -ngx_http_js_set_timer(njs_external_ptr_t external, uint64_t delay, - njs_vm_event_t vm_event) -{ - ngx_event_t *ev; - ngx_http_request_t *r; - ngx_http_js_event_t *js_event; - - r = (ngx_http_request_t *) external; - - ev = ngx_pcalloc(r->pool, sizeof(ngx_event_t)); - if (ev == NULL) { - return NULL; - } - - js_event = ngx_palloc(r->pool, sizeof(ngx_http_js_event_t)); - if (js_event == NULL) { - return NULL; - } - - js_event->request = r; - js_event->vm_event = vm_event; - js_event->ident = r->connection->fd; - - ev->data = js_event; - ev->log = r->connection->log; - ev->handler = ngx_http_js_timer_handler; - - ngx_add_timer(ev, delay); - - return ev; -} - - -static void -ngx_http_js_clear_timer(njs_external_ptr_t external, njs_host_event_t event) -{ - ngx_event_t *ev = event; - - if (ev->timer_set) { - ngx_del_timer(ev); - } -} - - -static void -ngx_http_js_timer_handler(ngx_event_t *ev) -{ - ngx_http_request_t *r; - ngx_http_js_event_t *js_event; - - js_event = (ngx_http_js_event_t *) ev->data; - - r = js_event->request; - - ngx_http_js_handle_vm_event(r, js_event->vm_event, NULL, 0); -} - - static ngx_pool_t * ngx_http_js_pool(njs_vm_t *vm, ngx_http_request_t *r) { @@ -4530,7 +4462,19 @@ ngx_http_js_handle_vm_event(ngx_http_request_t *r, njs_vm_event_t vm_event, 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_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http js event finalize rc: %i", (ngx_int_t) rc); + + if (rc == NJS_ERROR) { if (r->health_check) { ngx_http_js_periodic_finalize(r, NGX_ERROR); return; @@ -4548,6 +4492,13 @@ ngx_http_js_handle_vm_event(ngx_http_request_t *r, njs_vm_event_t vm_event, } +static ngx_js_ctx_t * +ngx_http_js_ctx(njs_vm_t *vm, ngx_http_request_t *r) +{ + return ngx_http_get_module_ctx(r, ngx_http_js_module); +} + + static njs_int_t ngx_js_http_init(njs_vm_t *vm) { diff --git a/nginx/ngx_js.c b/nginx/ngx_js.c index 4c0f8c29..eb4094ca 100644 --- a/nginx/ngx_js.c +++ b/nginx/ngx_js.c @@ -43,6 +43,12 @@ static njs_int_t ngx_js_ext_console_time(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_ext_console_time_end(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_set_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 njs_set_immediate(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_clear_timeout(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); static void ngx_js_cleanup_vm(void *data); static njs_int_t ngx_js_core_init(njs_vm_t *vm); @@ -344,6 +350,7 @@ ngx_js_invoke(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, 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; @@ -377,7 +384,13 @@ ngx_js_invoke(njs_vm_t *vm, ngx_str_t *fname, ngx_log_t *log, return NGX_ERROR; } - return (ret == NJS_AGAIN) ? NGX_AGAIN : NGX_OK; + if (ret == NJS_AGAIN) { + return NGX_AGAIN; + } + + ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm)); + + return njs_rbtree_is_empty(&ctx->waiting_events) ? NGX_OK : NGX_AGAIN; } @@ -430,6 +443,78 @@ ngx_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str) } +static njs_int_t +njs_function_bind(njs_vm_t *vm, const njs_str_t *name, + njs_function_native_t native, njs_bool_t ctor) +{ + njs_function_t *f; + njs_opaque_value_t value; + + f = njs_vm_function_alloc(vm, native, 1, ctor); + if (f == NULL) { + return NJS_ERROR; + } + + njs_value_function_set(njs_value_arg(&value), f); + + return njs_vm_bind(vm, name, njs_value_arg(&value), 1); +} + + + +static intptr_t +ngx_js_event_rbtree_compare(njs_rbtree_node_t *node1, njs_rbtree_node_t *node2) +{ + ngx_js_event_t *ev1, *ev2; + + ev1 = (ngx_js_event_t *) ((u_char *) node1 + - offsetof(ngx_js_event_t, node)); + ev2 = (ngx_js_event_t *) ((u_char *) node2 + - offsetof(ngx_js_event_t, node)); + + if (ev1->fd < ev2->fd) { + return -1; + } + + if (ev1->fd > ev2->fd) { + return 1; + } + + return 0; +} + + +void +ngx_js_ctx_init(ngx_js_ctx_t *ctx) +{ + 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_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); +} + + static njs_int_t ngx_js_core_init(njs_vm_t *vm) { @@ -437,6 +522,10 @@ ngx_js_core_init(njs_vm_t *vm) njs_str_t name; njs_opaque_value_t value; + static const njs_str_t set_timeout = njs_str("setTimeout"); + static const njs_str_t set_immediate = njs_str("setImmediate"); + static const njs_str_t clear_timeout = njs_str("clearTimeout"); + proto_id = njs_vm_external_prototype(vm, ngx_js_ext_core, njs_nitems(ngx_js_ext_core)); if (proto_id < 0) { @@ -476,6 +565,21 @@ ngx_js_core_init(njs_vm_t *vm) return NJS_ERROR; } + ret = njs_function_bind(vm, &set_timeout, njs_set_timeout, 1); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_function_bind(vm, &set_immediate, njs_set_immediate, 1); + if (ret != NJS_OK) { + return NJS_ERROR; + } + + ret = njs_function_bind(vm, &clear_timeout, njs_clear_timeout, 1); + if (ret != NJS_OK) { + return NJS_ERROR; + } + return NJS_OK; } @@ -859,6 +963,173 @@ 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_opaque_value_t retval; + + event = (ngx_js_event_t *) ((u_char *) ev - offsetof(ngx_js_event_t, ev)); + + vm = event->vm; + + ret = njs_vm_invoke(vm, event->function, event->args, event->nargs, + njs_value_arg(&retval)); + + 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); + } + + ngx_external_event_finalize(vm)(external, ret); +} + + +static void +ngx_js_clear_timer(njs_external_ptr_t external, ngx_js_event_t *event) +{ + if (event->ev.timer_set) { + ngx_del_timer(&event->ev); + } +} + + +static njs_int_t +njs_set_timer(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused, njs_bool_t immediate, njs_value_t *retval) +{ + uint64_t delay; + njs_uint_t n; + ngx_js_ctx_t *ctx; + ngx_js_event_t *event; + ngx_connection_t *c; + + if (njs_slow_path(nargs < 2)) { + njs_vm_type_error(vm, "too few arguments"); + return NJS_ERROR; + } + + if (njs_slow_path(!njs_value_is_function(njs_argument(args, 1)))) { + njs_vm_type_error(vm, "first arg must be a function"); + return NJS_ERROR; + } + + delay = 0; + + if (!immediate && nargs >= 3 + && njs_value_is_number(njs_argument(args, 2))) + { + delay = njs_value_number(njs_argument(args, 2)); + } + + n = immediate ? 2 : 3; + nargs = (nargs >= n) ? nargs - n : 0; + + event = njs_mp_zalloc(njs_vm_memory_pool(vm), + sizeof(ngx_js_event_t) + + sizeof(njs_opaque_value_t) * nargs); + if (njs_slow_path(event == NULL)) { + njs_vm_memory_error(vm); + return NJS_ERROR; + } + + event->vm = vm; + event->function = njs_value_function(njs_argument(args, 1)); + event->nargs = nargs; + event->args = (njs_value_t *) ((u_char *) event + sizeof(ngx_js_event_t)); + event->destructor = ngx_js_clear_timer; + + ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm)); + event->fd = ctx->event_id++; + + c = ngx_external_connection(vm, njs_vm_external_ptr(vm)); + + event->ev.log = c->log; + event->ev.data = event; + event->ev.handler = ngx_js_timer_handler; + + if (event->nargs != 0) { + memcpy(event->args, njs_argument(args, n), + sizeof(njs_opaque_value_t) * event->nargs); + } + + njs_rbtree_insert(&ctx->waiting_events, &event->node); + + ngx_add_timer(&event->ev, delay); + + njs_value_number_set(retval, event->fd); + + return NJS_OK; +} + + +static njs_int_t +njs_set_timeout(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused, njs_value_t *retval) +{ + return njs_set_timer(vm, args, nargs, unused, 0, retval); +} + + +static njs_int_t +njs_set_immediate(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t unused, njs_value_t *retval) +{ + return njs_set_timer(vm, args, nargs, unused, 1, 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) +{ + ngx_js_ctx_t *ctx; + ngx_js_event_t event_lookup, *event; + njs_rbtree_node_t *rb; + + if (nargs < 2 || !njs_value_is_number(njs_argument(args, 1))) { + njs_value_undefined_set(retval); + return NJS_OK; + } + + ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm)); + event_lookup.fd = njs_value_number(njs_argument(args, 1)); + + rb = njs_rbtree_find(&ctx->waiting_events, &event_lookup.node); + if (njs_slow_path(rb == NULL)) { + njs_vm_internal_error(vm, "failed to find timer"); + 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); + } + + njs_rbtree_delete(&ctx->waiting_events, (njs_rbtree_part_t *) rb); + + njs_value_undefined_set(retval); + + return NJS_OK; +} + + void ngx_js_logger(njs_vm_t *vm, njs_external_ptr_t external, njs_log_level_t level, const u_char *start, size_t length) diff --git a/nginx/ngx_js.h b/nginx/ngx_js.h index e7653ece..418fccb1 100644 --- a/nginx/ngx_js.h +++ b/nginx/ngx_js.h @@ -12,7 +12,9 @@ #include #include +#include #include +#include #include "ngx_js_fetch.h" #include "ngx_js_shared_dict.h" @@ -31,9 +33,15 @@ #define ngx_js_buffer_type(btype) ((btype) & ~NGX_JS_DEPRECATED) +typedef struct ngx_js_event_s ngx_js_event_t; +typedef struct ngx_js_dict_s ngx_js_dict_t; +typedef struct ngx_js_ctx_s ngx_js_ctx_t; + + 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 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, @@ -43,10 +51,10 @@ typedef ngx_flag_t (*ngx_external_flag_pt)(njs_vm_t *vm, typedef ngx_flag_t (*ngx_external_size_pt)(njs_vm_t *vm, njs_external_ptr_t e); typedef ngx_ssl_t *(*ngx_external_ssl_pt)(njs_vm_t *vm, njs_external_ptr_t e); +typedef ngx_js_ctx_t *(*ngx_js_external_ctx_pt)(njs_vm_t *vm, + njs_external_ptr_t e); -typedef struct ngx_js_dict_s ngx_js_dict_t; - typedef struct { ngx_str_t name; ngx_str_t path; @@ -55,6 +63,19 @@ typedef struct { } ngx_js_named_path_t; +struct ngx_js_event_s { + njs_vm_t *vm; + njs_function_t *function; + njs_value_t *args; + ngx_socket_t fd; + NJS_RBTREE_NODE (node); + njs_uint_t nargs; + void (*destructor)(njs_external_ptr_t external, + ngx_js_event_t *event); + ngx_event_t ev; +}; + + #define NGX_JS_COMMON_MAIN_CONF \ ngx_js_dict_t *dicts; \ ngx_array_t *periodics \ @@ -89,6 +110,12 @@ typedef struct { #endif +#define NGX_JS_COMMON_CTX \ + njs_vm_t *vm; \ + njs_rbtree_t waiting_events; \ + ngx_socket_t event_id + + typedef struct { NGX_JS_COMMON_MAIN_CONF; } ngx_js_main_conf_t; @@ -99,6 +126,11 @@ typedef struct { } ngx_js_loc_conf_t; +struct ngx_js_ctx_s { + NGX_JS_COMMON_CTX; +}; + + #define ngx_external_connection(vm, e) \ (*((ngx_connection_t **) ((u_char *) (e) + njs_vm_meta(vm, 0)))) #define ngx_external_pool(vm, e) \ @@ -122,6 +154,10 @@ typedef struct { #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) #define ngx_js_prop(vm, type, value, start, len) \ @@ -129,6 +165,12 @@ typedef struct { : njs_vm_value_buffer_set(vm, value, start, len)) +#define ngx_vm_pending(ctx) \ + (njs_vm_pending((ctx)->vm) || !njs_rbtree_is_empty(&(ctx)->waiting_events)) + + +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, 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, diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index e13f6f7f..bb19f811 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -48,7 +48,7 @@ typedef struct { typedef struct { - njs_vm_t *vm; + NGX_JS_COMMON_CTX; njs_opaque_value_t retval; njs_opaque_value_t args[3]; ngx_buf_t *buf; @@ -67,14 +67,6 @@ typedef struct { } ngx_stream_js_ctx_t; -typedef struct { - ngx_stream_session_t *session; - njs_vm_event_t vm_event; - void *unused; - ngx_int_t ident; -} ngx_stream_js_event_t; - - 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, @@ -121,11 +113,6 @@ static njs_int_t ngx_stream_js_periodic_variables(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -static njs_host_event_t ngx_stream_js_set_timer(njs_external_ptr_t external, - uint64_t delay, njs_vm_event_t vm_event); -static void ngx_stream_js_clear_timer(njs_external_ptr_t external, - njs_host_event_t event); -static void ngx_stream_js_timer_handler(ngx_event_t *ev); static ngx_pool_t *ngx_stream_js_pool(njs_vm_t *vm, ngx_stream_session_t *s); static ngx_resolver_t *ngx_stream_js_resolver(njs_vm_t *vm, ngx_stream_session_t *s); @@ -138,6 +125,8 @@ 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 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); static void ngx_stream_js_periodic_event_handler(ngx_event_t *ev); @@ -616,8 +605,6 @@ static njs_external_t ngx_stream_js_ext_session_flags[] = { static njs_vm_ops_t ngx_stream_js_ops = { - ngx_stream_js_set_timer, - ngx_stream_js_clear_timer, NULL, ngx_js_logger, }; @@ -635,6 +622,8 @@ static uintptr_t ngx_stream_js_uptr[] = { (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, }; @@ -762,7 +751,7 @@ ngx_stream_js_phase_handler(ngx_stream_session_t *s, ngx_str_t *name) return NGX_ERROR; } - if (njs_vm_pending(ctx->vm)) { + if (ngx_vm_pending(ctx)) { ctx->in_progress = 1; rc = ctx->events[NGX_JS_EVENT_UPLOAD].ev ? NGX_AGAIN : NGX_DONE; @@ -933,7 +922,7 @@ ngx_stream_js_variable_set(ngx_stream_session_t *s, ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module); - pending = njs_vm_pending(ctx->vm); + pending = ngx_vm_pending(ctx); rc = ngx_js_invoke(ctx->vm, fname, s->connection->log, &ctx->args[0], 1, &ctx->retval); @@ -1016,6 +1005,8 @@ ngx_stream_js_init_vm(ngx_stream_session_t *s, njs_int_t proto_id) return NGX_ERROR; } + ngx_js_ctx_init((ngx_js_ctx_t *) ctx); + njs_value_invalid_set(njs_value_arg(&ctx->retval)); ngx_stream_set_ctx(s, ctx, ngx_stream_js_module); @@ -1106,14 +1097,14 @@ ngx_stream_js_cleanup(void *data) ngx_stream_js_drop_events(ctx); - if (njs_vm_pending(ctx->vm)) { + if (ngx_vm_pending(ctx)) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, "pending events"); } ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream js vm destroy: %p", ctx->vm); - njs_vm_destroy(ctx->vm); + ngx_js_ctx_destroy((ngx_js_ctx_t *) ctx); } @@ -1672,65 +1663,6 @@ ngx_stream_js_periodic_variables(njs_vm_t *vm, njs_object_prop_t *prop, } -static njs_host_event_t -ngx_stream_js_set_timer(njs_external_ptr_t external, uint64_t delay, - njs_vm_event_t vm_event) -{ - ngx_event_t *ev; - ngx_stream_session_t *s; - ngx_stream_js_event_t *js_event; - - s = (ngx_stream_session_t *) external; - - ev = ngx_pcalloc(s->connection->pool, sizeof(ngx_event_t)); - if (ev == NULL) { - return NULL; - } - - js_event = ngx_palloc(s->connection->pool, sizeof(ngx_stream_js_event_t)); - if (js_event == NULL) { - return NULL; - } - - js_event->session = s; - js_event->vm_event = vm_event; - js_event->ident = s->connection->fd; - - ev->data = js_event; - ev->log = s->connection->log; - ev->handler = ngx_stream_js_timer_handler; - - ngx_add_timer(ev, delay); - - return ev; -} - - -static void -ngx_stream_js_clear_timer(njs_external_ptr_t external, njs_host_event_t event) -{ - ngx_event_t *ev = event; - - if (ev->timer_set) { - ngx_del_timer(ev); - } -} - - -static void -ngx_stream_js_timer_handler(ngx_event_t *ev) -{ - ngx_stream_session_t *s; - ngx_stream_js_event_t *js_event; - - js_event = (ngx_stream_js_event_t *) ev->data; - - s = js_event->session; - - ngx_stream_js_handle_event(s, js_event->vm_event, NULL, 0); -} - - static ngx_pool_t * ngx_stream_js_pool(njs_vm_t *vm, ngx_stream_session_t *s) { @@ -1816,13 +1748,26 @@ ngx_stream_js_handle_event(ngx_stream_session_t *s, njs_vm_event_t vm_event, 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_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "http js event finalize rc: %i", (ngx_int_t) rc); + if (rc == NJS_ERROR) { if (s->health_check) { ngx_stream_js_periodic_finalize(s, NGX_ERROR); return; } ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return; } if (rc == NJS_OK) { @@ -1831,6 +1776,13 @@ ngx_stream_js_handle_event(ngx_stream_session_t *s, njs_vm_event_t vm_event, } +static ngx_js_ctx_t * +ngx_stream_js_ctx(njs_vm_t *vm, ngx_stream_session_t *s) +{ + return ngx_stream_get_module_ctx(s, ngx_stream_js_module); +} + + static njs_int_t ngx_js_stream_init(njs_vm_t *vm) { @@ -2022,7 +1974,7 @@ ngx_stream_js_periodic_event_handler(ngx_event_t *ev) ctx = ngx_stream_get_module_ctx(s, ngx_stream_js_module); - if (!njs_vm_pending(ctx->vm)) { + if (!ngx_vm_pending(ctx)) { ngx_stream_js_periodic_finalize(s, NGX_OK); return; } @@ -2039,9 +1991,9 @@ ngx_stream_js_periodic_finalize(ngx_stream_session_t *s, ngx_int_t rc) ngx_log_debug4(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "stream js periodic finalize: \"%V\" rc: %i c: %i " "pending: %i", &ctx->periodic->method, rc, s->received, - njs_vm_pending(ctx->vm)); + ngx_vm_pending(ctx)); - if (s->received > 1 || (rc == NGX_OK && njs_vm_pending(ctx->vm))) { + if (s->received > 1 || (rc == NGX_OK && ngx_vm_pending(ctx))) { return; } diff --git a/src/njs.h b/src/njs.h index a68c4fc6..319924c8 100644 --- a/src/njs.h +++ b/src/njs.h @@ -240,8 +240,6 @@ typedef void (*njs_logger_t)(njs_vm_t *vm, njs_external_ptr_t external, typedef struct { - njs_set_timer_t set_timer; - njs_event_destructor_t clear_timer; njs_module_loader_t module_loader; njs_logger_t logger; } njs_vm_ops_t; diff --git a/src/njs_builtin.c b/src/njs_builtin.c index 355e82cf..f0d7e72d 100644 --- a/src/njs_builtin.c +++ b/src/njs_builtin.c @@ -1259,12 +1259,6 @@ static const njs_object_prop_t njs_global_this_object_properties[] = NJS_DECLARE_PROP_NATIVE("eval", njs_eval_function, 1, 0), - NJS_DECLARE_PROP_NATIVE("setTimeout", njs_set_timeout, 2, 0), - - NJS_DECLARE_PROP_NATIVE("setImmediate", njs_set_immediate, 4, 0), - - NJS_DECLARE_PROP_NATIVE("clearTimeout", njs_clear_timeout, 1, 0), - NJS_DECLARE_PROP_NATIVE("require", njs_module_require, 1, 0), /* Global objects. */ diff --git a/src/njs_main.h b/src/njs_main.h index 25d7d31e..dc764c68 100644 --- a/src/njs_main.h +++ b/src/njs_main.h @@ -81,7 +81,6 @@ #include #include -#include #include #include diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 951f24d9..e9ff3a6b 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -18947,25 +18947,6 @@ static njs_unit_test_t njs_test[] = { njs_str("require.hasOwnProperty('length')"), njs_str("true") }, - /* setTimeout(). */ - - { njs_str("setTimeout()"), - njs_str("TypeError: too few arguments") }, - - { njs_str("setTimeout(function(){})"), - njs_str("InternalError: not supported by host environment") }, - - { njs_str("setTimeout(function(){}, 12)"), - njs_str("InternalError: not supported by host environment") }, - - /* clearTimeout(). */ - - { njs_str("clearTimeout()"), - njs_str("undefined") }, - - { njs_str("clearTimeout(123)"), - njs_str("undefined") }, - /* Trick: number to boolean. */ { njs_str("var a = 0; !!a"), @@ -23368,11 +23349,6 @@ static njs_unit_test_t njs_backtraces_test[] = " at require (native)\n" " at main (:1)\n") }, - { njs_str("setTimeout()"), - njs_str("TypeError: too few arguments\n" - " at setTimeout (native)\n" - " at main (:1)\n") }, - { njs_str("require('crypto').createHash('sha')"), njs_str("TypeError: not supported algorithm: \"sha\"\n" " at crypto.createHash (native)\n" diff --git a/test/shell_test.exp b/test/shell_test.exp index eee76c34..a8c17dd2 100644 --- a/test/shell_test.exp +++ b/test/shell_test.exp @@ -420,7 +420,7 @@ njs_test { njs_test { {"setTimeout(function () {}, 1, 'a')\r\n" - "njs_console_set_timer(): async timers unsupported"} + "InternalError: njs_set_timer(): async timers unsupported"} } njs_test { -- 2.47.3