From 441722bc86221f26231319230e8eeebd0753162f Mon Sep 17 00:00:00 2001 From: theMackabu Date: Wed, 25 Mar 2026 23:52:44 -0700 Subject: [PATCH] revise TextEncoding and add brotli --- examples/spec/escapes.js | 7 ++- include/modules/textcodec.h | 2 + meson/deps/meson.build | 25 ++++++++++ src/escape.c | 2 +- src/modules/textcodec.c | 76 +++++++++++++++++++++++++----- src/streams/codec.c | 92 ++++++++++++++++++++++--------------- src/streams/compression.c | 25 +++++----- vendor/google-brotli.wrap | 14 ++++++ 8 files changed, 178 insertions(+), 65 deletions(-) create mode 100644 vendor/google-brotli.wrap diff --git a/examples/spec/escapes.js b/examples/spec/escapes.js index 99717fd..a5f6a06 100644 --- a/examples/spec/escapes.js +++ b/examples/spec/escapes.js @@ -10,8 +10,8 @@ test('vertical tab (\\v) charCodeAt', '\v'.charCodeAt(0), 11); test('form feed (\\f) charCodeAt', '\f'.charCodeAt(0), 12); test('carriage return (\\r) charCodeAt', '\r'.charCodeAt(0), 13); -test('escaped quote single', '\''.length, 1); -test('escaped quote double', "\"".length, 1); +test('escaped quote single', "'".length, 1); +test('escaped quote double', '"'.length, 1); test('escaped backslash', '\\'.charCodeAt(0), 92); test('hex escape \\x41', '\x41', 'A'); @@ -24,6 +24,9 @@ test('unicode \\u00e9 (é)', '\u00e9', 'é'); test('unicode \\u263A (smiley)', '\u263A', '☺'); test('unicode \\u4e2d (中)', '\u4e2d', '中'); +test('unicode code point escape keeps following chars', '\u{1F499} streams', '💙 streams'); +test('unicode code point escape in string body keeps spaces', 'I \u{1F499} streams', 'I 💙 streams'); + test('string with null char length', 'a\0b'.length, 3); test('string with null indexOf', 'a\0b'.indexOf('\0'), 1); diff --git a/include/modules/textcodec.h b/include/modules/textcodec.h index a2ba3fe..284fb08 100644 --- a/include/modules/textcodec.h +++ b/include/modules/textcodec.h @@ -11,6 +11,8 @@ typedef enum { TD_ENC_UTF8 = 0, TD_ENC_UTF16LE, TD_ENC_UTF16BE, + TD_ENC_WINDOWS_1252, + TD_ENC_ISO_8859_2, } td_encoding_t; typedef struct { diff --git a/meson/deps/meson.build b/meson/deps/meson.build index 312cd33..ff77d41 100644 --- a/meson/deps/meson.build +++ b/meson/deps/meson.build @@ -55,6 +55,10 @@ deps_info = { 'inc': '', 'build_dir': true, }, + 'google-brotli': { + 'dir': 'brotli-1.1.0', + 'inc': 'c/include', + }, } subprojects_src = src_root / 'vendor' @@ -72,6 +76,22 @@ zlib_dep = zlib_ng_sub.get_variable('zlib_ng_dep') zlib_ng_srcdir = subprojects_src / deps_info['zlib-ng']['dir'] zlib_ng_builddir = subprojects_build / deps_info['zlib-ng']['dir'] +brotli_common_dep = dependency('libbrotlicommon', + fallback: ['google-brotli', 'libbrotlicommon'], + required: true, + static: is_static, +) +brotli_dec_dep = dependency('libbrotlidec', + fallback: ['google-brotli', 'libbrotlidec'], + required: true, + static: is_static, +) +brotli_enc_dep = dependency('libbrotlienc', + fallback: ['google-brotli', 'libbrotlienc'], + required: true, + static: is_static, +) + cmake_prefix = get_option('deps_prefix_cmake') tlsuv_sub = subproject('tlsuv', default_options: [ @@ -174,6 +194,10 @@ deps_info = { 'inc': '', 'build_dir': true, }, + 'google-brotli': { + 'dir': 'brotli-1.1.0', + 'inc': 'c/include', + }, } subprojects_src = src_root / 'vendor' @@ -184,6 +208,7 @@ yyjson_include_path = subprojects_src / deps_info['yyjson']['dir'] / deps_info[' libuv_include_path = subprojects_src / deps_info['libuv']['dir'] / deps_info['libuv']['inc'] llhttp_include_path = subprojects_src / deps_info['llhttp']['dir'] / deps_info['llhttp']['inc'] zlib_include_path = subprojects_build / deps_info['zlib-ng']['dir'] / deps_info['zlib-ng']['inc'] +brotli_include_path = subprojects_src / deps_info['google-brotli']['dir'] / deps_info['google-brotli']['inc'] pkg_zig_dir = src_root / 'src' / 'pkg' pkg_build_dir = meson.current_build_dir() diff --git a/src/escape.c b/src/escape.c index 25ef09b..79f587b 100644 --- a/src/escape.c +++ b/src/escape.c @@ -30,7 +30,7 @@ static size_t decode_unicode_braced(const uint8_t *in, size_t pos, size_t end, u while (i < end && is_xdigit(in[i])) { cp = (cp << 4) | unhex(in[i]); i++; } if (i < end && in[i] == '}') { *out_pos += utf8_encode(cp, (char *)&out[*out_pos]); - return i - pos; + return i - pos - 1; } out[(*out_pos)++] = 'u'; diff --git a/src/modules/textcodec.c b/src/modules/textcodec.c index 2fe0f44..e916b5d 100644 --- a/src/modules/textcodec.c +++ b/src/modules/textcodec.c @@ -44,14 +44,16 @@ static void td_finalize(ant_t *js, ant_object_t *obj) { static int resolve_encoding(const char *s, size_t len) { static const struct { const char *label; uint8_t len; td_encoding_t enc; } map[] = { - {"unicode-1-1-utf-8", 18, TD_ENC_UTF8}, {"unicode11utf8", 13, TD_ENC_UTF8}, + {"unicode-1-1-utf-8", 17, TD_ENC_UTF8}, {"unicode11utf8", 13, TD_ENC_UTF8}, {"unicode20utf8", 13, TD_ENC_UTF8}, {"utf-8", 5, TD_ENC_UTF8}, {"utf8", 4, TD_ENC_UTF8}, {"x-unicode20utf8",17, TD_ENC_UTF8}, + {"windows-1252", 12, TD_ENC_WINDOWS_1252}, {"ascii", 5, TD_ENC_WINDOWS_1252}, {"unicodefffe", 11, TD_ENC_UTF16BE}, {"utf-16be", 8, TD_ENC_UTF16BE}, {"csunicode", 9, TD_ENC_UTF16LE}, {"iso-10646-ucs-2",16, TD_ENC_UTF16LE}, {"ucs-2", 5, TD_ENC_UTF16LE}, {"unicode", 7, TD_ENC_UTF16LE}, {"unicodefeff", 11, TD_ENC_UTF16LE}, {"utf-16", 6, TD_ENC_UTF16LE}, {"utf-16le", 8, TD_ENC_UTF16LE}, + {"iso-8859-2", 10, TD_ENC_ISO_8859_2}, {NULL, 0, 0} }; for (int i = 0; map[i].label; i++) { @@ -62,9 +64,11 @@ static int resolve_encoding(const char *s, size_t len) { static const char *encoding_name(td_encoding_t enc) { switch (enc) { - case TD_ENC_UTF16LE: return "utf-16le"; - case TD_ENC_UTF16BE: return "utf-16be"; - default: return "utf-8"; + case TD_ENC_UTF16LE: return "utf-16le"; + case TD_ENC_UTF16BE: return "utf-16be"; + case TD_ENC_WINDOWS_1252: return "windows-1252"; + case TD_ENC_ISO_8859_2: return "iso-8859-2"; + default: return "utf-8"; }} static const char *trim_label(const char *s, size_t len, size_t *out_len) { @@ -253,6 +257,48 @@ static inline size_t u8_fffd(char *out, size_t o) { #define U16_IS_LOW(cu) ((cu) >= 0xDC00 && (cu) <= 0xDFFF) #define U16_PAIR(hi,lo) (0x10000 + ((uint32_t)((hi) - 0xD800) << 10) + ((lo) - 0xDC00)) +static uint32_t decode_windows_1252_byte(uint8_t byte) { + static const uint16_t specials[32] = { + 0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F, + 0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178, + }; + if (byte < 0x80) return byte; + if (byte < 0xA0) return specials[byte - 0x80]; + return byte; +} + +static uint32_t decode_iso_8859_2_byte(uint8_t byte) { + static const uint16_t upper[96] = { + 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, + 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, + 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, + 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9, + }; + if (byte < 0xA0) return byte; + return upper[byte - 0xA0]; +} + +static utf8proc_ssize_t decode_single_byte(td_state_t *st, const uint8_t *src, size_t len, char *out) { + size_t o = 0; + for (size_t i = 0; i < len; i++) { + uint32_t cp = (st->encoding == TD_ENC_WINDOWS_1252) + ? decode_windows_1252_byte(src[i]) + : decode_iso_8859_2_byte(src[i]); + o = u8_emit(out, o, (utf8proc_int32_t)cp); + } + return (utf8proc_ssize_t)o; +} + static utf8proc_ssize_t utf16_decode(td_state_t *st, const uint8_t *src, size_t len, char *out, bool stream) { bool be = (st->encoding == TD_ENC_UTF16BE); size_t i = 0, o = 0; @@ -330,6 +376,10 @@ ant_value_t td_decode(ant_t *js, td_state_t *st, const uint8_t *input, size_t in utf8proc_ssize_t n; if (st->encoding == TD_ENC_UTF16LE || st->encoding == TD_ENC_UTF16BE) { n = utf16_decode(st, src, total, out, stream_mode); + } else if (st->encoding == TD_ENC_WINDOWS_1252 || st->encoding == TD_ENC_ISO_8859_2) { + n = decode_single_byte(st, src, total, out); + st->pending_len = 0; + st->bom_seen = false; } else { utf8_dec_t dec = { .ignore_bom = st->ignore_bom, .bom_seen = st->bom_seen }; n = utf8_whatwg_decode(&dec, src, total, out, st->fatal, stream_mode); @@ -377,17 +427,19 @@ static ant_value_t js_textdecoder_ctor(ant_t *js, ant_value_t *args, int nargs) return js_mkerr_typed(js, JS_ERR_TYPE, "TextDecoder constructor requires 'new'"); td_encoding_t enc = TD_ENC_UTF8; - if (nargs > 0 && vtype(args[0]) == T_STR) { - size_t llen; - const char *raw = js_getstr(js, args[0], &llen); - + if (nargs > 0 && !is_undefined(args[0])) { + ant_value_t label = (vtype(args[0]) == T_STR) ? args[0] : coerce_to_str(js, args[0]); + if (is_err(label)) return label; + + size_t llen; + const char *raw = js_getstr(js, label, &llen); if (raw) { size_t tlen; const char *trimmed = trim_label(raw, llen, &tlen); int resolved = resolve_encoding(trimmed, tlen); if (resolved < 0) return js_mkerr_typed( - js, JS_ERR_RANGE, "Failed to construct 'TextDecoder': The encoding label provided ('%.*s') is invalid.", + js, JS_ERR_RANGE, "Failed to construct 'TextDecoder': The encoding label provided ('%.*s') is invalid.", (int)tlen, trimmed ); @@ -398,9 +450,11 @@ static ant_value_t js_textdecoder_ctor(ant_t *js, ant_value_t *args, int nargs) bool ignore_bom = false; if (nargs > 1 && is_object_type(args[1])) { - ant_value_t fv = js_get(js, args[1], "fatal"); + ant_value_t fv = js_getprop_fallback(js, args[1], "fatal"); + if (is_err(fv)) return fv; if (vtype(fv) != T_UNDEF) fatal = js_truthy(js, fv); - ant_value_t bv = js_get(js, args[1], "ignoreBOM"); + ant_value_t bv = js_getprop_fallback(js, args[1], "ignoreBOM"); + if (is_err(bv)) return bv; if (vtype(bv) != T_UNDEF) ignore_bom = js_truthy(js, bv); } diff --git a/src/streams/codec.c b/src/streams/codec.c index e237c0a..1ae0d59 100644 --- a/src/streams/codec.c +++ b/src/streams/codec.c @@ -12,7 +12,6 @@ #include "modules/textcodec.h" #include "streams/codec.h" #include "streams/transform.h" -#include "streams/readable.h" ant_value_t g_tes_proto; ant_value_t g_tds_proto; @@ -114,12 +113,22 @@ static bool get_chunk_bytes(ant_t *js, ant_value_t chunk, const uint8_t **out, s return false; } +static ant_value_t codec_transform_controller(ant_value_t *args, int nargs) { + return (nargs > 1) ? args[1] : js_mkundef(); +} + +static ant_value_t codec_flush_controller(ant_value_t *args, int nargs) { + return (nargs > 0) ? args[0] : js_mkundef(); +} + static ant_value_t tes_transform(ant_t *js, ant_value_t *args, int nargs) { ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); ant_value_t state_val = js_get_slot(wrapper, SLOT_DATA); + tes_state_t *st = (tes_state_t *)(uintptr_t)(size_t)js_getnum(state_val); - + ant_value_t ctrl_obj = codec_transform_controller(args, nargs); ant_value_t chunk = (nargs > 0) ? args[0] : js_mkundef(); + size_t str_len = 0; const char *str = NULL; @@ -193,18 +202,16 @@ static ant_value_t tes_transform(ant_t *js, ant_value_t *args, int nargs) { free(out); ant_value_t result = create_typed_array(js, TYPED_ARRAY_UINT8, ab, 0, o, "Uint8Array"); - ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); - ant_value_t readable = ts_stream_readable(ts_obj); - ant_value_t rs_ctrl = rs_stream_controller(js, readable); - rs_controller_enqueue(js, rs_ctrl, result); - - return js_mkundef(); + return ts_is_controller(ctrl_obj) + ? ts_ctrl_enqueue(js, ctrl_obj, result) + : js_mkerr_typed(js, JS_ERR_TYPE, "Invalid TransformStreamDefaultController"); } static ant_value_t tes_flush(ant_t *js, ant_value_t *args, int nargs) { ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); ant_value_t state_val = js_get_slot(wrapper, SLOT_DATA); tes_state_t *st = (tes_state_t *)(uintptr_t)(size_t)js_getnum(state_val); + ant_value_t ctrl_obj = codec_flush_controller(args, nargs); if (st->pending_len > 0) { uint8_t fffd[3] = { 0xEF, 0xBF, 0xBD }; @@ -214,10 +221,9 @@ static ant_value_t tes_flush(ant_t *js, ant_value_t *args, int nargs) { st->pending_len = 0; ant_value_t result = create_typed_array(js, TYPED_ARRAY_UINT8, ab, 0, 3, "Uint8Array"); - ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); - ant_value_t readable = ts_stream_readable(ts_obj); - ant_value_t rs_ctrl = rs_stream_controller(js, readable); - rs_controller_enqueue(js, rs_ctrl, result); + if (!ts_is_controller(ctrl_obj)) + return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid TransformStreamDefaultController"); + return ts_ctrl_enqueue(js, ctrl_obj, result); } return js_mkundef(); @@ -281,13 +287,14 @@ static ant_value_t tds_transform(ant_t *js, ant_value_t *args, int nargs) { ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); ant_value_t state_val = js_get_slot(wrapper, SLOT_DATA); td_state_t *st = (td_state_t *)(uintptr_t)(size_t)js_getnum(state_val); + ant_value_t ctrl_obj = codec_transform_controller(args, nargs); ant_value_t chunk = (nargs > 0) ? args[0] : js_mkundef(); const uint8_t *input = NULL; size_t input_len = 0; - if (is_object_type(chunk)) - get_chunk_bytes(js, chunk, &input, &input_len); + if (!is_object_type(chunk) || !get_chunk_bytes(js, chunk, &input, &input_len)) + return js_mkerr_typed(js, JS_ERR_TYPE, "The provided value is not of type '(ArrayBuffer or ArrayBufferView)'"); ant_value_t result = td_decode(js, st, input, input_len, true); if (is_err(result)) return result; @@ -295,10 +302,9 @@ static ant_value_t tds_transform(ant_t *js, ant_value_t *args, int nargs) { size_t slen = 0; const char *sval = js_getstr(js, result, &slen); if (sval && slen > 0) { - ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); - ant_value_t readable = ts_stream_readable(ts_obj); - ant_value_t rs_ctrl = rs_stream_controller(js, readable); - rs_controller_enqueue(js, rs_ctrl, result); + if (!ts_is_controller(ctrl_obj)) + return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid TransformStreamDefaultController"); + return ts_ctrl_enqueue(js, ctrl_obj, result); } return js_mkundef(); @@ -308,6 +314,7 @@ static ant_value_t tds_flush(ant_t *js, ant_value_t *args, int nargs) { ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); ant_value_t state_val = js_get_slot(wrapper, SLOT_DATA); td_state_t *st = (td_state_t *)(uintptr_t)(size_t)js_getnum(state_val); + ant_value_t ctrl_obj = codec_flush_controller(args, nargs); ant_value_t result = td_decode(js, st, NULL, 0, false); if (is_err(result)) return result; @@ -315,10 +322,9 @@ static ant_value_t tds_flush(ant_t *js, ant_value_t *args, int nargs) { size_t slen = 0; const char *sval = js_getstr(js, result, &slen); if (sval && slen > 0) { - ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); - ant_value_t readable = ts_stream_readable(ts_obj); - ant_value_t rs_ctrl = rs_stream_controller(js, readable); - rs_controller_enqueue(js, rs_ctrl, result); + if (!ts_is_controller(ctrl_obj)) + return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid TransformStreamDefaultController"); + return ts_ctrl_enqueue(js, ctrl_obj, result); } return js_mkundef(); @@ -331,6 +337,8 @@ static ant_value_t js_tds_get_encoding(ant_t *js, ant_value_t *args, int nargs) switch (st->encoding) { case TD_ENC_UTF16LE: return js_mkstr(js, "utf-16le", 8); case TD_ENC_UTF16BE: return js_mkstr(js, "utf-16be", 8); + case TD_ENC_WINDOWS_1252: return js_mkstr(js, "windows-1252", 12); + case TD_ENC_ISO_8859_2: return js_mkstr(js, "iso-8859-2", 10); default: return js_mkstr(js, "utf-8", 5); } } @@ -368,14 +376,16 @@ static const char *tds_trim_label(const char *s, size_t len, size_t *out_len) { static int tds_resolve_encoding(const char *s, size_t len) { static const struct { const char *label; uint8_t label_len; td_encoding_t enc; } map[] = { - {"unicode-1-1-utf-8", 18, TD_ENC_UTF8}, {"unicode11utf8", 13, TD_ENC_UTF8}, + {"unicode-1-1-utf-8", 17, TD_ENC_UTF8}, {"unicode11utf8", 13, TD_ENC_UTF8}, {"unicode20utf8", 13, TD_ENC_UTF8}, {"utf-8", 5, TD_ENC_UTF8}, {"utf8", 4, TD_ENC_UTF8}, {"x-unicode20utf8",17, TD_ENC_UTF8}, + {"windows-1252", 12, TD_ENC_WINDOWS_1252}, {"ascii", 5, TD_ENC_WINDOWS_1252}, {"unicodefffe", 11, TD_ENC_UTF16BE}, {"utf-16be", 8, TD_ENC_UTF16BE}, {"csunicode", 9, TD_ENC_UTF16LE}, {"iso-10646-ucs-2",16, TD_ENC_UTF16LE}, {"ucs-2", 5, TD_ENC_UTF16LE}, {"unicode", 7, TD_ENC_UTF16LE}, {"unicodefeff", 11, TD_ENC_UTF16LE}, {"utf-16", 6, TD_ENC_UTF16LE}, {"utf-16le", 8, TD_ENC_UTF16LE}, + {"iso-8859-2", 10, TD_ENC_ISO_8859_2}, {NULL, 0, 0} }; for (int i = 0; map[i].label; i++) { @@ -389,26 +399,32 @@ static ant_value_t js_tds_ctor(ant_t *js, ant_value_t *args, int nargs) { return js_mkerr_typed(js, JS_ERR_TYPE, "TextDecoderStream constructor requires 'new'"); td_encoding_t enc = TD_ENC_UTF8; - if (nargs > 0 && vtype(args[0]) == T_STR) { - size_t llen; - const char *raw = js_getstr(js, args[0], &llen); - if (raw) { - size_t tlen; - const char *trimmed = tds_trim_label(raw, llen, &tlen); - int resolved = tds_resolve_encoding(trimmed, tlen); - if (resolved < 0) return js_mkerr_typed( - js, JS_ERR_RANGE, "Failed to construct 'TextDecoderStream': The encoding label provided ('%.*s') is invalid.", - (int)tlen, trimmed - ); - enc = (td_encoding_t)resolved; - }} + if (nargs > 0 && !is_undefined(args[0])) { + ant_value_t label = (vtype(args[0]) == T_STR) ? args[0] : coerce_to_str(js, args[0]); + if (is_err(label)) return label; + + size_t llen; + const char *raw = js_getstr(js, label, &llen); + if (raw) { + size_t tlen; + const char *trimmed = tds_trim_label(raw, llen, &tlen); + int resolved = tds_resolve_encoding(trimmed, tlen); + if (resolved < 0) return js_mkerr_typed( + js, JS_ERR_RANGE, "Failed to construct 'TextDecoderStream': The encoding label provided ('%.*s') is invalid.", + (int)tlen, trimmed + ); + enc = (td_encoding_t)resolved; + } + } bool fatal = false; bool ignore_bom = false; if (nargs > 1 && is_object_type(args[1])) { - ant_value_t fv = js_get(js, args[1], "fatal"); + ant_value_t fv = js_getprop_fallback(js, args[1], "fatal"); + if (is_err(fv)) return fv; if (vtype(fv) != T_UNDEF) fatal = js_truthy(js, fv); - ant_value_t bv = js_get(js, args[1], "ignoreBOM"); + ant_value_t bv = js_getprop_fallback(js, args[1], "ignoreBOM"); + if (is_err(bv)) return bv; if (vtype(bv) != T_UNDEF) ignore_bom = js_truthy(js, bv); } diff --git a/src/streams/compression.c b/src/streams/compression.c index dddd9d1..b8c05fa 100644 --- a/src/streams/compression.c +++ b/src/streams/compression.c @@ -12,7 +12,6 @@ #include "modules/buffer.h" #include "streams/compression.h" #include "streams/transform.h" -#include "streams/readable.h" ant_value_t g_cs_proto; ant_value_t g_ds_proto; @@ -135,14 +134,14 @@ static bool get_chunk_bytes(ant_t *js, ant_value_t chunk, const uint8_t **out, s return false; } -static ant_value_t enqueue_buffer(ant_t *js, ant_value_t ts_obj, const uint8_t *data, size_t len) { +static ant_value_t enqueue_buffer(ant_t *js, ant_value_t ctrl_obj, const uint8_t *data, size_t len) { ArrayBufferData *ab = create_array_buffer_data(len); if (!ab) return js_mkerr(js, "out of memory"); memcpy(ab->data, data, len); ant_value_t arr = create_typed_array(js, TYPED_ARRAY_UINT8, ab, 0, len, "Uint8Array"); - ant_value_t readable = ts_stream_readable(ts_obj); - ant_value_t rs_ctrl = rs_stream_controller(js, readable); - return rs_controller_enqueue(js, rs_ctrl, arr); + if (!ts_is_controller(ctrl_obj)) + return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid TransformStreamDefaultController"); + return ts_ctrl_enqueue(js, ctrl_obj, arr); } #define ZCHUNK_SIZE 16384 @@ -150,10 +149,11 @@ static ant_value_t enqueue_buffer(ant_t *js, ant_value_t ts_obj, const uint8_t * static ant_value_t cs_transform(ant_t *js, ant_value_t *args, int nargs) { ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); ant_value_t state_val = js_get_slot(wrapper, SLOT_DATA); + zstate_t *st = (zstate_t *)(uintptr_t)(size_t)js_getnum(state_val); - ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); - + ant_value_t ctrl_obj = (nargs > 1) ? args[1] : js_mkundef(); ant_value_t chunk = (nargs > 0) ? args[0] : js_mkundef(); + const uint8_t *input = NULL; size_t input_len = 0; @@ -174,7 +174,7 @@ static ant_value_t cs_transform(ant_t *js, ant_value_t *args, int nargs) { return js_mkerr_typed(js, JS_ERR_TYPE, "Compression failed"); size_t have = ZCHUNK_SIZE - st->strm.avail_out; if (have > 0) { - ant_value_t r = enqueue_buffer(js, ts_obj, out_buf, have); + ant_value_t r = enqueue_buffer(js, ctrl_obj, out_buf, have); if (is_err(r)) return r; } } while (st->strm.avail_out == 0); @@ -186,7 +186,7 @@ static ant_value_t cs_flush(ant_t *js, ant_value_t *args, int nargs) { ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); ant_value_t state_val = js_get_slot(wrapper, SLOT_DATA); zstate_t *st = (zstate_t *)(uintptr_t)(size_t)js_getnum(state_val); - ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); + ant_value_t ctrl_obj = (nargs > 0) ? args[0] : js_mkundef(); st->strm.next_in = NULL; st->strm.avail_in = 0; @@ -199,7 +199,7 @@ static ant_value_t cs_flush(ant_t *js, ant_value_t *args, int nargs) { ret = deflate(&st->strm, Z_FINISH); size_t have = ZCHUNK_SIZE - st->strm.avail_out; if (have > 0) { - ant_value_t r = enqueue_buffer(js, ts_obj, out_buf, have); + ant_value_t r = enqueue_buffer(js, ctrl_obj, out_buf, have); if (is_err(r)) return r; } } while (ret != Z_STREAM_END); @@ -274,7 +274,7 @@ static ant_value_t ds_transform(ant_t *js, ant_value_t *args, int nargs) { ant_value_t wrapper = js_get_slot(js->current_func, SLOT_DATA); ant_value_t state_val = js_get_slot(wrapper, SLOT_DATA); zstate_t *st = (zstate_t *)(uintptr_t)(size_t)js_getnum(state_val); - ant_value_t ts_obj = js_get_slot(wrapper, SLOT_ENTRIES); + ant_value_t ctrl_obj = (nargs > 1) ? args[1] : js_mkundef(); ant_value_t chunk = (nargs > 0) ? args[0] : js_mkundef(); const uint8_t *input = NULL; @@ -284,7 +284,6 @@ static ant_value_t ds_transform(ant_t *js, ant_value_t *args, int nargs) { return js_mkerr_typed(js, JS_ERR_TYPE, "The provided value is not of type '(ArrayBuffer or ArrayBufferView)'"); if (!input || input_len == 0) return js_mkundef(); - st->strm.next_in = (Bytef *)input; st->strm.avail_in = (uInt)input_len; @@ -297,7 +296,7 @@ static ant_value_t ds_transform(ant_t *js, ant_value_t *args, int nargs) { return js_mkerr_typed(js, JS_ERR_TYPE, "Decompression failed"); size_t have = ZCHUNK_SIZE - st->strm.avail_out; if (have > 0) { - ant_value_t r = enqueue_buffer(js, ts_obj, out_buf, have); + ant_value_t r = enqueue_buffer(js, ctrl_obj, out_buf, have); if (is_err(r)) return r; } if (ret == Z_STREAM_END) break; diff --git a/vendor/google-brotli.wrap b/vendor/google-brotli.wrap new file mode 100644 index 0000000..658204c --- /dev/null +++ b/vendor/google-brotli.wrap @@ -0,0 +1,14 @@ +[wrap-file] +directory = brotli-1.1.0 +source_url = https://github.com/google/brotli/archive/v1.1.0.tar.gz +source_filename = brotli-1.1.0.tar.gz +source_hash = e720a6ca29428b803f4ad165371771f5398faba397edf6778837a18599ea13ff +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/google-brotli_1.1.0-3/brotli-1.1.0.tar.gz +patch_filename = google-brotli_1.1.0-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/google-brotli_1.1.0-3/get_patch +patch_hash = 77e75a3bb019a4b653195a15af17cc65c56fb8cced2519154fce4e6bb43c74e2 +wrapdb_version = 1.1.0-3 + +[provide] +program_names = brotli +dependency_names = libbrotlicommon, libbrotlidec, libbrotlienc -- 2.51.2