Something went wrong. Try again.
javascript for 🐜's, a tiny runtime with big ambitions antjs.org
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484// TODO: split module into smaller files
#include <compat.h> // IWYU pragma: keep
#include <ctype.h>#include <math.h>#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h>
#include "ant.h"#include "cfunc.h"#include "ascii.h"#include "errors.h"#include "builder.h"#include "internal.h"#include "numbers.h"#include "esm/library.h"#include "silver/call.h"
#include "modules/buffer.h"#include "modules/date.h"#include "modules/json.h"#include "modules/io.h"#include "modules/util.h"#include "modules/abort.h"
typedef struct { char *buf; size_t len; size_t cap;} util_sb_t;
typedef struct { const char *name; const char *open; const char *close;} util_style_entry_t;
typedef enum { UTIL_PARSE_ARG_TYPE_BOOLEAN = 0, UTIL_PARSE_ARG_TYPE_STRING,} util_parse_arg_type_t;
typedef struct { char *name; char short_name; util_parse_arg_type_t type; bool multiple; ant_value_t default_value;} util_parse_arg_option_t;
// TODO: migrate to crprintfstatic const util_style_entry_t util_styles[] = { {"bold", "\x1b[1m", "\x1b[22m"}, {"dim", "\x1b[2m", "\x1b[22m"}, {"italic", "\x1b[3m", "\x1b[23m"}, {"underline", "\x1b[4m", "\x1b[24m"}, {"inverse", "\x1b[7m", "\x1b[27m"}, {"hidden", "\x1b[8m", "\x1b[28m"}, {"strikethrough", "\x1b[9m", "\x1b[29m"}, {"black", "\x1b[30m", "\x1b[39m"}, {"red", "\x1b[31m", "\x1b[39m"}, {"green", "\x1b[32m", "\x1b[39m"}, {"yellow", "\x1b[33m", "\x1b[39m"}, {"blue", "\x1b[34m", "\x1b[39m"}, {"magenta", "\x1b[35m", "\x1b[39m"}, {"cyan", "\x1b[36m", "\x1b[39m"}, {"white", "\x1b[37m", "\x1b[39m"}, {"gray", "\x1b[90m", "\x1b[39m"}, {"grey", "\x1b[90m", "\x1b[39m"}, {"bgBlack", "\x1b[40m", "\x1b[49m"}, {"bgRed", "\x1b[41m", "\x1b[49m"}, {"bgGreen", "\x1b[42m", "\x1b[49m"}, {"bgYellow", "\x1b[43m", "\x1b[49m"}, {"bgBlue", "\x1b[44m", "\x1b[49m"}, {"bgMagenta", "\x1b[45m", "\x1b[49m"}, {"bgCyan", "\x1b[46m", "\x1b[49m"}, {"bgWhite", "\x1b[47m", "\x1b[49m"},};
static bool util_sb_reserve(util_sb_t *sb, size_t extra) { size_t need = sb->len + extra + 1; if (need <= sb->cap) return true;
size_t next = sb->cap ? sb->cap : 128; while (next < need) next *= 2;
char *buf = (char *)realloc(sb->buf, next); if (!buf) return false;
sb->buf = buf; sb->cap = next; return true;}
static bool util_sb_append_n(util_sb_t *sb, const char *s, size_t n) { if (n == 0) return true; if (!util_sb_reserve(sb, n)) return false; memcpy(sb->buf + sb->len, s, n); sb->len += n; sb->buf[sb->len] = '\0'; return true;}
static bool util_sb_append_c(util_sb_t *sb, char c) { if (!util_sb_reserve(sb, 1)) return false; sb->buf[sb->len++] = c; sb->buf[sb->len] = '\0'; return true;}
static bool util_sb_append_jsval(ant_t *js, util_sb_t *sb, ant_value_t v) { char cbuf[512]; js_cstr_t cstr = js_to_cstr(js, v, cbuf, sizeof(cbuf)); size_t len = strlen(cstr.ptr); bool ok = util_sb_append_n(sb, cstr.ptr, len); if (cstr.needs_free) free((void *)cstr.ptr); return ok;}
static bool util_sb_append_inspect(ant_t *js, util_sb_t *sb, ant_value_t v, bool show_hidden) { char cbuf[512]; js_cstr_t cstr = show_hidden ? js_inspect_cstr_opts(js, v, cbuf, sizeof(cbuf), 4, ANT_INSPECT_SHOW_HIDDEN) : js_inspect_cstr(js, v, cbuf, sizeof(cbuf)); bool ok = util_sb_append_n(sb, cstr.ptr, strlen(cstr.ptr)); if (cstr.needs_free) free((void *)cstr.ptr); return ok;}
static bool util_set_named_value( ant_t *js, ant_value_t values, const char *name, ant_value_t value, bool multiple) { if (!multiple) { js_set(js, values, name, value); return !Ant_Exception_Pending(js); }
ant_value_t existing = js_get(js, values, name); if (is_err(existing)) return false;
if (vtype(existing) == kTypeUndefined) { ant_value_t arr = js_mkarr(js); js_arr_push(js, arr, value); js_set(js, values, name, arr); return !Ant_Exception_Pending(js); }
if (vtype(existing) == kTypeArray) { js_arr_push(js, existing, value); return !Ant_Exception_Pending(js); }
ant_value_t arr = js_mkarr(js); js_arr_push(js, arr, existing); js_arr_push(js, arr, value); js_set(js, values, name, arr); return !Ant_Exception_Pending(js);}
static util_parse_arg_option_t *util_find_option_by_name( util_parse_arg_option_t *options, size_t option_count, const char *name) { for (size_t i = 0; i < option_count; i++) { if (strcmp(options[i].name, name) == 0) return &options[i]; } return NULL;}
static util_parse_arg_option_t *util_find_option_by_short( util_parse_arg_option_t *options, size_t option_count, char short_name) { for (size_t i = 0; i < option_count; i++) { if (options[i].short_name == short_name) return &options[i]; } return NULL;}
static void util_free_parse_options(util_parse_arg_option_t *options, size_t option_count) { if (!options) return; for (size_t i = 0; i < option_count; i++) free(options[i].name); free(options);}
static ant_value_t util_parse_args(ant_params_t) { ant_value_t config = nargs > 0 ? args[0] : js_mkundef(); if (!is_object_type(config)) { return js_mkerr_typed(js, JS_ERR_TYPE, "parseArgs(config) requires an options object"); }
ant_value_t args_list = js_get(js, config, "args"); if (is_err(args_list)) return args_list; if (vtype(args_list) == kTypeUndefined) { ant_value_t process_obj = js_get(js, js_glob(js), "process"); if (is_err(process_obj)) return process_obj; args_list = js_get(js, process_obj, "argv"); if (is_err(args_list)) return args_list; }
ant_value_t options_obj = js_get(js, config, "options"); if (is_err(options_obj)) return options_obj; if (!is_object_type(options_obj)) options_obj = Ant_Object_CreateBare(js);
ant_value_t strict_value = js_get(js, config, "strict"); if (is_err(strict_value)) return strict_value;
bool strict = is_undefined(strict_value) || js_truthy(js, strict_value); ant_value_t allow_positionals_value = js_get(js, config, "allowPositionals");
if (is_err(allow_positionals_value)) return allow_positionals_value; bool allow_positionals = js_truthy(js, allow_positionals_value);
size_t option_count = 0; { ant_iter_t iter = js_prop_iter_begin(js, options_obj); const char *key = NULL; size_t key_len = 0; while (js_prop_iter_next(&iter, &key, &key_len, NULL)) option_count++; js_prop_iter_end(&iter); }
util_parse_arg_option_t *options = NULL; if (option_count > 0) { options = calloc(option_count, sizeof(*options)); if (!options) return js_mkerr(js, "Out of memory"); ant_iter_t iter = js_prop_iter_begin(js, options_obj); const char *key = NULL; size_t key_len = 0; size_t idx = 0; while (idx < option_count && js_prop_iter_next(&iter, &key, &key_len, NULL)) { ant_value_t spec = js_get(js, options_obj, key); if (is_err(spec)) goto option_error;
ant_value_t type_val = is_object_type(spec) ? js_get(js, spec, "type") : js_mkundef(); if (is_err(type_val)) goto option_error;
ant_value_t short_val = is_object_type(spec) ? js_get(js, spec, "short") : js_mkundef(); if (is_err(short_val)) goto option_error;
ant_value_t multiple_val = is_object_type(spec) ? js_get(js, spec, "multiple") : js_mkundef(); if (is_err(multiple_val)) goto option_error;
ant_value_t default_val = is_object_type(spec) ? js_get(js, spec, "default") : js_mkundef(); if (is_err(default_val)) goto option_error; options[idx].name = strndup(key, key_len); if (!options[idx].name) { js_prop_iter_end(&iter); util_free_parse_options(options, option_count); return js_mkerr(js, "Out of memory"); } options[idx].type = UTIL_PARSE_ARG_TYPE_BOOLEAN; if (vtype(type_val) == kTypeString) { size_t type_len = 0; const char *type_str = js_getstr(js, type_val, &type_len); if (type_str && type_len == 6 && memcmp(type_str, "string", 6) == 0) { options[idx].type = UTIL_PARSE_ARG_TYPE_STRING; } } if (vtype(short_val) == kTypeString) { size_t short_len = 0; const char *short_str = js_getstr(js, short_val, &short_len); if (short_str && short_len > 0) options[idx].short_name = short_str[0]; } options[idx].multiple = js_truthy(js, multiple_val); options[idx].default_value = default_val; idx++; continue;
option_error: js_prop_iter_end(&iter); util_free_parse_options(options, option_count); return Ant_Exception_Current(js); } js_prop_iter_end(&iter); }
ant_value_t values = Ant_Object_CreateBare(js); ant_value_t positionals = js_mkarr(js); ant_value_t out = Ant_Object_Create(js);
ant_offset_t arg_len = js_arr_len(js, args_list); bool stop_parsing = false;
for (ant_offset_t i = 0; i < arg_len; i++) { ant_value_t arg_val = js_arr_get(js, args_list, i); if (vtype(arg_val) != kTypeString) continue; size_t arg_slen = 0; const char *arg = js_getstr(js, arg_val, &arg_slen); if (!arg) continue; if (stop_parsing) { js_arr_push(js, positionals, arg_val); continue; } if (arg_slen == 2 && memcmp(arg, "--", 2) == 0) { stop_parsing = true; continue; } if (arg_slen > 2 && arg[0] == '-' && arg[1] == '-') { const char *name = arg + 2; size_t name_len = arg_slen - 2; const char *inline_value = NULL; size_t inline_len = 0; const char *eq = memchr(name, '=', name_len); if (eq) { name_len = (size_t)(eq - name); inline_value = eq + 1; inline_len = (size_t)(arg + arg_slen - inline_value); } char *name_buf = strndup(name, name_len); if (!name_buf) { util_free_parse_options(options, option_count); return js_mkerr(js, "Out of memory"); } util_parse_arg_option_t *opt = util_find_option_by_name(options, option_count, name_buf); if (!opt) { if (strict) { free(name_buf); util_free_parse_options(options, option_count); return js_mkerr_typed(js, JS_ERR_TYPE, "Unknown option '--%.*s'", (int)name_len, name); } ant_value_t unknown = inline_value ? js_mkstr(js, inline_value, inline_len) : js_true; js_set(js, values, name_buf, unknown); free(name_buf); continue; }
ant_value_t parsed_value = js_true; if (opt->type == UTIL_PARSE_ARG_TYPE_STRING) { if (inline_value) parsed_value = js_mkstr(js, inline_value, inline_len); else if (i + 1 < arg_len) parsed_value = js_arr_get(js, args_list, ++i); else { free(name_buf); util_free_parse_options(options, option_count); return js_mkerr_typed(js, JS_ERR_TYPE, "Option '--%s' requires a value", opt->name); } } else if (inline_value) parsed_value = js_mkstr(js, inline_value, inline_len); if (!util_set_named_value(js, values, opt->name, parsed_value, opt->multiple)) { free(name_buf); util_free_parse_options(options, option_count); return Ant_Exception_Pending(js) ? Ant_Exception_Current(js) : js_mkerr(js, "parseArgs failed"); } free(name_buf); continue; }
if (arg_slen > 1 && arg[0] == '-') { for (size_t j = 1; j < arg_slen; j++) { util_parse_arg_option_t *opt = util_find_option_by_short(options, option_count, arg[j]); if (!opt) { if (strict) { util_free_parse_options(options, option_count); return js_mkerr_typed(js, JS_ERR_TYPE, "Unknown option '-%c'", arg[j]); } char key[2] = {arg[j], '\0'}; js_set(js, values, key, js_true); continue; }
ant_value_t parsed_value = js_true; if (opt->type == UTIL_PARSE_ARG_TYPE_STRING) { if (j + 1 < arg_slen) { parsed_value = js_mkstr(js, arg + j + 1, arg_slen - (j + 1)); j = arg_slen; } else if (i + 1 < arg_len) { parsed_value = js_arr_get(js, args_list, ++i); j = arg_slen; } else { util_free_parse_options(options, option_count); return js_mkerr_typed(js, JS_ERR_TYPE, "Option '-%c' requires a value", arg[j]); } } if (!util_set_named_value(js, values, opt->name, parsed_value, opt->multiple)) { util_free_parse_options(options, option_count); return Ant_Exception_Pending(js) ? Ant_Exception_Current(js) : js_mkerr(js, "parseArgs failed"); } if (opt->type == UTIL_PARSE_ARG_TYPE_STRING) break; } continue; } if (!allow_positionals) { util_free_parse_options(options, option_count); return js_mkerr_typed(js, JS_ERR_TYPE, "Unexpected positional argument '%s'", arg); } js_arr_push(js, positionals, arg_val); }
for (size_t i = 0; i < option_count; i++) { if (vtype(options[i].default_value) == kTypeUndefined) continue; if (vtype(js_get(js, values, options[i].name)) != kTypeUndefined) continue; js_set(js, values, options[i].name, options[i].default_value); } util_free_parse_options(options, option_count); js_set(js, out, "values", values); js_set(js, out, "positionals", positionals); return out;}
static bool format_emit_number(const ant_format_sink_t *sink, void *ctx, double n, bool keep_negative_zero) { char buf[64]; size_t len; if (keep_negative_zero && n == 0 && signbit(n)) return sink->text(ctx, "-0", 2); len = ant_number_to_shortest(n, buf, sizeof(buf)); return sink->text(ctx, buf, len);}
static bool format_emit_bigint(ant_t *js, const ant_format_sink_t *sink, void *ctx, ant_value_t v) { char cbuf[64]; js_cstr_t cstr = js_to_cstr(js, v, cbuf, sizeof(cbuf)); bool ok = sink->text(ctx, cstr.ptr, strlen(cstr.ptr)); if (cstr.needs_free) free((void *)cstr.ptr); return ok;}
static bool format_emit_json(ant_t *js, const ant_format_sink_t *sink, void *ctx, ant_value_t v) { ant_value_t json = json_stringify_value(js, v); size_t len = 0; const char *s = vtype(json) == kTypeString ? js_getstr(js, json, &len) : NULL; return s ? sink->text(ctx, s, len) : sink->text(ctx, "[Circular]", 10);}
static inline bool format_spec_is_known(char spec) { return spec && strchr("sdifjoOc", spec) != NULL;}
int ant_format_walk( ant_native_params_t, int fmt_index, const ant_format_sink_t *sink, void *ctx) { size_t fmt_len = 0; const char *fmt = NULL; size_t run = 0; int argi = fmt_index + 1;
if ( fmt_index >= nargs || vtype(args[fmt_index]) != kTypeString ) return fmt_index; fmt = js_getstr(js, args[fmt_index], &fmt_len); if (!fmt) return fmt_index;
if (nargs - fmt_index == 1) { sink->text(ctx, fmt, fmt_len); return nargs; }
for (size_t i = 0; i < fmt_len; i++) { char spec = i + 1 < fmt_len ? fmt[i + 1] : '\0'; ant_value_t v; bool ok = true;
if (fmt[i] != '%' || !spec) { run++; continue; }
if (spec == '%') { if (!sink->text(ctx, fmt + i - run, run + 1)) return argi; run = 0; i++; continue; }
if (!format_spec_is_known(spec) || argi >= nargs) { run++; continue; } if (run && !sink->text(ctx, fmt + i - run, run)) return argi;
run = 0; v = args[argi++]; i++;
switch (spec) { case 'c': break; case 's': case 'o': case 'O': ok = sink->value(ctx, v, spec); break; case 'j': ok = format_emit_json(js, sink, ctx, v); break;
case 'd': if (vtype(v) == kTypeBigInt) ok = format_emit_bigint(js, sink, ctx, v); else if (vtype(v) == kTypeSymbol) ok = sink->text(ctx, "NaN", 3); else ok = format_emit_number(sink, ctx, js_to_number(js, v), true); break;
case 'i': if (vtype(v) == kTypeBigInt) ok = format_emit_bigint(js, sink, ctx, v); else if (vtype(v) == kTypeSymbol) ok = sink->text(ctx, "NaN", 3); else ok = format_emit_number(sink, ctx, js_parse_int_value(js, v), false); break;
case 'f': if (vtype(v) == kTypeSymbol) ok = sink->text(ctx, "NaN", 3); else ok = format_emit_number(sink, ctx, js_parse_float_value(js, v), false); break;
default: break; }
if (!ok) return argi; }
if (run) sink->text(ctx, fmt + fmt_len - run, run); return argi;}
typedef struct { ant_t *js; util_sb_t *sb;} util_format_ctx_t;
static bool util_format_text(void *ctx, const char *s, size_t len) { return util_sb_append_n(((util_format_ctx_t *)ctx)->sb, s, len);}
static bool util_format_value(void *ctx, ant_value_t value, char spec) { util_format_ctx_t *c = (util_format_ctx_t *)ctx; return spec == 's' ? util_sb_append_jsval(c->js, c->sb, value) : util_sb_append_inspect(c->js, c->sb, value, spec == 'o');}
static const ant_format_sink_t util_format_sink = { util_format_text, util_format_value };
static ant_value_t util_format_impl(ant_native_params_t, int fmt_index) { util_sb_t sb = {0}; util_format_ctx_t ctx = { js, &sb }; int start = ant_format_walk(js, args, nargs, fmt_index, &util_format_sink, &ctx); ant_value_t out;
for (int i = start; i < nargs; i++) { if (i > fmt_index) util_sb_append_c(&sb, ' '); util_sb_append_jsval(js, &sb, args[i]); }
out = js_mkstr(js, sb.buf ? sb.buf : "", sb.len); free(sb.buf);
return out;}
static ant_value_t util_format(ant_params_t) { return util_format_impl(js, args, nargs, 0);}
static ant_value_t util_format_with_options(ant_params_t) { if (nargs <= 1) return js_mkstr(js, "", 0); return util_format_impl(js, args, nargs, 1);}
static int util_inspect_depth(ant_t *js, ant_value_t *args, int nargs) { ant_value_t depth = js_mkundef(); if (nargs > 1 && is_object_type(args[1])) depth = js_get(js, args[1], "depth"); else if (nargs > 2) depth = args[2];
if (vtype(depth) == kTypeNull) return MAX_STRINGIFY_DEPTH; if (vtype(depth) != kTypeNumber) return ANT_INSPECT_MAX_DEPTH; double d = js_getnum(depth); if (!(d >= 0)) return ANT_INSPECT_MAX_DEPTH; return d >= MAX_STRINGIFY_DEPTH ? MAX_STRINGIFY_DEPTH : (int)d;}
static uint8_t util_inspect_flags(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return 0; if (!is_object_type(args[1])) return vtype(args[1]) == kTypeBool && js_truthy(js, args[1]) ? ANT_INSPECT_SHOW_HIDDEN : 0;
uint8_t flags = 0; if (js_truthy(js, js_get(js, args[1], "showHidden"))) flags |= ANT_INSPECT_SHOW_HIDDEN; if (js_get(js, args[1], "compact") == js_false) flags |= ANT_INSPECT_EXPAND; if (js_get(js, args[1], "sorted") == js_true) flags |= ANT_INSPECT_SORTED; return flags;}
static ant_value_t util_inspect(ant_params_t) { if (nargs < 1) return js_mkstr(js, "undefined", 9); char cbuf[512]; js_cstr_t cstr = js_inspect_cstr_opts( js, args[0], cbuf, sizeof(cbuf), util_inspect_depth(js, args, nargs), util_inspect_flags(js, args, nargs) ); ant_value_t out = js_mkstr(js, cstr.ptr, strlen(cstr.ptr)); if (cstr.needs_free) free((void *)cstr.ptr); return out;}
static bool util_has_proto_in_chain(ant_t *js, ant_value_t value, ant_value_t proto) { if (!is_special_object(proto)) return false;
ant_value_t current = value; while (is_special_object(current)) { current = js_get_proto(js, current); if (current == proto) return true; }
return false;}
static bool util_is_boxed_primitive(ant_value_t value, uint8_t *type_out) { ant_value_t primitive;
if (!is_object_type(value)) return false; primitive = js_get_slot(value, SLOT_PRIMITIVE); if (vtype(primitive) == kTypeUndefined) return false;
if (type_out) *type_out = vtype(primitive); return true;}
static ant_value_t util_is_array(ant_params_t) { bool result = false; ant_value_t checked = js_is_array_value_checked(js, nargs > 0 ? args[0] : js_mkundef(), &result); return is_err(checked) ? checked : js_bool(result);}
static bool util_is_arguments_object_value(ant_value_t value) { return js_is_arguments(value);}
static ant_value_t util_types_is_any_array_buffer(ant_params_t) { ArrayBufferData *buffer = (nargs > 0) ? buffer_get_arraybuffer_data(args[0]) : NULL; return js_bool(buffer != NULL);}
static ant_value_t util_types_is_array_buffer(ant_params_t) { ArrayBufferData *buffer = (nargs > 0) ? buffer_get_arraybuffer_data(args[0]) : NULL; return js_bool(buffer != NULL && !buffer->is_shared);}
static ant_value_t util_types_is_shared_array_buffer(ant_params_t) { ArrayBufferData *buffer = (nargs > 0) ? buffer_get_arraybuffer_data(args[0]) : NULL; return js_bool(buffer != NULL && buffer->is_shared);}
static ant_value_t util_types_is_array_buffer_view(ant_params_t) { if (nargs < 1) return js_false; return js_bool(buffer_is_dataview(args[0]) || buffer_get_typedarray_data(args[0]) != NULL);}
static ant_value_t util_types_is_data_view(ant_params_t) { if (nargs < 1) return js_false; return js_bool(buffer_is_dataview(args[0]));}
static ant_value_t util_types_is_typed_array(ant_params_t) { if (nargs < 1) return js_false; return js_bool(buffer_get_typedarray_data(args[0]) != NULL);}
static ant_value_t util_types_is_float16_array(ant_params_t) { TypedArrayData *typed_array = (nargs > 0) ? buffer_get_typedarray_data(args[0]) : NULL; if (!typed_array) return js_false; return js_bool(typed_array != NULL && typed_array->type == TYPED_ARRAY_FLOAT16);}
#define DEFINE_TYPED_ARRAY_CHECK(fn_name, typed_array_kind) \ static ant_value_t fn_name(ant_params_t) { \ TypedArrayData *typed_array = (nargs > 0) ? buffer_get_typedarray_data(args[0]) : NULL; \ if (!typed_array) return js_false; \ return js_bool(typed_array != NULL && typed_array->type == typed_array_kind); \ }
DEFINE_TYPED_ARRAY_CHECK(util_types_is_int8_array, TYPED_ARRAY_INT8)DEFINE_TYPED_ARRAY_CHECK(util_types_is_uint8_array, TYPED_ARRAY_UINT8)DEFINE_TYPED_ARRAY_CHECK(util_types_is_int16_array, TYPED_ARRAY_INT16)DEFINE_TYPED_ARRAY_CHECK(util_types_is_uint16_array, TYPED_ARRAY_UINT16)DEFINE_TYPED_ARRAY_CHECK(util_types_is_int32_array, TYPED_ARRAY_INT32)DEFINE_TYPED_ARRAY_CHECK(util_types_is_uint32_array, TYPED_ARRAY_UINT32)DEFINE_TYPED_ARRAY_CHECK(util_types_is_float32_array, TYPED_ARRAY_FLOAT32)DEFINE_TYPED_ARRAY_CHECK(util_types_is_float64_array, TYPED_ARRAY_FLOAT64)DEFINE_TYPED_ARRAY_CHECK(util_types_is_bigint64_array, TYPED_ARRAY_BIGINT64)DEFINE_TYPED_ARRAY_CHECK(util_types_is_biguint64_array, TYPED_ARRAY_BIGUINT64)DEFINE_TYPED_ARRAY_CHECK(util_types_is_uint8_clamped_array, TYPED_ARRAY_UINT8_CLAMPED)
static ant_value_t util_types_is_promise(ant_params_t) { if (nargs < 1) return js_false; return js_bool(vtype(args[0]) == kTypePromise);}
static ant_value_t util_types_is_proxy(ant_params_t) { if (nargs < 1 || !is_object_type(args[0])) return js_false; return js_bool(is_proxy(args[0]) && !js_proxy_is_host(args[0]));}
static ant_value_t util_types_is_regexp(ant_params_t) { if (nargs < 1 || !is_object_type(args[0])) return js_false; ant_object_t *obj = js_obj_ptr(js_as_obj(args[0])); return js_bool(obj && obj->flags.regexp_brand);}
static ant_value_t util_types_is_date(ant_params_t) { if (nargs < 1) return js_false; return js_bool(is_date_instance(args[0]));}
static ant_value_t util_types_is_map(ant_params_t) { if (nargs < 1 || vtype(args[0]) != kTypeObject) return js_false; return js_bool(js_obj_ptr(args[0])->type_tag == kTypeMap);}
static ant_value_t util_types_is_set(ant_params_t) { if (nargs < 1 || vtype(args[0]) != kTypeObject) return js_false; return js_bool(js_obj_ptr(args[0])->type_tag == kTypeSet);}
static ant_value_t util_types_is_weak_map(ant_params_t) { if (nargs < 1 || vtype(args[0]) != kTypeObject) return js_false; return js_bool(js_obj_ptr(args[0])->type_tag == kTypeWeakMap);}
static ant_value_t util_types_is_weak_set(ant_params_t) { if (nargs < 1 || vtype(args[0]) != kTypeObject) return js_false; return js_bool(js_obj_ptr(args[0])->type_tag == kTypeWeakSet);}
static ant_value_t util_types_is_async_function(ant_params_t) { ant_value_t func_obj; if (nargs < 1 || vtype(args[0]) != kTypeFunction) return js_false; func_obj = js_func_obj(args[0]); return js_bool(js_get_slot(func_obj, SLOT_ASYNC) == js_true);}
static ant_value_t util_types_is_generator_function(ant_params_t) { sv_closure_t *closure;
if (nargs < 1 || vtype(args[0]) != kTypeFunction) return js_false;
closure = js_func_closure(args[0]); return js_bool(closure != NULL && closure->func != NULL && closure->func->is_generator);}
static ant_value_t util_types_is_generator_object(ant_params_t) { if (nargs < 1) return js_false; return js_bool(vtype(args[0]) == kTypeGenerator);}
static ant_value_t util_types_is_arguments_object(ant_params_t) { if (nargs < 1) return js_false; return js_bool(util_is_arguments_object_value(args[0]));}
static ant_value_t util_types_is_native_error(ant_params_t) { if (nargs < 1 || !is_object_type(args[0])) return js_false; return js_bool(js_get_slot(args[0], SLOT_ERROR_BRAND) == js_true);}
static ant_value_t util_types_is_boxed_primitive(ant_params_t) { return js_bool(nargs > 0 && util_is_boxed_primitive(args[0], NULL));}
static ant_value_t util_types_is_boolean_object(ant_params_t) { uint8_t type = kTypeUndefined; return js_bool(nargs > 0 && util_is_boxed_primitive(args[0], &type) && type == kTypeBool);}
static ant_value_t util_types_is_number_object(ant_params_t) { uint8_t type = kTypeUndefined; return js_bool(nargs > 0 && util_is_boxed_primitive(args[0], &type) && type == kTypeNumber);}
static ant_value_t util_types_is_string_object(ant_params_t) { uint8_t type = kTypeUndefined; return js_bool(nargs > 0 && util_is_boxed_primitive(args[0], &type) && type == kTypeString);}
static ant_value_t util_types_is_symbol_object(ant_params_t) { uint8_t type = kTypeUndefined; return js_bool(nargs > 0 && util_is_boxed_primitive(args[0], &type) && type == kTypeSymbol);}
static ant_value_t util_types_is_bigint_object(ant_params_t) { uint8_t type = kTypeUndefined; return js_bool(nargs > 0 && util_is_boxed_primitive(args[0], &type) && type == kTypeBigInt);}
static ant_value_t util_types_is_map_iterator(ant_params_t) { if (nargs < 1 || !is_object_type(args[0])) return js_false; return js_bool(util_has_proto_in_chain(js, args[0], js->builtins.map_iter_proto));}
static ant_value_t util_types_is_set_iterator(ant_params_t) { if (nargs < 1 || !is_object_type(args[0])) return js_false; return js_bool(util_has_proto_in_chain(js, args[0], js->builtins.set_iter_proto));}
static ant_value_t util_types_is_module_namespace_object(ant_params_t) { if (nargs < 1) return js_false; return js_bool(js_check_brand(args[0], BRAND_MODULE_NAMESPACE));}
ant_value_t util_types_library(ant_t *js) { ant_value_t types = Ant_Object_CreateBare(js);
js_set(js, types, "isAnyArrayBuffer", Ant_Function_Create(util_types_is_any_array_buffer)); js_set(js, types, "isArrayBuffer", Ant_Function_Create(util_types_is_array_buffer)); js_set(js, types, "isArgumentsObject", Ant_Function_Create(util_types_is_arguments_object)); js_set(js, types, "isArrayBufferView", Ant_Function_Create(util_types_is_array_buffer_view)); js_set(js, types, "isAsyncFunction", Ant_Function_Create(util_types_is_async_function)); js_set(js, types, "isBigInt64Array", Ant_Function_Create(util_types_is_bigint64_array)); js_set(js, types, "isBigIntObject", Ant_Function_Create(util_types_is_bigint_object)); js_set(js, types, "isBigUint64Array", Ant_Function_Create(util_types_is_biguint64_array)); js_set(js, types, "isBooleanObject", Ant_Function_Create(util_types_is_boolean_object)); js_set(js, types, "isBoxedPrimitive", Ant_Function_Create(util_types_is_boxed_primitive)); js_set(js, types, "isDataView", Ant_Function_Create(util_types_is_data_view)); js_set(js, types, "isDate", Ant_Function_Create(util_types_is_date)); js_set(js, types, "isFloat16Array", Ant_Function_Create(util_types_is_float16_array)); js_set(js, types, "isFloat32Array", Ant_Function_Create(util_types_is_float32_array)); js_set(js, types, "isFloat64Array", Ant_Function_Create(util_types_is_float64_array)); js_set(js, types, "isGeneratorFunction", Ant_Function_Create(util_types_is_generator_function)); js_set(js, types, "isGeneratorObject", Ant_Function_Create(util_types_is_generator_object)); js_set(js, types, "isInt8Array", Ant_Function_Create(util_types_is_int8_array)); js_set(js, types, "isInt16Array", Ant_Function_Create(util_types_is_int16_array)); js_set(js, types, "isInt32Array", Ant_Function_Create(util_types_is_int32_array)); js_set(js, types, "isMap", Ant_Function_Create(util_types_is_map)); js_set(js, types, "isMapIterator", Ant_Function_Create(util_types_is_map_iterator)); js_set(js, types, "isModuleNamespaceObject", Ant_Function_Create(util_types_is_module_namespace_object)); js_set(js, types, "isNativeError", Ant_Function_Create(util_types_is_native_error)); js_set(js, types, "isNumberObject", Ant_Function_Create(util_types_is_number_object)); js_set(js, types, "isPromise", Ant_Function_Create(util_types_is_promise)); js_set(js, types, "isProxy", Ant_Function_Create(util_types_is_proxy)); js_set(js, types, "isRegExp", Ant_Function_Create(util_types_is_regexp)); js_set(js, types, "isSet", Ant_Function_Create(util_types_is_set)); js_set(js, types, "isSetIterator", Ant_Function_Create(util_types_is_set_iterator)); js_set(js, types, "isSharedArrayBuffer", Ant_Function_Create(util_types_is_shared_array_buffer)); js_set(js, types, "isStringObject", Ant_Function_Create(util_types_is_string_object)); js_set(js, types, "isSymbolObject", Ant_Function_Create(util_types_is_symbol_object)); js_set(js, types, "isTypedArray", Ant_Function_Create(util_types_is_typed_array)); js_set(js, types, "isUint8Array", Ant_Function_Create(util_types_is_uint8_array)); js_set(js, types, "isUint8ClampedArray", Ant_Function_Create(util_types_is_uint8_clamped_array)); js_set(js, types, "isUint16Array", Ant_Function_Create(util_types_is_uint16_array)); js_set(js, types, "isUint32Array", Ant_Function_Create(util_types_is_uint32_array)); js_set(js, types, "isWeakMap", Ant_Function_Create(util_types_is_weak_map)); js_set(js, types, "isWeakSet", Ant_Function_Create(util_types_is_weak_set));
return types;}
static ant_value_t util_get_types_object(ant_t *js) { ant_library_entry_t *types = ant_library_find("util/types", 10); return types ? ant_library_load(js, types) : util_types_library(js);}
static ant_value_t util_debuglog_call(ant_params_t) { return js_mkundef();}
static ant_value_t util_debuglog(ant_params_t) { ant_value_t logger = Ant_Function_Create(util_debuglog_call); js_set(js, logger, "enabled", js_false);
if (nargs >= 2 && is_callable(args[1])) { ant_value_t cb_args[1] = { logger }; ant_value_t result = sv_vm_call(js->vm, js, args[1], js_mkundef(), cb_args, 1, NULL, js_mkundef()); if (is_err(result) || Ant_Exception_Pending(js)) return result; }
return logger;}
static ant_value_t util_strip_vt_control_characters(ant_params_t) { if (nargs < 1) return js_mkstr(js, "", 0);
char cbuf[512]; js_cstr_t cstr = js_to_cstr(js, args[0], cbuf, sizeof(cbuf)); const char *src = cstr.ptr; size_t len = strlen(src);
util_sb_t sb = {0}; for (size_t i = 0; i < len; i++) { unsigned char ch = (unsigned char)src[i]; if (ch != 0x1b) { util_sb_append_c(&sb, (char)ch); continue; }
if (i + 1 < len && src[i + 1] == '[') { i += 2; while (i < len) { unsigned char c = (unsigned char)src[i]; if (c >= '@' && c <= '~') break; i++; } continue; }
if (i + 1 < len && src[i + 1] == ']') { i += 2; while (i < len) { if ((unsigned char)src[i] == 0x07) break; if ((unsigned char)src[i] == 0x1b && i + 1 < len && src[i + 1] == '\\') { i++; break; } i++; } continue; } }
ant_value_t out = js_mkstr(js, sb.buf ? sb.buf : "", sb.len); if (cstr.needs_free) free((void *)cstr.ptr); free(sb.buf); return out;}
static inline bool util_env_is_inline_ws(char ch) { return ch == ' ' || ch == '\t' || ch == '\r';}
static inline bool util_env_is_ident_start(char ch) { return ant_ascii_is_alpha(ch) || ch == '_';}
static inline bool util_env_is_ident_continue(char ch) { return util_env_is_ident_start(ch) || ant_ascii_is_digit(ch);}
static void util_env_skip_inline_ws(const char *src, size_t len, size_t *cursor) { while (*cursor < len && util_env_is_inline_ws(src[*cursor])) (*cursor)++;}
static void util_env_skip_line(const char *src, size_t len, size_t *cursor) { while (*cursor < len && src[*cursor] != '\n') (*cursor)++; if (*cursor < len && src[*cursor] == '\n') (*cursor)++;}
static bool util_env_consume_export(const char *src, size_t len, size_t *cursor) { if (*cursor + 6 > len) return false; if (memcmp(src + *cursor, "export", 6) != 0) return false; if ( *cursor + 6 < len && !util_env_is_inline_ws(src[*cursor + 6]) && src[*cursor + 6] != '\n' ) return false;
*cursor += 6; util_env_skip_inline_ws(src, len, cursor); return true;}
static bool util_env_parse_key( const char *src, size_t len, size_t *cursor, size_t *key_start, size_t *key_end) { if (*cursor >= len || !util_env_is_ident_start(src[*cursor])) return false; *key_start = *cursor; (*cursor)++; while (*cursor < len && util_env_is_ident_continue(src[*cursor])) (*cursor)++; *key_end = *cursor; return true;}
static void util_env_set_entry( ant_t *js, ant_value_t obj, const char *key, size_t key_len, ant_value_t value) { ant_value_t key_str = js_mkstr(js, key, key_len); js_setprop(js, obj, key_str, value);}
static ant_value_t util_env_parse_quoted_value( ant_t *js, const char *src, size_t len, size_t *cursor) { util_sb_t sb = {0}; ant_value_t value = js_mkstr(js, "", 0); char quote;
if (*cursor >= len) return value; quote = src[(*cursor)++];
while (*cursor < len) { char ch = src[(*cursor)++]; if (ch == quote) goto done; if (ch != '\\' || *cursor >= len) { util_sb_append_c(&sb, ch); continue; }
char esc = src[(*cursor)++]; if (quote != '"') { util_sb_append_c(&sb, esc); continue; }
switch (esc) { case 'n': util_sb_append_c(&sb, '\n'); break; case 'r': util_sb_append_c(&sb, '\r'); break; case 't': util_sb_append_c(&sb, '\t'); break; case '\\': util_sb_append_c(&sb, '\\'); break; case '"': util_sb_append_c(&sb, '"'); break; default: util_sb_append_c(&sb, esc); break; } }
done: value = js_mkstr(js, sb.buf ? sb.buf : "", sb.len); free(sb.buf);
while (*cursor < len && src[*cursor] != '\n') { if (src[*cursor] == '#') break; (*cursor)++; }
return value;}
static ant_value_t util_env_parse_unquoted_value( ant_t *js, const char *src, size_t len, size_t *cursor) { size_t value_start = *cursor; size_t value_end = *cursor; bool saw_space = false;
while (*cursor < len && src[*cursor] != '\n' && src[*cursor] != '\r') { if (src[*cursor] == '#') { if (*cursor == value_start || saw_space) goto done; }
saw_space = util_env_is_inline_ws(src[*cursor]); (*cursor)++; value_end = *cursor; }
done: while (value_start < value_end && util_env_is_inline_ws(src[value_start])) { value_start++; } while (value_end > value_start && util_env_is_inline_ws(src[value_end - 1])) { value_end--; }
return js_mkstr(js, src + value_start, value_end - value_start);}
static ant_value_t util_parse_env(ant_params_t) { ant_value_t out = Ant_Object_CreateBare(js); if (nargs < 1) return out;
char cbuf[512]; js_cstr_t cstr = js_to_cstr(js, args[0], cbuf, sizeof(cbuf)); const char *src = cstr.ptr; size_t len = strlen(src); size_t i = 0;
if (len >= 3 && (unsigned char)src[0] == 0xEF && (unsigned char)src[1] == 0xBB && (unsigned char)src[2] == 0xBF) { i = 3; }
while (i < len) { size_t key_start = 0; size_t key_end = 0; ant_value_t value = js_mkstr(js, "", 0);
util_env_skip_inline_ws(src, len, &i); if (i >= len) break; if (src[i] == '\n') { i++; continue; } if (src[i] == '#') goto skip_line;
util_env_consume_export(src, len, &i); if (!util_env_parse_key(src, len, &i, &key_start, &key_end)) goto skip_line;
util_env_skip_inline_ws(src, len, &i); if (i >= len || src[i] != '=') goto skip_line; i++; util_env_skip_inline_ws(src, len, &i);
if (i < len && (src[i] == '"' || src[i] == '\'' || src[i] == '`')) { value = util_env_parse_quoted_value(js, src, len, &i); } else { value = util_env_parse_unquoted_value(js, src, len, &i); }
util_env_set_entry(js, out, src + key_start, key_end - key_start, value);
skip_line: util_env_skip_line(src, len, &i); }
if (cstr.needs_free) free((void *)cstr.ptr); return out;}
static const util_style_entry_t *util_find_style(const char *name) { for (size_t i = 0; i < sizeof(util_styles) / sizeof(util_styles[0]); i++) { if (strcmp(name, util_styles[i].name) == 0) return &util_styles[i]; } return NULL;}
static bool util_style_should_colorize(ant_t *js, ant_value_t options) { ant_value_t stream = js_mkundef(); if (is_object_type(options)) { ant_value_t validate = js_get(js, options, "validateStream"); if (vtype(validate) == kTypeBool && !js_truthy(js, validate)) return true; stream = js_get(js, options, "stream"); }
int forced = io_color_override(); if (forced >= 0) return forced;
if (is_undefined(stream)) { ant_value_t process_obj = js_get(js, js_glob(js), "process"); if (is_object_type(process_obj)) stream = js_get(js, process_obj, "stdout"); }
if (!is_object_type(stream) || !js_truthy(js, js_get(js, stream, "isTTY"))) return false;
ant_value_t get_depth = js_get(js, stream, "getColorDepth"); if (!is_callable(get_depth)) return true;
ant_value_t depth = sv_vm_call(js->vm, js, get_depth, stream, NULL, 0, NULL, js_mkundef()); return vtype(depth) == kTypeNumber && js_getnum(depth) > 2;}
static ant_value_t util_style_text(ant_params_t) { if (nargs < 2) return js_mkstr(js, "", 0);
char text_buf[512]; js_cstr_t text_cstr = js_to_cstr(js, args[1], text_buf, sizeof(text_buf));
const util_style_entry_t *picked[16]; int picked_n = 0;
if (vtype(args[0]) == kTypeString) { const char *name = js_getstr(js, args[0], NULL); const util_style_entry_t *e = name ? util_find_style(name) : NULL; if (e) picked[picked_n++] = e; } else if (js_is_array(args[0])) { ant_offset_t len = js_arr_len(js, args[0]); for (ant_offset_t i = 0; i < len && picked_n < (int)(sizeof(picked) / sizeof(picked[0])); i++) { ant_value_t item = js_arr_get(js, args[0], i); if (vtype(item) != kTypeString) continue; const char *name = js_getstr(js, item, NULL); const util_style_entry_t *e = name ? util_find_style(name) : NULL; if (e) picked[picked_n++] = e; } }
if (picked_n == 0 || !util_style_should_colorize(js, nargs > 2 ? args[2] : js_mkundef())) { ant_value_t out = js_mkstr(js, text_cstr.ptr, strlen(text_cstr.ptr)); if (text_cstr.needs_free) free((void *)text_cstr.ptr); return out; }
util_sb_t sb = {0}; for (int i = 0; i < picked_n; i++) { util_sb_append_n(&sb, picked[i]->open, strlen(picked[i]->open)); } util_sb_append_n(&sb, text_cstr.ptr, strlen(text_cstr.ptr)); for (int i = picked_n - 1; i >= 0; i--) { util_sb_append_n(&sb, picked[i]->close, strlen(picked[i]->close)); }
ant_value_t out = js_mkstr(js, sb.buf ? sb.buf : "", sb.len); if (text_cstr.needs_free) free((void *)text_cstr.ptr); free(sb.buf); return out;}
static ant_value_t util_promisify_callback(ant_params_t) { ant_value_t fn = js_getcurrentfunc(js); ant_value_t ctx = js_get_slot(fn, SLOT_DATA); if (!is_object_type(ctx)) return js_mkundef();
ant_value_t settled = js_get_slot(ctx, SLOT_SETTLED); if (vtype(settled) == kTypeBool && settled == js_true) return js_mkundef(); js_set_slot(ctx, SLOT_SETTLED, js_true);
ant_value_t promise = js_get_slot(ctx, SLOT_DATA); if (!is_object_type(promise)) return js_mkundef();
if (nargs > 0 && !is_null(args[0]) && !is_undefined(args[0])) { js_reject_promise(js, promise, args[0]); return js_mkundef(); }
if (nargs <= 1) { js_resolve_promise(js, promise, js_mkundef()); return js_mkundef(); }
if (nargs == 2) { js_resolve_promise(js, promise, args[1]); return js_mkundef(); }
ant_value_t arr = js_mkarr(js); for (int i = 1; i < nargs; i++) js_arr_push(js, arr, args[i]); js_resolve_promise(js, promise, arr); return js_mkundef();}
static ant_value_t util_promisified_call(ant_params_t) { ant_value_t fn = js_getcurrentfunc(js); ant_value_t original = js_get_slot(fn, SLOT_DATA); if (!is_callable(original)) return js_mkerr(js, "promisified target is not callable");
ant_value_t promise = js_mkpromise(js); ant_value_t ctx = Ant_Object_CreateBare(js); js_set_slot(ctx, SLOT_DATA, promise); js_set_slot(ctx, SLOT_SETTLED, js_false); ant_value_t cb = js_heavy_mkfun(js, util_promisify_callback, ctx);
ant_value_t *call_args = (ant_value_t *)malloc((size_t)(nargs + 1) * sizeof(ant_value_t)); if (!call_args) { js_reject_promise(js, promise, js_mkerr(js, "Out of memory")); return promise; } for (int i = 0; i < nargs; i++) call_args[i] = args[i]; call_args[nargs] = cb;
GC_ROOT_SAVE(root_mark, js); GC_ROOT_PIN(js, cb); GC_ROOT_PIN(js, ctx); ant_value_t this_arg = js_getthis(js); ant_value_t call_result = sv_vm_call( js->vm, js, original, this_arg, call_args, nargs + 1, NULL, js_mkundef() ); GC_ROOT_RESTORE(js, root_mark); free(call_args);
ant_value_t settled = js_get_slot(ctx, SLOT_SETTLED); bool is_settled = (vtype(settled) == kTypeBool && settled == js_true);
if (is_err(call_result) || Ant_Exception_Pending(js)) { ant_value_t ex = js_take_thrown(js, call_result); if (!is_settled) { js_set_slot(ctx, SLOT_SETTLED, js_true); js_reject_promise(js, promise, ex); } }
return promise;}
static ant_value_t util_callbackify_success(ant_params_t) { ant_value_t state = js_get_slot(js_getcurrentfunc(js), SLOT_DATA); if (!is_object_type(state)) return js_mkundef();
ant_value_t callback = js_get_slot(state, SLOT_DATA); if (!is_callable(callback)) return js_mkundef();
ant_value_t cb_args[2] = { js_mknull(), nargs > 0 ? args[0] : js_mkundef() }; return sv_vm_call(js->vm, js, callback, js_mkundef(), cb_args, 2, NULL, js_mkundef());}
static ant_value_t util_callbackify_error(ant_params_t) { ant_value_t state = js_get_slot(js_getcurrentfunc(js), SLOT_DATA); if (!is_object_type(state)) return js_mkundef();
ant_value_t callback = js_get_slot(state, SLOT_DATA); if (!is_callable(callback)) return js_mkundef();
ant_value_t err = nargs > 0 ? args[0] : Ant_Error_Create(js, JS_ERR_TYPE, "Promise was rejected"); ant_value_t cb_args[1] = { err }; return sv_vm_call(js->vm, js, callback, js_mkundef(), cb_args, 1, NULL, js_mkundef());}
static ant_value_t util_callbackified_call(ant_params_t) { ant_value_t fn = js_getcurrentfunc(js); ant_value_t original = js_get_slot(fn, SLOT_DATA); if (!is_callable(original)) return js_mkerr(js, "callbackified target is not callable"); if (nargs < 1 || !is_callable(args[nargs - 1])) return js_mkerr_typed(js, JS_ERR_TYPE, "callbackified function requires a callback");
ant_value_t callback = args[nargs - 1]; int call_nargs = nargs - 1; ant_value_t *call_args = NULL;
if (call_nargs > 0) { call_args = (ant_value_t *)malloc((size_t)call_nargs * sizeof(ant_value_t)); if (!call_args) return js_mkerr(js, "Out of memory"); for (int i = 0; i < call_nargs; i++) call_args[i] = args[i]; }
ant_value_t result = sv_vm_call(js->vm, js, original, js_getthis(js), call_args, call_nargs, NULL, js_mkundef()); free(call_args);
if (is_err(result) || Ant_Exception_Pending(js)) { GC_ROOT_SAVE(root_mark, js); ant_value_t ex = js_take_thrown(js, result);
GC_ROOT_PIN(js, ex); ant_value_t cb_args[1] = { ex }; ant_value_t cb_result = sv_vm_call(js->vm, js, callback, js_mkundef(), cb_args, 1, NULL, js_mkundef());
GC_ROOT_RESTORE(js, root_mark); return is_err(cb_result) ? cb_result : js_mkundef(); }
if (vtype(result) != kTypePromise) { ant_value_t cb_args[2] = { js_mknull(), result }; ant_value_t cb_result = sv_vm_call(js->vm, js, callback, js_mkundef(), cb_args, 2, NULL, js_mkundef()); return is_err(cb_result) ? cb_result : js_mkundef(); }
ant_value_t state = Ant_Object_CreateBare(js); js_set_slot(state, SLOT_DATA, callback); ant_value_t success = js_heavy_mkfun(js, util_callbackify_success, state); ant_value_t error = js_heavy_mkfun(js, util_callbackify_error, state); ant_value_t then_result = js_promise_then(js, result, success, error); return is_err(then_result) ? then_result : js_mkundef();}
static ant_value_t util_deprecated_call(ant_params_t) { ant_value_t fn = js_getcurrentfunc(js); ant_value_t ctx = js_get_slot(fn, SLOT_DATA); if (!is_object_type(ctx)) return js_mkundef();
ant_value_t warned = js_get_slot(ctx, SLOT_SETTLED); if (!(vtype(warned) == kTypeBool && warned == js_true)) { js_set_slot(ctx, SLOT_SETTLED, js_true); ant_value_t msg_val = js_get(js, ctx, "msg"); const char *msg = js_getstr(js, msg_val, NULL); if (msg) fprintf(stderr, "DeprecationWarning: %s\n", msg); }
ant_value_t original = js_get_slot(ctx, SLOT_DATA); ant_value_t this_arg = js_getthis(js); return sv_vm_call(js->vm, js, original, this_arg, args, nargs, NULL, js_mkundef());}
static ant_value_t util_deprecate(ant_params_t) { if (nargs < 1 || !is_callable(args[0])) { return js_mkerr(js, "deprecate(fn, msg) requires a function"); }
ant_value_t ctx = Ant_Object_CreateBare(js); js_set_slot(ctx, SLOT_DATA, args[0]); js_set_slot(ctx, SLOT_SETTLED, js_false); if (nargs >= 2) js_set(js, ctx, "msg", args[1]);
return js_heavy_mkfun(js, util_deprecated_call, ctx);}
static ant_value_t util_promisify(ant_params_t) { if (nargs < 1 || !is_callable(args[0])) return js_mkerr(js, "promisify(fn) requires a function");
ant_value_t custom = js_get_symbol(js, args[0], "nodejs.util.promisify.custom"); if (is_err(custom)) return custom; if (is_callable(custom)) return custom;
return js_heavy_mkfun(js, util_promisified_call, args[0]);}
static ant_value_t util_callbackify(ant_params_t) { if (nargs < 1 || !is_callable(args[0])) return js_mkerr(js, "callbackify(fn) requires a function"); return js_heavy_mkfun(js, util_callbackified_call, args[0]);}
static ant_value_t util_aborted_listener(ant_params_t) { ant_value_t promise = js_get_slot(js_getcurrentfunc(js), SLOT_DATA); if (vtype(promise) == kTypePromise) js_resolve_promise(js, promise, js_mkundef()); return js_mkundef();}
static ant_value_t util_aborted(ant_params_t) { ant_value_t promise = js_mkpromise(js); if (nargs < 1 || !abort_signal_is_signal(args[0])) { js_reject_promise(js, promise, Ant_Error_Create(js, JS_ERR_TYPE, "aborted(signal, resource) requires an AbortSignal")); return promise; }
if (abort_signal_is_aborted(args[0])) { js_resolve_promise(js, promise, js_mkundef()); return promise; }
abort_signal_add_listener(js, args[0], js_heavy_mkfun(js, util_aborted_listener, promise)); return promise;}
static ant_value_t util_inherits(ant_params_t) { if (nargs < 2 || !is_callable(args[0]) || !is_callable(args[1])) { return js_mkerr(js, "inherits(ctor, superCtor) requires constructor functions"); }
ant_value_t ctor = args[0]; ant_value_t super_ctor = args[1]; ant_value_t ctor_proto = js_get(js, ctor, "prototype"); ant_value_t super_proto = js_get(js, super_ctor, "prototype");
if (!is_object_type(ctor_proto) || !is_object_type(super_proto)) { return js_mkerr(js, "inherits(ctor, superCtor) requires prototype objects"); }
js_set(js, ctor, "super_", super_ctor); js_set_proto_init(ctor_proto, super_proto); return js_mkundef();}
static ant_value_t util_is_deep_strict_equal(ant_params_t) { if (nargs < 2) return js_bool(true); return js_bool(js_deep_equal(js, args[0], args[1], true));}
ant_value_t util_library(ant_t *js) { ant_value_t lib = Ant_Object_CreateBare(js); ant_value_t types = util_get_types_object(js); ant_value_t promisify = Ant_Function_CreateWithData(js, util_promisify, "promisify", 1, js_mkundef()); js_set(js, promisify, "custom", js_mksym_for(js, "nodejs.util.promisify.custom"));
js_set(js, lib, "types", types); js_set(js, lib, "promisify", promisify); js_set(js, lib, "format", Ant_Function_Create(util_format)); js_set(js, lib, "inspect", Ant_Function_CreateWithArity(util_inspect, 2)); js_set(js, lib, "aborted", Ant_Function_Create(util_aborted)); js_set(js, lib, "debuglog", Ant_Function_CreateWithArity(util_debuglog, 2)); js_set(js, lib, "inherits", Ant_Function_CreateWithArity(util_inherits, 2)); js_set(js, lib, "parseEnv", Ant_Function_CreateWithArity(util_parse_env, 1)); js_set(js, lib, "deprecate", Ant_Function_CreateWithArity(util_deprecate, 3)); js_set(js, lib, "parseArgs", Ant_Function_Create(util_parse_args)); js_set(js, lib, "styleText", Ant_Function_CreateWithArity(util_style_text, 3)); js_set(js, lib, "callbackify", Ant_Function_CreateWithArity(util_callbackify, 1)); js_set(js, lib, "formatWithOptions", Ant_Function_CreateWithArity(util_format_with_options, 1)); js_set(js, lib, "isDeepStrictEqual", Ant_Function_CreateWithArity(util_is_deep_strict_equal, 3)); js_set(js, lib, "isArray", Ant_Function_CreateWithArity(util_is_array, 1)); js_set(js, lib, "stripVTControlCharacters", Ant_Function_CreateWithArity(util_strip_vt_control_characters, 1)); js_set(js, lib, "TextDecoder", js_get(js, js->global, "TextDecoder")); js_set(js, lib, "TextEncoder", js_get(js, js->global, "TextEncoder")); js_set_tostringtag(js, lib, js_mkstr(js, "util", 4)); return lib;}