#include #include #include #include #include "ant.h" #include "ptr.h" #include "errors.h" #include "internal.h" #include "silver/engine.h" #include "streams/brotli.h" #include "modules/buffer.h" #include "modules/events.h" #include "modules/symbol.h" #include "modules/zlib.h" #define ZLIB_CHUNK 16384 #define ZLIB_STREAM_TAG 0x5A4C4942u typedef enum { ZLIB_KIND_GZIP, ZLIB_KIND_GUNZIP, ZLIB_KIND_DEFLATE, ZLIB_KIND_INFLATE, ZLIB_KIND_DEFLATE_RAW, ZLIB_KIND_INFLATE_RAW, ZLIB_KIND_UNZIP, ZLIB_KIND_BROTLI_COMPRESS, ZLIB_KIND_BROTLI_DECOMPRESS, } zlib_kind_t; typedef struct zlib_stream_s { z_stream strm; brotli_stream_state_t *brotli; ant_value_t obj; ant_t *js; zlib_kind_t kind; uint32_t bytes_written; bool initialized; bool ended; bool destroyed; struct zlib_stream_s *next_active; } zlib_stream_t; static ant_value_t g_transform_proto = 0; static zlib_stream_t *g_active_streams = NULL; static bool zlib_kind_is_compress(zlib_kind_t k) { return k == ZLIB_KIND_GZIP || k == ZLIB_KIND_DEFLATE || k == ZLIB_KIND_DEFLATE_RAW || k == ZLIB_KIND_BROTLI_COMPRESS; } static int zlib_window_bits(zlib_kind_t k) { switch (k) { case ZLIB_KIND_GZIP: return 15 + 16; case ZLIB_KIND_GUNZIP: return 15 + 32; case ZLIB_KIND_UNZIP: return 15 + 32; case ZLIB_KIND_DEFLATE: return 15; case ZLIB_KIND_INFLATE: return 15; case ZLIB_KIND_DEFLATE_RAW: return -15; case ZLIB_KIND_INFLATE_RAW: return -15; default: return 15; } } static ant_value_t pick_callback(ant_value_t *args, int nargs) { if (nargs > 2 && is_callable(args[2])) return args[2]; if (nargs > 1 && is_callable(args[1])) return args[1]; return js_mkundef(); } static zlib_stream_t *zlib_stream_ptr(ant_value_t obj) { if (!js_check_native_tag(obj, ZLIB_STREAM_TAG)) return NULL; return (zlib_stream_t *)js_get_native_ptr(obj); } static void zlib_add_active(zlib_stream_t *st) { st->next_active = g_active_streams; g_active_streams = st; } static void zlib_remove_active(zlib_stream_t *st) { zlib_stream_t **it; for (it = &g_active_streams; *it; it = &(*it)->next_active) { if (*it == st) { *it = st->next_active; st->next_active = NULL; return; }} } static void zlib_stream_release(zlib_stream_t *st) { if (!st) return; if (st->brotli) { brotli_stream_state_destroy(st->brotli); st->brotli = NULL; } else if (st->initialized) { if (zlib_kind_is_compress(st->kind)) deflateEnd(&st->strm); else inflateEnd(&st->strm); st->initialized = false; } } static ant_value_t zlib_make_buffer(ant_t *js, const uint8_t *data, size_t len) { ArrayBufferData *ab = create_array_buffer_data(len); if (!ab) return js_mkerr(js, "out of memory"); if (data && len > 0) memcpy(ab->data, data, len); return create_typed_array(js, TYPED_ARRAY_UINT8, ab, 0, len, "Buffer"); } static void zlib_emit_data(ant_t *js, ant_value_t obj, const uint8_t *data, size_t len) { ant_value_t buf = zlib_make_buffer(js, data, len); if (!is_err(buf)) eventemitter_emit_args(js, obj, "data", &buf, 1); } typedef struct { ant_t *js; ant_value_t obj; } brotli_emit_ctx_t; typedef struct { ant_t *js; ant_value_t arr; bool error; } brotli_collect_ctx_t; static int brotli_emit_cb(void *ctx, const uint8_t *chunk, size_t len) { brotli_emit_ctx_t *ec = (brotli_emit_ctx_t *)ctx; zlib_emit_data(ec->js, ec->obj, chunk, len); return 0; } static int brotli_collect_cb(void *ctx, const uint8_t *chunk, size_t len) { brotli_collect_ctx_t *ec = (brotli_collect_ctx_t *)ctx; ant_value_t buf = zlib_make_buffer(ec->js, chunk, len); if (is_err(buf)) { ec->error = true; return -1; } js_arr_push(ec->js, ec->arr, buf); return 0; } static ant_value_t zlib_do_process( ant_t *js, zlib_stream_t *st, const uint8_t *input, size_t input_len, bool finish ) { if (st->destroyed || st->ended) return js_mkundef(); if (st->brotli) { brotli_emit_ctx_t ctx = { js, st->obj }; int rc; if (finish) { rc = brotli_stream_finish(st->brotli, brotli_emit_cb, &ctx); } else { rc = brotli_stream_process(st->brotli, input, input_len, brotli_emit_cb, &ctx); } if (rc < 0) return js_mkerr(js, "brotli operation failed"); return js_mkundef(); } bool compress = zlib_kind_is_compress(st->kind); int flush = finish ? Z_FINISH : Z_NO_FLUSH; uint8_t out[ZLIB_CHUNK]; if (!finish) { st->strm.next_in = (Bytef *)input; st->strm.avail_in = (uInt)input_len; } else { st->strm.next_in = NULL; st->strm.avail_in = 0; } int ret; do { st->strm.next_out = out; st->strm.avail_out = ZLIB_CHUNK; if (compress) { ret = deflate(&st->strm, flush); if (ret == Z_STREAM_ERROR) return js_mkerr(js, "zlib deflate error"); } else { ret = inflate(&st->strm, flush == Z_FINISH ? Z_SYNC_FLUSH : flush); if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) return js_mkerr(js, "zlib inflate error"); } size_t have = ZLIB_CHUNK - st->strm.avail_out; if (have > 0) zlib_emit_data(js, st->obj, out, have); if (ret == Z_STREAM_END) break; } while (st->strm.avail_out == 0); return js_mkundef(); } static ant_value_t zlib_process_chunk_sync( ant_t *js, zlib_stream_t *st, const uint8_t *input, size_t input_len, int flush_flag ) { ant_value_t arr = js_mkarr(js); if (st->brotli) { brotli_collect_ctx_t ctx = { js, arr, false }; int rc = 0; if (input && input_len > 0) rc = brotli_stream_process(st->brotli, input, input_len, brotli_collect_cb, &ctx); if (rc >= 0 && flush_flag == Z_FINISH) rc = brotli_stream_finish(st->brotli, brotli_collect_cb, &ctx); if (rc < 0 || ctx.error) return js_mkerr(js, "brotli operation failed"); return arr; } bool compress = zlib_kind_is_compress(st->kind); uint8_t out[ZLIB_CHUNK]; st->strm.next_in = input ? (Bytef *)input : NULL; st->strm.avail_in = input ? (uInt)input_len : 0; int ret; do { st->strm.next_out = out; st->strm.avail_out = ZLIB_CHUNK; if (compress) { ret = deflate(&st->strm, flush_flag); if (ret == Z_STREAM_ERROR) return js_mkerr(js, "zlib deflate error"); } else { ret = inflate(&st->strm, flush_flag); if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) return js_mkerr(js, "zlib inflate error"); } size_t have = ZLIB_CHUNK - st->strm.avail_out; if (have > 0) { ant_value_t buf = zlib_make_buffer(js, out, have); if (is_err(buf)) return buf; js_arr_push(js, arr, buf); } if (ret == Z_STREAM_END) break; } while (st->strm.avail_out == 0); return arr; } static ant_value_t js_zlib_process_chunk(ant_t *js, ant_value_t *args, int nargs) { zlib_stream_t *st = zlib_stream_ptr(js_getthis(js)); if (!st) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid zlib stream"); if (st->destroyed || st->ended) return js_mkarr(js); const uint8_t *input = NULL; size_t input_len = 0; if (nargs >= 1 && is_object_type(args[0])) buffer_source_get_bytes(js, args[0], &input, &input_len); int flush_flag = Z_NO_FLUSH; if (nargs >= 2 && vtype(args[1]) == T_NUM) flush_flag = (int)js_getnum(args[1]); return zlib_process_chunk_sync(js, st, input, input_len, flush_flag); } static ant_value_t js_zlib_write(ant_t *js, ant_value_t *args, int nargs) { zlib_stream_t *st = zlib_stream_ptr(js_getthis(js)); if (!st) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid zlib stream"); if (st->destroyed) return js_false; if (st->ended) return js_false; if (nargs < 1 || vtype(args[0]) == T_UNDEF || vtype(args[0]) == T_NULL) return js_true; const uint8_t *bytes = NULL; size_t len = 0; if (is_object_type(args[0])) { buffer_source_get_bytes(js, args[0], &bytes, &len); } if (!bytes) { size_t slen = 0; char *s = js_getstr(js, args[0], &slen); if (s) { bytes = (const uint8_t *)s; len = slen; } } if (!bytes || len == 0) return js_true; st->bytes_written += (uint32_t)len; ant_value_t r = zlib_do_process(js, st, bytes, len, false); if (is_err(r)) { eventemitter_emit_args(js, st->obj, "error", &r, 1); return js_false; } ant_value_t cb = pick_callback(args, nargs); if (is_callable(cb)) { ant_value_t null_val = js_mknull(); sv_vm_call(js->vm, js, cb, js_mkundef(), &null_val, 1, NULL, false); } return js_true; } static ant_value_t js_zlib_end(ant_t *js, ant_value_t *args, int nargs) { zlib_stream_t *st = zlib_stream_ptr(js_getthis(js)); ant_value_t self = js_getthis(js); if (!st) return js_mkerr_typed(js, JS_ERR_TYPE, "Invalid zlib stream"); if (st->destroyed || st->ended) return self; if (nargs > 0 && vtype(args[0]) != T_UNDEF && vtype(args[0]) != T_NULL) { ant_value_t write_args[1] = { args[0] }; js_zlib_write(js, write_args, 1); } st->ended = true; ant_value_t r = zlib_do_process(js, st, NULL, 0, true); if (is_err(r)) { eventemitter_emit_args(js, st->obj, "error", &r, 1); return self; } eventemitter_emit_args(js, st->obj, "end", NULL, 0); eventemitter_emit_args(js, st->obj, "finish", NULL, 0); eventemitter_emit_args(js, st->obj, "close", NULL, 0); ant_value_t cb = pick_callback(args, nargs); if (is_callable(cb)) sv_vm_call(js->vm, js, cb, js_mkundef(), NULL, 0, NULL, false); return self; } static ant_value_t js_zlib_destroy(ant_t *js, ant_value_t *args, int nargs) { zlib_stream_t *st = zlib_stream_ptr(js_getthis(js)); ant_value_t self = js_getthis(js); if (!st || st->destroyed) return self; st->destroyed = true; zlib_stream_release(st); if (nargs > 0 && !js_truthy(js, args[0])) { ant_value_t null_val = js_mknull(); eventemitter_emit_args(js, st->obj, "error", &null_val, 1); } eventemitter_emit_args(js, st->obj, "close", NULL, 0); return self; } static ant_value_t js_zlib_pause(ant_t *js, ant_value_t *args, int nargs) { return js_getthis(js); } static ant_value_t js_zlib_resume(ant_t *js, ant_value_t *args, int nargs) { return js_getthis(js); } static ant_value_t js_zlib_unpipe(ant_t *js, ant_value_t *args, int nargs) { return js_getthis(js); } static ant_value_t pipe_on_data(ant_t *js, ant_value_t *args, int nargs) { ant_value_t fn = js_getcurrentfunc(js); ant_value_t dest = js_get_slot(fn, SLOT_DATA); ant_value_t write_fn = js_get(js, dest, "write"); if (is_callable(write_fn) && nargs > 0) sv_vm_call(js->vm, js, write_fn, dest, args, 1, NULL, false); return js_mkundef(); } static ant_value_t pipe_on_end(ant_t *js, ant_value_t *args, int nargs) { ant_value_t fn = js_getcurrentfunc(js); ant_value_t dest = js_get_slot(fn, SLOT_DATA); ant_value_t end_fn = js_get(js, dest, "end"); if (is_callable(end_fn)) sv_vm_call(js->vm, js, end_fn, dest, NULL, 0, NULL, false); return js_mkundef(); } static ant_value_t js_zlib_pipe(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1 || !is_object_type(args[0])) return js_mkundef(); ant_value_t self = js_getthis(js); ant_value_t dest = args[0]; ant_value_t data_handler = js_heavy_mkfun(js, pipe_on_data, dest); ant_value_t end_handler = js_heavy_mkfun(js, pipe_on_end, dest); eventemitter_add_listener(js, self, "data", data_handler, false); eventemitter_add_listener(js, self, "end", end_handler, true); return dest; } static ant_value_t js_zlib_get_bytes_written(ant_t *js, ant_value_t *args, int nargs) { zlib_stream_t *st = zlib_stream_ptr(js_getthis(js)); if (!st) return js_mknum(0); return js_mknum((double)st->bytes_written); } static ant_value_t zlib_create_stream(ant_t *js, zlib_kind_t kind) { bool compress = zlib_kind_is_compress(kind); zlib_stream_t *st = calloc(1, sizeof(zlib_stream_t)); if (!st) return js_mkerr(js, "out of memory"); st->kind = kind; st->js = js; if (kind == ZLIB_KIND_BROTLI_COMPRESS || kind == ZLIB_KIND_BROTLI_DECOMPRESS) { st->brotli = brotli_stream_state_new(kind == ZLIB_KIND_BROTLI_DECOMPRESS); if (!st->brotli) { free(st); return js_mkerr(js, "brotli init failed"); } st->initialized = true; } else { int wbits = zlib_window_bits(kind); int ret; if (compress) { ret = deflateInit2(&st->strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, wbits, 8, Z_DEFAULT_STRATEGY); } else ret = inflateInit2(&st->strm, wbits); if (ret != Z_OK) { free(st); return js_mkerr(js, "zlib init failed"); } st->initialized = true; } ant_value_t obj = js_mkobj(js); if (is_object_type(g_transform_proto)) js_set_proto_init(obj, g_transform_proto); js_set_native_ptr(obj, st); js_set_native_tag(obj, ZLIB_STREAM_TAG); js_set(js, obj, "readable", js_true); js_set(js, obj, "writable", js_true); js_set(js, obj, "_processChunk", js_mkfun(js_zlib_process_chunk)); ant_value_t handle_obj = js_mkobj(js); js_set(js, handle_obj, "close", js_mkfun(js_zlib_destroy)); js_set(js, obj, "_handle", handle_obj); st->obj = obj; zlib_add_active(st); return obj; } static ant_value_t js_create_gzip(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_GZIP); } static ant_value_t js_create_gunzip(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_GUNZIP); } static ant_value_t js_create_deflate(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_DEFLATE); } static ant_value_t js_create_inflate(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_INFLATE); } static ant_value_t js_create_deflate_raw(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_DEFLATE_RAW); } static ant_value_t js_create_inflate_raw(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_INFLATE_RAW); } static ant_value_t js_create_unzip(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_UNZIP); } static ant_value_t js_create_brotli_compress(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_BROTLI_COMPRESS); } static ant_value_t js_create_brotli_decompress(ant_t *js, ant_value_t *args, int nargs) { return zlib_create_stream(js, ZLIB_KIND_BROTLI_DECOMPRESS); } typedef struct { uint8_t *data; size_t len; size_t cap; int error; } zbuf_t; static int zbuf_append(zbuf_t *b, const uint8_t *chunk, size_t n) { if (b->len + n > b->cap) { size_t newcap = b->cap ? b->cap * 2 : 4096; while (newcap < b->len + n) newcap *= 2; uint8_t *p = realloc(b->data, newcap); if (!p) { b->error = 1; return -1; } b->data = p; b->cap = newcap; } memcpy(b->data + b->len, chunk, n); b->len += n; return 0; } static int zbuf_brotli_cb(void *ctx, const uint8_t *chunk, size_t n) { return zbuf_append((zbuf_t *)ctx, chunk, n); } static ant_value_t zlib_sync_op( ant_t *js, zlib_kind_t kind, const uint8_t *input, size_t input_len ) { zbuf_t out = {0}; uint8_t tmp[ZLIB_CHUNK]; bool compress = zlib_kind_is_compress(kind); if (kind == ZLIB_KIND_BROTLI_COMPRESS || kind == ZLIB_KIND_BROTLI_DECOMPRESS) { brotli_stream_state_t *bs = brotli_stream_state_new(kind == ZLIB_KIND_BROTLI_DECOMPRESS); if (!bs) return js_mkerr(js, "brotli init failed"); int rc = brotli_stream_process(bs, input, input_len, zbuf_brotli_cb, &out); if (rc >= 0) rc = brotli_stream_finish(bs, zbuf_brotli_cb, &out); brotli_stream_state_destroy(bs); if (rc < 0 || out.error) { free(out.data); return js_mkerr(js, "brotli operation failed"); } ant_value_t buf = zlib_make_buffer(js, out.data, out.len); free(out.data); return buf; } z_stream strm = {0}; int wbits = zlib_window_bits(kind); int ret; if (compress) ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, wbits, 8, Z_DEFAULT_STRATEGY); else ret = inflateInit2(&strm, wbits); if (ret != Z_OK) return js_mkerr(js, "zlib init failed"); strm.next_in = (Bytef *)input; strm.avail_in = (uInt)input_len; do { strm.next_out = tmp; strm.avail_out = ZLIB_CHUNK; if (compress) ret = deflate(&strm, Z_FINISH); else ret = inflate(&strm, Z_SYNC_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) { if (compress) deflateEnd(&strm); else inflateEnd(&strm); free(out.data); return js_mkerr(js, "zlib operation failed"); } size_t have = ZLIB_CHUNK - strm.avail_out; if (have > 0 && zbuf_append(&out, tmp, have) < 0) { if (compress) deflateEnd(&strm); else inflateEnd(&strm); free(out.data); return js_mkerr(js, "out of memory"); } if (ret == Z_STREAM_END) break; } while (strm.avail_out == 0 || strm.avail_in > 0); if (compress) deflateEnd(&strm); else inflateEnd(&strm); ant_value_t buf = zlib_make_buffer(js, out.data, out.len); free(out.data); return buf; } static bool get_input_bytes(ant_t *js, ant_value_t val, const uint8_t **out_bytes, size_t *out_len) { if (is_object_type(val) && buffer_source_get_bytes(js, val, out_bytes, out_len)) return true; size_t slen = 0; char *s = js_getstr(js, val, &slen); if (s) { *out_bytes = (const uint8_t *)s; *out_len = slen; return true; } return false; } static ant_value_t zlib_sync_fn(ant_t *js, ant_value_t *args, int nargs, zlib_kind_t kind) { if (nargs < 1) return js_mkerr(js, "argument required"); const uint8_t *bytes = NULL; size_t len = 0; if (!get_input_bytes(js, args[0], &bytes, &len)) return js_mkerr_typed(js, JS_ERR_TYPE, "argument must be a string or Buffer"); return zlib_sync_op(js, kind, bytes, len); } static ant_value_t zlib_async_fn(ant_t *js, ant_value_t *args, int nargs, zlib_kind_t kind) { if (nargs < 1) return js_mkerr(js, "argument required"); const uint8_t *bytes = NULL; size_t len = 0; ant_value_t cb = pick_callback(args, nargs); if (!get_input_bytes(js, args[0], &bytes, &len)) return js_mkerr_typed(js, JS_ERR_TYPE, "argument must be a string or Buffer"); ant_value_t result = zlib_sync_op(js, kind, bytes, len); if (is_callable(cb)) { if (is_err(result)) { ant_value_t argv[1] = { result }; sv_vm_call(js->vm, js, cb, js_mkundef(), argv, 1, NULL, false); } else { ant_value_t null_val = js_mknull(); ant_value_t argv[2] = { null_val, result }; sv_vm_call(js->vm, js, cb, js_mkundef(), argv, 2, NULL, false); } return js_mkundef(); } return result; } #define ZLIB_SYNC_FN(name, kind) \ static ant_value_t js_##name##Sync(ant_t *js, ant_value_t *a, int n) { return zlib_sync_fn(js, a, n, kind); } #define ZLIB_ASYNC_FN(name, kind) \ static ant_value_t js_##name(ant_t *js, ant_value_t *a, int n) { return zlib_async_fn(js, a, n, kind); } ZLIB_SYNC_FN(gzip, ZLIB_KIND_GZIP) ZLIB_SYNC_FN(gunzip, ZLIB_KIND_GUNZIP) ZLIB_SYNC_FN(deflate, ZLIB_KIND_DEFLATE) ZLIB_SYNC_FN(inflate, ZLIB_KIND_INFLATE) ZLIB_SYNC_FN(deflateRaw, ZLIB_KIND_DEFLATE_RAW) ZLIB_SYNC_FN(inflateRaw, ZLIB_KIND_INFLATE_RAW) ZLIB_SYNC_FN(unzip, ZLIB_KIND_UNZIP) ZLIB_SYNC_FN(brotliCompress, ZLIB_KIND_BROTLI_COMPRESS) ZLIB_SYNC_FN(brotliDecompress, ZLIB_KIND_BROTLI_DECOMPRESS) ZLIB_ASYNC_FN(gzip, ZLIB_KIND_GZIP) ZLIB_ASYNC_FN(gunzip, ZLIB_KIND_GUNZIP) ZLIB_ASYNC_FN(deflate, ZLIB_KIND_DEFLATE) ZLIB_ASYNC_FN(inflate, ZLIB_KIND_INFLATE) ZLIB_ASYNC_FN(deflateRaw, ZLIB_KIND_DEFLATE_RAW) ZLIB_ASYNC_FN(inflateRaw, ZLIB_KIND_INFLATE_RAW) ZLIB_ASYNC_FN(unzip, ZLIB_KIND_UNZIP) ZLIB_ASYNC_FN(brotliCompress, ZLIB_KIND_BROTLI_COMPRESS) ZLIB_ASYNC_FN(brotliDecompress, ZLIB_KIND_BROTLI_DECOMPRESS) static ant_value_t js_zlib_crc32(ant_t *js, ant_value_t *args, int nargs) { if (nargs < 1) return js_mkerr(js, "argument required"); const uint8_t *bytes = NULL; size_t len = 0; uLong init_val = 0; if (nargs >= 2 && vtype(args[1]) == T_NUM) init_val = (uLong)js_getnum(args[1]); if (!get_input_bytes(js, args[0], &bytes, &len)) return js_mkerr_typed(js, JS_ERR_TYPE, "argument must be a string or Buffer"); uLong crc = crc32(init_val, bytes, (uInt)len); return js_mknum((double)(uint32_t)crc); } static ant_value_t make_constants(ant_t *js) { ant_value_t c = js_mkobj(js); js_set(js, c, "Z_NO_FLUSH", js_mknum(Z_NO_FLUSH)); js_set(js, c, "Z_PARTIAL_FLUSH", js_mknum(Z_PARTIAL_FLUSH)); js_set(js, c, "Z_SYNC_FLUSH", js_mknum(Z_SYNC_FLUSH)); js_set(js, c, "Z_FULL_FLUSH", js_mknum(Z_FULL_FLUSH)); js_set(js, c, "Z_FINISH", js_mknum(Z_FINISH)); js_set(js, c, "Z_BLOCK", js_mknum(Z_BLOCK)); js_set(js, c, "Z_OK", js_mknum(Z_OK)); js_set(js, c, "Z_STREAM_END", js_mknum(Z_STREAM_END)); js_set(js, c, "Z_NEED_DICT", js_mknum(Z_NEED_DICT)); js_set(js, c, "Z_ERRNO", js_mknum(Z_ERRNO)); js_set(js, c, "Z_STREAM_ERROR", js_mknum(Z_STREAM_ERROR)); js_set(js, c, "Z_DATA_ERROR", js_mknum(Z_DATA_ERROR)); js_set(js, c, "Z_MEM_ERROR", js_mknum(Z_MEM_ERROR)); js_set(js, c, "Z_BUF_ERROR", js_mknum(Z_BUF_ERROR)); js_set(js, c, "Z_VERSION_ERROR", js_mknum(Z_VERSION_ERROR)); js_set(js, c, "Z_NO_COMPRESSION", js_mknum(Z_NO_COMPRESSION)); js_set(js, c, "Z_BEST_SPEED", js_mknum(Z_BEST_SPEED)); js_set(js, c, "Z_BEST_COMPRESSION", js_mknum(Z_BEST_COMPRESSION)); js_set(js, c, "Z_DEFAULT_COMPRESSION", js_mknum(Z_DEFAULT_COMPRESSION)); js_set(js, c, "Z_FILTERED", js_mknum(Z_FILTERED)); js_set(js, c, "Z_HUFFMAN_ONLY", js_mknum(Z_HUFFMAN_ONLY)); js_set(js, c, "Z_RLE", js_mknum(Z_RLE)); js_set(js, c, "Z_FIXED", js_mknum(Z_FIXED)); js_set(js, c, "Z_DEFAULT_STRATEGY", js_mknum(Z_DEFAULT_STRATEGY)); js_set(js, c, "BROTLI_OPERATION_PROCESS", js_mknum(0)); js_set(js, c, "BROTLI_OPERATION_FLUSH", js_mknum(1)); js_set(js, c, "BROTLI_OPERATION_FINISH", js_mknum(2)); js_set(js, c, "BROTLI_OPERATION_EMIT_METADATA", js_mknum(3)); js_set(js, c, "BROTLI_PARAM_MODE", js_mknum(0)); js_set(js, c, "BROTLI_MODE_GENERIC", js_mknum(0)); js_set(js, c, "BROTLI_MODE_TEXT", js_mknum(1)); js_set(js, c, "BROTLI_MODE_FONT", js_mknum(2)); js_set(js, c, "BROTLI_PARAM_QUALITY", js_mknum(1)); js_set(js, c, "BROTLI_MIN_QUALITY", js_mknum(0)); js_set(js, c, "BROTLI_MAX_QUALITY", js_mknum(11)); js_set(js, c, "BROTLI_DEFAULT_QUALITY", js_mknum(11)); js_set(js, c, "BROTLI_PARAM_LGWIN", js_mknum(2)); js_set(js, c, "BROTLI_MIN_WINDOW_BITS", js_mknum(10)); js_set(js, c, "BROTLI_MAX_WINDOW_BITS", js_mknum(24)); js_set(js, c, "BROTLI_DEFAULT_WINDOW", js_mknum(22)); js_set(js, c, "BROTLI_PARAM_SIZE_HINT", js_mknum(3)); js_set(js, c, "BROTLI_PARAM_LARGE_WINDOW", js_mknum(4)); js_set(js, c, "BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION", js_mknum(0)); js_set(js, c, "BROTLI_DECODER_PARAM_LARGE_WINDOW", js_mknum(1)); js_set(js, c, "ZSTD_e_continue", js_mknum(0)); js_set(js, c, "ZSTD_e_flush", js_mknum(1)); js_set(js, c, "ZSTD_e_end", js_mknum(2)); return c; } static void zlib_init_proto(ant_t *js) { if (g_transform_proto) return; ant_value_t events = events_library(js); ant_value_t ee_ctor = js_get(js, events, "EventEmitter"); ant_value_t ee_proto = js_get(js, ee_ctor, "prototype"); g_transform_proto = js_mkobj(js); js_set_proto_init(g_transform_proto, ee_proto); js_set(js, g_transform_proto, "write", js_mkfun(js_zlib_write)); js_set(js, g_transform_proto, "end", js_mkfun(js_zlib_end)); js_set(js, g_transform_proto, "destroy", js_mkfun(js_zlib_destroy)); js_set(js, g_transform_proto, "pause", js_mkfun(js_zlib_pause)); js_set(js, g_transform_proto, "resume", js_mkfun(js_zlib_resume)); js_set(js, g_transform_proto, "unpipe", js_mkfun(js_zlib_unpipe)); js_set(js, g_transform_proto, "pipe", js_mkfun(js_zlib_pipe)); js_set_getter_desc(js, g_transform_proto, "bytesWritten", 12, js_mkfun(js_zlib_get_bytes_written), JS_DESC_C); } static ant_value_t zlib_mkctor(ant_t *js, ant_value_t (*fn)(ant_t *, ant_value_t *, int)) { ant_value_t ctor = js_heavy_mkfun(js, fn, js_mkundef()); js_mark_constructor(ctor, true); return ctor; } ant_value_t zlib_library(ant_t *js) { zlib_init_proto(js); ant_value_t lib = js_mkobj(js); ant_value_t consts = make_constants(js); js_set(js, lib, "gzip", js_mkfun(js_gzip)); js_set(js, lib, "gzipSync", js_mkfun(js_gzipSync)); js_set(js, lib, "Gzip", zlib_mkctor(js, js_create_gzip)); js_set(js, lib, "createGzip", js_mkfun(js_create_gzip)); js_set(js, lib, "gunzip", js_mkfun(js_gunzip)); js_set(js, lib, "gunzipSync", js_mkfun(js_gunzipSync)); js_set(js, lib, "Gunzip", zlib_mkctor(js, js_create_gunzip)); js_set(js, lib, "createGunzip", js_mkfun(js_create_gunzip)); js_set(js, lib, "deflate", js_mkfun(js_deflate)); js_set(js, lib, "deflateSync", js_mkfun(js_deflateSync)); js_set(js, lib, "Deflate", zlib_mkctor(js, js_create_deflate)); js_set(js, lib, "createDeflate", js_mkfun(js_create_deflate)); js_set(js, lib, "inflate", js_mkfun(js_inflate)); js_set(js, lib, "inflateSync", js_mkfun(js_inflateSync)); js_set(js, lib, "Inflate", zlib_mkctor(js, js_create_inflate)); js_set(js, lib, "createInflate", js_mkfun(js_create_inflate)); js_set(js, lib, "deflateRaw", js_mkfun(js_deflateRaw)); js_set(js, lib, "deflateRawSync", js_mkfun(js_deflateRawSync)); js_set(js, lib, "DeflateRaw", zlib_mkctor(js, js_create_deflate_raw)); js_set(js, lib, "createDeflateRaw", js_mkfun(js_create_deflate_raw)); js_set(js, lib, "inflateRaw", js_mkfun(js_inflateRaw)); js_set(js, lib, "inflateRawSync", js_mkfun(js_inflateRawSync)); js_set(js, lib, "InflateRaw", zlib_mkctor(js, js_create_inflate_raw)); js_set(js, lib, "createInflateRaw", js_mkfun(js_create_inflate_raw)); js_set(js, lib, "unzip", js_mkfun(js_unzip)); js_set(js, lib, "unzipSync", js_mkfun(js_unzipSync)); js_set(js, lib, "Unzip", zlib_mkctor(js, js_create_unzip)); js_set(js, lib, "createUnzip", js_mkfun(js_create_unzip)); js_set(js, lib, "brotliCompress", js_mkfun(js_brotliCompress)); js_set(js, lib, "brotliCompressSync", js_mkfun(js_brotliCompressSync)); js_set(js, lib, "BrotliCompress", zlib_mkctor(js, js_create_brotli_compress)); js_set(js, lib, "createBrotliCompress", js_mkfun(js_create_brotli_compress)); js_set(js, lib, "brotliDecompress", js_mkfun(js_brotliDecompress)); js_set(js, lib, "brotliDecompressSync", js_mkfun(js_brotliDecompressSync)); js_set(js, lib, "BrotliDecompress", zlib_mkctor(js, js_create_brotli_decompress)); js_set(js, lib, "createBrotliDecompress", js_mkfun(js_create_brotli_decompress)); js_set(js, lib, "default", lib); js_set(js, lib, "constants", consts); js_set(js, lib, "crc32", js_mkfun(js_zlib_crc32)); js_set_sym(js, lib, get_toStringTag_sym(), js_mkstr(js, "zlib", 4)); return lib; } void gc_mark_zlib(ant_t *js, void (*mark)(ant_t *, ant_value_t)) { if (g_transform_proto) mark(js, g_transform_proto); for (zlib_stream_t *st = g_active_streams; st; st = st->next_active) mark(js, st->obj); }