#include #include #include #include "runtime.h" #include "modules/textcodec.h" #include "modules/buffer.h" #include "modules/symbol.h" // TextEncoder.prototype.encode(string) static jsval_t js_textencoder_encode(struct js *js, jsval_t *args, int nargs) { size_t str_len = 0; const char *str = ""; if (nargs > 0 && js_type(args[0]) == JS_STR) { str = js_getstr(js, args[0], &str_len); if (!str) { str = ""; str_len = 0; } } jsval_t glob = js_glob(js); jsval_t uint8array_ctor = js_get(js, glob, "Uint8Array"); jsval_t len_arg = js_mknum((double)str_len); jsval_t arr = js_call(js, uint8array_ctor, &len_arg, 1); if (js_type(arr) == JS_ERR) return arr; if (str_len > 0) { jsval_t ta_data_val = js_get(js, arr, "__ta"); TypedArrayData *ta_data = (TypedArrayData *)js_gettypedarray(ta_data_val); if (ta_data && ta_data->buffer && ta_data->buffer->data) memcpy(ta_data->buffer->data, str, str_len); } return arr; } // TextEncoder.prototype.encodeInto(string, uint8array) static jsval_t js_textencoder_encodeInto(struct js *js, jsval_t *args, int nargs) { if (nargs < 2) { return js_mkerr(js, "encodeInto requires string and Uint8Array arguments"); } size_t str_len = 0; const char *str = ""; if (js_type(args[0]) == JS_STR) { str = js_getstr(js, args[0], &str_len); if (!str) { str = ""; str_len = 0; } } jsval_t ta_data_val = js_get(js, args[1], "__ta"); TypedArrayData *ta_data = (TypedArrayData *)js_gettypedarray(ta_data_val); if (!ta_data) return js_mkerr(js, "Second argument must be a Uint8Array"); size_t available = ta_data->byte_length; size_t to_write = str_len < available ? str_len : available; if (to_write > 0) { memcpy(ta_data->buffer->data + ta_data->byte_offset, str, to_write); } jsval_t result = js_mkobj(js); js_set(js, result, "read", js_mknum((double)to_write)); js_set(js, result, "written", js_mknum((double)to_write)); return result; } static jsval_t js_textencoder_constructor(struct js *js, jsval_t *args, int nargs) { (void)args; (void)nargs; jsval_t obj = js_mkobj(js); js_set(js, obj, "encoding", js_mkstr(js, "utf-8", 5)); js_set(js, obj, "encode", js_mkfun(js_textencoder_encode)); js_set(js, obj, "encodeInto", js_mkfun(js_textencoder_encodeInto)); js_set(js, obj, get_toStringTag_sym_key(), js_mkstr(js, "TextEncoder", 11)); return obj; } // TextDecoder.prototype.decode(bufferSource) static jsval_t js_textdecoder_decode(struct js *js, jsval_t *args, int nargs) { if (nargs < 1) { return js_mkstr(js, "", 0); } jsval_t ta_data_val = js_get(js, args[0], "__ta"); TypedArrayData *ta_data = (TypedArrayData *)js_gettypedarray(ta_data_val); if (ta_data) { if (!ta_data->buffer) return js_mkstr(js, "", 0); uint8_t *data = ta_data->buffer->data + ta_data->byte_offset; size_t len = ta_data->byte_length; return js_mkstr(js, (const char *)data, len); } jsval_t ab_data_val = js_get(js, args[0], "_arraybuffer_data"); if (js_type(ab_data_val) == JS_NUM) { ArrayBufferData *ab_data = (ArrayBufferData *)(uintptr_t)js_getnum(ab_data_val); if (!ab_data || !ab_data->data) return js_mkstr(js, "", 0); return js_mkstr(js, (const char *)ab_data->data, ab_data->length); } return js_mkstr(js, "", 0); } static jsval_t js_textdecoder_constructor(struct js *js, jsval_t *args, int nargs) { const char *encoding = "utf-8"; size_t encoding_len = 5; if (nargs > 0 && js_type(args[0]) == JS_STR) { encoding = js_getstr(js, args[0], &encoding_len); if (encoding && ( strcasecmp(encoding, "utf-8") == 0 || strcasecmp(encoding, "utf8") == 0) ) { encoding = "utf-8"; encoding_len = 5; } } jsval_t obj = js_mkobj(js); js_set(js, obj, "encoding", js_mkstr(js, encoding, encoding_len)); js_set(js, obj, "fatal", js_mkfalse()); js_set(js, obj, "ignoreBOM", js_mkfalse()); js_set(js, obj, "decode", js_mkfun(js_textdecoder_decode)); js_set(js, obj, get_toStringTag_sym_key(), js_mkstr(js, "TextDecoder", 11)); return obj; } void init_textcodec_module(void) { struct js *js = rt->js; jsval_t glob = js_glob(js); jsval_t textencoder_constructor = js_mkfun(js_textencoder_constructor); jsval_t textencoder_proto = js_mkobj(js); js_set(js, textencoder_proto, "encode", js_mkfun(js_textencoder_encode)); js_set(js, textencoder_proto, "encodeInto", js_mkfun(js_textencoder_encodeInto)); js_set(js, textencoder_proto, "encoding", js_mkstr(js, "utf-8", 5)); js_set(js, textencoder_constructor, "prototype", textencoder_proto); js_set(js, glob, "TextEncoder", textencoder_constructor); jsval_t textdecoder_constructor = js_mkfun(js_textdecoder_constructor); jsval_t textdecoder_proto = js_mkobj(js); js_set(js, textdecoder_proto, "decode", js_mkfun(js_textdecoder_decode)); js_set(js, textdecoder_proto, "encoding", js_mkstr(js, "utf-8", 5)); js_set(js, textdecoder_proto, "fatal", js_mkfalse()); js_set(js, textdecoder_proto, "ignoreBOM", js_mkfalse()); js_set(js, textdecoder_constructor, "prototype", textdecoder_proto); js_set(js, glob, "TextDecoder", textdecoder_constructor); }