Something went wrong. Try again.
MIRROR: javascript for ๐'s, a tiny runtime with big ambitions ant.themackabu.dev
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>
#include "ant.h"#include "ptr.h"#include "utf8.h"#include "utils.h"#include "errors.h"#include "base64.h"#include "internal.h"#include "runtime.h"#include "gc/roots.h"#include "descriptors.h"
#include "silver/engine.h"#include "modules/buffer.h"#include "modules/symbol.h"
#define BUFFER_REGISTRY_INITIAL_CAP 64
// Node compatibility exports only// Ant does not enforce these as allocation limits#define BUFFER_COMPAT_MAX_LENGTH 4294967296.0#define BUFFER_COMPAT_MAX_STRING_LENGTH 536870888.0#define BUFFER_COMPAT_INSPECT_MAX_BYTES 50.0
static size_t ta_metadata_bytes = 0;static size_t buffer_registry_count = 0;static size_t buffer_registry_cap = 0;
static ArrayBufferData **buffer_registry = NULL;static ant_value_t g_typedarray_iter_proto = 0;
enum { BUFFER_ARRAYBUFFER_NATIVE_TAG = 0x41425546u, // ABUF BUFFER_TYPEDARRAY_NATIVE_TAG = 0x54594152u, // TYAR BUFFER_DATAVIEW_NATIVE_TAG = 0x44564957u, // DVIW};
static void *ta_meta_alloc(size_t size) { void *ptr = ant_calloc(size); if (!ptr) return NULL; ta_metadata_bytes += size; return ptr;}
static void ta_meta_free(void *ptr, size_t size) { if (!ptr) return; if (ta_metadata_bytes >= size) ta_metadata_bytes -= size; else ta_metadata_bytes = 0; free(ptr);}
ArrayBufferData *buffer_get_arraybuffer_data(ant_value_t value) { if (!is_object_type(value) || buffer_is_dataview(value)) return NULL; if (js_check_native_tag(value, BUFFER_ARRAYBUFFER_NATIVE_TAG)) return (ArrayBufferData *)js_get_native_ptr(value); return NULL;}
TypedArrayData *buffer_get_typedarray_data(ant_value_t value) { if (vtype(value) == T_TYPEDARRAY) return (TypedArrayData *)js_gettypedarray(value); if (!is_object_type(value)) return NULL; if (js_check_native_tag(value, BUFFER_TYPEDARRAY_NATIVE_TAG)) return (TypedArrayData *)js_get_native_ptr(value); return NULL;}
DataViewData *buffer_get_dataview_data(ant_value_t value) { if (!is_object_type(value)) return NULL; if (js_check_native_tag(value, BUFFER_DATAVIEW_NATIVE_TAG)) return (DataViewData *)js_get_native_ptr(value); return NULL;}
static void arraybuffer_finalize(ant_t *js, ant_object_t *obj) { ant_value_t value = js_obj_from_ptr(obj); if (!js_check_native_tag(value, BUFFER_ARRAYBUFFER_NATIVE_TAG)) return; ArrayBufferData *data = (ArrayBufferData *)js_get_native_ptr(value); js_set_native_ptr(value, NULL); js_set_native_tag(value, 0); if (data) free_array_buffer_data(data);}
static void typedarray_finalize(ant_t *js, ant_object_t *obj) { ant_value_t value = js_obj_from_ptr(obj); if (!js_check_native_tag(value, BUFFER_TYPEDARRAY_NATIVE_TAG)) return; TypedArrayData *ta_data = (TypedArrayData *)js_get_native_ptr(value); js_set_native_ptr(value, NULL); js_set_native_tag(value, 0); if (!ta_data) return;
if (ta_data->buffer) free_array_buffer_data(ta_data->buffer); ta_meta_free(ta_data, sizeof(*ta_data));}
static void dataview_finalize(ant_t *js, ant_object_t *obj) { ant_value_t value = js_obj_from_ptr(obj); if (!js_check_native_tag(value, BUFFER_DATAVIEW_NATIVE_TAG)) return; DataViewData *dv_data = (DataViewData *)js_get_native_ptr(value); js_set_native_ptr(value, NULL); js_set_native_tag(value, 0); if (!dv_data) return;
if (dv_data->buffer) free_array_buffer_data(dv_data->buffer); ta_meta_free(dv_data, sizeof(*dv_data));}
bool buffer_is_dataview(ant_value_t obj) { return js_check_brand(obj, BRAND_DATAVIEW);}
bool buffer_is_binary_source(ant_value_t value) { if (vtype(value) == T_TYPEDARRAY) return true; if (!is_object_type(value)) return false; if (buffer_is_dataview(value)) return true; return buffer_get_typedarray_data(value) != NULL || buffer_get_arraybuffer_data(value) != NULL;}
bool buffer_source_get_bytes(ant_t *js, ant_value_t value, const uint8_t **out, size_t *len) { if (out) *out = NULL; if (len) *len = 0; if (!buffer_is_binary_source(value)) return false;
TypedArrayData *ta = buffer_get_typedarray_data(value); if (ta) { if (!ta->buffer || ta->buffer->is_detached) { *out = NULL; *len = 0; return true; } *out = ta->buffer->data + ta->byte_offset; *len = ta->byte_length; return true; }
ArrayBufferData *ab = buffer_get_arraybuffer_data(value); if (ab) { if (ab->is_detached) { *out = NULL; *len = 0; return true; } *out = ab->data; *len = ab->length; return true; }
if (buffer_is_dataview(value)) { DataViewData *dv = buffer_get_dataview_data(value); if (!dv || !dv->buffer || dv->buffer->is_detached) { *out = NULL; *len = 0; return true; } *out = dv->buffer->data + dv->byte_offset; *len = dv->byte_length; return true; }
return false;}
static bool advance_typedarray(ant_t *js, js_iter_t *it, ant_value_t *out) { ant_value_t iter = it->iterator; ant_value_t ta_obj = js_get_slot(iter, SLOT_DATA); ant_value_t state_v = js_get_slot(iter, SLOT_ITER_STATE); uint32_t state = (vtype(state_v) == T_NUM) ? (uint32_t)js_getnum(state_v) : 0; uint32_t kind = ITER_STATE_KIND(state); uint32_t idx = ITER_STATE_INDEX(state);
TypedArrayData *ta = buffer_get_typedarray_data(ta_obj); if (!ta || !ta->buffer || ta->buffer->is_detached || idx >= (uint32_t)ta->length) return false;
uint8_t *data = ta->buffer->data + ta->byte_offset; double value; switch (ta->type) { case TYPED_ARRAY_INT8: value = (double)((int8_t *)data)[idx]; break; case TYPED_ARRAY_UINT8: case TYPED_ARRAY_UINT8_CLAMPED: value = (double)data[idx]; break; case TYPED_ARRAY_INT16: value = (double)((int16_t *)data)[idx]; break; case TYPED_ARRAY_UINT16: value = (double)((uint16_t *)data)[idx]; break; case TYPED_ARRAY_INT32: value = (double)((int32_t *)data)[idx]; break; case TYPED_ARRAY_UINT32: value = (double)((uint32_t *)data)[idx]; break; case TYPED_ARRAY_FLOAT16: value = half_to_double(((uint16_t *)data)[idx]); break; case TYPED_ARRAY_FLOAT32: value = (double)((float *)data)[idx]; break; case TYPED_ARRAY_FLOAT64: value = ((double *)data)[idx]; break; default: return false; }
switch (kind) { case ARR_ITER_KEYS: *out = js_mknum((double)idx); break; case ARR_ITER_ENTRIES: { ant_value_t pair = js_mkarr(js); js_arr_push(js, pair, js_mknum((double)idx)); js_arr_push(js, pair, js_mknum(value)); *out = pair; break; } default: *out = js_mknum(value); break; }
js_set_slot(iter, SLOT_ITER_STATE, js_mknum((double)ITER_STATE_PACK(kind, idx + 1))); return true;}
static ant_value_t ta_iter_next(ant_t *js, ant_value_t *args, int nargs) { js_iter_t it = { .iterator = js->this_val }; ant_value_t value; return js_iter_result(js, advance_typedarray(js, &it, &value), value);}
static ant_value_t ta_values(ant_t *js, ant_value_t *args, int nargs) { ant_value_t iter = js_mkobj(js); js_set_slot_wb(js, iter, SLOT_DATA, js->this_val); js_set_slot(iter, SLOT_ITER_STATE, js_mknum((double)ITER_STATE_PACK(ARR_ITER_VALUES, 0))); js_set_proto_init(iter, g_typedarray_iter_proto); return iter;}
static ant_value_t ta_keys(ant_t *js, ant_value_t *args, int nargs) { ant_value_t iter = js_mkobj(js); js_set_slot_wb(js, iter, SLOT_DATA, js->this_val); js_set_slot(iter, SLOT_ITER_STATE, js_mknum((double)ITER_STATE_PACK(ARR_ITER_KEYS, 0))); js_set_proto_init(iter, g_typedarray_iter_proto); return iter;}
static ant_value_t ta_entries(ant_t *js, ant_value_t *args, int nargs) { ant_value_t iter = js_mkobj(js); js_set_slot_wb(js, iter, SLOT_DATA, js->this_val); js_set_slot(iter, SLOT_ITER_STATE, js_mknum((double)ITER_STATE_PACK(ARR_ITER_ENTRIES, 0))); js_set_proto_init(iter, g_typedarray_iter_proto); return iter;}
static void register_buffer(ArrayBufferData *data) { if (!data) return; if (!buffer_registry) { buffer_registry = calloc(BUFFER_REGISTRY_INITIAL_CAP, sizeof(ArrayBufferData *)); if (!buffer_registry) return; buffer_registry_cap = BUFFER_REGISTRY_INITIAL_CAP; } if (buffer_registry_count >= buffer_registry_cap) { size_t new_cap = buffer_registry_cap * 2; ArrayBufferData **new_reg = realloc(buffer_registry, new_cap * sizeof(ArrayBufferData *)); if (!new_reg) return; buffer_registry = new_reg; buffer_registry_cap = new_cap; } buffer_registry[buffer_registry_count++] = data;}
static void unregister_buffer(ArrayBufferData *data) { if (!data || !buffer_registry) return; for (size_t i = 0; i < buffer_registry_count; i++) { if (buffer_registry[i] == data) { buffer_registry[i] = buffer_registry[--buffer_registry_count]; return; }}}
static inline ssize_t normalize_index(ssize_t idx, ssize_t len) { if (idx < 0) idx += len; if (idx < 0) return 0; if (idx > len) return len; return idx;}
ArrayBufferData *create_array_buffer_data(size_t length) { ArrayBufferData *data = ant_calloc(sizeof(ArrayBufferData) + length); if (!data) return NULL; data->data = (uint8_t *)(data + 1); memset(data->data, 0, length); data->length = length; data->capacity = length; data->ref_count = 1; data->is_shared = 0; data->is_detached = 0; register_buffer(data); return data;}
static ArrayBufferData *create_shared_array_buffer_data(size_t length) { ArrayBufferData *data = create_array_buffer_data(length); if (data) data->is_shared = 1; return data;}
void free_array_buffer_data(ArrayBufferData *data) { if (!data) return; data->ref_count--; if (data->ref_count <= 0) { unregister_buffer(data); free(data); }}
static size_t get_element_size(TypedArrayType type) { static const void *dispatch[] = { &&L_1, &&L_1, &&L_1, &&L_2, &&L_2, &&L_4, &&L_4, &&L_2, &&L_4, &&L_8, &&L_8, &&L_8 }; if (type > TYPED_ARRAY_BIGUINT64) goto L_1; goto *dispatch[type]; L_1: return 1; L_2: return 2; L_4: return 4; L_8: return 8;}
const char *buffer_typedarray_type_name(TypedArrayType type) { static const char *const names[] = { "Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "Float16Array", "Float32Array", "Float64Array", "BigInt64Array", "BigUint64Array", };
int i = (int)type; if (i < 0 || i >= (int)(sizeof(names) / sizeof(names[0]))) return "Uint8Array"; return names[i];}
static ant_value_t create_typed_array_like( ant_t *js, ant_value_t this_val, TypedArrayType type, ArrayBufferData *buffer, size_t byte_offset, size_t length) { ant_value_t ab_obj = create_arraybuffer_obj(js, buffer); ant_value_t out = create_typed_array_with_buffer( js,type, buffer, byte_offset, length, buffer_typedarray_type_name(type), ab_obj ); if (is_err(out)) return out; ant_value_t proto = js_get_proto(js, this_val); if (is_special_object(proto)) js_set_proto_init(out, proto); return out;}
static ant_value_t js_arraybuffer_constructor(ant_t *js, ant_value_t *args, int nargs) { if (vtype(js->new_target) == T_UNDEF) { return js_mkerr_typed(js, JS_ERR_TYPE, "ArrayBuffer constructor requires 'new'"); } size_t length = 0; if (nargs > 0 && vtype(args[0]) == T_NUM) { length = (size_t)js_getnum(args[0]); } ArrayBufferData *data = create_array_buffer_data(length); if (!data) { return js_mkerr(js, "Failed to allocate ArrayBuffer"); } ant_value_t obj = js_mkobj(js); ant_value_t proto = js_get_ctor_proto(js, "ArrayBuffer", 11);
if (is_special_object(proto)) js_set_proto_init(obj, proto); js_set_native_ptr(obj, data); js_set_native_tag(obj, BUFFER_ARRAYBUFFER_NATIVE_TAG); js_set(js, obj, "byteLength", js_mknum((double)length)); js_set_finalizer(obj, arraybuffer_finalize);
return obj;}
// ArrayBuffer.prototype.slice(begin, end)static ant_value_t js_arraybuffer_slice(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); ArrayBufferData *data = buffer_get_arraybuffer_data(this_val); if (!data) return js_mkerr(js, "Invalid ArrayBuffer"); if (data->is_detached) return js_mkerr(js, "Cannot slice a detached ArrayBuffer"); ssize_t len = (ssize_t)data->length; ssize_t begin = 0, end = len; if (nargs > 0 && vtype(args[0]) == T_NUM) begin = (ssize_t)js_getnum(args[0]); if (nargs > 1 && vtype(args[1]) == T_NUM) end = (ssize_t)js_getnum(args[1]); begin = normalize_index(begin, len); end = normalize_index(end, len); if (end < begin) end = begin; size_t new_length = (size_t)(end - begin); ArrayBufferData *new_data = create_array_buffer_data(new_length); if (!new_data) return js_mkerr(js, "Failed to allocate new ArrayBuffer"); memcpy(new_data->data, data->data + begin, new_length);
ant_value_t new_obj = js_mkobj(js); ant_value_t proto = js_get_ctor_proto(js, "ArrayBuffer", 11);
if (is_special_object(proto)) js_set_proto_init(new_obj, proto); js_set_native_ptr(new_obj, new_data); js_set_native_tag(new_obj, BUFFER_ARRAYBUFFER_NATIVE_TAG); js_set(js, new_obj, "byteLength", js_mknum((double)new_length)); js_set_finalizer(new_obj, arraybuffer_finalize); return new_obj;}
// ArrayBuffer.prototype.transfer(newLength)static ant_value_t js_arraybuffer_transfer(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); ArrayBufferData *data = buffer_get_arraybuffer_data(this_val); if (!data) return js_mkerr(js, "Invalid ArrayBuffer"); if (data->is_detached) { return js_mkerr(js, "Cannot transfer a detached ArrayBuffer"); } if (data->is_shared) { return js_mkerr(js, "Cannot transfer a SharedArrayBuffer"); } size_t new_length = data->length; if (nargs > 0 && vtype(args[0]) == T_NUM) { new_length = (size_t)js_getnum(args[0]); } ArrayBufferData *new_data = create_array_buffer_data(new_length); if (!new_data) return js_mkerr(js, "Failed to allocate new ArrayBuffer"); size_t copy_length = data->length < new_length ? data->length : new_length; memcpy(new_data->data, data->data, copy_length); data->is_detached = 1; data->length = 0; js_set(js, this_val, "byteLength", js_mknum(0));
ant_value_t new_obj = js_mkobj(js); ant_value_t proto = js_get_ctor_proto(js, "ArrayBuffer", 11);
if (is_special_object(proto)) js_set_proto_init(new_obj, proto); js_set_native_ptr(new_obj, new_data); js_set_native_tag(new_obj, BUFFER_ARRAYBUFFER_NATIVE_TAG); js_set(js, new_obj, "byteLength", js_mknum((double)new_length)); js_set_finalizer(new_obj, arraybuffer_finalize); return new_obj;}
// ArrayBuffer.prototype.transferToFixedLength(newLength)static ant_value_t js_arraybuffer_transferToFixedLength(ant_t *js, ant_value_t *args, int nargs) { return js_arraybuffer_transfer(js, args, nargs);}
// ArrayBuffer.prototype.detached getterstatic ant_value_t js_arraybuffer_detached_getter(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); ArrayBufferData *data = buffer_get_arraybuffer_data(this_val); if (!data) return js_false; return js_bool(data->is_detached);}
static ant_value_t typedarray_index_getter(ant_t *js, ant_value_t obj, const char *key, size_t key_len) { if (key_len == 0 || key_len > 10) return js_mkundef(); size_t index = 0; for (size_t i = 0; i < key_len; i++) { char c = key[i]; if (c < '0' || c > '9') return js_mkundef(); index = index * 10 + (c - '0'); } TypedArrayData *ta_data = buffer_get_typedarray_data(obj); if (!ta_data || index >= ta_data->length) return js_mkundef(); if (!ta_data->buffer || ta_data->buffer->is_detached) return js_mkundef(); uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; double value; static const void *dispatch[] = { &&L_INT8, &&L_UINT8, &&L_UINT8, &&L_INT16, &&L_UINT16, &&L_INT32, &&L_UINT32, &&L_FLOAT16, &&L_FLOAT32, &&L_FLOAT64, &&L_UNDEF, &&L_UNDEF }; if (ta_data->type > TYPED_ARRAY_BIGUINT64) goto L_UNDEF; goto *dispatch[ta_data->type]; L_INT8: value = (double)((int8_t*)data)[index]; goto L_DONE; L_UINT8: value = (double)data[index]; goto L_DONE; L_INT16: value = (double)((int16_t*)data)[index]; goto L_DONE; L_UINT16: value = (double)((uint16_t*)data)[index]; goto L_DONE; L_INT32: value = (double)((int32_t*)data)[index]; goto L_DONE; L_UINT32: value = (double)((uint32_t*)data)[index]; goto L_DONE; L_FLOAT16: value = half_to_double(((uint16_t*)data)[index]); goto L_DONE; L_FLOAT32: value = (double)((float*)data)[index]; goto L_DONE; L_FLOAT64: value = ((double*)data)[index]; goto L_DONE; L_UNDEF: return js_mkundef(); L_DONE: return js_mknum(value);}
static bool typedarray_index_setter(ant_t *js, ant_value_t obj, const char *key, size_t key_len, ant_value_t value) { if (key_len == 0 || key_len > 10) return false; size_t index = 0; for (size_t i = 0; i < key_len; i++) { char c = key[i]; if (c < '0' || c > '9') return false; index = index * 10 + (c - '0'); } TypedArrayData *ta_data = buffer_get_typedarray_data(obj); if (!ta_data || index >= ta_data->length) return true; if (!ta_data->buffer || ta_data->buffer->is_detached) return true; double num_val = vtype(value) == T_NUM ? js_getnum(value) : 0; uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; static const void *dispatch[] = { &&S_INT8, &&S_UINT8, &&S_UINT8, &&S_INT16, &&S_UINT16, &&S_INT32, &&S_UINT32, &&S_FLOAT16, &&S_FLOAT32, &&S_FLOAT64, &&S_FAIL, &&S_FAIL }; if (ta_data->type > TYPED_ARRAY_BIGUINT64) goto S_FAIL; goto *dispatch[ta_data->type]; S_INT8: ((int8_t*)data)[index] = (int8_t)num_val; goto S_DONE; S_UINT8: data[index] = (uint8_t)num_val; goto S_DONE; S_INT16: ((int16_t*)data)[index] = (int16_t)num_val; goto S_DONE; S_UINT16: ((uint16_t*)data)[index] = (uint16_t)num_val; goto S_DONE; S_INT32: ((int32_t*)data)[index] = (int32_t)num_val; goto S_DONE; S_UINT32: ((uint32_t*)data)[index] = (uint32_t)num_val; goto S_DONE; S_FLOAT16: ((uint16_t*)data)[index] = double_to_half(num_val); goto S_DONE; S_FLOAT32: ((float*)data)[index] = (float)num_val; goto S_DONE; S_FLOAT64: ((double*)data)[index] = num_val; goto S_DONE; S_FAIL: return false; S_DONE: return true;}
static bool typedarray_read_number(const TypedArrayData *ta_data, size_t index, double *out) { if (!ta_data || !ta_data->buffer || ta_data->buffer->is_detached || index >= ta_data->length) return false; uint8_t *data = ta_data->buffer->data + ta_data->byte_offset;
static const void *dispatch[] = { &&R_INT8, &&R_UINT8, &&R_UINT8, &&R_INT16, &&R_UINT16, &&R_INT32, &&R_UINT32, &&R_FLOAT16, &&R_FLOAT32, &&R_FLOAT64, &&R_FAIL, &&R_FAIL };
if (ta_data->type > TYPED_ARRAY_BIGUINT64) goto R_FAIL; goto *dispatch[ta_data->type];
R_INT8: *out = (double)((int8_t *)data)[index]; return true; R_UINT8: *out = (double)data[index]; return true; R_INT16: *out = (double)((int16_t *)data)[index]; return true; R_UINT16: *out = (double)((uint16_t *)data)[index]; return true; R_INT32: *out = (double)((int32_t *)data)[index]; return true; R_UINT32: *out = (double)((uint32_t *)data)[index]; return true; R_FLOAT16: *out = half_to_double(((uint16_t *)data)[index]); return true; R_FLOAT32: *out = (double)((float *)data)[index]; return true; R_FLOAT64: *out = ((double *)data)[index]; return true; R_FAIL: return false;}
static bool typedarray_write_number(TypedArrayData *ta_data, size_t index, double value) { if (!ta_data || !ta_data->buffer || ta_data->buffer->is_detached || index >= ta_data->length) return false; uint8_t *data = ta_data->buffer->data + ta_data->byte_offset;
static const void *dispatch[] = { &&W_INT8, &&W_UINT8, &&W_UINT8, &&W_INT16, &&W_UINT16, &&W_INT32, &&W_UINT32, &&W_FLOAT16, &&W_FLOAT32, &&W_FLOAT64, &&W_FAIL, &&W_FAIL };
if (ta_data->type > TYPED_ARRAY_BIGUINT64) goto W_FAIL; goto *dispatch[ta_data->type];
W_INT8: ((int8_t *)data)[index] = (int8_t)value; return true; W_UINT8: data[index] = (uint8_t)value; return true; W_INT16: ((int16_t *)data)[index] = (int16_t)value; return true; W_UINT16: ((uint16_t *)data)[index] = (uint16_t)value; return true; W_INT32: ((int32_t *)data)[index] = (int32_t)value; return true; W_UINT32: ((uint32_t *)data)[index] = (uint32_t)value; return true; W_FLOAT16: ((uint16_t *)data)[index] = double_to_half(value); return true; W_FLOAT32: ((float *)data)[index] = (float)value; return true; W_FLOAT64: ((double *)data)[index] = value; return true; W_FAIL: return false;}
ant_value_t create_arraybuffer_obj(ant_t *js, ArrayBufferData *buffer) { ant_value_t ab_obj = js_mkobj(js); ant_value_t ab_proto = js_get_ctor_proto(js, "ArrayBuffer", 11); if (is_special_object(ab_proto)) js_set_proto_init(ab_obj, ab_proto); js_set_native_ptr(ab_obj, buffer); js_set_native_tag(ab_obj, BUFFER_ARRAYBUFFER_NATIVE_TAG); js_set(js, ab_obj, "byteLength", js_mknum((double)buffer->length)); js_set_finalizer(ab_obj, arraybuffer_finalize); buffer->ref_count++; return ab_obj;}
ant_value_t create_typed_array_with_buffer( ant_t *js, TypedArrayType type, ArrayBufferData *buffer, size_t byte_offset, size_t length, const char *type_name, ant_value_t arraybuffer_obj) { TypedArrayData *ta_data = ta_meta_alloc(sizeof(TypedArrayData)); if (!ta_data) return js_mkerr(js, "Failed to allocate TypedArray"); size_t element_size = get_element_size(type); ta_data->buffer = buffer; ta_data->type = type; ta_data->byte_offset = byte_offset; ta_data->byte_length = length * element_size; ta_data->length = length; buffer->ref_count++; ant_value_t obj = js_mkobj(js); ant_value_t proto = js_get_ctor_proto(js, type_name, strlen(type_name)); if (is_special_object(proto)) js_set_proto_init(obj, proto); js_set_native_ptr(obj, ta_data); js_set_native_tag(obj, BUFFER_TYPEDARRAY_NATIVE_TAG); js_set(js, obj, "length", js_mknum((double)length)); js_set(js, obj, "byteLength", js_mknum((double)(length * element_size))); js_set(js, obj, "byteOffset", js_mknum((double)byte_offset)); js_set(js, obj, "BYTES_PER_ELEMENT", js_mknum((double)element_size)); js_set(js, obj, "buffer", arraybuffer_obj); js_set_getter(obj, typedarray_index_getter); js_set_setter(obj, typedarray_index_setter); js_set_finalizer(obj, typedarray_finalize); return obj;}
ant_value_t create_typed_array( ant_t *js, TypedArrayType type, ArrayBufferData *buffer, size_t byte_offset, size_t length, const char *type_name) { ant_value_t ab_obj = create_arraybuffer_obj(js, buffer); ant_value_t result = create_typed_array_with_buffer(js, type, buffer, byte_offset, length, type_name, ab_obj); free_array_buffer_data(buffer); return result;}
ant_value_t create_dataview_with_buffer( ant_t *js, ArrayBufferData *buffer, size_t byte_offset, size_t byte_length, ant_value_t arraybuffer_obj) { DataViewData *dv_data = ta_meta_alloc(sizeof(DataViewData)); if (!dv_data) return js_mkerr(js, "Failed to allocate DataView");
dv_data->buffer = buffer; dv_data->byte_offset = byte_offset; dv_data->byte_length = byte_length; buffer->ref_count++;
ant_value_t obj = js_mkobj(js); ant_value_t proto = js_get_ctor_proto(js, "DataView", 8); if (is_special_object(proto)) js_set_proto_init(obj, proto);
js_set_native_ptr(obj, dv_data); js_set_native_tag(obj, BUFFER_DATAVIEW_NATIVE_TAG); js_set_slot(obj, SLOT_BRAND, js_mknum(BRAND_DATAVIEW)); js_mkprop_fast(js, obj, "buffer", 6, arraybuffer_obj); js_set_descriptor(js, obj, "buffer", 6, 0); js_set(js, obj, "byteLength", js_mknum((double)byte_length)); js_set(js, obj, "byteOffset", js_mknum((double)byte_offset)); js_set_finalizer(obj, dataview_finalize);
return obj;}
typedef struct { ant_value_t *values; size_t length; size_t capacity;} iter_collect_ctx_t;
static bool iter_collect_callback(ant_t *js, ant_value_t value, void *udata) { (void)js; iter_collect_ctx_t *ctx = (iter_collect_ctx_t *)udata; if (ctx->length >= ctx->capacity) { ctx->capacity *= 2; ant_value_t *new_values = realloc(ctx->values, ctx->capacity * sizeof(ant_value_t)); if (!new_values) return false; ctx->values = new_values; } ctx->values[ctx->length++] = value; return true;}
static ant_value_t js_typedarray_constructor(ant_t *js, ant_value_t *args, int nargs, TypedArrayType type, const char *type_name) { if (nargs == 0) { ArrayBufferData *buffer = create_array_buffer_data(0); return create_typed_array(js, type, buffer, 0, 0, type_name); } if (vtype(args[0]) == T_NUM) { size_t length = (size_t)js_getnum(args[0]); size_t element_size = get_element_size(type); ArrayBufferData *buffer = create_array_buffer_data(length * element_size); if (!buffer) return js_mkerr(js, "Failed to allocate buffer"); return create_typed_array(js, type, buffer, 0, length, type_name); } ArrayBufferData *arraybuffer = buffer_get_arraybuffer_data(args[0]); if (arraybuffer) { ArrayBufferData *buffer = arraybuffer; size_t byte_offset = 0; size_t length = buffer->length; if (nargs > 1 && vtype(args[1]) == T_NUM) { byte_offset = (size_t)js_getnum(args[1]); } size_t element_size = get_element_size(type); if (byte_offset > buffer->length) { return js_mkerr(js, "Start offset is outside the bounds of the buffer"); } if (nargs > 2 && vtype(args[2]) == T_NUM) { length = (size_t)js_getnum(args[2]); size_t available = buffer->length - byte_offset; if (length > available / element_size) { return js_mkerr(js, "Invalid TypedArray length"); } } else length = (buffer->length - byte_offset) / element_size; return create_typed_array_with_buffer(js, type, buffer, byte_offset, length, type_name, args[0]); } if (is_special_object(args[0])) { ant_value_t len_val = js_get(js, args[0], "length"); size_t length = 0; ant_value_t *values = NULL; bool is_iterable = false; if (vtype(len_val) == T_NUM) length = (size_t)js_getnum(len_val); else { iter_collect_ctx_t ctx = { .values = NULL, .length = 0, .capacity = 16 }; ctx.values = malloc(ctx.capacity * sizeof(ant_value_t)); if (!ctx.values) return js_mkerr(js, "Failed to allocate memory"); is_iterable = js_iter(js, args[0], iter_collect_callback, &ctx); if (is_iterable) { values = ctx.values; length = ctx.length; } else free(ctx.values); } if (length > 0 || is_iterable || vtype(len_val) == T_NUM) { size_t element_size = get_element_size(type); ArrayBufferData *buffer = create_array_buffer_data(length * element_size); if (!buffer) { if (values) free(values); return js_mkerr(js, "Failed to allocate buffer"); } ant_value_t result = create_typed_array(js, type, buffer, 0, length, type_name); uint8_t *data = buffer->data; static const void *write_dispatch[] = { &&W_INT8, &&W_UINT8, &&W_UINT8, &&W_INT16, &&W_UINT16, &&W_INT32, &&W_UINT32, &&W_FLOAT16, &&W_FLOAT32, &&W_FLOAT64, &&W_DONE, &&W_DONE }; for (size_t i = 0; i < length; i++) { ant_value_t elem; if (values) elem = values[i]; else { char idx_str[16]; snprintf(idx_str, sizeof(idx_str), "%zu", i); elem = js_get(js, args[0], idx_str); } double val = vtype(elem) == T_NUM ? js_getnum(elem) : js_to_number(js, elem); if (type > TYPED_ARRAY_BIGUINT64) goto W_DONE; goto *write_dispatch[type]; W_INT8: ((int8_t*)data)[i] = (int8_t)val; goto W_NEXT; W_UINT8: data[i] = (uint8_t)val; goto W_NEXT; W_INT16: ((int16_t*)data)[i] = (int16_t)val; goto W_NEXT; W_UINT16: ((uint16_t*)data)[i] = (uint16_t)val; goto W_NEXT; W_INT32: ((int32_t*)data)[i] = (int32_t)val; goto W_NEXT; W_UINT32: ((uint32_t*)data)[i] = (uint32_t)val; goto W_NEXT; W_FLOAT16: ((uint16_t*)data)[i] = double_to_half(val); goto W_NEXT; W_FLOAT32: ((float*)data)[i] = (float)val; goto W_NEXT; W_FLOAT64: ((double*)data)[i] = val; goto W_NEXT; W_NEXT:; } W_DONE: if (values) free(values); return result; } } return js_mkerr(js, "Invalid TypedArray constructor arguments");}
// TypedArray.prototype.slice(begin, end)// TypedArray.prototype.at(index)static ant_value_t js_typedarray_at(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid TypedArray"); if (nargs == 0 || vtype(args[0]) != T_NUM) return js_mkundef(); ssize_t len = (ssize_t)ta_data->length; ssize_t idx = (ssize_t)js_getnum(args[0]); if (idx < 0) idx += len; if (idx < 0 || idx >= len) return js_mkundef(); if (!ta_data->buffer || ta_data->buffer->is_detached) return js_mkundef(); size_t index = (size_t)idx; uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; double value; switch (ta_data->type) { case TYPED_ARRAY_INT8: value = (double)((int8_t*)data)[index]; break; case TYPED_ARRAY_UINT8: case TYPED_ARRAY_UINT8_CLAMPED: value = (double)data[index]; break; case TYPED_ARRAY_INT16: value = (double)((int16_t*)data)[index]; break; case TYPED_ARRAY_UINT16: value = (double)((uint16_t*)data)[index]; break; case TYPED_ARRAY_INT32: value = (double)((int32_t*)data)[index]; break; case TYPED_ARRAY_UINT32: value = (double)((uint32_t*)data)[index]; break; case TYPED_ARRAY_FLOAT16: value = half_to_double(((uint16_t*)data)[index]); break; case TYPED_ARRAY_FLOAT32: value = (double)((float*)data)[index]; break; case TYPED_ARRAY_FLOAT64: value = ((double*)data)[index]; break; default: return js_mkundef(); } return js_mknum(value);}
static ant_value_t js_typedarray_slice(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid TypedArray"); ssize_t len = (ssize_t)ta_data->length; ssize_t begin = 0, end = len; if (nargs > 0 && vtype(args[0]) == T_NUM) begin = (ssize_t)js_getnum(args[0]); if (nargs > 1 && vtype(args[1]) == T_NUM) end = (ssize_t)js_getnum(args[1]); begin = normalize_index(begin, len); end = normalize_index(end, len); if (end < begin) end = begin; size_t new_length = (size_t)(end - begin); size_t element_size = get_element_size(ta_data->type); ArrayBufferData *new_buffer = create_array_buffer_data(new_length * element_size); if (!new_buffer) return js_mkerr(js, "Failed to allocate new buffer"); memcpy( new_buffer->data, ta_data->buffer->data + ta_data->byte_offset + (size_t)begin * element_size, new_length * element_size ); ant_value_t out = create_typed_array_like( js, this_val, ta_data->type, new_buffer, 0, new_length ); free_array_buffer_data(new_buffer); return out;}
// TypedArray.prototype.subarray(begin, end)static ant_value_t js_typedarray_subarray(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid TypedArray"); ssize_t len = (ssize_t)ta_data->length; ssize_t begin = 0, end = len; if (nargs > 0 && vtype(args[0]) == T_NUM) begin = (ssize_t)js_getnum(args[0]); if (nargs > 1 && vtype(args[1]) == T_NUM) end = (ssize_t)js_getnum(args[1]); begin = normalize_index(begin, len); end = normalize_index(end, len); if (end < begin) end = begin; size_t new_length = (size_t)(end - begin); size_t element_size = get_element_size(ta_data->type); size_t new_offset = ta_data->byte_offset + (size_t)begin * element_size; return create_typed_array_like( js, this_val, ta_data->type, ta_data->buffer, new_offset, new_length );}
// TypedArray.prototype.fill(value, start, end)static ant_value_t js_typedarray_fill(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid TypedArray"); double value = 0; if (nargs > 0 && vtype(args[0]) == T_NUM) value = js_getnum(args[0]); ssize_t len = (ssize_t)ta_data->length; ssize_t start = 0, end = len; if (nargs > 1 && vtype(args[1]) == T_NUM) start = (ssize_t)js_getnum(args[1]); if (nargs > 2 && vtype(args[2]) == T_NUM) end = (ssize_t)js_getnum(args[2]); start = normalize_index(start, len); end = normalize_index(end, len); if (end < start) end = start; uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; static const void *dispatch[] = { &&L_INT8, &&L_UINT8, &&L_UINT8, &&L_INT16, &&L_UINT16, &&L_INT32, &&L_UINT32, &&L_FLOAT16, &&L_FLOAT32, &&L_FLOAT64, &&L_DONE, &&L_DONE }; if (ta_data->type > TYPED_ARRAY_BIGUINT64) goto L_DONE; goto *dispatch[ta_data->type]; L_INT8: for (ssize_t i = start; i < end; i++) ((int8_t*)data)[i] = (int8_t)value; goto L_DONE; L_UINT8: for (ssize_t i = start; i < end; i++) data[i] = (uint8_t)value; goto L_DONE; L_INT16: for (ssize_t i = start; i < end; i++) ((int16_t*)data)[i] = (int16_t)value; goto L_DONE; L_UINT16: for (ssize_t i = start; i < end; i++) ((uint16_t*)data)[i] = (uint16_t)value; goto L_DONE; L_INT32: for (ssize_t i = start; i < end; i++) ((int32_t*)data)[i] = (int32_t)value; goto L_DONE; L_UINT32: for (ssize_t i = start; i < end; i++) ((uint32_t*)data)[i] = (uint32_t)value; goto L_DONE; L_FLOAT16: for (ssize_t i = start; i < end; i++) ((uint16_t*)data)[i] = double_to_half(value); goto L_DONE; L_FLOAT32: for (ssize_t i = start; i < end; i++) ((float*)data)[i] = (float)value; goto L_DONE; L_FLOAT64: for (ssize_t i = start; i < end; i++) ((double*)data)[i] = value; goto L_DONE; L_DONE: return this_val;}
// TypedArray.prototype.set(source, offset = 0)static ant_value_t js_typedarray_set(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "set requires source argument");
ant_value_t this_val = js_getthis(js); TypedArrayData *dst = buffer_get_typedarray_data(this_val); if (!dst) return js_mkerr(js, "Invalid TypedArray"); if (!dst->buffer || dst->buffer->is_detached) return js_mkerr(js, "Cannot operate on a detached TypedArray");
ssize_t offset_i = 0; if (nargs > 1 && vtype(args[1]) == T_NUM) offset_i = (ssize_t)js_getnum(args[1]); if (offset_i < 0) return js_mkerr(js, "Offset out of bounds"); size_t offset = (size_t)offset_i; if (offset > dst->length) return js_mkerr(js, "Offset out of bounds");
ant_value_t src_val = args[0]; TypedArrayData *src_ta = buffer_get_typedarray_data(src_val);
if (src_ta && src_ta->buffer && !src_ta->buffer->is_detached) { size_t src_len = src_ta->length; if (offset + src_len > dst->length) return js_mkerr(js, "Source is too large");
if (src_ta->type == dst->type) { size_t el = get_element_size(dst->type); uint8_t *dst_data = dst->buffer->data + dst->byte_offset + offset * el; uint8_t *src_data = src_ta->buffer->data + src_ta->byte_offset; memmove(dst_data, src_data, src_len * el); return js_mkundef(); }
for (size_t i = 0; i < src_len; i++) { double value = 0; if (!typedarray_read_number(src_ta, i, &value)) value = 0; (void)typedarray_write_number(dst, offset + i, value); } return js_mkundef(); }
if (!is_special_object(src_val) && vtype(src_val) != T_STR) { return js_mkerr(js, "set source must be array-like or TypedArray"); }
size_t src_len = 0; if (vtype(src_val) == T_STR) { src_len = (size_t)vstrlen(js, src_val); } else { ant_value_t len_val = js_get(js, src_val, "length"); src_len = vtype(len_val) == T_NUM ? (size_t)js_getnum(len_val) : 0; }
if (offset + src_len > dst->length) return js_mkerr(js, "Source is too large");
for (size_t i = 0; i < src_len; i++) { double value = 0; if (vtype(src_val) == T_STR) { ant_offset_t slen = 0; ant_offset_t soff = vstr(js, src_val, &slen); const unsigned char *sptr = (const unsigned char *)(uintptr_t)soff; if (i < (size_t)slen) value = sptr[i]; } else { char idx[24]; size_t idx_len = uint_to_str(idx, sizeof(idx), (uint64_t)i); idx[idx_len] = '\0'; ant_value_t elem = js_get(js, src_val, idx); value = vtype(elem) == T_NUM ? js_getnum(elem) : 0; } (void)typedarray_write_number(dst, offset + i, value); }
return js_mkundef();}
// TypedArray.prototype.copyWithin(target, start, end)static ant_value_t js_typedarray_copyWithin(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); TypedArrayData *ta = buffer_get_typedarray_data(this_val); if (!ta) return js_mkerr(js, "Invalid TypedArray"); if (!ta->buffer || ta->buffer->is_detached) return js_mkerr(js, "Cannot operate on a detached TypedArray");
ssize_t len = (ssize_t)ta->length; if (len <= 0) return this_val;
ssize_t target = 0, start = 0, end = len; if (nargs > 0 && vtype(args[0]) == T_NUM) target = (ssize_t)js_getnum(args[0]); if (nargs > 1 && vtype(args[1]) == T_NUM) start = (ssize_t)js_getnum(args[1]); if (nargs > 2 && vtype(args[2]) == T_NUM) end = (ssize_t)js_getnum(args[2]);
target = normalize_index(target, len); start = normalize_index(start, len); end = normalize_index(end, len); if (end < start) end = start; if (target >= len || start >= len || end <= start) return this_val;
size_t count = (size_t)(end - start); size_t max_to_end = (size_t)(len - target); if (count > max_to_end) count = max_to_end; if (count == 0) return this_val;
size_t el = get_element_size(ta->type); uint8_t *base = ta->buffer->data + ta->byte_offset; memmove(base + (size_t)target * el, base + (size_t)start * el, count * el); return this_val;}
// TypedArray.prototype.toReversed()static ant_value_t js_typedarray_toReversed(ant_t *js, ant_value_t *args, int nargs) { (void)args; (void)nargs; ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid TypedArray"); size_t length = ta_data->length; size_t element_size = get_element_size(ta_data->type); ArrayBufferData *new_buffer = create_array_buffer_data(length * element_size); if (!new_buffer) return js_mkerr(js, "Failed to allocate new buffer"); uint8_t *src = ta_data->buffer->data + ta_data->byte_offset; uint8_t *dst = new_buffer->data; for (size_t i = 0; i < length; i++) { memcpy(dst + i * element_size, src + (length - 1 - i) * element_size, element_size); } ant_value_t out = create_typed_array_like( js, this_val, ta_data->type, new_buffer, 0, length ); free_array_buffer_data(new_buffer); return out;}
// TypedArray.prototype.toSorted(comparefn)static ant_value_t js_typedarray_toSorted(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid TypedArray"); size_t length = ta_data->length; size_t element_size = get_element_size(ta_data->type); ArrayBufferData *new_buffer = create_array_buffer_data(length * element_size); if (!new_buffer) return js_mkerr(js, "Failed to allocate new buffer"); memcpy(new_buffer->data, ta_data->buffer->data + ta_data->byte_offset, length * element_size); ant_value_t result = create_typed_array_like(js, this_val, ta_data->type, new_buffer, 0, length); free_array_buffer_data(new_buffer); if (is_err(result)) return result; TypedArrayData *result_ta = buffer_get_typedarray_data(result); uint8_t *data = result_ta->buffer->data; ant_value_t comparefn = (nargs > 0 && vtype(args[0]) == T_FUNC) ? args[0] : js_mkundef(); bool has_comparefn = vtype(comparefn) == T_FUNC; for (size_t i = 1; i < length; i++) { for (size_t j = i; j > 0; j--) { double a_val, b_val; int cmp; static const void *read_dispatch[] = { &&R_INT8, &&R_UINT8, &&R_UINT8, &&R_INT16, &&R_UINT16, &&R_INT32, &&R_UINT32, &&R_FLOAT16, &&R_FLOAT32, &&R_FLOAT64, &&R_DONE, &&R_DONE }; if (ta_data->type > TYPED_ARRAY_BIGUINT64) goto R_DONE; goto *read_dispatch[ta_data->type]; R_INT8: a_val = (double)((int8_t*)data)[j-1]; b_val = (double)((int8_t*)data)[j]; goto R_COMPARE; R_UINT8: a_val = (double)data[j-1]; b_val = (double)data[j]; goto R_COMPARE; R_INT16: a_val = (double)((int16_t*)data)[j-1]; b_val = (double)((int16_t*)data)[j]; goto R_COMPARE; R_UINT16: a_val = (double)((uint16_t*)data)[j-1]; b_val = (double)((uint16_t*)data)[j]; goto R_COMPARE; R_INT32: a_val = (double)((int32_t*)data)[j-1]; b_val = (double)((int32_t*)data)[j]; goto R_COMPARE; R_UINT32: a_val = (double)((uint32_t*)data)[j-1]; b_val = (double)((uint32_t*)data)[j]; goto R_COMPARE; R_FLOAT16: a_val = half_to_double(((uint16_t*)data)[j-1]); b_val = half_to_double(((uint16_t*)data)[j]); goto R_COMPARE; R_FLOAT32: a_val = (double)((float*)data)[j-1]; b_val = (double)((float*)data)[j]; goto R_COMPARE; R_FLOAT64: a_val = ((double*)data)[j-1]; b_val = ((double*)data)[j]; goto R_COMPARE; R_DONE: goto SORT_DONE; R_COMPARE: if (has_comparefn) { ant_value_t cmp_args[2] = { js_mknum(a_val), js_mknum(b_val) }; ant_value_t cmp_result = sv_vm_call(js->vm, js, comparefn, js_mkundef(), cmp_args, 2, NULL, false); cmp = (int)js_getnum(cmp_result); } else { cmp = (a_val > b_val) ? 1 : ((a_val < b_val) ? -1 : 0); } if (cmp <= 0) break; static const void *swap_dispatch[] = { &&S_INT8, &&S_UINT8, &&S_UINT8, &&S_INT16, &&S_UINT16, &&S_INT32, &&S_UINT32, &&S_FLOAT16, &&S_FLOAT32, &&S_FLOAT64, &&S_DONE, &&S_DONE }; if (ta_data->type > TYPED_ARRAY_BIGUINT64) goto S_DONE; goto *swap_dispatch[ta_data->type]; S_INT8: { int8_t tmp = ((int8_t*)data)[j-1]; ((int8_t*)data)[j-1] = ((int8_t*)data)[j]; ((int8_t*)data)[j] = tmp; goto S_DONE; } S_UINT8: { uint8_t tmp = data[j-1]; data[j-1] = data[j]; data[j] = tmp; goto S_DONE; } S_INT16: { int16_t tmp = ((int16_t*)data)[j-1]; ((int16_t*)data)[j-1] = ((int16_t*)data)[j]; ((int16_t*)data)[j] = tmp; goto S_DONE; } S_UINT16: { uint16_t tmp = ((uint16_t*)data)[j-1]; ((uint16_t*)data)[j-1] = ((uint16_t*)data)[j]; ((uint16_t*)data)[j] = tmp; goto S_DONE; } S_INT32: { int32_t tmp = ((int32_t*)data)[j-1]; ((int32_t*)data)[j-1] = ((int32_t*)data)[j]; ((int32_t*)data)[j] = tmp; goto S_DONE; } S_UINT32: { uint32_t tmp = ((uint32_t*)data)[j-1]; ((uint32_t*)data)[j-1] = ((uint32_t*)data)[j]; ((uint32_t*)data)[j] = tmp; goto S_DONE; } S_FLOAT16: { uint16_t tmp = ((uint16_t*)data)[j-1]; ((uint16_t*)data)[j-1] = ((uint16_t*)data)[j]; ((uint16_t*)data)[j] = tmp; goto S_DONE; } S_FLOAT32: { float tmp = ((float*)data)[j-1]; ((float*)data)[j-1] = ((float*)data)[j]; ((float*)data)[j] = tmp; goto S_DONE; } S_FLOAT64: { double tmp = ((double*)data)[j-1]; ((double*)data)[j-1] = ((double*)data)[j]; ((double*)data)[j] = tmp; goto S_DONE; } S_DONE:; } } SORT_DONE: return result;}
// TypedArray.prototype.with(index, value)static ant_value_t js_typedarray_with(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "with requires index and value"); ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid TypedArray"); ssize_t index = (ssize_t)js_getnum(args[0]); double value = js_getnum(args[1]); size_t length = ta_data->length; if (index < 0) index = (ssize_t)length + index; if (index < 0 || (size_t)index >= length) { return js_mkerr(js, "Index out of bounds"); } size_t element_size = get_element_size(ta_data->type); ArrayBufferData *new_buffer = create_array_buffer_data(length * element_size); if (!new_buffer) return js_mkerr(js, "Failed to allocate new buffer"); memcpy(new_buffer->data, ta_data->buffer->data + ta_data->byte_offset, length * element_size); uint8_t *data = new_buffer->data; static const void *dispatch[] = { &&W_INT8, &&W_UINT8, &&W_UINT8, &&W_INT16, &&W_UINT16, &&W_INT32, &&W_UINT32, &&W_FLOAT16, &&W_FLOAT32, &&W_FLOAT64, &&W_DONE, &&W_DONE }; if (ta_data->type > TYPED_ARRAY_BIGUINT64) goto W_DONE; goto *dispatch[ta_data->type]; W_INT8: ((int8_t*)data)[index] = (int8_t)value; goto W_DONE; W_UINT8: data[index] = (uint8_t)value; goto W_DONE; W_INT16: ((int16_t*)data)[index] = (int16_t)value; goto W_DONE; W_UINT16: ((uint16_t*)data)[index] = (uint16_t)value; goto W_DONE; W_INT32: ((int32_t*)data)[index] = (int32_t)value; goto W_DONE; W_UINT32: ((uint32_t*)data)[index] = (uint32_t)value; goto W_DONE; W_FLOAT16: ((uint16_t*)data)[index] = double_to_half(value); goto W_DONE; W_FLOAT32: ((float*)data)[index] = (float)value; goto W_DONE; W_FLOAT64: ((double*)data)[index] = value; goto W_DONE; W_DONE: ant_value_t out = create_typed_array_like( js, this_val, ta_data->type, new_buffer, 0, length ); free_array_buffer_data(new_buffer); return out;}
#define DEFINE_TYPEDARRAY_CONSTRUCTOR(name, type) \ static ant_value_t js_##name##_constructor(ant_t *js, ant_value_t *args, int nargs) { \ if (vtype(js->new_target) == T_UNDEF) return js_mkerr_typed(js, JS_ERR_TYPE, #name " constructor requires 'new'"); \ return js_typedarray_constructor(js, args, nargs, type, #name); \ }
DEFINE_TYPEDARRAY_CONSTRUCTOR(Int8Array, TYPED_ARRAY_INT8)DEFINE_TYPEDARRAY_CONSTRUCTOR(Uint8Array, TYPED_ARRAY_UINT8)DEFINE_TYPEDARRAY_CONSTRUCTOR(Uint8ClampedArray, TYPED_ARRAY_UINT8_CLAMPED)DEFINE_TYPEDARRAY_CONSTRUCTOR(Int16Array, TYPED_ARRAY_INT16)DEFINE_TYPEDARRAY_CONSTRUCTOR(Uint16Array, TYPED_ARRAY_UINT16)DEFINE_TYPEDARRAY_CONSTRUCTOR(Int32Array, TYPED_ARRAY_INT32)DEFINE_TYPEDARRAY_CONSTRUCTOR(Uint32Array, TYPED_ARRAY_UINT32)DEFINE_TYPEDARRAY_CONSTRUCTOR(Float16Array, TYPED_ARRAY_FLOAT16)DEFINE_TYPEDARRAY_CONSTRUCTOR(Float32Array, TYPED_ARRAY_FLOAT32)DEFINE_TYPEDARRAY_CONSTRUCTOR(Float64Array, TYPED_ARRAY_FLOAT64)DEFINE_TYPEDARRAY_CONSTRUCTOR(BigInt64Array, TYPED_ARRAY_BIGINT64)DEFINE_TYPEDARRAY_CONSTRUCTOR(BigUint64Array, TYPED_ARRAY_BIGUINT64)
static ant_value_t js_typedarray_from(ant_t *js, ant_value_t *args, int nargs, TypedArrayType type, const char *type_name) { if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "%s.from requires at least 1 argument", type_name);
ant_value_t source = args[0]; bool has_map = nargs >= 2 && vtype(args[1]) != T_UNDEF; ant_value_t map_fn = js_mkundef(); ant_value_t this_arg = nargs >= 3 ? args[2] : js_mkundef(); ant_value_t result = js_mkundef(); ant_value_t *collected = NULL; gc_temp_root_scope_t temp_roots = {0}; bool temp_roots_active = false;
if (has_map) { if (!is_callable(args[1])) return js_mkerr_typed( js, JS_ERR_TYPE, "%s.from: mapFn is not a function", type_name ); map_fn = args[1]; }
gc_temp_root_scope_begin(js, &temp_roots); temp_roots_active = true; if (!gc_temp_root_handle_valid(gc_temp_root_add(&temp_roots, source))) goto oom; if (!gc_temp_root_handle_valid(gc_temp_root_add(&temp_roots, map_fn))) goto oom; if (!gc_temp_root_handle_valid(gc_temp_root_add(&temp_roots, this_arg))) goto oom;
size_t count = 0, cap = 16; collected = malloc(cap * sizeof(ant_value_t)); if (!collected) goto oom;
js_iter_t it; if (js_iter_open(js, source, &it)) { ant_value_t item; while (js_iter_next(js, &it, &item)) { if (count >= cap) { cap *= 2; ant_value_t *tmp = realloc(collected, cap * sizeof(ant_value_t)); if (!tmp) goto oom; collected = tmp; } if (has_map) { ant_value_t map_args[2] = { item, js_mknum((double)count) }; item = sv_vm_call(js->vm, js, map_fn, this_arg, map_args, 2, NULL, false); if (is_err(item)) { result = item; goto done; } } collected[count++] = item; if (!gc_temp_root_handle_valid(gc_temp_root_add(&temp_roots, item))) goto oom; } js_iter_close(js, &it); } else { ant_value_t len_val = js_get(js, source, "length"); size_t len = vtype(len_val) == T_NUM ? (size_t)js_getnum(len_val) : 0; for (size_t i = 0; i < len; i++) { char idx[16]; snprintf(idx, sizeof(idx), "%zu", i); ant_value_t item = js_get(js, source, idx); if (count >= cap) { cap *= 2; ant_value_t *tmp = realloc(collected, cap * sizeof(ant_value_t)); if (!tmp) goto oom; collected = tmp; } if (has_map) { ant_value_t map_args[2] = { item, js_mknum((double)i) }; item = sv_vm_call(js->vm, js, map_fn, this_arg, map_args, 2, NULL, false); if (is_err(item)) { result = item; goto done; } } collected[count++] = item; if (!gc_temp_root_handle_valid(gc_temp_root_add(&temp_roots, item))) goto oom; } }
size_t elem_size = get_element_size(type); ArrayBufferData *buffer = create_array_buffer_data(count * elem_size); if (!buffer) goto oom;
result = create_typed_array(js, type, buffer, 0, count, type_name); if (is_err(result)) goto done; if (!gc_temp_root_handle_valid(gc_temp_root_add(&temp_roots, result))) goto oom; uint8_t *data = buffer->data;
for (size_t i = 0; i < count; i++) { double val = vtype(collected[i]) == T_NUM ? js_getnum(collected[i]) : js_to_number(js, collected[i]); switch (type) { case TYPED_ARRAY_INT8: ((int8_t *)data)[i] = (int8_t)val; break; case TYPED_ARRAY_UINT8: case TYPED_ARRAY_UINT8_CLAMPED: data[i] = (uint8_t)val; break; case TYPED_ARRAY_INT16: ((int16_t *)data)[i] = (int16_t)val; break; case TYPED_ARRAY_UINT16: ((uint16_t *)data)[i] = (uint16_t)val; break; case TYPED_ARRAY_INT32: ((int32_t *)data)[i] = (int32_t)val; break; case TYPED_ARRAY_UINT32: ((uint32_t *)data)[i] = (uint32_t)val; break; case TYPED_ARRAY_FLOAT16: ((uint16_t *)data)[i] = double_to_half(val); break; case TYPED_ARRAY_FLOAT32: ((float *)data)[i] = (float)val; break; case TYPED_ARRAY_FLOAT64: ((double *)data)[i] = val; break; default: break; }}
done: if (temp_roots_active) gc_temp_root_scope_end(&temp_roots); free(collected); return result;
oom: result = js_mkerr(js, "oom"); goto done;}
#define DEFINE_TYPEDARRAY_FROM(name, type) \ static ant_value_t js_##name##_from(ant_t *js, ant_value_t *args, int nargs) { \ return js_typedarray_from(js, args, nargs, type, #name); \ }
DEFINE_TYPEDARRAY_FROM(Int8Array, TYPED_ARRAY_INT8)DEFINE_TYPEDARRAY_FROM(Uint8Array, TYPED_ARRAY_UINT8)DEFINE_TYPEDARRAY_FROM(Uint8ClampedArray, TYPED_ARRAY_UINT8_CLAMPED)DEFINE_TYPEDARRAY_FROM(Int16Array, TYPED_ARRAY_INT16)DEFINE_TYPEDARRAY_FROM(Uint16Array, TYPED_ARRAY_UINT16)DEFINE_TYPEDARRAY_FROM(Int32Array, TYPED_ARRAY_INT32)DEFINE_TYPEDARRAY_FROM(Uint32Array, TYPED_ARRAY_UINT32)DEFINE_TYPEDARRAY_FROM(Float16Array, TYPED_ARRAY_FLOAT16)DEFINE_TYPEDARRAY_FROM(Float32Array, TYPED_ARRAY_FLOAT32)DEFINE_TYPEDARRAY_FROM(Float64Array, TYPED_ARRAY_FLOAT64)DEFINE_TYPEDARRAY_FROM(BigInt64Array, TYPED_ARRAY_BIGINT64)DEFINE_TYPEDARRAY_FROM(BigUint64Array, TYPED_ARRAY_BIGUINT64)
static ant_value_t js_dataview_constructor(ant_t *js, ant_value_t *args, int nargs) { if (vtype(js->new_target) == T_UNDEF) { return js_mkerr_typed(js, JS_ERR_TYPE, "DataView constructor requires 'new'"); } if (nargs < 1) { return js_mkerr(js, "DataView requires an ArrayBuffer"); } ArrayBufferData *buffer = buffer_get_arraybuffer_data(args[0]); if (!buffer) { return js_mkerr(js, "First argument must be an ArrayBuffer"); } size_t byte_offset = 0; size_t byte_length = buffer->length; if (nargs > 1 && vtype(args[1]) == T_NUM) { byte_offset = (size_t)js_getnum(args[1]); } if (byte_offset > buffer->length) { return js_mkerr(js, "Start offset is outside the bounds of the buffer"); } if (nargs > 2 && vtype(args[2]) == T_NUM) { byte_length = (size_t)js_getnum(args[2]); if (byte_length > buffer->length - byte_offset) { return js_mkerr(js, "Invalid DataView length"); } } else byte_length = buffer->length - byte_offset; DataViewData *dv_data = ta_meta_alloc(sizeof(DataViewData)); if (!dv_data) return js_mkerr(js, "Failed to allocate DataView"); dv_data->buffer = buffer; dv_data->byte_offset = byte_offset; dv_data->byte_length = byte_length; buffer->ref_count++; ant_value_t obj = js_mkobj(js); ant_value_t proto = js_get_ctor_proto(js, "DataView", 8); if (is_special_object(proto)) js_set_proto_init(obj, proto); js_set_native_ptr(obj, dv_data); js_set_native_tag(obj, BUFFER_DATAVIEW_NATIVE_TAG); js_set_slot(obj, SLOT_BRAND, js_mknum(BRAND_DATAVIEW)); js_mkprop_fast(js, obj, "buffer", 6, args[0]); js_set_descriptor(js, obj, "buffer", 6, 0);
js_set(js, obj, "byteLength", js_mknum((double)byte_length)); js_set(js, obj, "byteOffset", js_mknum((double)byte_offset)); js_set_finalizer(obj, dataview_finalize); return obj;}
// DataView.prototype.getUint8(byteOffset)static ant_value_t js_dataview_getInt8(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "getInt8 requires byteOffset"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); if (offset >= dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } int8_t value = (int8_t)dv->buffer->data[dv->byte_offset + offset]; return js_mknum((double)value);}
// DataView.prototype.setInt8(byteOffset, value)static ant_value_t js_dataview_setInt8(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "setInt8 requires byteOffset and value"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); int8_t value = (int8_t)js_to_int32(js_getnum(args[1])); if (offset >= dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } dv->buffer->data[dv->byte_offset + offset] = (uint8_t)value; return js_mkundef();}
// DataView.prototype.getUint8(byteOffset)static ant_value_t js_dataview_getUint8(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "getUint8 requires byteOffset"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); if (offset >= dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t value = dv->buffer->data[dv->byte_offset + offset]; return js_mknum((double)value);}
// DataView.prototype.setUint8(byteOffset, value)static ant_value_t js_dataview_setUint8(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "setUint8 requires byteOffset and value"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); uint8_t value = (uint8_t)js_to_uint32(js_getnum(args[1])); if (offset >= dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } dv->buffer->data[dv->byte_offset + offset] = value; return js_mkundef();}
// DataView.prototype.getInt16(byteOffset, littleEndian)static ant_value_t js_dataview_getInt16(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "getInt16 requires byteOffset"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); bool little_endian = (nargs > 1 && js_truthy(js, args[1])); if (offset + 2 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; int16_t value; if (little_endian) { value = (int16_t)(ptr[0] | (ptr[1] << 8)); } else { value = (int16_t)((ptr[0] << 8) | ptr[1]); } return js_mknum((double)value);}
// DataView.prototype.getUint16(byteOffset, littleEndian)static ant_value_t js_dataview_getUint16(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "getUint16 requires byteOffset"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); bool little_endian = (nargs > 1 && js_truthy(js, args[1])); if (offset + 2 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; uint16_t value; if (little_endian) value = (uint16_t)(ptr[0] | (ptr[1] << 8)); else value = (uint16_t)((ptr[0] << 8) | ptr[1]); return js_mknum((double)value);}
// DataView.prototype.setUint16(byteOffset, value, littleEndian)static ant_value_t js_dataview_setUint16(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "setUint16 requires byteOffset and value"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); uint16_t value = (uint16_t)js_to_uint32(js_getnum(args[1])); bool little_endian = (nargs > 2 && js_truthy(js, args[2])); if (offset + 2 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; if (little_endian) { ptr[0] = (uint8_t)(value & 0xFF); ptr[1] = (uint8_t)((value >> 8) & 0xFF); } else { ptr[0] = (uint8_t)((value >> 8) & 0xFF); ptr[1] = (uint8_t)(value & 0xFF); } return js_mkundef();}
// DataView.prototype.getInt32(byteOffset, littleEndian)static ant_value_t js_dataview_getInt32(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "getInt32 requires byteOffset"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); bool little_endian = (nargs > 1 && js_truthy(js, args[1])); if (offset + 4 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; int32_t value; if (little_endian) { value = (int32_t)(ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24)); } else { value = (int32_t)((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]); } return js_mknum((double)value);}
// DataView.prototype.getFloat32(byteOffset, littleEndian)static ant_value_t js_dataview_getFloat32(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "getFloat32 requires byteOffset"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); bool little_endian = (nargs > 1 && js_truthy(js, args[1])); if (offset + 4 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; uint32_t bits; if (little_endian) { bits = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); } else { bits = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]; } float value; memcpy(&value, &bits, 4); return js_mknum((double)value);}
// DataView.prototype.setInt16(byteOffset, value, littleEndian)static ant_value_t js_dataview_setInt16(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "setInt16 requires byteOffset and value"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); int16_t value = (int16_t)js_to_int32(js_getnum(args[1])); bool little_endian = (nargs > 2 && js_truthy(js, args[2])); if (offset + 2 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; if (little_endian) { ptr[0] = (uint8_t)(value & 0xFF); ptr[1] = (uint8_t)((value >> 8) & 0xFF); } else { ptr[0] = (uint8_t)((value >> 8) & 0xFF); ptr[1] = (uint8_t)(value & 0xFF); } return js_mkundef();}
// DataView.prototype.setInt32(byteOffset, value, littleEndian)static ant_value_t js_dataview_setInt32(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "setInt32 requires byteOffset and value"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); int32_t value = js_to_int32(js_getnum(args[1])); bool little_endian = (nargs > 2 && js_truthy(js, args[2])); if (offset + 4 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; if (little_endian) { ptr[0] = (uint8_t)(value & 0xFF); ptr[1] = (uint8_t)((value >> 8) & 0xFF); ptr[2] = (uint8_t)((value >> 16) & 0xFF); ptr[3] = (uint8_t)((value >> 24) & 0xFF); } else { ptr[0] = (uint8_t)((value >> 24) & 0xFF); ptr[1] = (uint8_t)((value >> 16) & 0xFF); ptr[2] = (uint8_t)((value >> 8) & 0xFF); ptr[3] = (uint8_t)(value & 0xFF); } return js_mkundef();}
// DataView.prototype.getUint32(byteOffset, littleEndian)static ant_value_t js_dataview_getUint32(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "getUint32 requires byteOffset"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); bool little_endian = (nargs > 1 && js_truthy(js, args[1])); if (offset + 4 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; uint32_t value; if (little_endian) value = (uint32_t)(ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24)); else value = (uint32_t)((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]); return js_mknum((double)value);}
// DataView.prototype.setUint32(byteOffset, value, littleEndian)static ant_value_t js_dataview_setUint32(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "setUint32 requires byteOffset and value"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); uint32_t value = js_to_uint32(js_getnum(args[1])); bool little_endian = (nargs > 2 && js_truthy(js, args[2])); if (offset + 4 > dv->byte_length) return js_mkerr(js, "Offset out of bounds"); uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; if (little_endian) { ptr[0] = (uint8_t)(value & 0xFF); ptr[1] = (uint8_t)((value >> 8) & 0xFF); ptr[2] = (uint8_t)((value >> 16) & 0xFF); ptr[3] = (uint8_t)((value >> 24) & 0xFF); } else { ptr[0] = (uint8_t)((value >> 24) & 0xFF); ptr[1] = (uint8_t)((value >> 16) & 0xFF); ptr[2] = (uint8_t)((value >> 8) & 0xFF); ptr[3] = (uint8_t)(value & 0xFF); } return js_mkundef();}
// DataView.prototype.setFloat32(byteOffset, value, littleEndian)static ant_value_t js_dataview_setFloat32(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "setFloat32 requires byteOffset and value"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); float value = (float)js_getnum(args[1]); bool little_endian = (nargs > 2 && js_truthy(js, args[2])); if (offset + 4 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; uint32_t bits; memcpy(&bits, &value, 4); if (little_endian) { ptr[0] = (uint8_t)(bits & 0xFF); ptr[1] = (uint8_t)((bits >> 8) & 0xFF); ptr[2] = (uint8_t)((bits >> 16) & 0xFF); ptr[3] = (uint8_t)((bits >> 24) & 0xFF); } else { ptr[0] = (uint8_t)((bits >> 24) & 0xFF); ptr[1] = (uint8_t)((bits >> 16) & 0xFF); ptr[2] = (uint8_t)((bits >> 8) & 0xFF); ptr[3] = (uint8_t)(bits & 0xFF); } return js_mkundef();}
// DataView.prototype.getFloat64(byteOffset, littleEndian)static ant_value_t js_dataview_getFloat64(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "getFloat64 requires byteOffset"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); bool little_endian = (nargs > 1 && js_truthy(js, args[1])); if (offset + 8 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; uint64_t bits; if (little_endian) { bits = (uint64_t)ptr[0] | ((uint64_t)ptr[1] << 8) | ((uint64_t)ptr[2] << 16) | ((uint64_t)ptr[3] << 24) | ((uint64_t)ptr[4] << 32) | ((uint64_t)ptr[5] << 40) | ((uint64_t)ptr[6] << 48) | ((uint64_t)ptr[7] << 56); } else { bits = ((uint64_t)ptr[0] << 56) | ((uint64_t)ptr[1] << 48) | ((uint64_t)ptr[2] << 40) | ((uint64_t)ptr[3] << 32) | ((uint64_t)ptr[4] << 24) | ((uint64_t)ptr[5] << 16) | ((uint64_t)ptr[6] << 8) | (uint64_t)ptr[7]; } double value; memcpy(&value, &bits, 8); return js_mknum(value);}
// DataView.prototype.setFloat64(byteOffset, value, littleEndian)static ant_value_t js_dataview_setFloat64(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "setFloat64 requires byteOffset and value"); ant_value_t this_val = js_getthis(js); DataViewData *dv = buffer_get_dataview_data(this_val); if (!dv) return js_mkerr(js, "Not a DataView"); size_t offset = (size_t)js_getnum(args[0]); double value = js_getnum(args[1]); bool little_endian = (nargs > 2 && js_truthy(js, args[2])); if (offset + 8 > dv->byte_length) { return js_mkerr(js, "Offset out of bounds"); } uint8_t *ptr = dv->buffer->data + dv->byte_offset + offset; uint64_t bits; memcpy(&bits, &value, 8); if (little_endian) { ptr[0] = (uint8_t)(bits & 0xFF); ptr[1] = (uint8_t)((bits >> 8) & 0xFF); ptr[2] = (uint8_t)((bits >> 16) & 0xFF); ptr[3] = (uint8_t)((bits >> 24) & 0xFF); ptr[4] = (uint8_t)((bits >> 32) & 0xFF); ptr[5] = (uint8_t)((bits >> 40) & 0xFF); ptr[6] = (uint8_t)((bits >> 48) & 0xFF); ptr[7] = (uint8_t)((bits >> 56) & 0xFF); } else { ptr[0] = (uint8_t)((bits >> 56) & 0xFF); ptr[1] = (uint8_t)((bits >> 48) & 0xFF); ptr[2] = (uint8_t)((bits >> 40) & 0xFF); ptr[3] = (uint8_t)((bits >> 32) & 0xFF); ptr[4] = (uint8_t)((bits >> 24) & 0xFF); ptr[5] = (uint8_t)((bits >> 16) & 0xFF); ptr[6] = (uint8_t)((bits >> 8) & 0xFF); ptr[7] = (uint8_t)(bits & 0xFF); } return js_mkundef();}
static uint8_t *hex_decode(const char *data, size_t len, size_t *out_len) { if (len % 2 != 0) return NULL; size_t decoded_len = len / 2; uint8_t *decoded = malloc(decoded_len); if (!decoded) return NULL; for (size_t i = 0; i < decoded_len; i++) { unsigned int byte; if (sscanf(data + i * 2, "%2x", &byte) != 1) { free(decoded); return NULL; } decoded[i] = (uint8_t)byte; } *out_len = decoded_len; return decoded;}
typedef enum { ENC_UTF8, ENC_HEX, ENC_BASE64, ENC_ASCII, ENC_LATIN1, ENC_UCS2, ENC_UNKNOWN} BufferEncoding;
static BufferEncoding parse_encoding(const char *enc, size_t len) { if (len == 3 && strncasecmp(enc, "hex", 3) == 0) return ENC_HEX; if (len == 5 && strncasecmp(enc, "ascii", 5) == 0) return ENC_ASCII; if (len == 6 && strncasecmp(enc, "base64", 6) == 0) return ENC_BASE64; if ((len == 4 && strncasecmp(enc, "utf8", 4) == 0) || (len == 5 && strncasecmp(enc, "utf-8", 5) == 0)) return ENC_UTF8; if ((len == 6 && strncasecmp(enc, "latin1", 6) == 0) || (len == 6 && strncasecmp(enc, "binary", 6) == 0)) return ENC_LATIN1; if ( (len == 4 && strncasecmp(enc, "ucs2", 4) == 0) || (len == 5 && strncasecmp(enc, "ucs-2", 5) == 0) || (len == 7 && strncasecmp(enc, "utf16le", 7) == 0) || (len == 8 && strncasecmp(enc, "utf-16le", 8) == 0) ) return ENC_UCS2; return ENC_UNKNOWN;}
// Buffer.from(array/string/buffer, encoding)static ant_value_t js_buffer_from(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "Buffer.from requires at least one argument"); if (vtype(args[0]) == T_STR) { size_t len; char *str = js_getstr(js, args[0], &len); BufferEncoding encoding = ENC_UTF8; if (nargs >= 2 && vtype(args[1]) == T_STR) { size_t enc_len; char *enc_str = js_getstr(js, args[1], &enc_len); encoding = parse_encoding(enc_str, enc_len); if (encoding == ENC_UNKNOWN) encoding = ENC_UTF8; } if (encoding == ENC_BASE64) { size_t decoded_len; uint8_t *decoded = ant_base64_decode(str, len, &decoded_len); if (!decoded) return js_mkerr(js, "Failed to decode base64"); ArrayBufferData *buffer = create_array_buffer_data(decoded_len); if (!buffer) { free(decoded); return js_mkerr(js, "Failed to allocate buffer"); } memcpy(buffer->data, decoded, decoded_len); free(decoded); return create_typed_array(js, TYPED_ARRAY_UINT8, buffer, 0, decoded_len, "Buffer"); } else if (encoding == ENC_HEX) { size_t decoded_len; uint8_t *decoded = hex_decode(str, len, &decoded_len); if (!decoded) return js_mkerr(js, "Failed to decode hex"); ArrayBufferData *buffer = create_array_buffer_data(decoded_len); if (!buffer) { free(decoded); return js_mkerr(js, "Failed to allocate buffer"); } memcpy(buffer->data, decoded, decoded_len); free(decoded); return create_typed_array(js, TYPED_ARRAY_UINT8, buffer, 0, decoded_len, "Buffer"); } else if (encoding == ENC_UCS2) { size_t decoded_len = len * 2; ArrayBufferData *buffer = create_array_buffer_data(decoded_len); if (!buffer) return js_mkerr(js, "Failed to allocate buffer"); for (size_t i = 0; i < len; i++) { buffer->data[i * 2] = (uint8_t)str[i]; buffer->data[i * 2 + 1] = 0; } return create_typed_array(js, TYPED_ARRAY_UINT8, buffer, 0, decoded_len, "Buffer"); } else { ArrayBufferData *buffer = create_array_buffer_data(len); if (!buffer) return js_mkerr(js, "Failed to allocate buffer"); memcpy(buffer->data, str, len); return create_typed_array(js, TYPED_ARRAY_UINT8, buffer, 0, len, "Buffer"); } } ant_value_t length_val = js_get(js, args[0], "length"); if (vtype(length_val) == T_NUM) { size_t len = (size_t)js_getnum(length_val); ArrayBufferData *buffer = create_array_buffer_data(len); if (!buffer) return js_mkerr(js, "Failed to allocate buffer"); for (size_t i = 0; i < len; i++) { char idx_str[32]; snprintf(idx_str, sizeof(idx_str), "%zu", i); ant_value_t elem = js_get(js, args[0], idx_str); if (vtype(elem) == T_NUM) { buffer->data[i] = (uint8_t)js_getnum(elem); } } return create_typed_array(js, TYPED_ARRAY_UINT8, buffer, 0, len, "Buffer"); } return js_mkerr(js, "Invalid argument to Buffer.from");}
// Buffer.alloc(size)static ant_value_t js_buffer_alloc(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) { return js_mkerr(js, "Buffer.alloc requires a size argument"); } size_t size = (size_t)js_getnum(args[0]); ArrayBufferData *buffer = create_array_buffer_data(size); if (!buffer) return js_mkerr(js, "Failed to allocate buffer"); memset(buffer->data, 0, size); return create_typed_array(js, TYPED_ARRAY_UINT8, buffer, 0, size, "Buffer");}
// Buffer.allocUnsafe(size)static ant_value_t js_buffer_allocUnsafe(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) { return js_mkerr(js, "Buffer.allocUnsafe requires a size argument"); } size_t size = (size_t)js_getnum(args[0]); ArrayBufferData *buffer = create_array_buffer_data(size); if (!buffer) return js_mkerr(js, "Failed to allocate buffer"); return create_typed_array(js, TYPED_ARRAY_UINT8, buffer, 0, size, "Buffer");}
static ant_value_t typedarray_join_with(ant_t *js, ant_value_t this_val, const char *sep, size_t sep_len) { TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkstr(js, "", 0); if (!ta_data->buffer || ta_data->buffer->is_detached || ta_data->length == 0) return js_mkstr(js, "", 0);
uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; size_t len = ta_data->length;
size_t cap = len * 12; char *buf = malloc(cap); if (!buf) return js_mkerr(js, "Out of memory"); size_t pos = 0;
for (size_t i = 0; i < len; i++) { if (i > 0) { if (pos + sep_len + 32 > cap) { cap *= 2; char *tmp = realloc(buf, cap); if (!tmp) { free(buf); return js_mkerr(js, "Out of memory"); } buf = tmp; } memcpy(buf + pos, sep, sep_len); pos += sep_len; }
if (pos + 32 > cap) { cap *= 2; char *tmp = realloc(buf, cap); if (!tmp) { free(buf); return js_mkerr(js, "Out of memory"); } buf = tmp; }
int written = 0; switch (ta_data->type) { case TYPED_ARRAY_INT8: written = snprintf(buf + pos, cap - pos, "%d", ((int8_t*)data)[i]); break; case TYPED_ARRAY_UINT8: case TYPED_ARRAY_UINT8_CLAMPED: written = snprintf(buf + pos, cap - pos, "%u", data[i]); break; case TYPED_ARRAY_INT16: written = snprintf(buf + pos, cap - pos, "%d", ((int16_t*)data)[i]); break; case TYPED_ARRAY_UINT16: written = snprintf(buf + pos, cap - pos, "%u", ((uint16_t*)data)[i]); break; case TYPED_ARRAY_INT32: written = snprintf(buf + pos, cap - pos, "%d", ((int32_t*)data)[i]); break; case TYPED_ARRAY_UINT32: written = snprintf(buf + pos, cap - pos, "%u", ((uint32_t*)data)[i]); break; case TYPED_ARRAY_FLOAT16: written = snprintf(buf + pos, cap - pos, "%g", half_to_double(((uint16_t*)data)[i])); break; case TYPED_ARRAY_FLOAT32: written = snprintf(buf + pos, cap - pos, "%g", (double)((float*)data)[i]); break; case TYPED_ARRAY_FLOAT64: written = snprintf(buf + pos, cap - pos, "%g", ((double*)data)[i]); break; case TYPED_ARRAY_BIGINT64: written = snprintf(buf + pos, cap - pos, "%lld", ((long long*)data)[i]); break; case TYPED_ARRAY_BIGUINT64: written = snprintf(buf + pos, cap - pos, "%llu", ((unsigned long long*)data)[i]); break; default: break; } if (written > 0) pos += (size_t)written; }
ant_value_t ret = js_mkstr(js, buf, pos); free(buf); return ret;}
// TypedArray.prototype.toString()static ant_value_t js_typedarray_toString(ant_t *js, ant_value_t *args, int nargs) { return typedarray_join_with(js, js_getthis(js), ",", 1);}
// TypedArray.prototype.join(separator)static ant_value_t js_typedarray_join(ant_t *js, ant_value_t *args, int nargs) { const char *sep = ","; size_t sep_len = 1; if (nargs > 0 && vtype(args[0]) == T_STR) sep = js_getstr(js, args[0], &sep_len); return typedarray_join_with(js, js_getthis(js), sep, sep_len);}
static ant_value_t js_typedarray_indexOf(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data || !ta_data->buffer || ta_data->buffer->is_detached) return js_mknum(-1);
size_t len = ta_data->length; if (len == 0 || nargs < 1) return js_mknum(-1);
int64_t from_index = 0; if (nargs > 1 && vtype(args[1]) != T_UNDEF) { from_index = (int64_t)js_to_number(js, args[1]); if (from_index < 0) { from_index += (int64_t)len; if (from_index < 0) from_index = 0; }} if ((size_t)from_index >= len) return js_mknum(-1); uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; double needle_num = js_to_number(js, args[0]);
for (size_t i = (size_t)from_index; i < len; i++) { bool match = false; switch (ta_data->type) { case TYPED_ARRAY_INT8: match = ((int8_t *)data)[i] == (int8_t)needle_num; break; case TYPED_ARRAY_UINT8: case TYPED_ARRAY_UINT8_CLAMPED: match = data[i] == (uint8_t)needle_num; break; case TYPED_ARRAY_INT16: match = ((int16_t *)data)[i] == (int16_t)needle_num; break; case TYPED_ARRAY_UINT16: match = ((uint16_t *)data)[i] == (uint16_t)needle_num; break; case TYPED_ARRAY_INT32: match = ((int32_t *)data)[i] == (int32_t)needle_num; break; case TYPED_ARRAY_UINT32: match = ((uint32_t *)data)[i] == (uint32_t)needle_num; break; case TYPED_ARRAY_FLOAT16: match = half_to_double(((uint16_t *)data)[i]) == needle_num; break; case TYPED_ARRAY_FLOAT32: match = ((float *)data)[i] == (float)needle_num; break; case TYPED_ARRAY_FLOAT64: match = ((double *)data)[i] == needle_num; break; case TYPED_ARRAY_BIGINT64: match = ((int64_t *)data)[i] == (int64_t)needle_num; break; case TYPED_ARRAY_BIGUINT64: match = ((uint64_t *)data)[i] == (uint64_t)needle_num; break; default: break; } if (match) return js_mknum((double)i); }
return js_mknum(-1);}
// Buffer.prototype.toString(encoding)static ant_value_t js_buffer_slice(ant_t *js, ant_value_t *args, int nargs) { return js_typedarray_subarray(js, args, nargs);}
// Buffer.prototype.toString(encoding)static ant_value_t js_buffer_toString(ant_t *js, ant_value_t *args, int nargs) { ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid Buffer"); BufferEncoding encoding = ENC_UTF8; if (nargs > 0 && vtype(args[0]) == T_STR) { size_t enc_len; char *enc_str = js_getstr(js, args[0], &enc_len); encoding = parse_encoding(enc_str, enc_len); if (encoding == ENC_UNKNOWN) encoding = ENC_UTF8; } if (!ta_data->buffer || ta_data->buffer->is_detached) { return js_mkerr(js, "Cannot read from detached buffer"); } uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; size_t len = ta_data->byte_length; if (encoding == ENC_BASE64) { size_t out_len; char *encoded = ant_base64_encode(data, len, &out_len); if (!encoded) return js_mkerr(js, "Failed to encode base64"); ant_value_t result = js_mkstr(js, encoded, out_len); free(encoded); return result; } else if (encoding == ENC_HEX) { char *hex = malloc(len * 2 + 1); if (!hex) return js_mkerr(js, "Failed to allocate hex string"); for (size_t i = 0; i < len; i++) { snprintf(hex + i * 2, 3, "%02x", data[i]); } ant_value_t result = js_mkstr(js, hex, len * 2); free(hex); return result; } else if (encoding == ENC_UCS2) { size_t char_count = len / 2; char *str = malloc(char_count + 1); if (!str) return js_mkerr(js, "Failed to allocate string"); for (size_t i = 0; i < char_count; i++) str[i] = (char)data[i * 2]; str[char_count] = '\0'; ant_value_t result = js_mkstr(js, str, char_count); free(str); return result; } else { size_t out_cap = len * 3 + 1; char *out = malloc(out_cap); if (!out) return js_mkerr(js, "Failed to allocate string"); utf8_dec_t dec = { .bom_seen = true, .ignore_bom = true }; utf8proc_ssize_t out_len = utf8_whatwg_decode(&dec, data, len, out, false, false); if (out_len < 0) { free(out); return js_mkerr(js, "Failed to decode buffer as UTF-8"); } ant_value_t result = js_mkstr(js, out, (size_t)out_len); free(out); return result; }}
// Buffer.prototype.toBase64()static ant_value_t js_buffer_toBase64(ant_t *js, ant_value_t *args, int nargs) { (void)args; (void)nargs; ant_value_t encoding_arg = js_mkstr(js, "base64", 6); ant_value_t new_args[1] = {encoding_arg}; return js_buffer_toString(js, new_args, 1);}
// Buffer.prototype.write(string, offset, length, encoding)static ant_value_t js_buffer_write(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "write requires a string"); ant_value_t this_val = js_getthis(js); TypedArrayData *ta_data = buffer_get_typedarray_data(this_val); if (!ta_data) return js_mkerr(js, "Invalid Buffer"); size_t str_len; char *str = js_getstr(js, args[0], &str_len); size_t offset = 0; size_t length = ta_data->byte_length; if (nargs > 1 && vtype(args[1]) == T_NUM) { offset = (size_t)js_getnum(args[1]); } if (nargs > 2 && vtype(args[2]) == T_NUM) { length = (size_t)js_getnum(args[2]); } if (offset >= ta_data->byte_length) { return js_mknum(0); } size_t available = ta_data->byte_length - offset; size_t to_write = (str_len < length) ? str_len : length; to_write = (to_write < available) ? to_write : available; memcpy(ta_data->buffer->data + ta_data->byte_offset + offset, str, to_write); return js_mknum((double)to_write);}
static ant_value_t js_buffer_copy(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "copy requires a target buffer");
TypedArrayData *src = buffer_get_typedarray_data(js_getthis(js)); TypedArrayData *dst = buffer_get_typedarray_data(args[0]); if (!src || !dst) return js_mkerr(js, "copy requires Buffer arguments");
size_t target_start = (nargs > 1 && vtype(args[1]) == T_NUM) ? (size_t)js_getnum(args[1]) : 0; size_t source_start = (nargs > 2 && vtype(args[2]) == T_NUM) ? (size_t)js_getnum(args[2]) : 0; size_t source_end = (nargs > 3 && vtype(args[3]) == T_NUM) ? (size_t)js_getnum(args[3]) : src->byte_length;
if (target_start > dst->byte_length) target_start = dst->byte_length; if (source_start > src->byte_length) source_start = src->byte_length; if (source_end > src->byte_length) source_end = src->byte_length; if (source_end < source_start) source_end = source_start;
size_t src_len = source_end - source_start; size_t dst_len = dst->byte_length - target_start; size_t copy_len = src_len < dst_len ? src_len : dst_len; if (copy_len == 0) return js_mknum(0);
uint8_t *src_ptr = src->buffer->data + src->byte_offset + source_start; uint8_t *dst_ptr = dst->buffer->data + dst->byte_offset + target_start; memmove(dst_ptr, src_ptr, copy_len); return js_mknum((double)copy_len);}
static ant_value_t js_buffer_writeInt16BE(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "writeInt16BE requires a value");
TypedArrayData *ta = buffer_get_typedarray_data(js_getthis(js)); if (!ta) return js_mkerr(js, "Invalid Buffer");
int16_t value = (int16_t)js_to_int32(js_getnum(args[0])); size_t offset = (nargs > 1 && vtype(args[1]) == T_NUM) ? (size_t)js_getnum(args[1]) : 0; if (offset + 2 > ta->byte_length) return js_mkerr(js, "Offset out of bounds");
uint8_t *ptr = ta->buffer->data + ta->byte_offset + offset; ptr[0] = (uint8_t)((value >> 8) & 0xff); ptr[1] = (uint8_t)(value & 0xff); return js_mknum((double)(offset + 2));}
static ant_value_t js_buffer_writeInt32BE(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "writeInt32BE requires a value");
TypedArrayData *ta = buffer_get_typedarray_data(js_getthis(js)); if (!ta) return js_mkerr(js, "Invalid Buffer");
int32_t value = js_to_int32(js_getnum(args[0])); size_t offset = (nargs > 1 && vtype(args[1]) == T_NUM) ? (size_t)js_getnum(args[1]) : 0; if (offset + 4 > ta->byte_length) return js_mkerr(js, "Offset out of bounds");
uint8_t *ptr = ta->buffer->data + ta->byte_offset + offset; ptr[0] = (uint8_t)((value >> 24) & 0xff); ptr[1] = (uint8_t)((value >> 16) & 0xff); ptr[2] = (uint8_t)((value >> 8) & 0xff); ptr[3] = (uint8_t)(value & 0xff); return js_mknum((double)(offset + 4));}
static ant_value_t js_buffer_writeUInt32BE(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "writeUInt32BE requires a value");
TypedArrayData *ta = buffer_get_typedarray_data(js_getthis(js)); if (!ta) return js_mkerr(js, "Invalid Buffer");
uint32_t value = js_to_uint32(js_getnum(args[0])); size_t offset = (nargs > 1 && vtype(args[1]) == T_NUM) ? (size_t)js_getnum(args[1]) : 0; if (offset + 4 > ta->byte_length) return js_mkerr(js, "Offset out of bounds");
uint8_t *ptr = ta->buffer->data + ta->byte_offset + offset; ptr[0] = (uint8_t)((value >> 24) & 0xff); ptr[1] = (uint8_t)((value >> 16) & 0xff); ptr[2] = (uint8_t)((value >> 8) & 0xff); ptr[3] = (uint8_t)(value & 0xff); return js_mknum((double)(offset + 4));}
static ant_value_t js_buffer_readInt16BE(ant_t *js, ant_value_t *args, int nargs) { TypedArrayData *ta = buffer_get_typedarray_data(js_getthis(js)); if (!ta) return js_mkerr(js, "Invalid Buffer");
size_t offset = (nargs > 0 && vtype(args[0]) == T_NUM) ? (size_t)js_getnum(args[0]) : 0; if (offset + 2 > ta->byte_length) return js_mkerr(js, "Offset out of bounds");
uint8_t *ptr = ta->buffer->data + ta->byte_offset + offset; int16_t value = (int16_t)((ptr[0] << 8) | ptr[1]); return js_mknum((double)value);}
static ant_value_t js_buffer_readInt32BE(ant_t *js, ant_value_t *args, int nargs) { TypedArrayData *ta = buffer_get_typedarray_data(js_getthis(js)); if (!ta) return js_mkerr(js, "Invalid Buffer");
size_t offset = (nargs > 0 && vtype(args[0]) == T_NUM) ? (size_t)js_getnum(args[0]) : 0; if (offset + 4 > ta->byte_length) return js_mkerr(js, "Offset out of bounds");
uint8_t *ptr = ta->buffer->data + ta->byte_offset + offset; int32_t value = (int32_t)(((uint32_t)ptr[0] << 24) | ((uint32_t)ptr[1] << 16) | ((uint32_t)ptr[2] << 8) | (uint32_t)ptr[3]); return js_mknum((double)value);}
static ant_value_t js_buffer_readUInt32BE(ant_t *js, ant_value_t *args, int nargs) { TypedArrayData *ta = buffer_get_typedarray_data(js_getthis(js)); if (!ta) return js_mkerr(js, "Invalid Buffer");
size_t offset = (nargs > 0 && vtype(args[0]) == T_NUM) ? (size_t)js_getnum(args[0]) : 0; if (offset + 4 > ta->byte_length) return js_mkerr(js, "Offset out of bounds");
uint8_t *ptr = ta->buffer->data + ta->byte_offset + offset; uint32_t value = ((uint32_t)ptr[0] << 24) | ((uint32_t)ptr[1] << 16) | ((uint32_t)ptr[2] << 8) | (uint32_t)ptr[3]; return js_mknum((double)value);}
// Buffer.isBuffer(obj)static ant_value_t js_buffer_isBuffer(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_false; if (!is_special_object(args[0])) return js_false; ant_value_t proto = js_get_proto(js, args[0]); ant_value_t buffer_proto = js_get_ctor_proto(js, "Buffer", 6); return js_bool(proto == buffer_proto);}
// Buffer.isEncoding(encoding)static ant_value_t js_buffer_isEncoding(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1 || vtype(args[0]) != T_STR) return js_false; size_t len; char *enc = js_getstr(js, args[0], &len); if ((len == 4 && strncasecmp(enc, "utf8", 4) == 0) || (len == 5 && strncasecmp(enc, "utf-8", 5) == 0) || (len == 3 && strncasecmp(enc, "hex", 3) == 0) || (len == 6 && strncasecmp(enc, "base64", 6) == 0) || (len == 5 && strncasecmp(enc, "ascii", 5) == 0) || (len == 6 && strncasecmp(enc, "latin1", 6) == 0) || (len == 6 && strncasecmp(enc, "binary", 6) == 0) || (len == 4 && strncasecmp(enc, "ucs2", 4) == 0) || (len == 5 && strncasecmp(enc, "ucs-2", 5) == 0) || (len == 7 && strncasecmp(enc, "utf16le", 7) == 0) || (len == 8 && strncasecmp(enc, "utf-16le", 8) == 0)) { return js_true; } return js_false;}
// Buffer.byteLength(string, encoding)static ant_value_t js_buffer_byteLength(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mknum(0); ant_value_t arg = args[0]; if (is_special_object(arg)) { ant_value_t bytelen = js_get(js, arg, "byteLength"); if (vtype(bytelen) == T_NUM) return bytelen; ant_value_t len = js_get(js, arg, "length"); if (vtype(len) == T_NUM) return len; } if (vtype(arg) == T_STR) { size_t len; js_getstr(js, arg, &len); return js_mknum((double)len); } return js_mknum(0);}
// Buffer.concat(list, totalLength)static ant_value_t js_buffer_concat(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1 || !is_special_object(args[0])) { return js_mkerr(js, "First argument must be an array"); } ant_value_t list = args[0]; ant_value_t len_val = js_get(js, list, "length"); if (vtype(len_val) != T_NUM) { return js_mkerr(js, "First argument must be an array"); } size_t list_len = (size_t)js_getnum(len_val); size_t total_length = 0; if (nargs > 1 && vtype(args[1]) == T_NUM) { total_length = (size_t)js_getnum(args[1]); } else { for (size_t i = 0; i < list_len; i++) { char idx[16]; snprintf(idx, sizeof(idx), "%zu", i); ant_value_t buf = js_get(js, list, idx); ant_value_t buf_len = js_get(js, buf, "length"); if (vtype(buf_len) == T_NUM) total_length += (size_t)js_getnum(buf_len); } } ArrayBufferData *buffer = create_array_buffer_data(total_length); if (!buffer) return js_mkerr(js, "Failed to allocate buffer"); size_t offset = 0; for (size_t i = 0; i < list_len && offset < total_length; i++) { char idx[16]; snprintf(idx, sizeof(idx), "%zu", i); ant_value_t buf = js_get(js, list, idx); TypedArrayData *ta = buffer_get_typedarray_data(buf); if (!ta || !ta->buffer) continue; size_t copy_len = ta->byte_length; if (offset + copy_len > total_length) { copy_len = total_length - offset; } memcpy(buffer->data + offset, ta->buffer->data + ta->byte_offset, copy_len); offset += copy_len; } return create_typed_array(js, TYPED_ARRAY_UINT8, buffer, 0, total_length, "Buffer");}
// Buffer.compare(buf1, buf2)static ant_value_t js_buffer_compare(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 2) return js_mkerr(js, "Buffer.compare requires two arguments"); TypedArrayData *ta1 = buffer_get_typedarray_data(args[0]); TypedArrayData *ta2 = buffer_get_typedarray_data(args[1]); if (!ta1 || !ta2) { return js_mkerr(js, "Arguments must be Buffers"); } if (!ta1 || !ta1->buffer || !ta2 || !ta2->buffer) { return js_mkerr(js, "Invalid buffer"); } size_t len = ta1->byte_length < ta2->byte_length ? ta1->byte_length : ta2->byte_length; int cmp = memcmp(ta1->buffer->data + ta1->byte_offset, ta2->buffer->data + ta2->byte_offset, len); if (cmp == 0) { if (ta1->byte_length < ta2->byte_length) cmp = -1; else if (ta1->byte_length > ta2->byte_length) cmp = 1; } else cmp = cmp < 0 ? -1 : 1; return js_mknum((double)cmp);}
static ant_value_t js_sharedarraybuffer_constructor(ant_t *js, ant_value_t *args, int nargs) { if (vtype(js->new_target) == T_UNDEF) { return js_mkerr_typed(js, JS_ERR_TYPE, "SharedArrayBuffer constructor requires 'new'"); } size_t length = 0; if (nargs > 0 && vtype(args[0]) == T_NUM) { length = (size_t)js_getnum(args[0]); } ArrayBufferData *data = create_shared_array_buffer_data(length); if (!data) { return js_mkerr(js, "Failed to allocate SharedArrayBuffer"); } ant_value_t obj = js_mkobj(js); ant_value_t proto = js_get_ctor_proto(js, "SharedArrayBuffer", 17);
if (is_special_object(proto)) js_set_proto_init(obj, proto); js_set_native_ptr(obj, data); js_set_native_tag(obj, BUFFER_ARRAYBUFFER_NATIVE_TAG); js_set(js, obj, "byteLength", js_mknum((double)length)); js_set_finalizer(obj, arraybuffer_finalize); return obj;}
static ant_value_t buffer_make_constants(ant_t *js) { ant_value_t constants = js_newobj(js); js_set(js, constants, "MAX_LENGTH", js_mknum(BUFFER_COMPAT_MAX_LENGTH)); js_set(js, constants, "MAX_STRING_LENGTH", js_mknum(BUFFER_COMPAT_MAX_STRING_LENGTH)); return constants;}
ant_value_t buffer_library(ant_t *js) { ant_value_t glob = js_glob(js); ant_value_t lib = js_newobj(js);
js_set(js, lib, "Buffer", js_get(js, glob, "Buffer")); js_set(js, lib, "Blob", js_get(js, glob, "Blob")); js_set(js, lib, "File", js_get(js, glob, "File")); js_set(js, lib, "atob", js_get(js, glob, "atob")); js_set(js, lib, "btoa", js_get(js, glob, "btoa")); js_set(js, lib, "constants", buffer_make_constants(js)); js_set(js, lib, "kMaxLength", js_mknum(BUFFER_COMPAT_MAX_LENGTH)); js_set(js, lib, "kStringMaxLength", js_mknum(BUFFER_COMPAT_MAX_STRING_LENGTH)); js_set(js, lib, "INSPECT_MAX_BYTES", js_mknum(BUFFER_COMPAT_INSPECT_MAX_BYTES));
return lib;}
void init_buffer_module() { ant_t *js = rt->js; ant_value_t glob = js->global; ant_value_t object_proto = js->sym.object_proto;
ant_value_t arraybuffer_ctor_obj = js_mkobj(js); ant_value_t arraybuffer_proto = js_mkobj(js); js_set_proto_init(arraybuffer_proto, object_proto); js_set(js, arraybuffer_proto, "slice", js_mkfun(js_arraybuffer_slice)); js_set(js, arraybuffer_proto, "transfer", js_mkfun(js_arraybuffer_transfer)); js_set(js, arraybuffer_proto, "transferToFixedLength", js_mkfun(js_arraybuffer_transferToFixedLength)); js_set_getter_desc(js, arraybuffer_proto, "detached", 8, js_mkfun(js_arraybuffer_detached_getter), JS_DESC_E); js_set_sym(js, arraybuffer_proto, get_toStringTag_sym(), js_mkstr(js, "ArrayBuffer", 11)); js_set_slot(arraybuffer_ctor_obj, SLOT_CFUNC, js_mkfun(js_arraybuffer_constructor)); js_mkprop_fast(js, arraybuffer_ctor_obj, "prototype", 9, arraybuffer_proto); js_mkprop_fast(js, arraybuffer_ctor_obj, "name", 4, ANT_STRING("ArrayBuffer")); js_set_descriptor(js, arraybuffer_ctor_obj, "name", 4, 0); js_define_species_getter(js, arraybuffer_ctor_obj); ant_value_t arraybuffer_ctor = js_obj_to_func(arraybuffer_ctor_obj); js_set(js, arraybuffer_proto, "constructor", arraybuffer_ctor); js_set_descriptor(js, arraybuffer_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); js_set(js, glob, "ArrayBuffer", arraybuffer_ctor); ant_value_t typedarray_proto = js_mkobj(js); js_set_proto_init(typedarray_proto, object_proto); js_set(js, typedarray_proto, "at", js_mkfun(js_typedarray_at)); js_set(js, typedarray_proto, "set", js_mkfun(js_typedarray_set)); js_set(js, typedarray_proto, "copyWithin", js_mkfun(js_typedarray_copyWithin)); js_set(js, typedarray_proto, "slice", js_mkfun(js_typedarray_slice)); js_set(js, typedarray_proto, "subarray", js_mkfun(js_typedarray_subarray)); js_set(js, typedarray_proto, "fill", js_mkfun(js_typedarray_fill)); js_set(js, typedarray_proto, "toReversed", js_mkfun(js_typedarray_toReversed)); js_set(js, typedarray_proto, "toSorted", js_mkfun(js_typedarray_toSorted)); js_set(js, typedarray_proto, "with", js_mkfun(js_typedarray_with)); js_set(js, typedarray_proto, "toString", js_mkfun(js_typedarray_toString)); js_set(js, typedarray_proto, "join", js_mkfun(js_typedarray_join)); js_set(js, typedarray_proto, "indexOf", js_mkfun(js_typedarray_indexOf)); js_set_sym(js, typedarray_proto, get_toStringTag_sym(), js_mkstr(js, "TypedArray", 10));
g_typedarray_iter_proto = js_mkobj(js); js_set_proto_init(g_typedarray_iter_proto, js->sym.iterator_proto); js_set(js, g_typedarray_iter_proto, "next", js_mkfun(ta_iter_next)); js_iter_register_advance(g_typedarray_iter_proto, advance_typedarray);
ant_value_t ta_values_fn = js_mkfun(ta_values); js_set(js, typedarray_proto, "values", ta_values_fn); js_set(js, typedarray_proto, "keys", js_mkfun(ta_keys)); js_set(js, typedarray_proto, "entries", js_mkfun(ta_entries)); js_set_sym(js, typedarray_proto, get_iterator_sym(), ta_values_fn); #define SETUP_TYPEDARRAY(name) \ do { \ ant_value_t name##_ctor_obj = js_mkobj(js); \ ant_value_t name##_proto = js_mkobj(js); \ js_set_proto_init(name##_proto, typedarray_proto); \ js_set_sym(js, name##_proto, get_toStringTag_sym(), js_mkstr(js, #name, sizeof(#name) - 1)); \ js_set_slot(name##_ctor_obj, SLOT_CFUNC, js_mkfun(js_##name##_constructor)); \ js_setprop(js, name##_ctor_obj, js_mkstr(js, "prototype", 9), name##_proto); \ js_mkprop_fast(js, name##_ctor_obj, "name", 4, ANT_STRING(#name)); \ js_set_descriptor(js, name##_ctor_obj, "name", 4, 0); \ js_define_species_getter(js, name##_ctor_obj); \ js_set(js, name##_ctor_obj, "from", js_mkfun(js_##name##_from)); \ ant_value_t name##_ctor = js_obj_to_func(name##_ctor_obj); \ js_setprop(js, name##_proto, ANT_STRING("constructor"), name##_ctor); \ js_set_descriptor(js, name##_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); \ js_set(js, glob, #name, name##_ctor); \ } while(0) SETUP_TYPEDARRAY(Int8Array); SETUP_TYPEDARRAY(Uint8Array); SETUP_TYPEDARRAY(Uint8ClampedArray); SETUP_TYPEDARRAY(Int16Array); SETUP_TYPEDARRAY(Uint16Array); SETUP_TYPEDARRAY(Int32Array); SETUP_TYPEDARRAY(Uint32Array); SETUP_TYPEDARRAY(Float16Array); SETUP_TYPEDARRAY(Float32Array); SETUP_TYPEDARRAY(Float64Array); SETUP_TYPEDARRAY(BigInt64Array); SETUP_TYPEDARRAY(BigUint64Array); ant_value_t dataview_ctor_obj = js_mkobj(js); ant_value_t dataview_proto = js_mkobj(js); js_set_proto_init(dataview_proto, object_proto); js_set(js, dataview_proto, "getInt8", js_mkfun(js_dataview_getInt8)); js_set(js, dataview_proto, "setInt8", js_mkfun(js_dataview_setInt8)); js_set(js, dataview_proto, "getUint8", js_mkfun(js_dataview_getUint8)); js_set(js, dataview_proto, "setUint8", js_mkfun(js_dataview_setUint8)); js_set(js, dataview_proto, "getInt16", js_mkfun(js_dataview_getInt16)); js_set(js, dataview_proto, "setInt16", js_mkfun(js_dataview_setInt16)); js_set(js, dataview_proto, "getUint16", js_mkfun(js_dataview_getUint16)); js_set(js, dataview_proto, "setUint16", js_mkfun(js_dataview_setUint16)); js_set(js, dataview_proto, "getInt32", js_mkfun(js_dataview_getInt32)); js_set(js, dataview_proto, "setInt32", js_mkfun(js_dataview_setInt32)); js_set(js, dataview_proto, "getUint32", js_mkfun(js_dataview_getUint32)); js_set(js, dataview_proto, "setUint32", js_mkfun(js_dataview_setUint32)); js_set(js, dataview_proto, "getFloat32", js_mkfun(js_dataview_getFloat32)); js_set(js, dataview_proto, "setFloat32", js_mkfun(js_dataview_setFloat32)); js_set(js, dataview_proto, "getFloat64", js_mkfun(js_dataview_getFloat64)); js_set(js, dataview_proto, "setFloat64", js_mkfun(js_dataview_setFloat64)); js_set_sym(js, dataview_proto, get_toStringTag_sym(), js_mkstr(js, "DataView", 8));
js_set_slot(dataview_ctor_obj, SLOT_CFUNC, js_mkfun(js_dataview_constructor)); js_mkprop_fast(js, dataview_ctor_obj, "prototype", 9, dataview_proto); js_mkprop_fast(js, dataview_ctor_obj, "name", 4, ANT_STRING("DataView")); js_set_descriptor(js, dataview_ctor_obj, "name", 4, 0); ant_value_t dataview_ctor = js_obj_to_func(dataview_ctor_obj); js_set(js, dataview_proto, "constructor", dataview_ctor); js_set_descriptor(js, dataview_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); js_set(js, glob, "DataView", dataview_ctor); ant_value_t sharedarraybuffer_ctor_obj = js_mkobj(js); ant_value_t sharedarraybuffer_proto = js_mkobj(js); js_set_proto_init(sharedarraybuffer_proto, object_proto); js_set(js, sharedarraybuffer_proto, "slice", js_mkfun(js_arraybuffer_slice)); js_set_sym(js, sharedarraybuffer_proto, get_toStringTag_sym(), js_mkstr(js, "SharedArrayBuffer", 17)); js_set_slot(sharedarraybuffer_ctor_obj, SLOT_CFUNC, js_mkfun(js_sharedarraybuffer_constructor)); js_mkprop_fast(js, sharedarraybuffer_ctor_obj, "prototype", 9, sharedarraybuffer_proto); js_mkprop_fast(js, sharedarraybuffer_ctor_obj, "name", 4, ANT_STRING("SharedArrayBuffer")); js_set_descriptor(js, sharedarraybuffer_ctor_obj, "name", 4, 0); ant_value_t sharedarraybuffer_ctor = js_obj_to_func(sharedarraybuffer_ctor_obj); js_set(js, sharedarraybuffer_proto, "constructor", sharedarraybuffer_ctor); js_set_descriptor(js, sharedarraybuffer_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); js_set(js, glob, "SharedArrayBuffer", sharedarraybuffer_ctor); ant_value_t buffer_ctor_obj = js_mkobj(js); ant_value_t buffer_proto = js_mkobj(js); ant_value_t uint8array_ctor = js_get(js, glob, "Uint8Array"); ant_value_t uint8array_proto = js_get(js, uint8array_ctor, "prototype"); if (is_special_object(uint8array_proto)) js_set_proto_init(buffer_proto, uint8array_proto); else js_set_proto_init(buffer_proto, typedarray_proto); js_set(js, buffer_proto, "slice", js_mkfun(js_buffer_slice)); js_set(js, buffer_proto, "toString", js_mkfun(js_buffer_toString)); js_set(js, buffer_proto, "toBase64", js_mkfun(js_buffer_toBase64)); js_set(js, buffer_proto, "write", js_mkfun(js_buffer_write)); js_set(js, buffer_proto, "copy", js_mkfun(js_buffer_copy)); js_set(js, buffer_proto, "writeInt16BE", js_mkfun(js_buffer_writeInt16BE)); js_set(js, buffer_proto, "writeInt32BE", js_mkfun(js_buffer_writeInt32BE)); js_set(js, buffer_proto, "writeUInt32BE", js_mkfun(js_buffer_writeUInt32BE)); js_set(js, buffer_proto, "readInt16BE", js_mkfun(js_buffer_readInt16BE)); js_set(js, buffer_proto, "readInt32BE", js_mkfun(js_buffer_readInt32BE)); js_set(js, buffer_proto, "readUInt32BE", js_mkfun(js_buffer_readUInt32BE)); js_set_sym(js, buffer_proto, get_toStringTag_sym(), js_mkstr(js, "Buffer", 6)); js_set_sym(js, buffer_proto, get_iterator_sym(), ta_values_fn); js_set(js, buffer_proto, "values", ta_values_fn); js_set(js, buffer_ctor_obj, "from", js_mkfun(js_buffer_from)); js_set(js, buffer_ctor_obj, "alloc", js_mkfun(js_buffer_alloc)); js_set(js, buffer_ctor_obj, "allocUnsafe", js_mkfun(js_buffer_allocUnsafe)); js_set(js, buffer_ctor_obj, "isBuffer", js_mkfun(js_buffer_isBuffer)); js_set(js, buffer_ctor_obj, "isEncoding", js_mkfun(js_buffer_isEncoding)); js_set(js, buffer_ctor_obj, "byteLength", js_mkfun(js_buffer_byteLength)); js_set(js, buffer_ctor_obj, "concat", js_mkfun(js_buffer_concat)); js_set(js, buffer_ctor_obj, "compare", js_mkfun(js_buffer_compare));
js_set_slot(buffer_ctor_obj, SLOT_CFUNC, js_mkfun(js_buffer_from)); js_mkprop_fast(js, buffer_ctor_obj, "prototype", 9, buffer_proto); js_mkprop_fast(js, buffer_ctor_obj, "name", 4, ANT_STRING("Buffer")); js_set_descriptor(js, buffer_ctor_obj, "name", 4, 0); ant_value_t buffer_ctor = js_obj_to_func(buffer_ctor_obj); js_set(js, buffer_proto, "constructor", buffer_ctor); js_set_descriptor(js, buffer_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); js_set(js, glob, "Buffer", buffer_ctor);}
void cleanup_buffer_module(void) { if (buffer_registry) { for (size_t i = 0; i < buffer_registry_count; i++) { if (buffer_registry[i]) free(buffer_registry[i]); } free(buffer_registry); buffer_registry = NULL; buffer_registry_count = 0; buffer_registry_cap = 0; } ta_metadata_bytes = 0;}
size_t buffer_get_external_memory(void) { size_t total = ta_metadata_bytes; for (size_t i = 0; i < buffer_registry_count; i++) { if (buffer_registry[i]) total += sizeof(ArrayBufferData) + buffer_registry[i]->capacity; } total += buffer_registry_cap * sizeof(ArrayBufferData *); return total;}