Something went wrong. Try again.
javascript for 🐜's, a tiny runtime with big ambitions antjs.org
Something went wrong. Try again.
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741#include <compat.h> // IWYU pragma: keep
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <argtable3.h>#include <crprintf.h>
#include "ant.h"#include "gc.h"#include "crash.h"#include "repl.h"#include "debug.h"#include "utils.h"#include "watch.h"#include "reactor.h"#include "runtime.h"#include "snapshot.h"#include "esm/loader.h"#include "esm/library.h"#include "esm/remote.h"#include "internal.h"#include "silver/vm.h"#include "messages.h"
#include "cli/pkg.h"#include "cli/misc.h"#include "cli/version.h"
#include "modules/builtin.h"#include "modules/buffer.h"#include "modules/atomics.h"#include "modules/os.h"#include "modules/io.h"#include "modules/fs.h"#include "modules/crypto.h"#include "modules/server.h"#include "modules/timer.h"#include "modules/json.h"#include "modules/fetch.h"#include "modules/request.h"#include "modules/response.h"#include "modules/shell.h"#include "modules/process.h"#include "modules/tty.h"#include "modules/path.h"#include "modules/ffi.h"#include "modules/events.h"#include "modules/lmdb.h"#include "modules/performance.h"#include "modules/uri.h"#include "modules/url.h"#include "modules/reflect.h"#include "modules/symbol.h"#include "modules/date.h"#include "modules/math.h"#include "modules/bigint.h"#include "modules/regex.h"#include "modules/textcodec.h"#include "modules/sessionstorage.h"#include "modules/localstorage.h"#include "modules/navigator.h"#include "modules/child_process.h"#include "modules/readline.h"#include "modules/observable.h"#include "modules/collections.h"#include "modules/iterator.h"#include "modules/generator.h"#include "modules/module.h"#include "modules/util.h"#include "modules/async_hooks.h"#include "modules/net.h"#include "modules/tls.h"#include "modules/http_metadata.h"#include "modules/http_parser.h"#include "modules/http_writer.h"#include "modules/dns.h"#include "modules/assert.h"#include "modules/domexception.h"#include "modules/abort.h"#include "modules/globals.h"#include "modules/intl.h"#include "modules/wasm.h"#include "modules/string_decoder.h"#include "modules/stream.h"#include "modules/structured-clone.h"#include "modules/v8.h"#include "modules/worker_threads.h"#include "modules/headers.h"#include "modules/blob.h"#include "modules/formdata.h"#include "modules/zlib.h"#include "streams/queuing.h"#include "streams/readable.h"#include "streams/writable.h"#include "streams/transform.h"#include "streams/codec.h"#include "streams/compression.h"
int js_result = EXIT_SUCCESS;typedef int (*cmd_fn)(int argc, char **argv);
typedef struct { const char *name; const char *alias; const char *desc; cmd_fn fn;} subcommand_t;
static const subcommand_t subcommands[] = { {"init", NULL, "Create a new package.json", pkg_cmd_init}, {"install", "i", "Install dependencies from lockfile", pkg_cmd_install}, {"update", "up", "Re-resolve dependencies and refresh lockfile", pkg_cmd_update}, {"add", "a", "Add a package to dependencies", pkg_cmd_add}, {"remove", "rm", "Remove a package from dependencies", pkg_cmd_remove}, {"trust", NULL, "Run lifecycle scripts for packages", pkg_cmd_trust}, {"run", NULL, "Run a script from package.json", pkg_cmd_run}, {"exec", "x", "Run a command from node_modules/.bin", pkg_cmd_exec}, {"why", "explain", "Show why a package is installed", pkg_cmd_why}, {"info", NULL, "Show package information from registry", pkg_cmd_info}, {"ls", "list", "List installed packages", pkg_cmd_ls}, {"cache", NULL, "Manage the package cache", pkg_cmd_cache}, {"create", NULL, "Scaffold a project from a template", pkg_cmd_create}, {NULL, NULL, NULL, NULL}};
static void ant_debug_apply(const char *key, const char *val) { if (strcmp(key, "gc") == 0) { if (strcmp(val, "disable") == 0) gc_disabled = true; }
else if (strcmp(key, "dump/parse") == 0) { if (strcmp(val, "trace") == 0) sv_debug_enable(SV_DEBUG_PARSE); }
else if (strcmp(key, "dump/compile") == 0) { if (strcmp(val, "trace") == 0) sv_debug_enable(SV_DEBUG_COMPILE); }
else if (strcmp(key, "dump/crprintf") == 0) { if (strcmp(val, "bytecode") == 0 || strcmp(val, "all") == 0) crprintf_set_debug(true); if (strcmp(val, "hex") == 0 || strcmp(val, "all") == 0) crprintf_set_debug_hex(true); }
else if (strcmp(key, "dump/vm") == 0) { if (strcmp(val, "bytecode") == 0 || strcmp(val, "all") == 0) sv_debug_enable(SV_DEBUG_DUMP_BYTECODE); if (strcmp(val, "jit") == 0 || strcmp(val, "all") == 0) sv_debug_enable(SV_DEBUG_DUMP_JIT); if (strcmp(val, "op-warn") == 0 || strcmp(val, "all") == 0) sv_debug_enable(SV_DEBUG_JIT_WARN); }}
static inline void setup_console_colors(void) { crprintf_var("version", ANT_VERSION); crprintf_var("fatal", "<bold+red>FATAL</bold>"); crprintf_var("error", "<red>Error</red>"); crprintf_var("warn", "<yellow>Warning</yellow>");}
static void parse_ant_debug_flags(void) { const char *env = getenv("ANT_DEBUG"); if (!env || !*env) return;
char *buf = strdup(env); if (!buf) return;
char *sp = NULL, *vp = NULL; for (char *e = strtok_r(buf, " ", &sp); e; e = strtok_r(NULL, " ", &sp)) { char *sep = strchr(e, ':'); if (!sep) { crfprintf(stderr, msg.unknown_flag_warn, e); continue; } *sep++ = '\0'; for (char *v = strtok_r(sep, ",", &vp); v; v = strtok_r(NULL, ",", &vp)) ant_debug_apply(e, v); }
free(buf);}
static const subcommand_t *find_subcommand(const char *name) { for (const subcommand_t *cmd = subcommands; cmd->name; cmd++) { if (strcmp(name, cmd->name) == 0) return cmd; if (cmd->alias && strcmp(name, cmd->alias) == 0) return cmd; } return NULL;}
static void print_subcommands(void) { crprintf("<bold>Commands:</>\n"); for (const subcommand_t *cmd = subcommands; cmd->name; cmd++) { crprintf(" <pad=18>%s</pad> %s\n", cmd->name, cmd->desc); } crprintf(msg.ant_command_extra); printf("\n");}
static void print_commands(void **argtable) { crprintf(msg.ant_help_header); print_subcommands(); crprintf(msg.ant_help_flags); print_flags_help(stdout, argtable); print_flag(stdout, (flag_help_t){ .l = "verbose", .g = "enable verbose output" }); print_flag(stdout, (flag_help_t){ .l = "no-color", .g = "disable colored output" });}
typedef struct { int argc; char **argv; } argv_split_t;
static bool is_valued_flag(const char *arg) { return strcmp(arg, "-e") == 0 || strcmp(arg, "--eval") == 0 || strcmp(arg, "--localstorage-file") == 0;}
static int find_argv_token_index(int argc, char **argv, const char *token) { if (!token) return -1; for (int i = 1; i < argc; i++) if (argv[i] == token) return i; return -1;}
static argv_split_t split_script_args(int *argc, char **argv) { for (int i = 1; i < *argc; i++) { if (strcmp(argv[i], "--") == 0) { argv_split_t tail = { *argc - i - 1, argv + i + 1 }; *argc = i; return tail; } if (argv[i][0] == '-') { if (is_valued_flag(argv[i]) && i + 1 < *argc) i++; continue; } argv_split_t tail = { *argc - i - 1, argv + i + 1 }; *argc = i + 1; return tail; } return (argv_split_t){ 0, NULL };}
static argv_split_t build_process_argv(int argc, char **argv, const char *module, argv_split_t script) { if (!module || script.argc == 0) return (argv_split_t){ argc, argv };
int total = 2 + script.argc; char **out = try_oom(sizeof(char*) * (total + 1));
out[0] = argv[0]; out[1] = (char *)module; for (int i = 0; i < script.argc; i++) out[2 + i] = script.argv[i]; out[total] = NULL;
return (argv_split_t){ total, out };}
static char *read_stdin(size_t *len) { size_t cap = 4096; *len = 0; char *buf = malloc(cap); if (!buf) return NULL; size_t n; while ((n = fread(buf + *len, 1, cap - *len, stdin)) > 0) { *len += n; if (*len == cap) { cap *= 2; char *next = realloc(buf, cap); if (!next) { free(buf); return NULL; } buf = next; } } buf[*len] = '\0'; return buf;}
static char *read_file(const char *filename, size_t *len) { FILE *fp = fopen(filename, "rb"); if (!fp) return NULL; fseek(fp, 0, SEEK_END); long size = ftell(fp); fseek(fp, 0, SEEK_SET); char *buffer = malloc(size + 1); if (!buffer) { fclose(fp); return NULL; } *len = fread(buffer, 1, size, fp); fclose(fp); buffer[*len] = '\0'; return buffer;}
static void eval_code(ant_t *js, const char *script, size_t len, const char *tag, bool should_print) { js_set_filename(js, tag); js_setup_import_meta(js, tag); js_set(js, js_glob(js), "__dirname", js_mkstr(js, ".", 1)); js_set(js, js_glob(js), "__filename", js_mkstr(js, tag, strlen(tag))); ant_value_t result = js_eval_bytecode_eval(js, script, len); js_run_event_loop(js); if (print_uncaught_throw(js)) { js_result = EXIT_FAILURE; return; } char cbuf_stack[512]; js_cstr_t cstr = js_to_cstr( js, result, cbuf_stack, sizeof(cbuf_stack) ); if (vtype(result) == T_ERR) { fprintf(stderr, "%s\n", cstr.ptr); js_result = EXIT_FAILURE; } else if (should_print) { if (vtype(result) == T_STR) printf("%s\n", cstr.ptr ? cstr.ptr : ""); else if (cstr.ptr && strcmp(cstr.ptr, "undefined") != 0) { print_value_colored(cstr.ptr, stdout); printf("\n"); } } if (cstr.needs_free) free((void *)cstr.ptr);}
static int execute_module(ant_t *js, const char *filename) { char *use_path_owned = NULL; const char *use_path = filename; const char *stable_use_path = filename;
ant_value_t ns = 0; ant_value_t specifier = 0; ant_value_t default_export = 0; if (esm_is_url(filename)) { js_set(js, js_glob(js), "__dirname", js_mkundef()); specifier = js_mkstr(js, filename, strlen(filename)); } else { char *file_path = strdup(filename); char *dir = dirname(file_path); js_set(js, js_glob(js), "__dirname", js_mkstr(js, dir, strlen(dir))); free(file_path); use_path_owned = realpath(filename, NULL); if (use_path_owned) use_path = use_path_owned; specifier = js_esm_make_file_url(js, use_path); }
const char *interned = intern_string(use_path, strlen(use_path)); if (interned) stable_use_path = interned; else stable_use_path = use_path; js_set(js, js_glob(js), "__filename", js_mkstr(js, filename, strlen(filename)) ); js_set_filename(js, stable_use_path); js_setup_import_meta(js, stable_use_path); ns = js_esm_import_sync(js, specifier); free(use_path_owned); if (print_uncaught_throw(js)) return EXIT_FAILURE; if (vtype(ns) == T_ERR) { fprintf(stderr, "%s\n", js_str(js, ns)); return EXIT_FAILURE; }
default_export = js_get(js, ns, "default"); return server_maybe_start_from_export(js, default_export);}
int main(int argc, char *argv[]) { bool internal_crash_report_mode = ant_crash_is_internal_report(argc, argv); if (internal_crash_report_mode) argc = 1; if (!internal_crash_report_mode && !getenv("ANT_NO_CRASH_HANDLER")) ant_crash_init(argc, argv); setup_console_colors(); parse_ant_debug_flags(); int filtered_argc = 0; int original_argc = argc; char **original_argv = argv; const char *binary_name = strrchr(argv[0], '/'); binary_name = binary_name ? binary_name + 1 : argv[0];
if (strcmp(binary_name, "antx") == 0) { char **exec_argv = try_oom(sizeof(char*) * (argc + 2)); exec_argv[0] = argv[0]; exec_argv[1] = "x"; for (int i = 1; i < argc; i++) exec_argv[i + 1] = argv[i]; exec_argv[argc + 1] = NULL; int exitcode = pkg_cmd_exec(argc, exec_argv + 1); free(exec_argv); return exitcode; } char **filtered_argv = try_oom(sizeof(char*) * argc); for (int i = 0; i < argc; i++) { if (strcmp(argv[i], "--verbose") == 0) pkg_verbose = true; else if (strcmp(argv[i], "--no-color") == 0) { crprintf_set_color(false); io_no_color = true; } else if (strncmp(argv[i], "--stack-size=", 13) == 0) sv_user_stack_size_kb = atoi(argv[i] + 13); else filtered_argv[filtered_argc++] = argv[i]; } argc = filtered_argc; argv = filtered_argv; argv_split_t script_tail = split_script_args(&argc, argv); argv_split_t proc_argv = { 0, NULL };
#define ARG_ITEMS(X) \ X(struct arg_str *, eval, arg_str0("e", "eval", "<script>", "evaluate script")) \ X(struct arg_lit *, print, arg_lit0("p", "print", "evaluate script and print result")) \ X(struct arg_lit *, watch, arg_lit0("w", "watch", "restart process when entry file changes")) \ X(struct arg_lit *, no_clear_screen, arg_lit0(NULL, "no-clear-screen", "keep output when restarting in watch mode")) \ X(struct arg_file *, localstorage_file, arg_file0(NULL, "localstorage-file", "<path>", "file path for localStorage persistence")) \ X(struct arg_file *, file, arg_filen(NULL, NULL, NULL, 0, argc, NULL)) \ X(struct arg_lit *, version, arg_lit0("v", "version", "display version information and exit")) \ X(struct arg_lit *, version_raw, arg_lit0(NULL, "version-raw", "raw version number for scripts")) \ X(struct arg_lit *, help, arg_lit0("h", "help", "display this help and exit")) \ X(struct arg_end *, end, arg_end(20)) #define DECL(t, n, init) t n = init; ARG_ITEMS(DECL) #undef DECL #define REF(t, n, init) n, void *argtable[] = { ARG_ITEMS(REF) }; int nerrors = arg_parse(argc, argv, argtable); #undef REF #define CLEANUP_ARGS_AND_ARGV() ({ \ if (proc_argv.argv != argv) free(proc_argv.argv); \ arg_freetable(argtable, ARGTABLE_COUNT); \ free(filtered_argv); \ }) if (help->count > 0) { print_commands(argtable); CLEANUP_ARGS_AND_ARGV(); return EXIT_SUCCESS; } if (version_raw->count > 0) { fputs(ANT_VERSION "\n", stdout); CLEANUP_ARGS_AND_ARGV(); return EXIT_SUCCESS; } if (version->count > 0) { int res = ant_version(argtable); free(filtered_argv); return res; }
if (nerrors > 0) { print_errors(stdout, end); print_commands(argtable); CLEANUP_ARGS_AND_ARGV(); return EXIT_FAILURE; }
if (no_clear_screen->count > 0 && watch->count == 0) { crfprintf(stderr, msg.misuse_clear_screen); CLEANUP_ARGS_AND_ARGV(); return EXIT_FAILURE; }
if (eval->count == 0 && file->count > 0 && file->filename[0] != NULL) { const char *positional = file->filename[0]; int first_pos_idx = find_argv_token_index(argc, argv, positional); if (first_pos_idx <= 0 || first_pos_idx >= argc) { crfprintf(stderr, msg.argument_fatal); CLEANUP_ARGS_AND_ARGV(); return EXIT_FAILURE; }
const subcommand_t *cmd = find_subcommand(positional);
if (cmd) { if (watch->count > 0) { crfprintf(stderr, msg.watch_subcommand_error); CLEANUP_ARGS_AND_ARGV(); return EXIT_FAILURE; }
int cmd_argc = argc - first_pos_idx; char **cmd_argv = argv + first_pos_idx; char **cmd_argv_full = NULL; if (script_tail.argc > 0) { cmd_argv_full = try_oom(sizeof(*cmd_argv_full) * (size_t)(cmd_argc + script_tail.argc + 1)); memcpy(cmd_argv_full, cmd_argv, sizeof(*cmd_argv_full) * (size_t)cmd_argc); memcpy(cmd_argv_full + cmd_argc, script_tail.argv, sizeof(*cmd_argv_full) * (size_t)script_tail.argc); cmd_argc += script_tail.argc; cmd_argv_full[cmd_argc] = NULL; cmd_argv = cmd_argv_full; }
int exitcode = cmd->fn(cmd_argc, cmd_argv); free(cmd_argv_full); CLEANUP_ARGS_AND_ARGV(); return exitcode; }
if (pkg_script_exists("package.json", positional)) { if (watch->count > 0) { crfprintf(stderr, msg.watch_subcommand_error); CLEANUP_ARGS_AND_ARGV(); return EXIT_FAILURE; }
int run_argc = argc - first_pos_idx + 1 + script_tail.argc; char **run_argv = try_oom(sizeof(*run_argv) * (size_t)(run_argc + 1)); run_argv[0] = argv[0]; int copied = argc - first_pos_idx; memcpy(run_argv + 1, argv + first_pos_idx, sizeof(*run_argv) * (size_t)copied); if (script_tail.argc > 0) { memcpy(run_argv + 1 + copied, script_tail.argv, sizeof(*run_argv) * (size_t)script_tail.argc); } run_argv[run_argc] = NULL; int exitcode = pkg_cmd_run(run_argc, run_argv); free(run_argv); CLEANUP_ARGS_AND_ARGV(); return exitcode; } } bool has_stdin = !isatty(STDIN_FILENO); bool repl_mode = (file->count == 0 && eval->count == 0 && !has_stdin); bool stdin_mode = (has_stdin && file->count == 0); if (watch->count > 0 && (eval->count > 0 || repl_mode || stdin_mode)) { crfprintf(stderr, msg.watch_module_error); CLEANUP_ARGS_AND_ARGV(); return EXIT_FAILURE; } const char *module_file = (repl_mode || file->count == 0) ? NULL : file->filename[0];
if (watch->count > 0) { char *resolved_file = NULL;
resolved_file = resolve_js_file(module_file); if (resolved_file) module_file = resolved_file;
if (!module_file || esm_is_url(module_file)) { crfprintf(stderr, msg.watch_entrypoint_error); if (resolved_file) free(resolved_file); CLEANUP_ARGS_AND_ARGV(); return EXIT_FAILURE; }
int res = ant_watch_run(original_argc, original_argv, module_file, no_clear_screen->count > 0); if (resolved_file) free(resolved_file); CLEANUP_ARGS_AND_ARGV(); return res; } ant_t *js; volatile char stack_base; if (!(js = js_create_dynamic())) { crfprintf(stderr, msg.ant_allocation_fatal); CLEANUP_ARGS_AND_ARGV(); return EXIT_FAILURE; } js_setstackbase(js, (void *)&stack_base); js_setstacklimit(js, os_thread_stack_size() * 3 / 4); proc_argv = build_process_argv(argc, argv, module_file, script_tail); ant_runtime_init(js, proc_argv.argc, proc_argv.argv, localstorage_file);
init_symbol_module(); init_iterator_module(); init_generator_module(); init_timer_module(); init_domexception_module(); init_globals_module(); init_intl_module(); init_wasm_module(); init_builtin_module(); init_buffer_module(); init_structured_clone_module(); init_abort_module(); init_headers_module(); init_blob_module(); init_formdata_module(); init_math_module(); init_bigint_module(); init_date_module(); init_regex_module(); init_collections_module(); init_queuing_strategies_module(); init_readable_stream_module(); init_writable_stream_module(); init_transform_stream_module(); init_codec_stream_module(); init_compression_stream_module(); init_fs_module(); init_atomics_module(); init_crypto_module(); init_request_module(); init_response_module(); init_fetch_module(); init_console_module(); init_json_module(); init_process_module(); init_tty_module(); init_events_module(); init_performance_module(); init_uri_module(); init_url_module(); init_reflect_module(); init_textcodec_module(); init_sessionstorage_module(); init_localstorage_module(); init_navigator_module(); init_observable_module(); ant_register_library(shell_library, "ant:shell", NULL); ant_register_library(ffi_library, "ant:ffi", NULL); ant_register_library(lmdb_library, "ant:lmdb", NULL); ant_register_library(internal_tls_library, "ant:internal/tls", NULL); ant_register_library(internal_http_parser_library, "ant:internal/http_parser", NULL); ant_register_library(internal_http_writer_library, "ant:internal/http_writer", NULL); ant_register_library(internal_http_metadata_library, "ant:internal/http_metadata", NULL);
ant_standard_library("util", util_library); ant_standard_library("util/types", util_types_library); ant_standard_library("console", console_library); ant_standard_library("net", net_library); ant_standard_library("dns", dns_library); ant_standard_library("assert", assert_library); ant_standard_library("module", module_library); ant_standard_library("buffer", buffer_library); ant_standard_library("path", path_library); ant_standard_library("fs", fs_library); ant_standard_library("constants", fs_constants_library); ant_standard_library("os", os_library); ant_standard_library("url", url_library); ant_standard_library("perf_hooks", perf_hooks_library); ant_standard_library("process", process_library); ant_standard_library("crypto", crypto_library); ant_standard_library("events", events_library); ant_standard_library("tty", tty_library); ant_standard_library("readline", readline_library); ant_standard_library("child_process", child_process_library); ant_standard_library("worker_threads", worker_threads_library); ant_standard_library("async_hooks", async_hooks_library); ant_standard_library("v8", v8_library); ant_standard_library("zlib", zlib_library); ant_standard_library("string_decoder", string_decoder_library); ant_standard_library("stream", stream_library); ant_standard_library("timers", timers_library); ant_register_library(path_posix_library, "path/posix", "ant:path/posix", "node:path/posix", NULL); ant_register_library(path_win32_library, "path/win32", "ant:path/win32", "node:path/win32", NULL); ant_standard_library("fs/promises", fs_promises_library); ant_standard_library("timers/promises", timers_promises_library); ant_standard_library("readline/promises", readline_promises_library); ant_standard_library("stream/promises", stream_promises_library); ant_standard_library("stream/web", stream_web_library);
ant_value_t snapshot_result = ant_load_snapshot(js); if (vtype(snapshot_result) == T_ERR) { crfprintf(stderr, msg.snapshot_warn, js_str(js, snapshot_result)); }
if (internal_crash_report_mode) { js_result = ant_crash_run_internal_report(js); }
else if (eval->count > 0) { const char *script = eval->sval[0]; eval_code(js, script, strlen(script), "[eval]", print->count > 0); } else if (repl_mode) { ant_repl_run(); } else if (stdin_mode) { size_t len = 0; char *buf = read_stdin(&len); if (!buf) { crfprintf(stderr, msg.ant_allocation_fatal); js_result = EXIT_FAILURE; goto cleanup; } eval_code(js, buf, len, "[stdin]", print->count > 0); free(buf); } else { for (int fi = 0; fi < file->count; fi++) { const char *fl = file->filename[fi]; char *resolved_file = resolve_js_file(fl); if (!resolved_file) { crfprintf(stderr, msg.module_not_found, fl); js_result = EXIT_FAILURE; break; } fl = resolved_file; js_result = execute_module(js, fl); js_run_event_loop(js); free(resolved_file); if (js_result != EXIT_SUCCESS) break; }} cleanup: { js_destroy(js); CLEANUP_ARGS_AND_ARGV(); } #undef CLEANUP_ARGS_AND_ARGV return js_result;}