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.

remove private event loops, use uv_default_loop() directly

fs, fetch, and child_process each had their own uv_loop_t* variable
that was always set to uv_default_loop(). This caused a deadlock when
async fs operations (e.g. stream()) ran on a private loop that nobody
polled while the reactor blocked on the default loop.

+100 -126
+47 -16
BUILDING.md
··· 4 4 differ. After you've built a binary, running the 5 5 test suite to confirm that the binary works as intended is a good next step. 6 6 7 + If you can reproduce a test failure, search for it in the <br> 8 + [Ant issue tracker](https://github.com/theMackabu/ant/issues) or file a new issue. 9 + 7 10 ## Table of contents 8 11 9 12 - [Supported platforms](#supported-platforms) ··· 174 177 175 178 #### Building Ant 176 179 180 + > [!IMPORTANT] 181 + > If the path to your build directory contains a space, the build will likely 182 + > fail. 183 + 177 184 To build Ant: 178 185 179 186 ```bash ··· 190 197 maid build # compiles 191 198 maid run <file> # builds and runs a JS file 192 199 ``` 200 + 201 + > [!TIP] 202 + > `maid setup` automatically configures ccache and lld for faster builds. 203 + > Use `maid run <file>` during development to build and execute in one step. 193 204 194 205 To verify the build: 195 206 ··· 229 240 ./build/ant examples/spec/run.js 230 241 ``` 231 242 243 + > [!NOTE] 244 + > Remember to recompile with `meson compile -C build` (or `maid build`) 245 + > between test runs if you change code in the `src/` directory. 246 + 232 247 #### Building a debug build 233 248 234 249 A debug build disables optimizations and LTO, and preserves debug symbols: ··· 258 273 259 274 #### Building an ASan build 260 275 261 - [ASan](https://github.com/google/sanitizers) can help detect memory bugs: 276 + [ASan](https://github.com/google/sanitizers) can help detect memory bugs. 277 + 278 + > [!WARNING] 279 + > ASan builds are significantly slower than release builds. The debug flags 280 + > are not required but can produce clearer stack traces when ASan detects 281 + > an issue. 262 282 263 283 ```bash 264 284 meson subprojects download ··· 286 306 If you plan to frequently rebuild Ant, installing `ccache` can greatly 287 307 reduce build times. The `maid setup` task configures ccache automatically. 288 308 309 + > [!TIP] 310 + > Using both `ccache` and `lld` together provides the best rebuild 311 + > performance. `ccache` caches compilation, while `lld` speeds up linking 312 + > (which cannot be cached). 313 + 289 314 On GNU/Linux: 290 315 291 316 ```bash ··· 308 333 export CC_LD="$(which lld)" # Linux 309 334 ``` 310 335 311 - Note: LTO is enabled by default with 8 threads (`b_lto=true`, 312 - `b_lto_threads=8`). Disable it with `-Db_lto=false` for faster iteration 313 - during development. 336 + > [!NOTE] 337 + > LTO is enabled by default with 8 threads (`b_lto=true`, 338 + > `b_lto_threads=8`). Disable it with `-Db_lto=false` for faster iteration 339 + > during development. 314 340 315 341 #### Troubleshooting Unix and macOS builds 316 342 ··· 339 365 340 366 #### Windows prerequisites 341 367 342 - Ant on Windows is built using the MSYS2 MINGW64 toolchain. Native MSVC 343 - builds are not currently supported. 368 + Ant on Windows is built using the MSYS2 MINGW64 toolchain. 369 + 370 + > [!IMPORTANT] 371 + > Native MSVC builds are not currently supported. You must use the MSYS2 372 + > MINGW64 environment. 344 373 345 374 1. Install [MSYS2](https://www.msys2.org/) 346 375 2. Open the **MINGW64** shell and install dependencies: ··· 366 395 meson compile -C build 367 396 ``` 368 397 369 - Note: Windows builds use `-Dc_std=gnu2x` instead of `gnu23` due to MinGW 370 - toolchain compatibility. 398 + > [!NOTE] 399 + > Windows builds use `-Dc_std=gnu2x` instead of `gnu23` due to MinGW 400 + > toolchain compatibility. 371 401 372 402 To verify: 373 403 ··· 375 405 ./build/ant.exe --version 376 406 ``` 377 407 378 - Windows builds require bundling the following DLLs alongside `ant.exe`: 379 - 380 - - `libssl-3-x64.dll` 381 - - `libcrypto-3-x64.dll` 382 - - `libsodium-26.dll` 383 - 384 - These are found in the MSYS2 MINGW64 bin directory 385 - (`/mingw64/bin/` or equivalent). 408 + > [!WARNING] 409 + > Windows builds require bundling the following DLLs alongside `ant.exe`: 410 + > 411 + > - `libssl-3-x64.dll` 412 + > - `libcrypto-3-x64.dll` 413 + > - `libsodium-26.dll` 414 + > 415 + > These are found in the MSYS2 MINGW64 bin directory 416 + > (`/mingw64/bin/` or equivalent). 386 417 387 418 ## Meson build options 388 419
+8
README.md
··· 7 7 8 8 ๐Ÿ“– [Read the blog post about Ant](https://s.tail.so/js-in-one-month) 9 9 10 + ## Table of contents 11 + 12 + * [Installation](#installation) 13 + * [Building Ant](#building-ant) 14 + * [Security](#security) 15 + * [Contributing to Ant](#contributing-to-ant) 16 + * [Current project team members](#current-project-team-members) 17 + 10 18 ## Installation 11 19 12 20 ```bash
+1 -2
include/modules/child_process.h
··· 5 5 #include "types.h" 6 6 7 7 jsval_t child_process_library(struct js *js); 8 - int has_pending_child_processes(void); 9 8 10 - void child_process_poll_events(void); 9 + int has_pending_child_processes(void); 11 10 void child_process_gc_update_roots(GC_OP_VAL_ARGS); 12 11 13 12 #endif
-1
include/modules/fetch.h
··· 4 4 #include "gc.h" 5 5 6 6 void init_fetch_module(void); 7 - void fetch_poll_events(void); 8 7 void fetch_gc_update_roots(GC_OP_VAL_ARGS); 9 8 10 9 int has_pending_fetches(void);
-1
include/modules/fs.h
··· 8 8 int has_pending_fs_ops(void); 9 9 10 10 void init_fs_module(void); 11 - void fs_poll_events(void); 12 11 void fs_gc_update_roots(GC_OP_VAL_ARGS); 13 12 14 13 #endif
+2 -3
include/runtime.h
··· 4 4 #include "types.h" 5 5 #include <argtable3.h> 6 6 7 - #define ANT_RUNTIME_CRYPTO_INIT (1u << 0) 8 - #define ANT_RUNTIME_EXT_EVENT_LOOP (1u << 1) 9 - #define CODE_ARENA_BLOCK_SIZE (64 * 1024) 7 + #define ANT_RUNTIME_CRYPTO_INIT (1u << 0) 8 + #define CODE_ARENA_BLOCK_SIZE (64 * 1024) 10 9 11 10 struct ant_runtime { 12 11 struct js *js;
+13 -27
src/modules/child_process.c
··· 76 76 77 77 static child_process_t *pending_children_head = NULL; 78 78 static child_process_t *pending_children_tail = NULL; 79 - static uv_loop_t *cp_loop = NULL; 80 - 81 - static void ensure_cp_loop(void) { 82 - if (cp_loop == NULL) cp_loop = uv_default_loop(); 83 - } 84 79 85 80 static void add_pending_child(child_process_t *cp) { 86 81 cp->next = NULL; ··· 507 502 if (nargs < 1) return js_mkerr(js, "spawn() requires a command"); 508 503 if (vtype(args[0]) != T_STR) return js_mkerr(js, "Command must be a string"); 509 504 510 - ensure_cp_loop(); 511 - 512 505 size_t cmd_len; 513 506 char *cmd = js_getstr(js, args[0], &cmd_len); 514 507 char *cmd_str = strndup(cmd, cmd_len); ··· 555 548 cp->cwd = cwd; 556 549 cp->promise = js_mkundef(); 557 550 558 - uv_pipe_init(cp_loop, &cp->stdin_pipe, 0); 559 - uv_pipe_init(cp_loop, &cp->stdout_pipe, 0); 560 - uv_pipe_init(cp_loop, &cp->stderr_pipe, 0); 551 + uv_pipe_init(uv_default_loop(), &cp->stdin_pipe, 0); 552 + uv_pipe_init(uv_default_loop(), &cp->stdout_pipe, 0); 553 + uv_pipe_init(uv_default_loop(), &cp->stderr_pipe, 0); 561 554 562 555 cp->stdin_pipe.data = cp; 563 556 cp->stdout_pipe.data = cp; ··· 615 608 options.args = final_args; 616 609 options.stdio_count = 3; 617 610 options.stdio = stdio; 611 + 618 612 if (cwd) options.cwd = cwd; 619 613 if (detached) options.flags = UV_PROCESS_DETACHED; 620 - 621 - int r = uv_spawn(cp_loop, &cp->process, &options); 614 + int r = uv_spawn(uv_default_loop(), &cp->process, &options); 622 615 623 616 if (use_shell) { 624 617 free(final_args[0]); ··· 628 621 } else { 629 622 for (int i = 0; i < final_argc; i++) { 630 623 if (final_args[i]) free(final_args[i]); 631 - } 632 - free(final_args); 624 + } free(final_args); 633 625 } 634 626 635 627 free_args_array(spawn_args, spawn_argc); ··· 643 635 uv_read_start((uv_stream_t *)&cp->stderr_pipe, alloc_buffer, on_stderr_read); 644 636 645 637 add_pending_child(cp); 646 - 647 638 cp->child_obj = create_child_object(js, cp); 639 + 648 640 return cp->child_obj; 649 641 } 650 642 651 643 static jsval_t builtin_exec(struct js *js, jsval_t *args, int nargs) { 652 644 if (nargs < 1) return js_mkerr(js, "exec() requires a command"); 653 645 if (vtype(args[0]) != T_STR) return js_mkerr(js, "Command must be a string"); 654 - 655 - ensure_cp_loop(); 656 646 657 647 size_t cmd_len; 658 648 char *cmd = js_getstr(js, args[0], &cmd_len); ··· 680 670 cp->cwd = cwd; 681 671 cp->promise = js_mkpromise(js); 682 672 683 - uv_pipe_init(cp_loop, &cp->stdin_pipe, 0); 684 - uv_pipe_init(cp_loop, &cp->stdout_pipe, 0); 685 - uv_pipe_init(cp_loop, &cp->stderr_pipe, 0); 673 + uv_pipe_init(uv_default_loop(), &cp->stdin_pipe, 0); 674 + uv_pipe_init(uv_default_loop(), &cp->stdout_pipe, 0); 675 + uv_pipe_init(uv_default_loop(), &cp->stderr_pipe, 0); 686 676 687 677 cp->stdin_pipe.data = cp; 688 678 cp->stdout_pipe.data = cp; ··· 709 699 options.args = shell_args; 710 700 options.stdio_count = 3; 711 701 options.stdio = stdio; 712 - if (cwd) options.cwd = cwd; 713 702 714 - int r = uv_spawn(cp_loop, &cp->process, &options); 703 + if (cwd) options.cwd = cwd; 704 + int r = uv_spawn(uv_default_loop(), &cp->process, &options); 715 705 free(cmd_str); 716 706 717 707 if (r < 0) { ··· 1148 1138 } 1149 1139 1150 1140 int has_pending_child_processes(void) { 1151 - return pending_children_head != NULL || (cp_loop && uv_loop_alive(cp_loop)); 1152 - } 1153 - 1154 - void child_process_poll_events(void) { 1155 - if (cp_loop && uv_loop_alive(cp_loop)) uv_run(cp_loop, UV_RUN_NOWAIT); 1141 + return pending_children_head != NULL; 1156 1142 } 1157 1143 1158 1144 void child_process_gc_update_roots(GC_OP_VAL_ARGS) {
+4 -15
src/modules/fetch.c
··· 40 40 size_t body_len; 41 41 } fetch_request_t; 42 42 43 - static uv_loop_t *fetch_loop = NULL; 44 43 static UT_array *pending_requests = NULL; 45 44 46 45 static void free_fetch_request(fetch_request_t *req) { ··· 224 223 return js_mkundef(); 225 224 } 226 225 227 - if (!pending_requests) utarray_new(pending_requests, &ut_ptr_icd); 228 226 utarray_push_back(pending_requests, &req); 229 227 230 228 const char *scheme_end = strstr(url_str, "://"); ··· 248 246 if (!host_url) return fetch_fail_oom(js, promise, req, false, "Out of memory", 13); 249 247 snprintf(host_url, scheme_len + 3 + host_len + 1, "%.*s://%.*s", (int)scheme_len, url_str, (int)host_len, host_start); 250 248 251 - int rc = tlsuv_http_init(fetch_loop, &req->http_client, host_url); free(host_url); 249 + int rc = tlsuv_http_init(uv_default_loop(), &req->http_client, host_url); free(host_url); 252 250 if (rc != 0) return fetch_fail_oom(js, promise, req, false, "Failed to initialize HTTP client", 33); 253 251 254 252 req->http_client.data = req; ··· 340 338 } 341 339 342 340 void init_fetch_module() { 343 - if (!fetch_loop) fetch_loop = uv_default_loop(); 344 - struct js *js = rt->js; 345 - js_set(js, js_glob(js), "fetch", js_mkfun(js_fetch)); 341 + utarray_new(pending_requests, &ut_ptr_icd); 342 + js_set(rt->js, rt->js->global, "fetch", js_mkfun(js_fetch)); 346 343 } 347 344 348 345 int has_pending_fetches(void) { 349 - return (pending_requests && utarray_len(pending_requests) > 0) || (fetch_loop && uv_loop_alive(fetch_loop)); 350 - } 351 - 352 - void fetch_poll_events(void) { 353 - if (fetch_loop && fetch_loop == uv_default_loop() && (rt->flags & ANT_RUNTIME_EXT_EVENT_LOOP)) return; 354 - if (fetch_loop && uv_loop_alive(fetch_loop)) { 355 - uv_run(fetch_loop, fetch_loop == uv_default_loop() ? UV_RUN_NOWAIT : UV_RUN_ONCE); 356 - if (pending_requests && utarray_len(pending_requests) > 0) usleep(1000); 357 - } 346 + return pending_requests && utarray_len(pending_requests) > 0; 358 347 } 359 348 360 349 void fetch_gc_update_roots(GC_OP_VAL_ARGS) {
+25 -57
src/modules/fs.c
··· 51 51 char *error_msg; 52 52 } fs_request_t; 53 53 54 - static uv_loop_t *fs_loop = NULL; 55 54 static UT_array *pending_requests = NULL; 56 55 57 56 static void free_fs_request(fs_request_t *req) { ··· 110 109 } 111 110 112 111 req->data_len = uv_req->result; 113 - 114 112 uv_fs_t close_req; 115 - uv_fs_close(fs_loop, &close_req, req->fd, NULL); 113 + 114 + uv_fs_close(uv_default_loop(), &close_req, req->fd, NULL); 116 115 uv_fs_req_cleanup(&close_req); 117 116 118 117 req->completed = 1; ··· 134 133 uv_fs_req_cleanup(uv_req); 135 134 136 135 uv_fs_t stat_req; 137 - int stat_result = uv_fs_fstat(fs_loop, &stat_req, req->fd, NULL); 136 + int stat_result = uv_fs_fstat(uv_default_loop(), &stat_req, req->fd, NULL); 138 137 139 138 if (stat_result < 0) { 140 139 req->failed = 1; 141 140 req->error_msg = strdup(uv_strerror(stat_result)); 142 141 req->completed = 1; 143 142 uv_fs_t close_req; 144 - uv_fs_close(fs_loop, &close_req, req->fd, NULL); 143 + uv_fs_close(uv_default_loop(), &close_req, req->fd, NULL); 145 144 uv_fs_req_cleanup(&close_req); 146 145 complete_request(req); 147 146 return; ··· 157 156 req->error_msg = strdup("Out of memory"); 158 157 req->completed = 1; 159 158 uv_fs_t close_req; 160 - uv_fs_close(fs_loop, &close_req, req->fd, NULL); 159 + uv_fs_close(uv_default_loop(), &close_req, req->fd, NULL); 161 160 uv_fs_req_cleanup(&close_req); 162 161 complete_request(req); 163 162 return; 164 163 } 165 164 166 165 uv_buf_t buf = uv_buf_init(req->data, (unsigned int)file_size); 167 - int read_result = uv_fs_read(fs_loop, uv_req, req->fd, &buf, 1, 0, on_read_complete); 166 + int read_result = uv_fs_read(uv_default_loop(), uv_req, req->fd, &buf, 1, 0, on_read_complete); 168 167 169 168 if (read_result < 0) { 170 169 req->failed = 1; 171 170 req->error_msg = strdup(uv_strerror(read_result)); 172 171 req->completed = 1; 173 172 uv_fs_t close_req; 174 - uv_fs_close(fs_loop, &close_req, req->fd, NULL); 173 + uv_fs_close(uv_default_loop(), &close_req, req->fd, NULL); 175 174 uv_fs_req_cleanup(&close_req); 176 175 complete_request(req); 177 176 return; ··· 187 186 } 188 187 189 188 uv_fs_t close_req; 190 - uv_fs_close(fs_loop, &close_req, req->fd, NULL); 189 + uv_fs_close(uv_default_loop(), &close_req, req->fd, NULL); 191 190 uv_fs_req_cleanup(&close_req); 192 191 193 192 req->completed = 1; ··· 209 208 uv_fs_req_cleanup(uv_req); 210 209 211 210 uv_buf_t buf = uv_buf_init(req->data, (unsigned int)req->data_len); 212 - int write_result = uv_fs_write(fs_loop, uv_req, req->fd, &buf, 1, 0, on_write_complete); 211 + int write_result = uv_fs_write(uv_default_loop(), uv_req, req->fd, &buf, 1, 0, on_write_complete); 213 212 214 213 if (write_result < 0) { 215 214 req->failed = 1; 216 215 req->error_msg = strdup(uv_strerror(write_result)); 217 216 req->completed = 1; 218 217 uv_fs_t close_req; 219 - uv_fs_close(fs_loop, &close_req, req->fd, NULL); 218 + uv_fs_close(uv_default_loop(), &close_req, req->fd, NULL); 220 219 uv_fs_req_cleanup(&close_req); 221 220 complete_request(req); 222 221 return; ··· 342 341 free_fs_request(req); 343 342 } 344 343 345 - static void ensure_fs_loop(void) { 346 - if (!fs_loop) { 347 - if (rt->flags & ANT_RUNTIME_EXT_EVENT_LOOP) { 348 - fs_loop = uv_default_loop(); 349 - } else { 350 - fs_loop = malloc(sizeof(uv_loop_t)); 351 - uv_loop_init(fs_loop); 352 - } 353 - } 354 - 355 - if (!pending_requests) { 356 - utarray_new(pending_requests, &ut_ptr_icd); 357 - } 358 - } 359 - 360 344 static jsval_t builtin_fs_readFileSync(struct js *js, jsval_t *args, int nargs) { 361 345 if (nargs < 1) return js_mkerr(js, "readFileSync() requires a path argument"); 362 346 ··· 468 452 char *path = js_getstr(js, args[0], &path_len); 469 453 if (!path) return js_mkerr(js, "Failed to get path string"); 470 454 471 - ensure_fs_loop(); 472 455 473 456 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 474 457 if (!req) return js_mkerr(js, "Out of memory"); ··· 480 463 req->uv_req.data = req; 481 464 482 465 utarray_push_back(pending_requests, &req); 483 - int result = uv_fs_open(fs_loop, &req->uv_req, req->path, O_RDONLY, 0, on_open_for_read); 466 + int result = uv_fs_open(uv_default_loop(), &req->uv_req, req->path, O_RDONLY, 0, on_open_for_read); 484 467 485 468 if (result < 0) { 486 469 req->failed = 1; ··· 501 484 char *path = js_getstr(js, args[0], &path_len); 502 485 if (!path) return js_mkerr(js, "Failed to get path string"); 503 486 504 - ensure_fs_loop(); 505 487 506 488 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 507 489 if (!req) return js_mkerr(js, "Out of memory"); ··· 513 495 req->uv_req.data = req; 514 496 515 497 utarray_push_back(pending_requests, &req); 516 - int result = uv_fs_open(fs_loop, &req->uv_req, req->path, O_RDONLY, 0, on_open_for_read); 498 + int result = uv_fs_open(uv_default_loop(), &req->uv_req, req->path, O_RDONLY, 0, on_open_for_read); 517 499 518 500 if (result < 0) { 519 501 req->failed = 1; ··· 693 675 694 676 if (!path || !data) return js_mkerr(js, "Failed to get arguments"); 695 677 696 - ensure_fs_loop(); 697 678 698 679 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 699 680 if (!req) return js_mkerr(js, "Out of memory"); ··· 714 695 req->uv_req.data = req; 715 696 716 697 utarray_push_back(pending_requests, &req); 717 - int result = uv_fs_open(fs_loop, &req->uv_req, req->path, O_WRONLY | O_CREAT | O_TRUNC, 0644, on_open_for_write); 698 + int result = uv_fs_open(uv_default_loop(), &req->uv_req, req->path, O_WRONLY | O_CREAT | O_TRUNC, 0644, on_open_for_write); 718 699 719 700 if (result < 0) { 720 701 req->failed = 1; ··· 759 740 char *path = js_getstr(js, args[0], &path_len); 760 741 if (!path) return js_mkerr(js, "Failed to get path string"); 761 742 762 - ensure_fs_loop(); 763 743 764 744 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 765 745 if (!req) return js_mkerr(js, "Out of memory"); ··· 771 751 req->uv_req.data = req; 772 752 773 753 utarray_push_back(pending_requests, &req); 774 - int result = uv_fs_unlink(fs_loop, &req->uv_req, req->path, on_unlink_complete); 754 + int result = uv_fs_unlink(uv_default_loop(), &req->uv_req, req->path, on_unlink_complete); 775 755 776 756 if (result < 0) { 777 757 req->failed = 1; ··· 849 829 mode = (int)js_getnum(args[1]); 850 830 } 851 831 852 - ensure_fs_loop(); 853 832 854 833 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 855 834 if (!req) return js_mkerr(js, "Out of memory"); ··· 861 840 req->uv_req.data = req; 862 841 863 842 utarray_push_back(pending_requests, &req); 864 - int result = uv_fs_mkdir(fs_loop, &req->uv_req, req->path, mode, on_mkdir_complete); 843 + int result = uv_fs_mkdir(uv_default_loop(), &req->uv_req, req->path, mode, on_mkdir_complete); 865 844 866 845 if (result < 0) { 867 846 req->failed = 1; ··· 910 889 char *path = js_getstr(js, args[0], &path_len); 911 890 if (!path) return js_mkerr(js, "Failed to get path string"); 912 891 913 - ensure_fs_loop(); 914 892 915 893 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 916 894 if (!req) return js_mkerr(js, "Out of memory"); ··· 922 900 req->uv_req.data = req; 923 901 924 902 utarray_push_back(pending_requests, &req); 925 - int result = uv_fs_rmdir(fs_loop, &req->uv_req, req->path, on_rmdir_complete); 903 + int result = uv_fs_rmdir(uv_default_loop(), &req->uv_req, req->path, on_rmdir_complete); 926 904 927 905 if (result < 0) { 928 906 req->failed = 1; ··· 1033 1011 char *path = js_getstr(js, args[0], &path_len); 1034 1012 if (!path) return js_mkerr(js, "Failed to get path string"); 1035 1013 1036 - ensure_fs_loop(); 1037 1014 1038 1015 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 1039 1016 if (!req) return js_mkerr(js, "Out of memory"); ··· 1045 1022 req->uv_req.data = req; 1046 1023 1047 1024 utarray_push_back(pending_requests, &req); 1048 - int result = uv_fs_stat(fs_loop, &req->uv_req, req->path, on_stat_complete); 1025 + int result = uv_fs_stat(uv_default_loop(), &req->uv_req, req->path, on_stat_complete); 1049 1026 1050 1027 if (result < 0) { 1051 1028 req->failed = 1; ··· 1085 1062 char *path = js_getstr(js, args[0], &path_len); 1086 1063 if (!path) return js_mkerr(js, "Failed to get path string"); 1087 1064 1088 - ensure_fs_loop(); 1089 1065 1090 1066 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 1091 1067 if (!req) return js_mkerr(js, "Out of memory"); ··· 1097 1073 req->uv_req.data = req; 1098 1074 1099 1075 utarray_push_back(pending_requests, &req); 1100 - int result = uv_fs_stat(fs_loop, &req->uv_req, req->path, on_exists_complete); 1076 + int result = uv_fs_stat(uv_default_loop(), &req->uv_req, req->path, on_exists_complete); 1101 1077 1102 1078 if (result < 0) { 1103 1079 req->completed = 1; ··· 1151 1127 mode = (int)js_getnum(args[1]); 1152 1128 } 1153 1129 1154 - ensure_fs_loop(); 1155 1130 1156 1131 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 1157 1132 if (!req) return js_mkerr(js, "Out of memory"); ··· 1163 1138 req->uv_req.data = req; 1164 1139 1165 1140 utarray_push_back(pending_requests, &req); 1166 - int result = uv_fs_access(fs_loop, &req->uv_req, req->path, mode, on_access_complete); 1141 + int result = uv_fs_access(uv_default_loop(), &req->uv_req, req->path, mode, on_access_complete); 1167 1142 1168 1143 if (result < 0) { 1169 1144 req->failed = 1; ··· 1218 1193 char *path = js_getstr(js, args[0], &path_len); 1219 1194 if (!path) return js_mkerr(js, "Failed to get path string"); 1220 1195 1221 - ensure_fs_loop(); 1222 1196 1223 1197 fs_request_t *req = calloc(1, sizeof(fs_request_t)); 1224 1198 if (!req) return js_mkerr(js, "Out of memory"); ··· 1230 1204 req->uv_req.data = req; 1231 1205 1232 1206 utarray_push_back(pending_requests, &req); 1233 - int result = uv_fs_scandir(fs_loop, &req->uv_req, req->path, 0, on_readdir_complete); 1207 + int result = uv_fs_scandir(uv_default_loop(), &req->uv_req, req->path, 0, on_readdir_complete); 1234 1208 1235 1209 if (result < 0) { 1236 1210 req->failed = 1; ··· 1243 1217 } 1244 1218 1245 1219 void init_fs_module(void) { 1246 - struct js *js = rt->js; 1247 - jsval_t glob = js_glob(js); 1220 + utarray_new(pending_requests, &ut_ptr_icd); 1221 + 1222 + ant_t *js = rt->js; 1223 + jsval_t glob = js->global; 1248 1224 1249 1225 jsval_t stats_ctor = js_mkobj(js); 1250 1226 jsval_t stats_proto = js_mkobj(js); ··· 1300 1276 } 1301 1277 1302 1278 int has_pending_fs_ops(void) { 1303 - return (pending_requests && utarray_len(pending_requests) > 0) || (fs_loop && uv_loop_alive(fs_loop)); 1304 - } 1305 - 1306 - void fs_poll_events(void) { 1307 - if (fs_loop && fs_loop == uv_default_loop() && (rt->flags & ANT_RUNTIME_EXT_EVENT_LOOP)) return; 1308 - if (fs_loop && uv_loop_alive(fs_loop)) { 1309 - uv_run(fs_loop, fs_loop == uv_default_loop() ? UV_RUN_NOWAIT : UV_RUN_ONCE); 1310 - if (pending_requests && utarray_len(pending_requests) > 0) usleep(1000); 1311 - } 1279 + return pending_requests && utarray_len(pending_requests) > 0; 1312 1280 } 1313 1281 1314 1282 void fs_gc_update_roots(GC_OP_VAL_ARGS) {
-4
src/reactor.c
··· 21 21 void js_poll_events(ant_t *js) { 22 22 coros_this_tick = 0; 23 23 24 - if (has_pending_fetches()) fetch_poll_events(); 25 - if (has_pending_fs_ops()) fs_poll_events(); 26 - if (has_pending_child_processes()) child_process_poll_events(); 27 - 28 24 process_immediates(js); 29 25 process_microtasks(js); 30 26