From 9aef0e8e261cc57fdf002a44610d1d5331c16652 Mon Sep 17 00:00:00 2001 From: theMackabu Date: Thu, 18 Dec 2025 18:42:58 -0800 Subject: [PATCH] process_immediates --- include/modules/timer.h | 2 + meson.build | 2 +- src/ant.c | 9 +++-- src/modules/server.c | 13 ++++--- src/modules/timer.c | 82 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 97 insertions(+), 11 deletions(-) diff --git a/include/modules/timer.h b/include/modules/timer.h index 2945b55..71637d5 100644 --- a/include/modules/timer.h +++ b/include/modules/timer.h @@ -6,9 +6,11 @@ void init_timer_module(void); void process_timers(struct js *js); void process_microtasks(struct js *js); +void process_immediates(struct js *js); void queue_microtask(struct js *js, jsval_t callback); int has_pending_timers(void); int has_pending_microtasks(void); +int has_pending_immediates(void); int64_t get_next_timer_timeout(void); #endif diff --git a/meson.build b/meson.build index 003af34..c16c174 100644 --- a/meson.build +++ b/meson.build @@ -74,7 +74,7 @@ endif build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() version_conf = configuration_data() -version_conf.set('ANT_VERSION', '0.1.1.5') +version_conf.set('ANT_VERSION', '0.1.1.6') version_conf.set('ANT_GIT_HASH', git_hash) version_conf.set('ANT_BUILD_DATE', build_date) diff --git a/src/ant.c b/src/ant.c index 668cc1d..b784a02 100644 --- a/src/ant.c +++ b/src/ant.c @@ -655,6 +655,7 @@ void js_poll_events(struct js *js) { if (next_timeout_ms <= 0) process_timers(js); } + process_immediates(js); process_microtasks(js); coroutine_t *temp = pending_coroutines.head; @@ -699,15 +700,15 @@ void js_poll_events(struct js *js) { } void js_run_event_loop(struct js *js) { - while (has_pending_microtasks() || has_pending_timers() || has_pending_coroutines() || has_pending_fetches() || has_pending_fs_ops()) { + while (has_pending_microtasks() || has_pending_timers() || has_pending_immediates() || has_pending_coroutines() || has_pending_fetches() || has_pending_fs_ops()) { js_poll_events(js); - if (!has_pending_microtasks() && has_pending_timers() && !has_ready_coroutines()) { + if (!has_pending_microtasks() && !has_pending_immediates() && has_pending_timers() && !has_ready_coroutines()) { int64_t next_timeout_ms = get_next_timer_timeout(); if (next_timeout_ms > 0) usleep(next_timeout_ms > 1000000 ? 1000000 : next_timeout_ms * 1000); } - if (!has_pending_microtasks() && !has_pending_timers() && !has_pending_coroutines() && !has_pending_fetches() && !has_pending_fs_ops()) break; + if (!has_pending_microtasks() && !has_pending_timers() && !has_pending_immediates() && !has_pending_coroutines() && !has_pending_fetches() && !has_pending_fs_ops()) break; } js_poll_events(js); @@ -8384,7 +8385,7 @@ static jsval_t js_stmt(struct js *js) { case TOK_LBRACE: res = js_block(js, !(js->flags & F_NOEXEC)); break; case TOK_FOR: res = js_for(js); break; case TOK_RETURN: res = js_return(js); break; - case TOK_TRY: res = js_try(js); break; + case TOK_TRY: res = js_try(js); break; default: res = resolveprop(js, js_expr(js)); while (next(js) == TOK_COMMA) { diff --git a/src/modules/server.c b/src/modules/server.c index 2417b06..804a24c 100644 --- a/src/modules/server.c +++ b/src/modules/server.c @@ -105,9 +105,12 @@ static void server_signal_handler(int signum) { static void on_js_timer(uv_timer_t *handle) { struct js *js = (struct js*)handle->data; - if (js && has_pending_timers()) { - int64_t next_timeout = get_next_timer_timeout(); - if (next_timeout <= 0) process_timers(js); + if (js) { + if (has_pending_immediates()) process_immediates(js); + if (has_pending_timers()) { + int64_t next_timeout = get_next_timer_timeout(); + if (next_timeout <= 0) process_timers(js); + } } } @@ -982,10 +985,10 @@ jsval_t js_serve(struct js *js, jsval_t *args, int nargs) { rt->flags |= ANT_RUNTIME_EXT_EVENT_LOOP; while (uv_loop_alive(g_loop)) { - if (has_pending_timers()) { + if (has_pending_timers() || has_pending_immediates()) { int64_t next_timeout_ms = get_next_timer_timeout(); if (next_timeout_ms >= 0) { - uint64_t timeout = next_timeout_ms > 0 ? (uint64_t)next_timeout_ms : 0; + uint64_t timeout = has_pending_immediates() ? 0 : (next_timeout_ms > 0 ? (uint64_t)next_timeout_ms : 0); uv_timer_start(&g_js_timer, on_js_timer, timeout, 0); } } else uv_timer_stop(&g_js_timer); diff --git a/src/modules/timer.c b/src/modules/timer.c index e81679d..403fec7 100644 --- a/src/modules/timer.c +++ b/src/modules/timer.c @@ -23,13 +23,23 @@ typedef struct microtask_entry { struct microtask_entry *next; } microtask_entry_t; +typedef struct immediate_entry { + jsval_t callback; + int immediate_id; + int active; + struct immediate_entry *next; +} immediate_entry_t; + static struct { struct js *js; timer_entry_t *timers; microtask_entry_t *microtasks; microtask_entry_t *microtasks_tail; + immediate_entry_t *immediates; + immediate_entry_t *immediates_tail; int next_timer_id; -} timer_state = {NULL, NULL, NULL, NULL, 1}; + int next_immediate_id; +} timer_state = {NULL, NULL, NULL, NULL, NULL, NULL, 1, 1}; static uint64_t get_current_time_ms(void) { struct timeval tv; @@ -115,6 +125,47 @@ static jsval_t js_clear_timeout(struct js *js, jsval_t *args, int nargs) { return js_mkundef(); } +// setImmediate(callback) +static jsval_t js_set_immediate(struct js *js, jsval_t *args, int nargs) { + if (nargs < 1) { + return js_mkerr(js, "setImmediate requires 1 argument (callback)"); + } + + jsval_t callback = args[0]; + + immediate_entry_t *entry = malloc(sizeof(immediate_entry_t)); + if (entry == NULL) { + return js_mkerr(js, "failed to allocate immediate"); + } + + entry->callback = callback; + entry->immediate_id = timer_state.next_immediate_id++; + entry->active = 1; + entry->next = NULL; + + if (timer_state.immediates_tail == NULL) { + timer_state.immediates = entry; + timer_state.immediates_tail = entry; + } else { + timer_state.immediates_tail->next = entry; + timer_state.immediates_tail = entry; + } + + return js_mknum((double)entry->immediate_id); +} + +// clearImmediate(immediateId) +static jsval_t js_clear_immediate(struct js *js, jsval_t *args, int nargs) { + if (nargs < 1) return js_mkundef(); + int immediate_id = (int)js_getnum(args[0]); + + for (immediate_entry_t *entry = timer_state.immediates; entry != NULL; entry = entry->next) { + if (entry->immediate_id == immediate_id) { entry->active = 0; break; } + } + + return js_mkundef(); +} + // queueMicrotask(callback) static jsval_t js_queue_microtask(struct js *js, jsval_t *args, int nargs) { if (nargs < 1) { @@ -157,6 +208,33 @@ void process_microtasks(struct js *js) { } } +void process_immediates(struct js *js) { + while (timer_state.immediates != NULL) { + immediate_entry_t *entry = timer_state.immediates; + timer_state.immediates = entry->next; + + if (timer_state.immediates == NULL) { + timer_state.immediates_tail = NULL; + } + + if (entry->active) { + jsval_t args[0]; + js_call(js, entry->callback, args, 0); + process_microtasks(js); + } + + free(entry); + } +} + +int has_pending_immediates(void) { + for ( + immediate_entry_t *entry = timer_state.immediates; + entry != NULL; entry = entry->next + ) if (entry->active) return 1; + return 0; +} + void process_timers(struct js *js) { if (timer_state.timers == NULL) return; @@ -228,5 +306,7 @@ void init_timer_module() { js_set(js, global, "clearTimeout", js_mkfun(js_clear_timeout)); js_set(js, global, "setInterval", js_mkfun(js_set_interval)); js_set(js, global, "clearInterval", js_mkfun(js_clear_timeout)); + js_set(js, global, "setImmediate", js_mkfun(js_set_immediate)); + js_set(js, global, "clearImmediate", js_mkfun(js_clear_immediate)); js_set(js, global, "queueMicrotask", js_mkfun(js_queue_microtask)); } -- 2.51.2