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.

revise buffer semantics and root collection

+86 -15
+3 -1
include/modules/timer.h
··· 8 8 void init_timer_module(void); 9 9 void process_microtasks(ant_t *js); 10 10 void process_immediates(ant_t *js); 11 - void queue_microtask(ant_t *js, ant_value_t callback); 12 11 void queue_promise_trigger(ant_t *js, ant_value_t promise); 12 + 13 + void queue_microtask(ant_t *js, ant_value_t callback); 14 + void queue_microtask_with_args(ant_t *js, ant_value_t callback, ant_value_t *args, int nargs); 13 15 14 16 bool js_maybe_drain_microtasks(ant_t *js); 15 17 bool js_maybe_drain_microtasks_after_async_settle(ant_t *js);
+5 -3
src/gc/objects.c
··· 254 254 if (obj->type_tag == T_MAP) { 255 255 map_entry_t **head = (map_entry_t **)(uintptr_t)js_getnum(obj->u.data.value); 256 256 if (head) { 257 - map_entry_t *e, *tmp; 258 - HASH_ITER(hh, *head, e, tmp) { gc_mark_value(js, e->value); } 259 - } 257 + map_entry_t *e, *tmp; 258 + HASH_ITER(hh, *head, e, tmp) { 259 + gc_mark_value(js, e->key_val); 260 + gc_mark_value(js, e->value); 261 + }} 260 262 } else if (obj->type_tag == T_SET) { 261 263 set_entry_t **head = (set_entry_t **)(uintptr_t)js_getnum(obj->u.data.value); 262 264 if (head) {
+23 -1
src/modules/buffer.c
··· 11 11 #endif 12 12 13 13 #include "ant.h" 14 + #include "utf8.h" 14 15 #include "utils.h" 15 16 #include "errors.h" 16 17 #include "base64.h" ··· 2067 2068 if (encoding == ENC_UNKNOWN) encoding = ENC_UTF8; 2068 2069 } 2069 2070 2071 + if (!ta_data->buffer || ta_data->buffer->is_detached) { 2072 + return js_mkerr(js, "Cannot read from detached buffer"); 2073 + } 2074 + 2070 2075 uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; 2071 2076 size_t len = ta_data->byte_length; 2072 2077 ··· 2100 2105 ant_value_t result = js_mkstr(js, str, char_count); 2101 2106 free(str); 2102 2107 return result; 2103 - } else return js_mkstr(js, (char *)data, len); 2108 + } else { 2109 + size_t out_cap = len * 3 + 1; 2110 + char *out = malloc(out_cap); 2111 + if (!out) return js_mkerr(js, "Failed to allocate string"); 2112 + 2113 + utf8_dec_t dec = { .bom_seen = true, .ignore_bom = true }; 2114 + utf8proc_ssize_t out_len = utf8_whatwg_decode(&dec, data, len, out, false, false); 2115 + 2116 + if (out_len < 0) { 2117 + free(out); 2118 + return js_mkerr(js, "Failed to decode buffer as UTF-8"); 2119 + } 2120 + 2121 + ant_value_t result = js_mkstr(js, out, (size_t)out_len); 2122 + free(out); 2123 + 2124 + return result; 2125 + } 2104 2126 } 2105 2127 2106 2128 // Buffer.prototype.toBase64()
+11 -1
src/modules/collections.c
··· 4 4 #include <math.h> 5 5 6 6 #include "ant.h" 7 + #include "gc.h" 7 8 #include "errors.h" 8 9 #include "runtime.h" 9 10 #include "internal.h" ··· 232 233 if (!map_store_entry(js, map_ptr, args[0], key_val, args[1])) 233 234 return js_mkerr(js, "out of memory"); 234 235 236 + ant_object_t *map_obj = js_obj_ptr(this_val); 237 + if (map_obj) { 238 + gc_write_barrier(js, map_obj, key_val); 239 + gc_write_barrier(js, map_obj, args[1]); 240 + } 241 + 235 242 return this_val; 236 243 } 237 244 ··· 436 443 437 444 if (!set_store_entry(js, set_ptr, args[0])) 438 445 return js_mkerr(js, "out of memory"); 439 - 446 + 447 + ant_object_t *set_obj = js_obj_ptr(this_val); 448 + if (set_obj) gc_write_barrier(js, set_obj, args[0]); 449 + 440 450 return this_val; 441 451 } 442 452
+15
src/modules/process.c
··· 41 41 #include "modules/symbol.h" 42 42 #include "modules/buffer.h" 43 43 #include "modules/napi.h" 44 + #include "modules/timer.h" 44 45 45 46 #ifndef _WIN32 46 47 extern char **environ; ··· 1690 1691 return js_get(js, js_glob(js), "process"); 1691 1692 } 1692 1693 1694 + static ant_value_t process_next_tick(ant_t *js, ant_value_t *args, int nargs) { 1695 + if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "process.nextTick requires a callback"); 1696 + 1697 + ant_value_t cb = args[0]; 1698 + if (vtype(cb) != T_FUNC && vtype(cb) != T_CFUNC) 1699 + return js_mkerr_typed(js, JS_ERR_TYPE, "process.nextTick callback is not a function"); 1700 + 1701 + if (nargs <= 1) queue_microtask(js, cb); 1702 + else queue_microtask_with_args(js, cb, args + 1, nargs - 1); 1703 + 1704 + return js_mkundef(); 1705 + } 1706 + 1693 1707 void init_process_module() { 1694 1708 ant_t *js = rt->js; 1695 1709 ant_value_t global = js_glob(js); ··· 1715 1729 js_set(js, process_proto, "kill", js_mkfun(process_kill)); 1716 1730 js_set(js, process_proto, "abort", js_mkfun(process_abort)); 1717 1731 js_set(js, process_proto, "umask", js_mkfun(process_umask)); 1732 + js_set(js, process_proto, "nextTick", js_mkfun(process_next_tick)); 1718 1733 1719 1734 ant_value_t mem_usage_fn = js_heavy_mkfun(js, process_memory_usage, js_mkundef()); 1720 1735 js_set(js, mem_usage_fn, "rss", js_mkfun(process_memory_usage_rss));
+29 -9
src/modules/timer.c
··· 33 33 ant_value_t callback; 34 34 ant_value_t promise; 35 35 struct microtask_entry *next; 36 + uint8_t argc; 37 + ant_value_t argv[]; 36 38 } microtask_entry_t; 37 39 38 40 typedef struct immediate_entry { ··· 513 515 return js_timers_promises_setImmediate(js, args, nargs); 514 516 } 515 517 518 + static void queue_microtask_entry(microtask_entry_t *entry) { 519 + if (timer_state.microtasks_tail == NULL) { 520 + timer_state.microtasks = entry; 521 + timer_state.microtasks_tail = entry; 522 + } else { 523 + timer_state.microtasks_tail->next = entry; 524 + timer_state.microtasks_tail = entry; 525 + }} 526 + 516 527 void queue_microtask(ant_t *js, ant_value_t callback) { 517 528 microtask_entry_t *entry = ant_calloc(sizeof(microtask_entry_t)); 518 529 if (entry == NULL) return; ··· 520 531 entry->callback = callback; 521 532 entry->promise = js_mkundef(); 522 533 entry->next = NULL; 534 + entry->argc = 0; 523 535 524 - if (timer_state.microtasks_tail == NULL) { 525 - timer_state.microtasks = entry; 526 - timer_state.microtasks_tail = entry; 527 - } else { 528 - timer_state.microtasks_tail->next = entry; 529 - timer_state.microtasks_tail = entry; 530 - } 536 + queue_microtask_entry(entry); 537 + } 538 + 539 + void queue_microtask_with_args(ant_t *js, ant_value_t callback, ant_value_t *args, int nargs) { 540 + if (nargs <= 0) { queue_microtask(js, callback); return; } 541 + 542 + microtask_entry_t *entry = ant_calloc(sizeof(microtask_entry_t) + (size_t)nargs * sizeof(ant_value_t)); 543 + if (entry == NULL) return; 544 + 545 + entry->callback = callback; 546 + entry->promise = js_mkundef(); 547 + entry->next = NULL; 548 + entry->argc = (uint8_t)nargs; 549 + 550 + for (int i = 0; i < nargs; i++) entry->argv[i] = args[i]; 551 + queue_microtask_entry(entry); 531 552 } 532 553 533 554 void queue_promise_trigger(ant_t *js, ant_value_t promise) { ··· 571 592 ant_value_t callback = entry->callback; 572 593 GC_ROOT_PIN(js, callback); 573 594 574 - ant_value_t args[0]; 575 - sv_vm_call(js->vm, js, callback, js_mkundef(), args, 0, NULL, false); 595 + sv_vm_call(js->vm, js, callback, js_mkundef(), entry->argv, entry->argc, NULL, false); 576 596 GC_ROOT_RESTORE(js, root_mark); 577 597 } 578 598