MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

process_immediates

+97 -11
+2
include/modules/timer.h
··· 6 6 void init_timer_module(void); 7 7 void process_timers(struct js *js); 8 8 void process_microtasks(struct js *js); 9 + void process_immediates(struct js *js); 9 10 void queue_microtask(struct js *js, jsval_t callback); 10 11 int has_pending_timers(void); 11 12 int has_pending_microtasks(void); 13 + int has_pending_immediates(void); 12 14 int64_t get_next_timer_timeout(void); 13 15 14 16 #endif
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.1.1.5') 77 + version_conf.set('ANT_VERSION', '0.1.1.6') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+5 -4
src/ant.c
··· 655 655 if (next_timeout_ms <= 0) process_timers(js); 656 656 } 657 657 658 + process_immediates(js); 658 659 process_microtasks(js); 659 660 660 661 coroutine_t *temp = pending_coroutines.head; ··· 699 700 } 700 701 701 702 void js_run_event_loop(struct js *js) { 702 - while (has_pending_microtasks() || has_pending_timers() || has_pending_coroutines() || has_pending_fetches() || has_pending_fs_ops()) { 703 + while (has_pending_microtasks() || has_pending_timers() || has_pending_immediates() || has_pending_coroutines() || has_pending_fetches() || has_pending_fs_ops()) { 703 704 js_poll_events(js); 704 705 705 - if (!has_pending_microtasks() && has_pending_timers() && !has_ready_coroutines()) { 706 + if (!has_pending_microtasks() && !has_pending_immediates() && has_pending_timers() && !has_ready_coroutines()) { 706 707 int64_t next_timeout_ms = get_next_timer_timeout(); 707 708 if (next_timeout_ms > 0) usleep(next_timeout_ms > 1000000 ? 1000000 : next_timeout_ms * 1000); 708 709 } 709 710 710 - if (!has_pending_microtasks() && !has_pending_timers() && !has_pending_coroutines() && !has_pending_fetches() && !has_pending_fs_ops()) break; 711 + if (!has_pending_microtasks() && !has_pending_timers() && !has_pending_immediates() && !has_pending_coroutines() && !has_pending_fetches() && !has_pending_fs_ops()) break; 711 712 } 712 713 713 714 js_poll_events(js); ··· 8384 8385 case TOK_LBRACE: res = js_block(js, !(js->flags & F_NOEXEC)); break; 8385 8386 case TOK_FOR: res = js_for(js); break; 8386 8387 case TOK_RETURN: res = js_return(js); break; 8387 - case TOK_TRY: res = js_try(js); break; 8388 + case TOK_TRY: res = js_try(js); break; 8388 8389 default: 8389 8390 res = resolveprop(js, js_expr(js)); 8390 8391 while (next(js) == TOK_COMMA) {
+8 -5
src/modules/server.c
··· 105 105 106 106 static void on_js_timer(uv_timer_t *handle) { 107 107 struct js *js = (struct js*)handle->data; 108 - if (js && has_pending_timers()) { 109 - int64_t next_timeout = get_next_timer_timeout(); 110 - if (next_timeout <= 0) process_timers(js); 108 + if (js) { 109 + if (has_pending_immediates()) process_immediates(js); 110 + if (has_pending_timers()) { 111 + int64_t next_timeout = get_next_timer_timeout(); 112 + if (next_timeout <= 0) process_timers(js); 113 + } 111 114 } 112 115 } 113 116 ··· 982 985 rt->flags |= ANT_RUNTIME_EXT_EVENT_LOOP; 983 986 984 987 while (uv_loop_alive(g_loop)) { 985 - if (has_pending_timers()) { 988 + if (has_pending_timers() || has_pending_immediates()) { 986 989 int64_t next_timeout_ms = get_next_timer_timeout(); 987 990 if (next_timeout_ms >= 0) { 988 - uint64_t timeout = next_timeout_ms > 0 ? (uint64_t)next_timeout_ms : 0; 991 + uint64_t timeout = has_pending_immediates() ? 0 : (next_timeout_ms > 0 ? (uint64_t)next_timeout_ms : 0); 989 992 uv_timer_start(&g_js_timer, on_js_timer, timeout, 0); 990 993 } 991 994 } else uv_timer_stop(&g_js_timer);
+81 -1
src/modules/timer.c
··· 23 23 struct microtask_entry *next; 24 24 } microtask_entry_t; 25 25 26 + typedef struct immediate_entry { 27 + jsval_t callback; 28 + int immediate_id; 29 + int active; 30 + struct immediate_entry *next; 31 + } immediate_entry_t; 32 + 26 33 static struct { 27 34 struct js *js; 28 35 timer_entry_t *timers; 29 36 microtask_entry_t *microtasks; 30 37 microtask_entry_t *microtasks_tail; 38 + immediate_entry_t *immediates; 39 + immediate_entry_t *immediates_tail; 31 40 int next_timer_id; 32 - } timer_state = {NULL, NULL, NULL, NULL, 1}; 41 + int next_immediate_id; 42 + } timer_state = {NULL, NULL, NULL, NULL, NULL, NULL, 1, 1}; 33 43 34 44 static uint64_t get_current_time_ms(void) { 35 45 struct timeval tv; ··· 115 125 return js_mkundef(); 116 126 } 117 127 128 + // setImmediate(callback) 129 + static jsval_t js_set_immediate(struct js *js, jsval_t *args, int nargs) { 130 + if (nargs < 1) { 131 + return js_mkerr(js, "setImmediate requires 1 argument (callback)"); 132 + } 133 + 134 + jsval_t callback = args[0]; 135 + 136 + immediate_entry_t *entry = malloc(sizeof(immediate_entry_t)); 137 + if (entry == NULL) { 138 + return js_mkerr(js, "failed to allocate immediate"); 139 + } 140 + 141 + entry->callback = callback; 142 + entry->immediate_id = timer_state.next_immediate_id++; 143 + entry->active = 1; 144 + entry->next = NULL; 145 + 146 + if (timer_state.immediates_tail == NULL) { 147 + timer_state.immediates = entry; 148 + timer_state.immediates_tail = entry; 149 + } else { 150 + timer_state.immediates_tail->next = entry; 151 + timer_state.immediates_tail = entry; 152 + } 153 + 154 + return js_mknum((double)entry->immediate_id); 155 + } 156 + 157 + // clearImmediate(immediateId) 158 + static jsval_t js_clear_immediate(struct js *js, jsval_t *args, int nargs) { 159 + if (nargs < 1) return js_mkundef(); 160 + int immediate_id = (int)js_getnum(args[0]); 161 + 162 + for (immediate_entry_t *entry = timer_state.immediates; entry != NULL; entry = entry->next) { 163 + if (entry->immediate_id == immediate_id) { entry->active = 0; break; } 164 + } 165 + 166 + return js_mkundef(); 167 + } 168 + 118 169 // queueMicrotask(callback) 119 170 static jsval_t js_queue_microtask(struct js *js, jsval_t *args, int nargs) { 120 171 if (nargs < 1) { ··· 157 208 } 158 209 } 159 210 211 + void process_immediates(struct js *js) { 212 + while (timer_state.immediates != NULL) { 213 + immediate_entry_t *entry = timer_state.immediates; 214 + timer_state.immediates = entry->next; 215 + 216 + if (timer_state.immediates == NULL) { 217 + timer_state.immediates_tail = NULL; 218 + } 219 + 220 + if (entry->active) { 221 + jsval_t args[0]; 222 + js_call(js, entry->callback, args, 0); 223 + process_microtasks(js); 224 + } 225 + 226 + free(entry); 227 + } 228 + } 229 + 230 + int has_pending_immediates(void) { 231 + for ( 232 + immediate_entry_t *entry = timer_state.immediates; 233 + entry != NULL; entry = entry->next 234 + ) if (entry->active) return 1; 235 + return 0; 236 + } 237 + 160 238 void process_timers(struct js *js) { 161 239 if (timer_state.timers == NULL) return; 162 240 ··· 228 306 js_set(js, global, "clearTimeout", js_mkfun(js_clear_timeout)); 229 307 js_set(js, global, "setInterval", js_mkfun(js_set_interval)); 230 308 js_set(js, global, "clearInterval", js_mkfun(js_clear_timeout)); 309 + js_set(js, global, "setImmediate", js_mkfun(js_set_immediate)); 310 + js_set(js, global, "clearImmediate", js_mkfun(js_clear_immediate)); 231 311 js_set(js, global, "queueMicrotask", js_mkfun(js_queue_microtask)); 232 312 }