Something went wrong. Try again.
javascript for 🐜's, a tiny runtime with big ambitions antjs.org
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223#include "errors.h"#include "utf8.h"#include "internal.h"#include "silver/call.h"#include "modules/buffer.h"#include "modules/date.h"#include "modules/napi.h"#include "napi_internal.h"
#if defined(__has_include)#if __has_include(<uchar.h>)#include <uchar.h>#elsetypedef uint16_t char16_t;#endif#elsetypedef uint16_t char16_t;#endif
void ant_napi_link_values(void) {}
static bool napi_get_typedarray_data( ant_t *js, napi_value value, TypedArrayData **out) { TypedArrayData *ta = buffer_get_typedarray_data((ant_value_t)value); if (!Ant_Buffer_ViewIsLive(ta)) return false; *out = ta; return true;}
static const TypedArrayType napi_typedarray_kinds[] = { [napi_int8_array] = TYPED_ARRAY_INT8, [napi_uint8_array] = TYPED_ARRAY_UINT8, [napi_uint8_clamped_array] = TYPED_ARRAY_UINT8_CLAMPED, [napi_int16_array] = TYPED_ARRAY_INT16, [napi_uint16_array] = TYPED_ARRAY_UINT16, [napi_int32_array] = TYPED_ARRAY_INT32, [napi_uint32_array] = TYPED_ARRAY_UINT32, [napi_float32_array] = TYPED_ARRAY_FLOAT32, [napi_float64_array] = TYPED_ARRAY_FLOAT64, [napi_bigint64_array] = TYPED_ARRAY_BIGINT64, [napi_biguint64_array] = TYPED_ARRAY_BIGUINT64,};
static constexpr unsigned NAPI_TYPEDARRAY_KIND_COUNT = sizeof(napi_typedarray_kinds) / sizeof(napi_typedarray_kinds[0]);
static bool napi_to_ant_typedarray_type(napi_typedarray_type in, TypedArrayType *out) { if ((unsigned)in >= NAPI_TYPEDARRAY_KIND_COUNT) return false; *out = napi_typedarray_kinds[in]; return true;}
static napi_typedarray_type napi_from_ant_typedarray_type(TypedArrayType in) { for (unsigned i = 0; i < NAPI_TYPEDARRAY_KIND_COUNT; i++) if (napi_typedarray_kinds[i] == in) return (napi_typedarray_type)i; return napi_uint8_array;}
static ant_value_t napi_make_string(ant_t *js, const char *s, size_t len) { if (!s) return js_mkstr(js, "", 0); if (len == NAPI_AUTO_LENGTH) len = strlen(s); return js_mkstr(js, s, len);}
static bool napi_checked_add_size(size_t a, size_t b, size_t *out) { if (a > SIZE_MAX - b) return false; *out = a + b; return true;}
static bool napi_checked_mul_size(size_t a, size_t b, size_t *out) { if (a != 0 && b > SIZE_MAX / a) return false; *out = a * b; return true;}
static bool napi_make_bigint_limbs( ant_t *js, const uint32_t *limbs, size_t count, bool negative, ant_value_t *out) { uint32_t zero = 0; if (!out) return false;
if (!limbs || count == 0) { limbs = &zero; count = 1; }
while (count > 1 && limbs[count - 1] == 0) count--; if (count == 1 && limbs[0] == 0) negative = false; if (count > UINT32_MAX) return false;
size_t limbs_bytes = 0; if (!napi_checked_mul_size(count, sizeof(uint32_t), &limbs_bytes)) return false;
size_t payload_size = 0; if (!napi_checked_add_size(offsetof(napi_bigint_payload_t, limbs), limbs_bytes, &payload_size)) { return false; }
napi_bigint_payload_t *payload = (napi_bigint_payload_t *)js_type_alloc( js, ANT_ALLOC_BIGINT, payload_size, _Alignof(napi_bigint_payload_t) );
if (!payload) return false; payload->sign = negative ? 1 : 0; payload->pad[0] = 0; payload->pad[1] = 0; payload->pad[2] = 0; payload->limb_count = (uint32_t)count; memcpy(payload->limbs, limbs, limbs_bytes); *out = mkref(kTypeBigInt, payload);
return true;}
static const napi_bigint_payload_t *napi_bigint_payload(napi_value value) { return (const napi_bigint_payload_t *)vptr((ant_value_t)value);}
static const uint32_t *napi_bigint_limbs(napi_value value, size_t *count) { const napi_bigint_payload_t *payload = napi_bigint_payload(value); if (!payload) { if (count) *count = 0; return NULL; }
size_t limb_count = payload->limb_count; if (limb_count == 0) limb_count = 1;
while (limb_count > 1 && payload->limbs[limb_count - 1] == 0) limb_count--; if (count) *count = limb_count;
return payload->limbs;}
static bool napi_bigint_is_negative(napi_value value) { const napi_bigint_payload_t *payload = napi_bigint_payload(value); return payload && payload->sign == 1;}
static bool napi_bigint_limbs_is_zero(const uint32_t *limbs, size_t count) { return count <= 1 && (!limbs || limbs[0] == 0);}
static uint64_t napi_bigint_low_u64(const uint32_t *limbs, size_t count) { uint64_t out = 0; if (count > 0 && limbs) out |= (uint64_t)limbs[0]; if (count > 1 && limbs) out |= ((uint64_t)limbs[1] << 32); return out;}
static napi_status napi_create_date_common(napi_env env, double time, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
ant_value_t date = js_mkdate(nenv->js, date_timeclip(time)); if (is_err(date)) return napi_check_pending_from_result(env, date); *result = NAPI_RETURN(nenv, date); return napi_set_last(env, napi_ok, NULL);}
static napi_status napi_make_error_object( napi_env env, js_err_type_t err_type, napi_value msg, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) { return napi_set_last(env, napi_invalid_arg, "invalid argument"); }
ant_t *js = nenv->js; ant_value_t message = (ant_value_t)msg; if (vtype(message) != kTypeString) { message = coerce_to_str(js, message); if (is_err(message)) return napi_check_pending_from_result(env, message); }
const char *name = js_err_type_name(err_type); ant_value_t err = Ant_Object_CreateBare(js); js_set(js, err, "name", js_mkstr(js, name, strlen(name))); js_set(js, err, "message", message);
ant_value_t proto = js->builtins.error_protos[err_type]; if (is_object_type(proto)) js_set_proto_init(err, proto);
*result = NAPI_RETURN(nenv, err); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_undefined(napi_env env, napi_value *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = (napi_value)js_mkundef(); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_null(napi_env env, napi_value *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = (napi_value)js_mknull(); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_global(napi_env env, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = NAPI_RETURN(nenv, js_glob(nenv->js)); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_boolean(napi_env env, bool value, napi_value *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = (napi_value)js_bool(value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_object(napi_env env, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = NAPI_RETURN(nenv, Ant_Object_CreateBare(nenv->js)); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_array(napi_env env, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = NAPI_RETURN(nenv, js_mkarr(nenv->js)); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_array_with_length( napi_env env, size_t length, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); ant_value_t arr = js_mkarr(nenv->js); ant_value_t r = js_setprop( nenv->js, arr, js_mkstr(nenv->js, "length", 6), js_mknum((double)length) ); if (is_err(r) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, r); *result = NAPI_RETURN(nenv, arr); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_double(napi_env env, double value, napi_value *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = (napi_value)js_mknum(value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_int32(napi_env env, int32_t value, napi_value *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = (napi_value)js_mknum((double)value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_uint32(napi_env env, uint32_t value, napi_value *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = (napi_value)js_mknum((double)value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_int64(napi_env env, int64_t value, napi_value *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = (napi_value)js_mknum((double)value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_string_latin1( napi_env env, const char *str, size_t length, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result || !str) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = NAPI_RETURN(nenv, napi_make_string(nenv->js, str, length)); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_string_utf8( napi_env env, const char *str, size_t length, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result || !str) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = NAPI_RETURN(nenv, napi_make_string(nenv->js, str, length)); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_date( napi_env env, double time, napi_value *result) { return napi_create_date_common(env, time, result);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_bigint_int64( napi_env env, int64_t value, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
uint64_t magnitude = value < 0 ? (uint64_t)(-(value + 1)) + 1 : (uint64_t)value;
uint32_t limbs[2] = { (uint32_t)(magnitude & 0xffffffffu), (uint32_t)(magnitude >> 32) };
size_t count = limbs[1] == 0 ? 1 : 2; ant_value_t out = js_mkundef();
if (!napi_make_bigint_limbs(nenv->js, limbs, count, value < 0, &out)) { return napi_set_last(env, napi_generic_failure, "out of memory"); }
*result = NAPI_RETURN(nenv, out); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_bigint_uint64( napi_env env, uint64_t value, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
uint32_t limbs[2] = { (uint32_t)(value & 0xffffffffu), (uint32_t)(value >> 32) }; size_t count = limbs[1] == 0 ? 1 : 2;
ant_value_t out = js_mkundef(); if (!napi_make_bigint_limbs(nenv->js, limbs, count, false, &out)) { return napi_set_last(env, napi_generic_failure, "out of memory"); }
*result = NAPI_RETURN(nenv, out); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_bigint_words( napi_env env, int sign_bit, size_t word_count, const uint64_t *words, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result || (word_count > 0 && !words)) { return napi_set_last(env, napi_invalid_arg, "invalid argument"); }
size_t limb_count = 1; if (word_count > 0 && !napi_checked_mul_size(word_count, 2, &limb_count)) { return napi_set_last(env, napi_invalid_arg, "word count overflow"); } uint32_t *limbs = (uint32_t *)calloc(limb_count, sizeof(uint32_t)); if (!limbs) return napi_set_last(env, napi_generic_failure, "out of memory");
if (word_count == 0) limbs[0] = 0; else for (size_t i = 0; i < word_count; i++) { limbs[i * 2] = (uint32_t)(words[i] & 0xffffffffu); limbs[(i * 2) + 1] = (uint32_t)(words[i] >> 32); }
ant_value_t out = js_mkundef(); bool ok = napi_make_bigint_limbs(nenv->js, limbs, limb_count, sign_bit != 0, &out); free(limbs); if (!ok) return napi_set_last(env, napi_generic_failure, "out of memory");
*result = NAPI_RETURN(nenv, out); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_symbol( napi_env env, napi_value description, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
const char *desc = NULL; if (vtype((ant_value_t)description) == kTypeString) { desc = js_getstr(nenv->js, (ant_value_t)description, NULL); } else if (!is_undefined((ant_value_t)description) && !is_null((ant_value_t)description)) { ant_value_t s = coerce_to_str(nenv->js, (ant_value_t)description); if (is_err(s) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, s); desc = js_getstr(nenv->js, s, NULL); }
*result = NAPI_RETURN(nenv, js_mksym(nenv->js, desc)); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_error( napi_env env, napi_value code, napi_value msg, napi_value *result) { return napi_make_error_object(env, JS_ERR_GENERIC, msg, result);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_type_error( napi_env env, napi_value code, napi_value msg, napi_value *result) { return napi_make_error_object(env, JS_ERR_TYPE, msg, result);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_range_error( napi_env env, napi_value code, napi_value msg, napi_value *result) { return napi_make_error_object(env, JS_ERR_RANGE, msg, result);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_promise( napi_env env, napi_deferred *deferred, napi_value *promise) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !deferred || !promise) { return napi_set_last(env, napi_invalid_arg, "invalid argument"); }
struct napi_deferred__ *def = (struct napi_deferred__ *)calloc(1, sizeof(*def)); if (!def) return napi_set_last(env, napi_generic_failure, "out of memory");
ant_value_t p = js_mkpromise(nenv->js); def->env = nenv; def->promise_val = p; def->settled = false;
def->prev = NULL; def->next = nenv->deferreds; if (nenv->deferreds) nenv->deferreds->prev = def; nenv->deferreds = def;
*deferred = (napi_deferred)def; *promise = (napi_value)p; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_resolve_deferred( napi_env env, napi_deferred deferred, napi_value resolution) { struct napi_deferred__ *def = (struct napi_deferred__ *)deferred; ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !def || def->settled) { return napi_set_last(env, napi_invalid_arg, "invalid deferred"); }
ant_value_t promise = def->promise_val; js_resolve_promise(nenv->js, promise, (ant_value_t)resolution); def->settled = true; def->promise_val = js_mkundef();
if (def->prev) def->prev->next = def->next; else if (nenv->deferreds == def) nenv->deferreds = def->next; if (def->next) def->next->prev = def->prev;
return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_reject_deferred( napi_env env, napi_deferred deferred, napi_value rejection) { struct napi_deferred__ *def = (struct napi_deferred__ *)deferred; ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !def || def->settled) { return napi_set_last(env, napi_invalid_arg, "invalid deferred"); }
ant_value_t promise = def->promise_val; js_reject_promise(nenv->js, promise, (ant_value_t)rejection); def->settled = true; def->promise_val = js_mkundef();
if (def->prev) def->prev->next = def->next; else if (nenv->deferreds == def) nenv->deferreds = def->next; if (def->next) def->next->prev = def->prev;
return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_buffer( napi_env env, size_t length, void **data, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
ArrayBufferData *buf = create_array_buffer_data(nenv->js, length); if (!buf) return napi_set_last(env, napi_generic_failure, "allocation failed");
ant_value_t value = create_typed_array(nenv->js, TYPED_ARRAY_UINT8, buf, 0, length, nenv->js->builtins.buffer_proto); if (is_err(value)) return napi_check_pending_from_result(env, value);
if (data) *data = buf->data; *result = NAPI_RETURN(nenv, value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_buffer_copy( napi_env env, size_t length, const void *data, void **result_data, napi_value *result) { void *buf_ptr = NULL; napi_status st = napi_create_buffer(env, length, &buf_ptr, result); if (st != napi_ok) return st;
if (length > 0 && data && buf_ptr) memcpy(buf_ptr, data, length); if (result_data) *result_data = buf_ptr; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_external_buffer( napi_env env, size_t length, void *data, node_api_basic_finalize finalize_cb, void *finalize_hint, napi_value *result) { (void)finalize_cb; (void)finalize_hint; return napi_create_buffer_copy(env, length, data, NULL, result);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_arraybuffer( napi_env env, size_t byte_length, void **data, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
ant_value_t ab_obj = create_arraybuffer_copy(nenv->js, NULL, byte_length); if (is_err(ab_obj)) return napi_set_last(env, napi_generic_failure, "allocation failed");
if (data) *data = buffer_get_arraybuffer_data(ab_obj)->data; *result = NAPI_RETURN(nenv, ab_obj); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_external_arraybuffer( napi_env env, void *external_data, size_t byte_length, node_api_basic_finalize finalize_cb, void *finalize_hint, napi_value *result) { (void)finalize_cb; (void)finalize_hint; void *out = NULL; napi_status st = napi_create_arraybuffer(env, byte_length, &out, result); if (st != napi_ok) return st; if (external_data && out && byte_length > 0) memcpy(out, external_data, byte_length); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_set_instance_data( napi_env env, void *data, node_api_basic_finalize finalize_cb, void *finalize_hint) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv) return napi_set_last(env, napi_invalid_arg, "invalid env");
nenv->instance_data = data; nenv->instance_data_finalize_cb = finalize_cb; nenv->instance_data_finalize_hint = finalize_hint; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_instance_data( napi_env env, void **data) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !data) return napi_set_last(env, napi_invalid_arg, "invalid argument");
*data = nenv->instance_data; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_create_typedarray( napi_env env, napi_typedarray_type type, size_t length, napi_value arraybuffer, size_t byte_offset, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result || !is_object_type((ant_value_t)arraybuffer)) { return napi_set_last(env, napi_invalid_arg, "invalid argument"); }
ArrayBufferData *ab = buffer_get_arraybuffer_data((ant_value_t)arraybuffer); if (!ab || ab->is_detached) return napi_set_last(env, napi_arraybuffer_expected, "invalid arraybuffer");
TypedArrayType ta_type; if (!napi_to_ant_typedarray_type(type, &ta_type)) { return napi_set_last(env, napi_invalid_arg, "invalid typedarray type"); }
size_t element_size = 1; switch (ta_type) { case TYPED_ARRAY_INT16: case TYPED_ARRAY_UINT16: element_size = 2; break; case TYPED_ARRAY_INT32: case TYPED_ARRAY_UINT32: case TYPED_ARRAY_FLOAT32: element_size = 4; break; case TYPED_ARRAY_FLOAT64: case TYPED_ARRAY_BIGINT64: case TYPED_ARRAY_BIGUINT64: element_size = 8; break; default: break; }
size_t byte_len = length * element_size; if (byte_offset + byte_len > ab->length) { return napi_set_last(env, napi_invalid_arg, "typedarray out of bounds"); }
ant_value_t out = create_typed_array_with_buffer( nenv->js, ta_type, ab, byte_offset, length, nenv->js->builtins.typedarray_protos[ta_type], (ant_value_t)arraybuffer );
if (is_err(out)) return napi_check_pending_from_result(env, out); *result = NAPI_RETURN(nenv, out); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_double( napi_env env, napi_value value, double *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (vtype((ant_value_t)value) != kTypeNumber) return napi_set_last(env, napi_number_expected, "number expected"); *result = js_getnum((ant_value_t)value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_int32( napi_env env, napi_value value, int32_t *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (vtype((ant_value_t)value) != kTypeNumber) return napi_set_last(env, napi_number_expected, "number expected"); *result = (int32_t)js_getnum((ant_value_t)value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_uint32( napi_env env, napi_value value, uint32_t *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (vtype((ant_value_t)value) != kTypeNumber) return napi_set_last(env, napi_number_expected, "number expected"); *result = (uint32_t)js_getnum((ant_value_t)value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_int64( napi_env env, napi_value value, int64_t *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (vtype((ant_value_t)value) != kTypeNumber) return napi_set_last(env, napi_number_expected, "number expected"); *result = (int64_t)js_getnum((ant_value_t)value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_bool( napi_env env, napi_value value, bool *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (vtype((ant_value_t)value) != kTypeBool) return napi_set_last(env, napi_boolean_expected, "boolean expected"); *result = ((ant_value_t)value == js_true); return napi_set_last(env, napi_ok, NULL);}
static napi_status napi_get_string_common( napi_env env, napi_value value, char *buf, size_t bufsize, size_t *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js) return napi_set_last(env, napi_invalid_arg, "invalid env"); if (vtype((ant_value_t)value) != kTypeString) return napi_set_last(env, napi_string_expected, "string expected");
size_t len = 0; const char *str = js_getstr(nenv->js, (ant_value_t)value, &len); if (!str) return napi_set_last(env, napi_string_expected, "string expected");
if (result) *result = len; if (!buf || bufsize == 0) return napi_set_last(env, napi_ok, NULL);
size_t n = (len < (bufsize - 1)) ? len : (bufsize - 1); memcpy(buf, str, n); buf[n] = '\0'; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_string_utf8( napi_env env, napi_value value, char *buf, size_t bufsize, size_t *result) { return napi_get_string_common(env, value, buf, bufsize, result);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_string_latin1( napi_env env, napi_value value, char *buf, size_t bufsize, size_t *result) { return napi_get_string_common(env, value, buf, bufsize, result);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_string_utf16( napi_env env, napi_value value, char16_t *buf, size_t bufsize, size_t *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js) return napi_set_last(env, napi_invalid_arg, "invalid env"); if (vtype((ant_value_t)value) != kTypeString) return napi_set_last(env, napi_string_expected, "string expected");
size_t byte_len = 0; const char *str = js_getstr(nenv->js, (ant_value_t)value, &byte_len); if (!str) return napi_set_last(env, napi_string_expected, "string expected");
size_t utf16_len = (size_t)str_utf16_len(nenv->js, (ant_value_t)value); if (result) *result = utf16_len; if (!buf || bufsize == 0) return napi_set_last(env, napi_ok, NULL);
size_t n = utf16_len < (bufsize - 1) ? utf16_len : (bufsize - 1); for (size_t i = 0; i < n; i++) buf[i] = (char16_t)utf16_code_unit_at(str, byte_len, i); buf[n] = 0; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_date_value( napi_env env, napi_value value, double *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (!is_date_instance((ant_value_t)value)) return napi_set_last(env, napi_date_expected, "date expected");
ant_value_t time_val = js_get_slot((ant_value_t)value, SLOT_DATA); *result = vtype(time_val) == kTypeNumber ? js_getnum(time_val) : JS_NAN; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_bigint_int64( napi_env env, napi_value value, int64_t *result, bool *lossless) { if (!env || !result || !lossless) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (vtype((ant_value_t)value) != kTypeBigInt) return napi_set_last(env, napi_bigint_expected, "bigint expected");
size_t limb_count = 0; const uint32_t *limbs = napi_bigint_limbs(value, &limb_count); uint64_t magnitude = napi_bigint_low_u64(limbs, limb_count); bool negative = napi_bigint_is_negative(value) && !napi_bigint_limbs_is_zero(limbs, limb_count); uint64_t bits = negative ? (uint64_t)(~magnitude + 1) : magnitude;
*result = (int64_t)bits; *lossless = limb_count <= 2 && ((!negative && magnitude <= (uint64_t)INT64_MAX) || (negative && magnitude <= (UINT64_C(1) << 63))); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_bigint_uint64( napi_env env, napi_value value, uint64_t *result, bool *lossless) { if (!env || !result || !lossless) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (vtype((ant_value_t)value) != kTypeBigInt) return napi_set_last(env, napi_bigint_expected, "bigint expected");
size_t limb_count = 0; const uint32_t *limbs = napi_bigint_limbs(value, &limb_count); uint64_t magnitude = napi_bigint_low_u64(limbs, limb_count); bool negative = napi_bigint_is_negative(value) && !napi_bigint_limbs_is_zero(limbs, limb_count);
*result = negative ? (uint64_t)(~magnitude + 1) : magnitude; *lossless = !negative && limb_count <= 2; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_value_bigint_words( napi_env env, napi_value value, int *sign_bit, size_t *word_count, uint64_t *words) { if (!env || !word_count) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (vtype((ant_value_t)value) != kTypeBigInt) return napi_set_last(env, napi_bigint_expected, "bigint expected");
size_t limb_count = 0; const uint32_t *limbs = napi_bigint_limbs(value, &limb_count); size_t actual_words = limb_count == 0 ? 0 : (limb_count + 1) / 2; size_t capacity = words ? *word_count : 0;
if (sign_bit) { bool negative = napi_bigint_is_negative(value) && !napi_bigint_limbs_is_zero(limbs, limb_count); *sign_bit = negative ? 1 : 0; }
if (words) { size_t n = capacity < actual_words ? capacity : actual_words; for (size_t i = 0; i < n; i++) { uint64_t lo = i * 2 < limb_count ? (uint64_t)limbs[i * 2] : 0; uint64_t hi = (i * 2 + 1) < limb_count ? (uint64_t)limbs[i * 2 + 1] : 0; words[i] = lo | (hi << 32); }}
*word_count = actual_words; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_array_length( napi_env env, napi_value value, uint32_t *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
ant_value_t v = (ant_value_t)value; if (!js_is_array(v)) return napi_set_last(env, napi_array_expected, "array expected"); *result = (uint32_t)js_arr_len(nenv->js, v); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_buffer_info( napi_env env, napi_value value, void **data, size_t *length) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js) return napi_set_last(env, napi_invalid_arg, "invalid env");
TypedArrayData *ta = NULL; if (!napi_get_typedarray_data(nenv->js, value, &ta)) { return napi_set_last(env, napi_invalid_arg, "not a buffer"); }
uint8_t *bytes; size_t size; Ant_Buffer_GetViewBytes(ta, &bytes, &size); if (data) *data = bytes; if (length) *length = size; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_arraybuffer_info( napi_env env, napi_value arraybuffer, void **data, size_t *byte_length) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js) return napi_set_last(env, napi_invalid_arg, "invalid env"); if (!is_object_type((ant_value_t)arraybuffer)) return napi_set_last(env, napi_arraybuffer_expected, "arraybuffer expected");
ArrayBufferData *ab = buffer_get_arraybuffer_data((ant_value_t)arraybuffer); if (!ab || ab->is_detached) return napi_set_last(env, napi_arraybuffer_expected, "arraybuffer expected");
if (data) *data = ab->data; if (byte_length) *byte_length = ab->length; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_typedarray_info( napi_env env, napi_value typedarray, napi_typedarray_type *type, size_t *length, void **data, napi_value *arraybuffer, size_t *byte_offset) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js) return napi_set_last(env, napi_invalid_arg, "invalid env");
TypedArrayData *ta = NULL; if (!napi_get_typedarray_data(nenv->js, typedarray, &ta)) { return napi_set_last(env, napi_invalid_arg, "typedarray expected"); }
uint8_t *bytes; size_t size; bool live = Ant_Buffer_GetViewBytes(ta, &bytes, &size); if (type) *type = napi_from_ant_typedarray_type(ta->type); if (length) *length = live ? ta->length : 0; if (data) *data = bytes; if (arraybuffer) { ant_value_t buffer = js_get(nenv->js, (ant_value_t)typedarray, "buffer"); if (is_err(buffer) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, buffer); *arraybuffer = NAPI_RETURN(nenv, buffer); } if (byte_offset) *byte_offset = ta->byte_offset; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_get_prototype( napi_env env, napi_value object, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); ant_value_t proto = js_get_proto(nenv->js, (ant_value_t)object); if (is_err(proto) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, proto); *result = NAPI_RETURN(nenv, proto); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_typeof( napi_env env, napi_value value, napi_valuetype *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
ant_value_t v = (ant_value_t)value; uint8_t t = vtype(v);
if (ant_napi_is_external(nenv->js, value)) { *result = napi_external; return napi_set_last(env, napi_ok, NULL); }
switch (t) { case kTypeUndefined: *result = napi_undefined; break; case kTypeNull: *result = napi_null; break; case kTypeBool: *result = napi_boolean; break; case kTypeNumber: *result = napi_number; break; case kTypeString: *result = napi_string; break; case kTypeSymbol: *result = napi_symbol; break; case kTypeFunction: case kTypeBuiltin: *result = napi_function; break; case kTypeBigInt: *result = napi_bigint; break; default: *result = napi_object; break; }
return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_is_array( napi_env env, napi_value value, bool *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); ant_napi_env_t *nenv = (ant_napi_env_t *)env;
if (!nenv || !nenv->js) return napi_set_last(env, napi_invalid_arg, "invalid env"); ant_value_t r = js_is_array_value_checked(nenv->js, (ant_value_t)value, result);
if (is_err(r) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, r); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_is_date( napi_env env, napi_value value, bool *result) { if (!env || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = is_date_instance((ant_value_t)value); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_is_arraybuffer( napi_env env, napi_value value, bool *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (!is_object_type((ant_value_t)value)) { *result = false; return napi_set_last(env, napi_ok, NULL); }
*result = buffer_get_arraybuffer_data((ant_value_t)value) != NULL; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_is_buffer( napi_env env, napi_value value, bool *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
TypedArrayData *ta = NULL; if (!napi_get_typedarray_data(nenv->js, value, &ta)) { *result = false; return napi_set_last(env, napi_ok, NULL); }
ant_value_t buffer_proto = nenv->js->builtins.buffer_proto; *result = is_object_type(buffer_proto) && proto_chain_contains(nenv->js, (ant_value_t)value, buffer_proto); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_is_typedarray( napi_env env, napi_value value, bool *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); TypedArrayData *ta = NULL; *result = napi_get_typedarray_data(nenv->js, value, &ta); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_is_dataview( napi_env env, napi_value value, bool *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (!is_object_type((ant_value_t)value)) { *result = false; } else { *result = buffer_get_dataview_data((ant_value_t)value) != NULL; } return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_is_error( napi_env env, napi_value value, bool *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); if (!is_object_type((ant_value_t)value)) { *result = false; } else { ant_value_t et = js_get_slot((ant_value_t)value, SLOT_ERR_TYPE); *result = vtype(et) == kTypeNumber; } return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_is_promise( napi_env env, napi_value value, bool *is_promise) { if (!env || !is_promise) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *is_promise = vtype((ant_value_t)value) == kTypePromise; return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_instanceof( napi_env env, napi_value object, napi_value constructor, bool *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); ant_value_t r = do_instanceof(nenv->js, (ant_value_t)object, (ant_value_t)constructor); if (is_err(r) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, r); *result = js_truthy(nenv->js, r); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_strict_equals( napi_env env, napi_value lhs, napi_value rhs, bool *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); *result = strict_eq_values(nenv->js, (ant_value_t)lhs, (ant_value_t)rhs); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_coerce_to_bool( napi_env env, napi_value value, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); bool truthy = js_truthy(nenv->js, (ant_value_t)value); if (Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, js_mkundef()); *result = NAPI_RETURN(nenv, js_bool(truthy)); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_coerce_to_number( napi_env env, napi_value value, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); double num = js_to_number(nenv->js, (ant_value_t)value); if (Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, js_mkundef()); *result = NAPI_RETURN(nenv, js_mknum(num)); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_coerce_to_object( napi_env env, napi_value value, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument");
if (is_object_type((ant_value_t)value)) { *result = value; return napi_set_last(env, napi_ok, NULL); }
ant_value_t obj_ctor = js_get(nenv->js, js_glob(nenv->js), "Object"); if (is_err(obj_ctor) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, obj_ctor); if (!is_callable(obj_ctor)) return napi_set_last(env, napi_generic_failure, "Object constructor missing"); ant_value_t arg = (ant_value_t)value; ant_value_t out = sv_vm_call(nenv->js->vm, nenv->js, obj_ctor, js_mkundef(), &arg, 1, NULL, js_mkundef()); if (is_err(out) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, out); *result = NAPI_RETURN(nenv, out); return napi_set_last(env, napi_ok, NULL);}
NAPI_EXTERN napi_status NAPI_CDECL napi_coerce_to_string( napi_env env, napi_value value, napi_value *result) { ant_napi_env_t *nenv = (ant_napi_env_t *)env; if (!nenv || !nenv->js || !result) return napi_set_last(env, napi_invalid_arg, "invalid argument"); ant_value_t out = coerce_to_str(nenv->js, (ant_value_t)value); if (is_err(out) || Ant_Exception_Pending(nenv->js)) return napi_check_pending_from_result(env, out); *result = NAPI_RETURN(nenv, out); return napi_set_last(env, napi_ok, NULL);}