From 572e7fc264e451c2c11cc70f7ae03ffbab977556 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 7 Mar 2024 22:39:42 -0500 Subject: [PATCH] Examples: Update fflate (#27883) --- examples/jsm/libs/fflate.module.js | 1190 ++++++++++++++++------------ 1 file changed, 694 insertions(+), 496 deletions(-) diff --git a/examples/jsm/libs/fflate.module.js b/examples/jsm/libs/fflate.module.js index 808000a503cf63..06383895963036 100644 --- a/examples/jsm/libs/fflate.module.js +++ b/examples/jsm/libs/fflate.module.js @@ -2,7 +2,7 @@ fflate - fast JavaScript compression/decompression Licensed under MIT. https://github.com/101arrowz/fflate/blob/master/LICENSE -version 0.6.9 +version 0.8.2 */ // DEFLATE is a complex format; to read this code, you should probably check the RFC first: @@ -15,31 +15,30 @@ version 0.6.9 // Sometimes 0 will appear where -1 would be more appropriate. This is because using a uint // is better for memory in most engines (I *think*). var ch2 = {}; -var durl = function (c) { return URL.createObjectURL(new Blob([c], { type: 'text/javascript' })); }; -var cwk = function (u) { return new Worker(u); }; -try { - URL.revokeObjectURL(durl('')); -} -catch (e) { - // We're in Deno or a very old browser - durl = function (c) { return 'data:application/javascript;charset=UTF-8,' + encodeURI(c); }; - // If Deno, this is necessary; if not, this changes nothing - cwk = function (u) { return new Worker(u, { type: 'module' }); }; -} var wk = (function (c, id, msg, transfer, cb) { - var w = cwk(ch2[id] || (ch2[id] = durl(c))); - w.onerror = function (e) { return cb(e.error, null); }; - w.onmessage = function (e) { return cb(null, e.data); }; + var w = new Worker(ch2[id] || (ch2[id] = URL.createObjectURL(new Blob([ + c + ';addEventListener("error",function(e){e=e.error;postMessage({$e$:[e.message,e.code,e.stack]})})' + ], { type: 'text/javascript' })))); + w.onmessage = function (e) { + var d = e.data, ed = d.$e$; + if (ed) { + var err = new Error(ed[0]); + err['code'] = ed[1]; + err.stack = ed[2]; + cb(err, null); + } + else + cb(null, d); + }; w.postMessage(msg, transfer); return w; }); // aliases for shorter compressed code (most minifers don't do this) -var u8 = Uint8Array, u16 = Uint16Array, u32 = Uint32Array; +var u8 = Uint8Array, u16 = Uint16Array, i32 = Int32Array; // fixed length extra bits var fleb = new u8([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, /* unused */ 0, 0, /* impossible */ 0]); // fixed distance extra bits -// see fleb note var fdeb = new u8([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, /* unused */ 0, 0]); // code length index map var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); @@ -50,26 +49,26 @@ var freb = function (eb, start) { b[i] = start += 1 << eb[i - 1]; } // numbers here are at max 18 bits - var r = new u32(b[30]); + var r = new i32(b[30]); for (var i = 1; i < 30; ++i) { for (var j = b[i]; j < b[i + 1]; ++j) { r[j] = ((j - b[i]) << 5) | i; } } - return [b, r]; + return { b: b, r: r }; }; -var _a = freb(fleb, 2), fl = _a[0], revfl = _a[1]; +var _a = freb(fleb, 2), fl = _a.b, revfl = _a.r; // we can ignore the fact that the other numbers are wrong; they never happen anyway fl[28] = 258, revfl[258] = 28; -var _b = freb(fdeb, 0), fd = _b[0], revfd = _b[1]; +var _b = freb(fdeb, 0), fd = _b.b, revfd = _b.r; // map of value to reverse (assuming 16 bits) var rev = new u16(32768); for (var i = 0; i < 32768; ++i) { // reverse table algorithm from SO - var x = ((i & 0xAAAA) >>> 1) | ((i & 0x5555) << 1); - x = ((x & 0xCCCC) >>> 2) | ((x & 0x3333) << 2); - x = ((x & 0xF0F0) >>> 4) | ((x & 0x0F0F) << 4); - rev[i] = (((x & 0xFF00) >>> 8) | ((x & 0x00FF) << 8)) >>> 1; + var x = ((i & 0xAAAA) >> 1) | ((i & 0x5555) << 1); + x = ((x & 0xCCCC) >> 2) | ((x & 0x3333) << 2); + x = ((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4); + rev[i] = (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8)) >> 1; } // create huffman tree from u8 "map": index -> code length for code index // mb (max bits) must be at most 15 @@ -81,11 +80,13 @@ var hMap = (function (cd, mb, r) { // u16 "map": index -> # of codes with bit length = index var l = new u16(mb); // length of cd must be 288 (total # of codes) - for (; i < s; ++i) - ++l[cd[i] - 1]; + for (; i < s; ++i) { + if (cd[i]) + ++l[cd[i] - 1]; + } // u16 "map": index -> minimum code for bit length = index var le = new u16(mb); - for (i = 0; i < mb; ++i) { + for (i = 1; i < mb; ++i) { le[i] = (le[i - 1] + l[i - 1]) << 1; } var co; @@ -106,7 +107,7 @@ var hMap = (function (cd, mb, r) { // m is end value for (var m = v | ((1 << r_1) - 1); v <= m; ++v) { // every 16 bit value starting with the code yields the same result - co[rev[v] >>> rvb] = sv; + co[rev[v] >> rvb] = sv; } } } @@ -115,7 +116,7 @@ var hMap = (function (cd, mb, r) { co = new u16(s); for (i = 0; i < s; ++i) { if (cd[i]) { - co[i] = rev[le[cd[i] - 1]++] >>> (15 - cd[i]); + co[i] = rev[le[cd[i] - 1]++] >> (15 - cd[i]); } } } @@ -159,7 +160,7 @@ var bits16 = function (d, p) { return ((d[o] | (d[o + 1] << 8) | (d[o + 2] << 16)) >> (p & 7)); }; // get end of byte -var shft = function (p) { return ((p / 8) | 0) + (p & 7 && 1); }; +var shft = function (p) { return ((p + 7) / 8) | 0; }; // typed array slice - allows garbage collector to free original reference, // while being more compatible than .slice var slc = function (v, s, e) { @@ -168,24 +169,69 @@ var slc = function (v, s, e) { if (e == null || e > v.length) e = v.length; // can't use .constructor in case user-supplied - var n = new (v instanceof u16 ? u16 : v instanceof u32 ? u32 : u8)(e - s); - n.set(v.subarray(s, e)); - return n; + return new u8(v.subarray(s, e)); +}; +/** + * Codes for errors generated within this library + */ +export var FlateErrorCode = { + UnexpectedEOF: 0, + InvalidBlockType: 1, + InvalidLengthLiteral: 2, + InvalidDistance: 3, + StreamFinished: 4, + NoStreamHandler: 5, + InvalidHeader: 6, + NoCallback: 7, + InvalidUTF8: 8, + ExtraFieldTooLong: 9, + InvalidDate: 10, + FilenameTooLong: 11, + StreamFinishing: 12, + InvalidZipData: 13, + UnknownCompressionMethod: 14 +}; +// error codes +var ec = [ + 'unexpected EOF', + 'invalid block type', + 'invalid length/literal', + 'invalid distance', + 'stream finished', + 'no stream handler', + , + 'no callback', + 'invalid UTF-8 data', + 'extra field too long', + 'date not in range 1980-2099', + 'filename too long', + 'stream finishing', + 'invalid zip data' + // determined by unknown compression method +]; +; +var err = function (ind, msg, nt) { + var e = new Error(msg || ec[ind]); + e.code = ind; + if (Error.captureStackTrace) + Error.captureStackTrace(e, err); + if (!nt) + throw e; + return e; }; // expands raw DEFLATE data -var inflt = function (dat, buf, st) { - // source length - var sl = dat.length; - if (!sl || (st && !st.l && sl < 5)) +var inflt = function (dat, st, buf, dict) { + // source length dict length + var sl = dat.length, dl = dict ? dict.length : 0; + if (!sl || st.f && !st.l) return buf || new u8(0); + var noBuf = !buf; // have to estimate size - var noBuf = !buf || st; + var resize = noBuf || st.i != 2; // no state - var noSt = !st || st.i; - if (!st) - st = {}; + var noSt = st.i; // Assumes roughly 33% compression ratio average - if (!buf) + if (noBuf) buf = new u8(sl * 3); // ensure buffer can fit at least l elements var cbuf = function (l) { @@ -205,7 +251,7 @@ var inflt = function (dat, buf, st) { do { if (!lm) { // BFINAL - this is only 1 when last chunk is next - st.f = final = bits(dat, pos, 1); + final = bits(dat, pos, 1); // type: 0 = no compression, 1 = fixed huffman, 2 = dynamic huffman var type = bits(dat, pos + 1, 3); pos += 3; @@ -214,16 +260,16 @@ var inflt = function (dat, buf, st) { var s = shft(pos) + 4, l = dat[s - 4] | (dat[s - 3] << 8), t = s + l; if (t > sl) { if (noSt) - throw 'unexpected EOF'; + err(0); break; } // ensure size - if (noBuf) + if (resize) cbuf(bt + l); // Copy over uncompressed data buf.set(dat.subarray(s, t), bt); // Get new bitpos, update byte count - st.b = bt += l, st.p = pos = t * 8; + st.b = bt += l, st.p = pos = t * 8, st.f = final; continue; } else if (type == 1) @@ -251,7 +297,7 @@ var inflt = function (dat, buf, st) { // bits read pos += r & 15; // symbol - var s = r >>> 4; + var s = r >> 4; // code length to copy if (s < 16) { ldt[i++] = s; @@ -279,30 +325,30 @@ var inflt = function (dat, buf, st) { dm = hMap(dt, dbt, 1); } else - throw 'invalid block type'; + err(1); if (pos > tbts) { if (noSt) - throw 'unexpected EOF'; + err(0); break; } } // Make sure the buffer can hold this + the largest possible addition - // Maximum chunk size (practically, theoretically infinite) is 2^17; - if (noBuf) + // Maximum chunk size (practically, theoretically infinite) is 2^17 + if (resize) cbuf(bt + 131072); var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1; var lpos = pos; for (;; lpos = pos) { // bits read, code - var c = lm[bits16(dat, pos) & lms], sym = c >>> 4; + var c = lm[bits16(dat, pos) & lms], sym = c >> 4; pos += c & 15; if (pos > tbts) { if (noSt) - throw 'unexpected EOF'; + err(0); break; } if (!c) - throw 'invalid length/literal'; + err(2); if (sym < 256) buf[bt++] = sym; else if (sym == 256) { @@ -319,52 +365,55 @@ var inflt = function (dat, buf, st) { pos += b; } // dist - var d = dm[bits16(dat, pos) & dms], dsym = d >>> 4; + var d = dm[bits16(dat, pos) & dms], dsym = d >> 4; if (!d) - throw 'invalid distance'; + err(3); pos += d & 15; var dt = fd[dsym]; if (dsym > 3) { var b = fdeb[dsym]; - dt += bits16(dat, pos) & ((1 << b) - 1), pos += b; + dt += bits16(dat, pos) & (1 << b) - 1, pos += b; } if (pos > tbts) { if (noSt) - throw 'unexpected EOF'; + err(0); break; } - if (noBuf) + if (resize) cbuf(bt + 131072); var end = bt + add; - for (; bt < end; bt += 4) { - buf[bt] = buf[bt - dt]; - buf[bt + 1] = buf[bt + 1 - dt]; - buf[bt + 2] = buf[bt + 2 - dt]; - buf[bt + 3] = buf[bt + 3 - dt]; + if (bt < dt) { + var shift = dl - dt, dend = Math.min(dt, end); + if (shift + bt < 0) + err(3); + for (; bt < dend; ++bt) + buf[bt] = dict[shift + bt]; } - bt = end; + for (; bt < end; ++bt) + buf[bt] = buf[bt - dt]; } } - st.l = lm, st.p = lpos, st.b = bt; + st.l = lm, st.p = lpos, st.b = bt, st.f = final; if (lm) final = 1, st.m = lbt, st.d = dm, st.n = dbt; } while (!final); - return bt == buf.length ? buf : slc(buf, 0, bt); + // don't reallocate for streams or user buffers + return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt); }; // starting at p, write the minimum number of bits that can hold v to d var wbits = function (d, p, v) { v <<= p & 7; var o = (p / 8) | 0; d[o] |= v; - d[o + 1] |= v >>> 8; + d[o + 1] |= v >> 8; }; // starting at p, write the minimum number of bits (>8) that can hold v to d var wbits16 = function (d, p, v) { v <<= p & 7; var o = (p / 8) | 0; d[o] |= v; - d[o + 1] |= v >>> 8; - d[o + 2] |= v >>> 16; + d[o + 1] |= v >> 8; + d[o + 2] |= v >> 16; }; // creates code lengths from a frequency table var hTree = function (d, mb) { @@ -377,11 +426,11 @@ var hTree = function (d, mb) { var s = t.length; var t2 = t.slice(); if (!s) - return [et, 0]; + return { t: et, l: 0 }; if (s == 1) { var v = new u8(t[0].s + 1); v[t[0].s] = 1; - return [v, 1]; + return { t: v, l: 1 }; } t.sort(function (a, b) { return a.f - b.f; }); // after i2 reaches last ind, will be stopped @@ -425,7 +474,7 @@ var hTree = function (d, mb) { else break; } - dt >>>= lft; + dt >>= lft; while (dt > 0) { var i2_2 = t2[i].s; if (tr[i2_2] < mb) @@ -442,7 +491,7 @@ var hTree = function (d, mb) { } mbt = mb; } - return [new u8(tr), mbt]; + return { t: new u8(tr), l: mbt }; }; // get the max length and assign length codes var ln = function (n, l, d) { @@ -485,7 +534,7 @@ var lc = function (c) { cln = c[i]; } } - return [cl.subarray(0, cli), s]; + return { c: cl.subarray(0, cli), n: s }; }; // calculate the length of output from tree, code lengths var clen = function (cf, cl) { @@ -501,7 +550,7 @@ var wfblk = function (out, pos, dat) { var s = dat.length; var o = shft(pos + 2); out[o] = s & 255; - out[o + 1] = s >>> 8; + out[o + 1] = s >> 8; out[o + 2] = out[o] ^ 255; out[o + 3] = out[o + 1] ^ 255; for (var i = 0; i < s; ++i) @@ -512,23 +561,23 @@ var wfblk = function (out, pos, dat) { var wblk = function (dat, out, final, syms, lf, df, eb, li, bs, bl, p) { wbits(out, p++, final); ++lf[256]; - var _a = hTree(lf, 15), dlt = _a[0], mlb = _a[1]; - var _b = hTree(df, 15), ddt = _b[0], mdb = _b[1]; - var _c = lc(dlt), lclt = _c[0], nlc = _c[1]; - var _d = lc(ddt), lcdt = _d[0], ndc = _d[1]; + var _a = hTree(lf, 15), dlt = _a.t, mlb = _a.l; + var _b = hTree(df, 15), ddt = _b.t, mdb = _b.l; + var _c = lc(dlt), lclt = _c.c, nlc = _c.n; + var _d = lc(ddt), lcdt = _d.c, ndc = _d.n; var lcfreq = new u16(19); for (var i = 0; i < lclt.length; ++i) - lcfreq[lclt[i] & 31]++; + ++lcfreq[lclt[i] & 31]; for (var i = 0; i < lcdt.length; ++i) - lcfreq[lcdt[i] & 31]++; - var _e = hTree(lcfreq, 7), lct = _e[0], mlcb = _e[1]; + ++lcfreq[lcdt[i] & 31]; + var _e = hTree(lcfreq, 7), lct = _e.t, mlcb = _e.l; var nlcc = 19; for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc) ; var flen = (bl + 5) << 3; var ftlen = clen(lf, flt) + clen(df, fdt) + eb; - var dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + (2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18]); - if (flen <= ftlen && flen <= dtlen) + var dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + 2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18]; + if (bs >= 0 && flen <= ftlen && flen <= dtlen) return wfblk(out, p, dat.subarray(bs, bs + bl)); var lm, ll, dm, dl; wbits(out, p, 1 + (dtlen < ftlen)), p += 2; @@ -549,7 +598,7 @@ var wblk = function (dat, out, final, syms, lf, df, eb, li, bs, bl, p) { var len = clct[i] & 31; wbits(out, p, llm[len]), p += lct[len]; if (len > 15) - wbits(out, p, (clct[i] >>> 5) & 127), p += clct[i] >>> 12; + wbits(out, p, (clct[i] >> 5) & 127), p += clct[i] >> 12; } } } @@ -557,67 +606,55 @@ var wblk = function (dat, out, final, syms, lf, df, eb, li, bs, bl, p) { lm = flm, ll = flt, dm = fdm, dl = fdt; } for (var i = 0; i < li; ++i) { - if (syms[i] > 255) { - var len = (syms[i] >>> 18) & 31; + var sym = syms[i]; + if (sym > 255) { + var len = (sym >> 18) & 31; wbits16(out, p, lm[len + 257]), p += ll[len + 257]; if (len > 7) - wbits(out, p, (syms[i] >>> 23) & 31), p += fleb[len]; - var dst = syms[i] & 31; + wbits(out, p, (sym >> 23) & 31), p += fleb[len]; + var dst = sym & 31; wbits16(out, p, dm[dst]), p += dl[dst]; if (dst > 3) - wbits16(out, p, (syms[i] >>> 5) & 8191), p += fdeb[dst]; + wbits16(out, p, (sym >> 5) & 8191), p += fdeb[dst]; } else { - wbits16(out, p, lm[syms[i]]), p += ll[syms[i]]; + wbits16(out, p, lm[sym]), p += ll[sym]; } } wbits16(out, p, lm[256]); return p + ll[256]; }; // deflate options (nice << 13) | chain -var deo = /*#__PURE__*/ new u32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]); +var deo = /*#__PURE__*/ new i32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]); // empty var et = /*#__PURE__*/ new u8(0); // compresses data into a raw DEFLATE buffer -var dflt = function (dat, lvl, plvl, pre, post, lst) { - var s = dat.length; +var dflt = function (dat, lvl, plvl, pre, post, st) { + var s = st.z || dat.length; var o = new u8(pre + s + 5 * (1 + Math.ceil(s / 7000)) + post); // writing to this writes to the output buffer var w = o.subarray(pre, o.length - post); - var pos = 0; - if (!lvl || s < 8) { - for (var i = 0; i <= s; i += 65535) { - // end - var e = i + 65535; - if (e < s) { - // write full block - pos = wfblk(w, pos, dat.subarray(i, e)); - } - else { - // write final block - w[i] = lst; - pos = wfblk(w, pos, dat.subarray(i, s)); - } - } - } - else { + var lst = st.l; + var pos = (st.r || 0) & 7; + if (lvl) { + if (pos) + w[0] = st.r >> 3; var opt = deo[lvl - 1]; - var n = opt >>> 13, c = opt & 8191; + var n = opt >> 13, c = opt & 8191; var msk_1 = (1 << plvl) - 1; // prev 2-byte val map curr 2-byte val map - var prev = new u16(32768), head = new u16(msk_1 + 1); + var prev = st.p || new u16(32768), head = st.h || new u16(msk_1 + 1); var bs1_1 = Math.ceil(plvl / 3), bs2_1 = 2 * bs1_1; var hsh = function (i) { return (dat[i] ^ (dat[i + 1] << bs1_1) ^ (dat[i + 2] << bs2_1)) & msk_1; }; // 24576 is an arbitrary number of maximum symbols per block // 424 buffer for last block - var syms = new u32(25000); + var syms = new i32(25000); // length/literal freq distance freq var lf = new u16(288), df = new u16(32); - // l/lcnt exbits index l/lind waitdx bitpos - var lc_1 = 0, eb = 0, i = 0, li = 0, wi = 0, bs = 0; - for (; i < s; ++i) { + // l/lcnt exbits index l/lind waitdx blkpos + var lc_1 = 0, eb = 0, i = st.i || 0, li = 0, wi = st.w || 0, bs = 0; + for (; i + 2 < s; ++i) { // hash value - // deopt when i > s - 3 - at end, deopt acceptable var hv = hsh(i); // index mod 32768 previous index mod var imod = i & 32767, pimod = head[hv]; @@ -628,7 +665,7 @@ var dflt = function (dat, lvl, plvl, pre, post, lst) { if (wi <= i) { // bytes remaining var rem = s - i; - if ((lc_1 > 7000 || li > 24576) && rem > 423) { + if ((lc_1 > 7000 || li > 24576) && (rem > 423 || !lst)) { pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos); li = lc_1 = eb = 0, bs = i; for (var j = 0; j < 286; ++j) @@ -637,7 +674,7 @@ var dflt = function (dat, lvl, plvl, pre, post, lst) { df[j] = 0; } // len dist chain - var l = 2, d = 0, ch_1 = c, dif = (imod - pimod) & 32767; + var l = 2, d = 0, ch_1 = c, dif = imod - pimod & 32767; if (rem > 2 && hv == hsh(i - dif)) { var maxn = Math.min(n, rem) - 1; var maxd = Math.min(32767, i); @@ -660,9 +697,9 @@ var dflt = function (dat, lvl, plvl, pre, post, lst) { var mmd = Math.min(dif, nl - 2); var md = 0; for (var j = 0; j < mmd; ++j) { - var ti = (i - dif + j + 32768) & 32767; + var ti = i - dif + j & 32767; var pti = prev[ti]; - var cd = (ti - pti + 32768) & 32767; + var cd = ti - pti & 32767; if (cd > md) md = cd, pimod = ti; } @@ -670,12 +707,12 @@ var dflt = function (dat, lvl, plvl, pre, post, lst) { } // check the previous match imod = pimod, pimod = prev[imod]; - dif += (imod - pimod + 32768) & 32767; + dif += imod - pimod & 32767; } } // d will be nonzero only when a match was found if (d) { - // store both dist and len data in one Uint32 + // store both dist and len data in one int32 // Make sure this is recognized as a len/dist with 28th bit (2^28) syms[li++] = 268435456 | (revfl[l] << 18) | revfd[d]; var lin = revfl[l] & 31, din = revfd[d] & 31; @@ -691,20 +728,40 @@ var dflt = function (dat, lvl, plvl, pre, post, lst) { } } } + for (i = Math.max(i, wi); i < s; ++i) { + syms[li++] = dat[i]; + ++lf[dat[i]]; + } pos = wblk(dat, w, lst, syms, lf, df, eb, li, bs, i - bs, pos); - // this is the easiest way to avoid needing to maintain state - if (!lst && pos & 7) - pos = wfblk(w, pos + 1, et); + if (!lst) { + st.r = (pos & 7) | w[(pos / 8) | 0] << 3; + // shft(pos) now 1 less if pos & 7 != 0 + pos -= 7; + st.h = head, st.p = prev, st.i = i, st.w = wi; + } + } + else { + for (var i = st.w || 0; i < s + lst; i += 65535) { + // end + var e = i + 65535; + if (e >= s) { + // write final block + w[(pos / 8) | 0] = lst; + e = s; + } + pos = wfblk(w, pos + 1, dat.subarray(i, e)); + } + st.i = s; } return slc(o, 0, pre + shft(pos) + post); }; // CRC32 table var crct = /*#__PURE__*/ (function () { - var t = new u32(256); + var t = new Int32Array(256); for (var i = 0; i < 256; ++i) { var c = i, k = 9; while (--k) - c = ((c & 1) && 0xEDB88320) ^ (c >>> 1); + c = ((c & 1) && -306674912) ^ (c >>> 1); t[i] = c; } return t; @@ -723,14 +780,14 @@ var crc = function () { d: function () { return ~c; } }; }; -// Alder32 +// Adler32 var adler = function () { var a = 1, b = 0; return { p: function (d) { // closures have awful performance var n = a, m = b; - var l = d.length; + var l = d.length | 0; for (var i = 0; i != l;) { var e = Math.min(i + 2655, l); for (; i < e; ++i) @@ -741,14 +798,25 @@ var adler = function () { }, d: function () { a %= 65521, b %= 65521; - return (a & 255) << 24 | (a >>> 8) << 16 | (b & 255) << 8 | (b >>> 8); + return (a & 255) << 24 | (a & 0xFF00) << 8 | (b & 255) << 8 | (b >> 8); } }; }; ; // deflate with opts var dopt = function (dat, opt, pre, post, st) { - return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : (12 + opt.mem), pre, post, !st); + if (!st) { + st = { l: 1 }; + if (opt.dictionary) { + var dict = opt.dictionary.subarray(-32768); + var newDat = new u8(dict.length + dat.length); + newDat.set(dict); + newDat.set(dat, dict.length); + dat = newDat; + st.w = dict.length; + } + } + return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? (st.l ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : 20) : (12 + opt.mem), pre, post, st); }; // Walmart object spread var mrg = function (a, b) { @@ -769,7 +837,7 @@ var mrg = function (a, b) { var wcln = function (fn, fnStr, td) { var dt = fn(); var st = fn.toString(); - var ks = st.slice(st.indexOf('[') + 1, st.lastIndexOf(']')).replace(/ /g, '').split(','); + var ks = st.slice(st.indexOf('[') + 1, st.lastIndexOf(']')).replace(/\s+/g, '').split(','); for (var i = 0; i < dt.length; ++i) { var v = dt[i], k = ks[i]; if (typeof v == 'function') { @@ -793,33 +861,33 @@ var wcln = function (fn, fnStr, td) { else td[k] = v; } - return [fnStr, td]; + return fnStr; }; var ch = []; // clone bufs var cbfs = function (v) { var tl = []; for (var k in v) { - if (v[k] instanceof u8 || v[k] instanceof u16 || v[k] instanceof u32) + if (v[k].buffer) { tl.push((v[k] = new v[k].constructor(v[k])).buffer); + } } return tl; }; // use a worker to execute code var wrkr = function (fns, init, id, cb) { - var _a; if (!ch[id]) { var fnStr = '', td_1 = {}, m = fns.length - 1; for (var i = 0; i < m; ++i) - _a = wcln(fns[i], fnStr, td_1), fnStr = _a[0], td_1 = _a[1]; - ch[id] = wcln(fns[m], fnStr, td_1); + fnStr = wcln(fns[i], fnStr, td_1); + ch[id] = { c: wcln(fns[m], fnStr, td_1), e: td_1 }; } - var td = mrg({}, ch[id][1]); - return wk(ch[id][0] + ';onmessage=function(e){for(var k in e.data)self[k]=e.data[k];onmessage=' + init.toString() + '}', id, td, cbfs(td), cb); + var td = mrg({}, ch[id].e); + return wk(ch[id].c + ';onmessage=function(e){for(var k in e.data)self[k]=e.data[k];onmessage=' + init.toString() + '}', id, td, cbfs(td), cb); }; // base async inflate fn -var bInflt = function () { return [u8, u16, u32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, hMap, max, bits, bits16, shft, slc, inflt, inflateSync, pbf, gu8]; }; -var bDflt = function () { return [u8, u16, u32, fleb, fdeb, clim, revfl, revfd, flm, flt, fdm, fdt, rev, deo, et, hMap, wbits, wbits16, hTree, ln, lc, clen, wfblk, wblk, shft, slc, dflt, dopt, deflateSync, pbf]; }; +var bInflt = function () { return [u8, u16, i32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, ec, hMap, max, bits, bits16, shft, slc, err, inflt, inflateSync, pbf, gopt]; }; +var bDflt = function () { return [u8, u16, i32, fleb, fdeb, clim, revfl, revfd, flm, flt, fdm, fdt, rev, deo, et, hMap, wbits, wbits16, hTree, ln, lc, clen, wfblk, wblk, shft, slc, dflt, dopt, deflateSync, pbf]; }; // gzip extra var gze = function () { return [gzh, gzhl, wbytes, crc, crct]; }; // gunzip extra @@ -827,11 +895,14 @@ var guze = function () { return [gzs, gzl]; }; // zlib extra var zle = function () { return [zlh, wbytes, adler]; }; // unzlib extra -var zule = function () { return [zlv]; }; +var zule = function () { return [zls]; }; // post buf var pbf = function (msg) { return postMessage(msg, [msg.buffer]); }; -// get u8 -var gu8 = function (o) { return o && o.size && new u8(o.size); }; +// get opts +var gopt = function (o) { return o && { + out: o.size && new u8(o.size), + dictionary: o.dictionary +}; }; // async helper var cbify = function (dat, opts, fns, init, id, cb) { var w = wrkr(fns, init, id, function (err, dat) { @@ -844,14 +915,28 @@ var cbify = function (dat, opts, fns, init, id, cb) { // auto stream var astrm = function (strm) { strm.ondata = function (dat, final) { return postMessage([dat, final], [dat.buffer]); }; - return function (ev) { return strm.push(ev.data[0], ev.data[1]); }; + return function (ev) { + if (ev.data.length) { + strm.push(ev.data[0], ev.data[1]); + postMessage([ev.data[0].length]); + } + else + strm.flush(); + }; }; // async stream attach -var astrmify = function (fns, strm, opts, init, id) { +var astrmify = function (fns, strm, opts, init, id, flush, ext) { var t; var w = wrkr(fns, init, id, function (err, dat) { if (err) w.terminate(), strm.ondata.call(strm, err); + else if (!Array.isArray(dat)) + ext(dat); + else if (dat.length == 1) { + strm.queuedSize -= dat[0]; + if (strm.ondrain) + strm.ondrain(dat[0]); + } else { if (dat[1]) w.terminate(); @@ -859,14 +944,19 @@ var astrmify = function (fns, strm, opts, init, id) { } }); w.postMessage(opts); + strm.queuedSize = 0; strm.push = function (d, f) { - if (t) - throw 'stream finished'; if (!strm.ondata) - throw 'no stream handler'; + err(5); + if (t) + strm.ondata(err(4, 0, 1), null, !!f); + strm.queuedSize += d.length; w.postMessage([d, t = f], [d.buffer]); }; strm.terminate = function () { w.terminate(); }; + if (flush) { + strm.flush = function () { w.postMessage([]); }; + } }; // read 2 bytes var b2 = function (d, b) { return d[b] | (d[b + 1] << 8); }; @@ -894,11 +984,11 @@ var gzh = function (c, o) { // gzip start var gzs = function (d) { if (d[0] != 31 || d[1] != 139 || d[2] != 8) - throw 'invalid gzip data'; + err(6, 'invalid gzip data'); var flg = d[3]; var st = 10; if (flg & 4) - st += d[10] | (d[11] << 8) + 2; + st += (d[10] | d[11] << 8) + 2; for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++]) ; return st + (flg & 2); @@ -906,41 +996,56 @@ var gzs = function (d) { // gzip length var gzl = function (d) { var l = d.length; - return ((d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16) | (d[l - 1] << 24)) >>> 0; + return (d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16 | d[l - 1] << 24) >>> 0; }; // gzip header length -var gzhl = function (o) { return 10 + ((o.filename && (o.filename.length + 1)) || 0); }; +var gzhl = function (o) { return 10 + (o.filename ? o.filename.length + 1 : 0); }; // zlib header var zlh = function (c, o) { var lv = o.level, fl = lv == 0 ? 0 : lv < 6 ? 1 : lv == 9 ? 3 : 2; - c[0] = 120, c[1] = (fl << 6) | (fl ? (32 - 2 * fl) : 1); + c[0] = 120, c[1] = (fl << 6) | (o.dictionary && 32); + c[1] |= 31 - ((c[0] << 8) | c[1]) % 31; + if (o.dictionary) { + var h = adler(); + h.p(o.dictionary); + wbytes(c, 2, h.d()); + } }; -// zlib valid -var zlv = function (d) { - if ((d[0] & 15) != 8 || (d[0] >>> 4) > 7 || ((d[0] << 8 | d[1]) % 31)) - throw 'invalid zlib data'; - if (d[1] & 32) - throw 'invalid zlib data: preset dictionaries not supported'; +// zlib start +var zls = function (d, dict) { + if ((d[0] & 15) != 8 || (d[0] >> 4) > 7 || ((d[0] << 8 | d[1]) % 31)) + err(6, 'invalid zlib data'); + if ((d[1] >> 5 & 1) == +!dict) + err(6, 'invalid zlib data: ' + (d[1] & 32 ? 'need' : 'unexpected') + ' dictionary'); + return (d[1] >> 3 & 4) + 2; }; -function AsyncCmpStrm(opts, cb) { - if (!cb && typeof opts == 'function') +function StrmOpt(opts, cb) { + if (typeof opts == 'function') cb = opts, opts = {}; this.ondata = cb; return opts; } -// zlib footer: -4 to -0 is Adler32 /** * Streaming DEFLATE compression */ var Deflate = /*#__PURE__*/ (function () { function Deflate(opts, cb) { - if (!cb && typeof opts == 'function') + if (typeof opts == 'function') cb = opts, opts = {}; this.ondata = cb; this.o = opts || {}; + this.s = { l: 0, i: 32768, w: 32768, z: 32768 }; + // Buffer length must always be 0 mod 32768 for index calculations to be correct when modifying head and prev + // 98304 = 32768 (lookback) + 65536 (common chunk size) + this.b = new u8(98304); + if (this.o.dictionary) { + var dict = this.o.dictionary.subarray(-32768); + this.b.set(dict, 32768 - dict.length); + this.s.i = 32768 - dict.length; + } } Deflate.prototype.p = function (c, f) { - this.ondata(dopt(c, this.o, 0, 0, !f), f); + this.ondata(dopt(c, this.o, 0, 0, this.s), f); }; /** * Pushes a chunk to be deflated @@ -948,12 +1053,47 @@ var Deflate = /*#__PURE__*/ (function () { * @param final Whether this is the last chunk */ Deflate.prototype.push = function (chunk, final) { - if (this.d) - throw 'stream finished'; if (!this.ondata) - throw 'no stream handler'; - this.d = final; - this.p(chunk, final || false); + err(5); + if (this.s.l) + err(4); + var endLen = chunk.length + this.s.z; + if (endLen > this.b.length) { + if (endLen > 2 * this.b.length - 32768) { + var newBuf = new u8(endLen & -32768); + newBuf.set(this.b.subarray(0, this.s.z)); + this.b = newBuf; + } + var split = this.b.length - this.s.z; + this.b.set(chunk.subarray(0, split), this.s.z); + this.s.z = this.b.length; + this.p(this.b, false); + this.b.set(this.b.subarray(-32768)); + this.b.set(chunk.subarray(split), 32768); + this.s.z = chunk.length - split + 32768; + this.s.i = 32766, this.s.w = 32768; + } + else { + this.b.set(chunk, this.s.z); + this.s.z += chunk.length; + } + this.s.l = final & 1; + if (this.s.z > this.s.w + 8191 || final) { + this.p(this.b, final || false); + this.s.w = this.s.i, this.s.i -= 2; + } + }; + /** + * Flushes buffered uncompressed data. Useful to immediately retrieve the + * deflated output for small inputs. + */ + Deflate.prototype.flush = function () { + if (!this.ondata) + err(5); + if (this.s.l) + err(4); + this.p(this.b, false); + this.s.w = this.s.i, this.s.i -= 2; }; return Deflate; }()); @@ -966,10 +1106,10 @@ var AsyncDeflate = /*#__PURE__*/ (function () { astrmify([ bDflt, function () { return [astrm, Deflate]; } - ], this, AsyncCmpStrm.call(this, opts, cb), function (ev) { + ], this, StrmOpt.call(this, opts, cb), function (ev) { var strm = new Deflate(ev.data); onmessage = astrm(strm); - }, 6); + }, 6, 1); } return AsyncDeflate; }()); @@ -978,7 +1118,7 @@ export function deflate(data, opts, cb) { if (!cb) cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); return cbify(data, opts, [ bDflt, ], function (ev) { return pbf(deflateSync(ev.data[0], ev.data[1])); }, 0, cb); @@ -996,28 +1136,34 @@ export function deflateSync(data, opts) { * Streaming DEFLATE decompression */ var Inflate = /*#__PURE__*/ (function () { - /** - * Creates an inflation stream - * @param cb The callback to call whenever data is inflated - */ - function Inflate(cb) { - this.s = {}; - this.p = new u8(0); + function Inflate(opts, cb) { + // no StrmOpt here to avoid adding to workerizer + if (typeof opts == 'function') + cb = opts, opts = {}; this.ondata = cb; + var dict = opts && opts.dictionary && opts.dictionary.subarray(-32768); + this.s = { i: 0, b: dict ? dict.length : 0 }; + this.o = new u8(32768); + this.p = new u8(0); + if (dict) + this.o.set(dict); } Inflate.prototype.e = function (c) { - if (this.d) - throw 'stream finished'; if (!this.ondata) - throw 'no stream handler'; - var l = this.p.length; - var n = new u8(l + c.length); - n.set(this.p), n.set(c, l), this.p = n; + err(5); + if (this.d) + err(4); + if (!this.p.length) + this.p = c; + else if (c.length) { + var n = new u8(this.p.length + c.length); + n.set(this.p), n.set(c, this.p.length), this.p = n; + } }; Inflate.prototype.c = function (final) { - this.d = this.s.i = final || false; + this.s.i = +(this.d = final || false); var bts = this.s.b; - var dt = inflt(this.p, this.o, this.s); + var dt = inflt(this.p, this.s, this.o); this.ondata(slc(dt, bts, this.s.b), this.d); this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length; this.p = slc(this.p, (this.s.p / 8) | 0), this.s.p &= 7; @@ -1037,19 +1183,14 @@ export { Inflate }; * Asynchronous streaming DEFLATE decompression */ var AsyncInflate = /*#__PURE__*/ (function () { - /** - * Creates an asynchronous inflation stream - * @param cb The callback to call whenever data is deflated - */ - function AsyncInflate(cb) { - this.ondata = cb; + function AsyncInflate(opts, cb) { astrmify([ bInflt, function () { return [astrm, Inflate]; } - ], this, 0, function () { - var strm = new Inflate(); + ], this, StrmOpt.call(this, opts, cb), function (ev) { + var strm = new Inflate(ev.data); onmessage = astrm(strm); - }, 7); + }, 7, 0); } return AsyncInflate; }()); @@ -1058,19 +1199,19 @@ export function inflate(data, opts, cb) { if (!cb) cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); return cbify(data, opts, [ bInflt - ], function (ev) { return pbf(inflateSync(ev.data[0], gu8(ev.data[1]))); }, 1, cb); + ], function (ev) { return pbf(inflateSync(ev.data[0], gopt(ev.data[1]))); }, 1, cb); } /** * Expands DEFLATE data with no wrapper * @param data The data to decompress - * @param out Where to write the data. Saves memory if you know the decompressed size and provide an output buffer of that length. + * @param opts The decompression options * @returns The decompressed version of the data */ -export function inflateSync(data, out) { - return inflt(data, out); +export function inflateSync(data, opts) { + return inflt(data, { i: 2 }, opts && opts.out, opts && opts.dictionary); } // before you yell at me for not just using extends, my reason is that TS inheritance is hard to workerize. /** @@ -1089,18 +1230,25 @@ var Gzip = /*#__PURE__*/ (function () { * @param final Whether this is the last chunk */ Gzip.prototype.push = function (chunk, final) { + this.c.p(chunk); + this.l += chunk.length; Deflate.prototype.push.call(this, chunk, final); }; Gzip.prototype.p = function (c, f) { - this.c.p(c); - this.l += c.length; - var raw = dopt(c, this.o, this.v && gzhl(this.o), f && 8, !f); + var raw = dopt(c, this.o, this.v && gzhl(this.o), f && 8, this.s); if (this.v) gzh(raw, this.o), this.v = 0; if (f) wbytes(raw, raw.length - 8, this.c.d()), wbytes(raw, raw.length - 4, this.l); this.ondata(raw, f); }; + /** + * Flushes buffered uncompressed data. Useful to immediately retrieve the + * GZIPped output for small inputs. + */ + Gzip.prototype.flush = function () { + Deflate.prototype.flush.call(this); + }; return Gzip; }()); export { Gzip }; @@ -1113,10 +1261,10 @@ var AsyncGzip = /*#__PURE__*/ (function () { bDflt, gze, function () { return [astrm, Deflate, Gzip]; } - ], this, AsyncCmpStrm.call(this, opts, cb), function (ev) { + ], this, StrmOpt.call(this, opts, cb), function (ev) { var strm = new Gzip(ev.data); onmessage = astrm(strm); - }, 8); + }, 8, 1); } return AsyncGzip; }()); @@ -1125,7 +1273,7 @@ export function gzip(data, opts, cb) { if (!cb) cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); return cbify(data, opts, [ bDflt, gze, @@ -1147,16 +1295,13 @@ export function gzipSync(data, opts) { return gzh(d, opts), wbytes(d, s - 8, c.d()), wbytes(d, s - 4, l), d; } /** - * Streaming GZIP decompression + * Streaming single or multi-member GZIP decompression */ var Gunzip = /*#__PURE__*/ (function () { - /** - * Creates a GUNZIP stream - * @param cb The callback to call whenever data is inflated - */ - function Gunzip(cb) { + function Gunzip(opts, cb) { this.v = 1; - Inflate.call(this, cb); + this.r = 0; + Inflate.call(this, opts, cb); } /** * Pushes a chunk to be GUNZIPped @@ -1165,42 +1310,48 @@ var Gunzip = /*#__PURE__*/ (function () { */ Gunzip.prototype.push = function (chunk, final) { Inflate.prototype.e.call(this, chunk); + this.r += chunk.length; if (this.v) { - var s = this.p.length > 3 ? gzs(this.p) : 4; - if (s >= this.p.length && !final) - return; - this.p = this.p.subarray(s), this.v = 0; - } - if (final) { - if (this.p.length < 8) - throw 'invalid gzip stream'; - this.p = this.p.subarray(0, -8); + var p = this.p.subarray(this.v - 1); + var s = p.length > 3 ? gzs(p) : 4; + if (s > p.length) { + if (!final) + return; + } + else if (this.v > 1 && this.onmember) { + this.onmember(this.r - p.length); + } + this.p = p.subarray(s), this.v = 0; } // necessary to prevent TS from using the closure value // This allows for workerization to function correctly Inflate.prototype.c.call(this, final); + // process concatenated GZIP + if (this.s.f && !this.s.l && !final) { + this.v = shft(this.s.p) + 9; + this.s = { i: 0 }; + this.o = new u8(0); + this.push(new u8(0), final); + } }; return Gunzip; }()); export { Gunzip }; /** - * Asynchronous streaming GZIP decompression + * Asynchronous streaming single or multi-member GZIP decompression */ var AsyncGunzip = /*#__PURE__*/ (function () { - /** - * Creates an asynchronous GUNZIP stream - * @param cb The callback to call whenever data is deflated - */ - function AsyncGunzip(cb) { - this.ondata = cb; + function AsyncGunzip(opts, cb) { + var _this = this; astrmify([ bInflt, guze, function () { return [astrm, Inflate, Gunzip]; } - ], this, 0, function () { - var strm = new Gunzip(); + ], this, StrmOpt.call(this, opts, cb), function (ev) { + var strm = new Gunzip(ev.data); + strm.onmember = function (offset) { return postMessage(offset); }; onmessage = astrm(strm); - }, 9); + }, 9, 0, function (offset) { return _this.onmember && _this.onmember(offset); }); } return AsyncGunzip; }()); @@ -1209,21 +1360,24 @@ export function gunzip(data, opts, cb) { if (!cb) cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); return cbify(data, opts, [ bInflt, guze, function () { return [gunzipSync]; } - ], function (ev) { return pbf(gunzipSync(ev.data[0])); }, 3, cb); + ], function (ev) { return pbf(gunzipSync(ev.data[0], ev.data[1])); }, 3, cb); } /** * Expands GZIP data * @param data The data to decompress - * @param out Where to write the data. GZIP already encodes the output size, so providing this doesn't save memory. + * @param opts The decompression options * @returns The decompressed version of the data */ -export function gunzipSync(data, out) { - return inflt(data.subarray(gzs(data), -8), out || new u8(gzl(data))); +export function gunzipSync(data, opts) { + var st = gzs(data); + if (st + 8 > data.length) + err(6, 'invalid gzip data'); + return inflt(data.subarray(st, -8), { i: 2 }, opts && opts.out || new u8(gzl(data)), opts && opts.dictionary); } /** * Streaming Zlib compression @@ -1240,17 +1394,24 @@ var Zlib = /*#__PURE__*/ (function () { * @param final Whether this is the last chunk */ Zlib.prototype.push = function (chunk, final) { + this.c.p(chunk); Deflate.prototype.push.call(this, chunk, final); }; Zlib.prototype.p = function (c, f) { - this.c.p(c); - var raw = dopt(c, this.o, this.v && 2, f && 4, !f); + var raw = dopt(c, this.o, this.v && (this.o.dictionary ? 6 : 2), f && 4, this.s); if (this.v) zlh(raw, this.o), this.v = 0; if (f) wbytes(raw, raw.length - 4, this.c.d()); this.ondata(raw, f); }; + /** + * Flushes buffered uncompressed data. Useful to immediately retrieve the + * zlibbed output for small inputs. + */ + Zlib.prototype.flush = function () { + Deflate.prototype.flush.call(this); + }; return Zlib; }()); export { Zlib }; @@ -1263,10 +1424,10 @@ var AsyncZlib = /*#__PURE__*/ (function () { bDflt, zle, function () { return [astrm, Deflate, Zlib]; } - ], this, AsyncCmpStrm.call(this, opts, cb), function (ev) { + ], this, StrmOpt.call(this, opts, cb), function (ev) { var strm = new Zlib(ev.data); onmessage = astrm(strm); - }, 10); + }, 10, 1); } return AsyncZlib; }()); @@ -1275,7 +1436,7 @@ export function zlib(data, opts, cb) { if (!cb) cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); return cbify(data, opts, [ bDflt, zle, @@ -1293,20 +1454,16 @@ export function zlibSync(data, opts) { opts = {}; var a = adler(); a.p(data); - var d = dopt(data, opts, 2, 4); + var d = dopt(data, opts, opts.dictionary ? 6 : 2, 4); return zlh(d, opts), wbytes(d, d.length - 4, a.d()), d; } /** * Streaming Zlib decompression */ var Unzlib = /*#__PURE__*/ (function () { - /** - * Creates a Zlib decompression stream - * @param cb The callback to call whenever data is inflated - */ - function Unzlib(cb) { - this.v = 1; - Inflate.call(this, cb); + function Unzlib(opts, cb) { + Inflate.call(this, opts, cb); + this.v = opts && opts.dictionary ? 2 : 1; } /** * Pushes a chunk to be unzlibbed @@ -1316,13 +1473,13 @@ var Unzlib = /*#__PURE__*/ (function () { Unzlib.prototype.push = function (chunk, final) { Inflate.prototype.e.call(this, chunk); if (this.v) { - if (this.p.length < 2 && !final) + if (this.p.length < 6 && !final) return; - this.p = this.p.subarray(2), this.v = 0; + this.p = this.p.subarray(zls(this.p, this.v - 1)), this.v = 0; } if (final) { if (this.p.length < 4) - throw 'invalid zlib stream'; + err(6, 'invalid zlib data'); this.p = this.p.subarray(0, -4); } // necessary to prevent TS from using the closure value @@ -1336,20 +1493,15 @@ export { Unzlib }; * Asynchronous streaming Zlib decompression */ var AsyncUnzlib = /*#__PURE__*/ (function () { - /** - * Creates an asynchronous Zlib decompression stream - * @param cb The callback to call whenever data is deflated - */ - function AsyncUnzlib(cb) { - this.ondata = cb; + function AsyncUnzlib(opts, cb) { astrmify([ bInflt, zule, function () { return [astrm, Inflate, Unzlib]; } - ], this, 0, function () { - var strm = new Unzlib(); + ], this, StrmOpt.call(this, opts, cb), function (ev) { + var strm = new Unzlib(ev.data); onmessage = astrm(strm); - }, 11); + }, 11, 0); } return AsyncUnzlib; }()); @@ -1358,40 +1510,43 @@ export function unzlib(data, opts, cb) { if (!cb) cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); return cbify(data, opts, [ bInflt, zule, function () { return [unzlibSync]; } - ], function (ev) { return pbf(unzlibSync(ev.data[0], gu8(ev.data[1]))); }, 5, cb); + ], function (ev) { return pbf(unzlibSync(ev.data[0], gopt(ev.data[1]))); }, 5, cb); } /** * Expands Zlib data * @param data The data to decompress - * @param out Where to write the data. Saves memory if you know the decompressed size and provide an output buffer of that length. + * @param opts The decompression options * @returns The decompressed version of the data */ -export function unzlibSync(data, out) { - return inflt((zlv(data), data.subarray(2, -4)), out); +export function unzlibSync(data, opts) { + return inflt(data.subarray(zls(data, opts && opts.dictionary), -4), { i: 2 }, opts && opts.out, opts && opts.dictionary); } // Default algorithm for compression (used because having a known output size allows faster decompression) export { gzip as compress, AsyncGzip as AsyncCompress }; -// Default algorithm for compression (used because having a known output size allows faster decompression) export { gzipSync as compressSync, Gzip as Compress }; /** * Streaming GZIP, Zlib, or raw DEFLATE decompression */ var Decompress = /*#__PURE__*/ (function () { - /** - * Creates a decompression stream - * @param cb The callback to call whenever data is decompressed - */ - function Decompress(cb) { + function Decompress(opts, cb) { + this.o = StrmOpt.call(this, opts, cb) || {}; this.G = Gunzip; this.I = Inflate; this.Z = Unzlib; - this.ondata = cb; } + // init substream + // overriden by AsyncDecompress + Decompress.prototype.i = function () { + var _this = this; + this.s.ondata = function (dat, final) { + _this.ondata(dat, final); + }; + }; /** * Pushes a chunk to be decompressed * @param chunk The chunk to push @@ -1399,7 +1554,7 @@ var Decompress = /*#__PURE__*/ (function () { */ Decompress.prototype.push = function (chunk, final) { if (!this.ondata) - throw 'no stream handler'; + err(5); if (!this.s) { if (this.p && this.p.length) { var n = new u8(this.p.length + chunk.length); @@ -1408,13 +1563,12 @@ var Decompress = /*#__PURE__*/ (function () { else this.p = chunk; if (this.p.length > 2) { - var _this_1 = this; - var cb = function () { _this_1.ondata.apply(_this_1, arguments); }; this.s = (this.p[0] == 31 && this.p[1] == 139 && this.p[2] == 8) - ? new this.G(cb) + ? new this.G(this.o) : ((this.p[0] & 15) != 8 || (this.p[0] >> 4) > 7 || ((this.p[0] << 8 | this.p[1]) % 31)) - ? new this.I(cb) - : new this.Z(cb); + ? new this.I(this.o) + : new this.Z(this.o); + this.i(); this.s.push(this.p, final); this.p = null; } @@ -1429,22 +1583,31 @@ export { Decompress }; * Asynchronous streaming GZIP, Zlib, or raw DEFLATE decompression */ var AsyncDecompress = /*#__PURE__*/ (function () { - /** - * Creates an asynchronous decompression stream - * @param cb The callback to call whenever data is decompressed - */ - function AsyncDecompress(cb) { + function AsyncDecompress(opts, cb) { + Decompress.call(this, opts, cb); + this.queuedSize = 0; this.G = AsyncGunzip; this.I = AsyncInflate; this.Z = AsyncUnzlib; - this.ondata = cb; } + AsyncDecompress.prototype.i = function () { + var _this = this; + this.s.ondata = function (err, dat, final) { + _this.ondata(err, dat, final); + }; + this.s.ondrain = function (size) { + _this.queuedSize -= size; + if (_this.ondrain) + _this.ondrain(size); + }; + }; /** * Pushes a chunk to be decompressed * @param chunk The chunk to push * @param final Whether this is the last chunk */ AsyncDecompress.prototype.push = function (chunk, final) { + this.queuedSize += chunk.length; Decompress.prototype.push.call(this, chunk, final); }; return AsyncDecompress; @@ -1454,7 +1617,7 @@ export function decompress(data, opts, cb) { if (!cb) cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); return (data[0] == 31 && data[1] == 139 && data[2] == 8) ? gunzip(data, opts, cb) : ((data[0] & 15) != 8 || (data[0] >> 4) > 7 || ((data[0] << 8 | data[1]) % 31)) @@ -1464,26 +1627,28 @@ export function decompress(data, opts, cb) { /** * Expands compressed GZIP, Zlib, or raw DEFLATE data, automatically detecting the format * @param data The data to decompress - * @param out Where to write the data. Saves memory if you know the decompressed size and provide an output buffer of that length. + * @param opts The decompression options * @returns The decompressed version of the data */ -export function decompressSync(data, out) { +export function decompressSync(data, opts) { return (data[0] == 31 && data[1] == 139 && data[2] == 8) - ? gunzipSync(data, out) + ? gunzipSync(data, opts) : ((data[0] & 15) != 8 || (data[0] >> 4) > 7 || ((data[0] << 8 | data[1]) % 31)) - ? inflateSync(data, out) - : unzlibSync(data, out); + ? inflateSync(data, opts) + : unzlibSync(data, opts); } // flatten a directory structure var fltn = function (d, p, t, o) { for (var k in d) { - var val = d[k], n = p + k; + var val = d[k], n = p + k, op = o; + if (Array.isArray(val)) + op = mrg(o, val[1]), val = val[0]; if (val instanceof u8) - t[n] = [val, o]; - else if (Array.isArray(val)) - t[n] = [val[0], mrg(o, val[1])]; - else - fltn(val, n + '/', t, o); + t[n] = [val, op]; + else { + t[n += '/'] = [new u8(0), op]; + fltn(val, n, t, o); + } } }; // text encoder @@ -1503,7 +1668,7 @@ var dutf8 = function (d) { var c = d[i++]; var eb = (c > 127) + (c > 223) + (c > 239); if (i + eb > d.length) - return [r, slc(d, i - 1)]; + return { s: r, r: slc(d, i - 1) }; if (!eb) r += String.fromCharCode(c); else if (eb == 3) { @@ -1538,31 +1703,31 @@ var DecodeUTF8 = /*#__PURE__*/ (function () { */ DecodeUTF8.prototype.push = function (chunk, final) { if (!this.ondata) - throw 'no callback'; + err(5); final = !!final; if (this.t) { this.ondata(this.t.decode(chunk, { stream: true }), final); if (final) { if (this.t.decode().length) - throw 'invalid utf-8 data'; + err(8); this.t = null; } return; } if (!this.p) - throw 'stream finished'; + err(4); var dat = new u8(this.p.length + chunk.length); dat.set(this.p); dat.set(chunk, this.p.length); - var _a = dutf8(dat), ch = _a[0], np = _a[1]; + var _a = dutf8(dat), s = _a.s, r = _a.r; if (final) { - if (np.length) - throw 'invalid utf-8 data'; + if (r.length) + err(8); this.p = null; } else - this.p = np; - this.ondata(ch, final); + this.p = r; + this.ondata(s, final); }; return DecodeUTF8; }()); @@ -1585,9 +1750,9 @@ var EncodeUTF8 = /*#__PURE__*/ (function () { */ EncodeUTF8.prototype.push = function (chunk, final) { if (!this.ondata) - throw 'no callback'; + err(5); if (this.d) - throw 'stream finished'; + err(4); this.ondata(strToU8(chunk), this.d = final || false); }; return EncodeUTF8; @@ -1646,13 +1811,14 @@ export function strFromU8(dat, latin1) { r += String.fromCharCode.apply(null, dat.subarray(i, i + 16384)); return r; } - else if (td) + else if (td) { return td.decode(dat); + } else { - var _a = dutf8(dat), out = _a[0], ext = _a[1]; - if (ext.length) - throw 'invalid utf-8 data'; - return out; + var _a = dutf8(dat), s = _a.s, r = _a.r; + if (r.length) + err(8); + return s; } } ; @@ -1679,7 +1845,7 @@ var exfl = function (ex) { for (var k in ex) { var l = ex[k].length; if (l > 65535) - throw 'extra field too long'; + err(9); le += l + 4; } } @@ -1693,15 +1859,15 @@ var wzh = function (d, b, f, fn, u, c, ce, co) { if (ce != null) d[b++] = 20, d[b++] = f.os; d[b] = 20, b += 2; // spec compliance? what's that? - d[b++] = (f.flag << 1) | (c == null && 8), d[b++] = u && 8; + d[b++] = (f.flag << 1) | (c < 0 && 8), d[b++] = u && 8; d[b++] = f.compression & 255, d[b++] = f.compression >> 8; var dt = new Date(f.mtime == null ? Date.now() : f.mtime), y = dt.getFullYear() - 1980; if (y < 0 || y > 119) - throw 'date not in range 1980-2099'; - wbytes(d, b, (y << 25) | ((dt.getMonth() + 1) << 21) | (dt.getDate() << 16) | (dt.getHours() << 11) | (dt.getMinutes() << 5) | (dt.getSeconds() >>> 1)), b += 4; - if (c != null) { + err(10); + wbytes(d, b, (y << 25) | ((dt.getMonth() + 1) << 21) | (dt.getDate() << 16) | (dt.getHours() << 11) | (dt.getMinutes() << 5) | (dt.getSeconds() >> 1)), b += 4; + if (c != -1) { wbytes(d, b, f.crc); - wbytes(d, b + 4, c); + wbytes(d, b + 4, c < 0 ? -c - 2 : c); wbytes(d, b + 8, f.size); } wbytes(d, b + 12, fl); @@ -1767,7 +1933,7 @@ var ZipPassThrough = /*#__PURE__*/ (function () { */ ZipPassThrough.prototype.push = function (chunk, final) { if (!this.ondata) - throw 'no callback - add to ZIP archive before pushing'; + err(5); this.c.p(chunk); this.size += chunk.length; if (final) @@ -1789,12 +1955,12 @@ var ZipDeflate = /*#__PURE__*/ (function () { * @param opts The compression options */ function ZipDeflate(filename, opts) { - var _this_1 = this; + var _this = this; if (!opts) opts = {}; ZipPassThrough.call(this, filename); this.d = new Deflate(opts, function (dat, final) { - _this_1.ondata(null, dat, final); + _this.ondata(null, dat, final); }); this.compression = 8; this.flag = dbf(opts.level); @@ -1823,17 +1989,17 @@ export { ZipDeflate }; */ var AsyncZipDeflate = /*#__PURE__*/ (function () { /** - * Creates a DEFLATE stream that can be added to ZIP archives + * Creates an asynchronous DEFLATE stream that can be added to ZIP archives * @param filename The filename to associate with this data stream * @param opts The compression options */ function AsyncZipDeflate(filename, opts) { - var _this_1 = this; + var _this = this; if (!opts) opts = {}; ZipPassThrough.call(this, filename); this.d = new AsyncDeflate(opts, function (err, dat, final) { - _this_1.ondata(err, dat, final); + _this.ondata(err, dat, final); }); this.compression = 8; this.flag = dbf(opts.level); @@ -1873,74 +2039,79 @@ var Zip = /*#__PURE__*/ (function () { * @param file The file stream to add */ Zip.prototype.add = function (file) { - var _this_1 = this; + var _this = this; + if (!this.ondata) + err(5); + // finishing or finished if (this.d & 2) - throw 'stream finished'; - var f = strToU8(file.filename), fl = f.length; - var com = file.comment, o = com && strToU8(com); - var u = fl != file.filename.length || (o && (com.length != o.length)); - var hl = fl + exfl(file.extra) + 30; - if (fl > 65535) - throw 'filename too long'; - var header = new u8(hl); - wzh(header, 0, file, f, u); - var chks = [header]; - var pAll = function () { - for (var _i = 0, chks_1 = chks; _i < chks_1.length; _i++) { - var chk = chks_1[_i]; - _this_1.ondata(null, chk, false); - } - chks = []; - }; - var tr = this.d; - this.d = 0; - var ind = this.u.length; - var uf = mrg(file, { - f: f, - u: u, - o: o, - t: function () { - if (file.terminate) - file.terminate(); - }, - r: function () { - pAll(); - if (tr) { - var nxt = _this_1.u[ind + 1]; - if (nxt) - nxt.r(); - else - _this_1.d = 1; + this.ondata(err(4 + (this.d & 1) * 8, 0, 1), null, false); + else { + var f = strToU8(file.filename), fl_1 = f.length; + var com = file.comment, o = com && strToU8(com); + var u = fl_1 != file.filename.length || (o && (com.length != o.length)); + var hl_1 = fl_1 + exfl(file.extra) + 30; + if (fl_1 > 65535) + this.ondata(err(11, 0, 1), null, false); + var header = new u8(hl_1); + wzh(header, 0, file, f, u, -1); + var chks_1 = [header]; + var pAll_1 = function () { + for (var _i = 0, chks_2 = chks_1; _i < chks_2.length; _i++) { + var chk = chks_2[_i]; + _this.ondata(null, chk, false); } - tr = 1; - } - }); - var cl = 0; - file.ondata = function (err, dat, final) { - if (err) { - _this_1.ondata(err, dat, final); - _this_1.terminate(); - } - else { - cl += dat.length; - chks.push(dat); - if (final) { - var dd = new u8(16); - wbytes(dd, 0, 0x8074B50); - wbytes(dd, 4, file.crc); - wbytes(dd, 8, cl); - wbytes(dd, 12, file.size); - chks.push(dd); - uf.c = cl, uf.b = hl + cl + 16, uf.crc = file.crc, uf.size = file.size; - if (tr) - uf.r(); - tr = 1; + chks_1 = []; + }; + var tr_1 = this.d; + this.d = 0; + var ind_1 = this.u.length; + var uf_1 = mrg(file, { + f: f, + u: u, + o: o, + t: function () { + if (file.terminate) + file.terminate(); + }, + r: function () { + pAll_1(); + if (tr_1) { + var nxt = _this.u[ind_1 + 1]; + if (nxt) + nxt.r(); + else + _this.d = 1; + } + tr_1 = 1; } - else if (tr) - pAll(); - } - }; - this.u.push(uf); + }); + var cl_1 = 0; + file.ondata = function (err, dat, final) { + if (err) { + _this.ondata(err, dat, final); + _this.terminate(); + } + else { + cl_1 += dat.length; + chks_1.push(dat); + if (final) { + var dd = new u8(16); + wbytes(dd, 0, 0x8074B50); + wbytes(dd, 4, file.crc); + wbytes(dd, 8, cl_1); + wbytes(dd, 12, file.size); + chks_1.push(dd); + uf_1.c = cl_1, uf_1.b = hl_1 + cl_1 + 16, uf_1.crc = file.crc, uf_1.size = file.size; + if (tr_1) + uf_1.r(); + tr_1 = 1; + } + else if (tr_1) + pAll_1(); + } + }; + this.u.push(uf_1); + } }; /** * Ends the process of adding files and prepares to emit the final chunks. @@ -1948,21 +2119,20 @@ var Zip = /*#__PURE__*/ (function () { * ZIP file to work properly. */ Zip.prototype.end = function () { - var _this_1 = this; + var _this = this; if (this.d & 2) { - if (this.d & 1) - throw 'stream finishing'; - throw 'stream finished'; + this.ondata(err(4 + (this.d & 1) * 8, 0, 1), null, true); + return; } if (this.d) this.e(); else this.u.push({ r: function () { - if (!(_this_1.d & 1)) + if (!(_this.d & 1)) return; - _this_1.u.splice(-1, 1); - _this_1.e(); + _this.u.splice(-1, 1); + _this.e(); }, t: function () { } }); @@ -1977,7 +2147,7 @@ var Zip = /*#__PURE__*/ (function () { var out = new u8(tl + 22); for (var _b = 0, _c = this.u; _b < _c.length; _b++) { var f = _c[_b]; - wzh(out, bt, f, f.f, f.u, f.c, l, f.o); + wzh(out, bt, f, f.f, f.u, -f.c - 2, l, f.o); bt += 46 + f.f.length + exfl(f.extra) + (f.o ? f.o.length : 0), l += f.b; } wzf(out, bt, this.u.length, tl, l); @@ -2002,7 +2172,7 @@ export function zip(data, opts, cb) { if (!cb) cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); var r = {}; fltn(data, '', r, opts); var k = Object.keys(r); @@ -2013,6 +2183,10 @@ export function zip(data, opts, cb) { for (var i = 0; i < term.length; ++i) term[i](); }; + var cbd = function (a, b) { + mt(function () { cb(a, b); }); + }; + mt(function () { cbd = cb; }); var cbf = function () { var out = new u8(tot + 22), oe = o, cdl = tot - o; tot = 0; @@ -2027,11 +2201,11 @@ export function zip(data, opts, cb) { wzh(out, o, f, f.f, f.u, l, tot, f.m), o += 16 + badd + (f.m ? f.m.length : 0), tot = loc + l; } catch (e) { - return cb(e, null); + return cbd(e, null); } } wzf(out, o, files.length, cdl, oe); - cb(null, out); + cbd(null, out); }; if (!lft) cbf(); @@ -2047,7 +2221,7 @@ export function zip(data, opts, cb) { var cbl = function (e, d) { if (e) { tAll(); - cb(e, null); + cbd(e, null); } else { var l = d.length; @@ -2067,7 +2241,7 @@ export function zip(data, opts, cb) { } }; if (s > 65535) - cbl('filename too long', null); + cbl(err(11, 0, 1), null); if (!compression) cbl(null, file); else if (size < 160000) { @@ -2109,7 +2283,7 @@ export function zipSync(data, opts) { var com = p.comment, m = com && strToU8(com), ms = m && m.length; var exl = exfl(p.extra); if (s > 65535) - throw 'filename too long'; + err(11); var d = compression ? deflateSync(file, p) : file, l = d.length; var c = crc(); c.p(file); @@ -2159,9 +2333,9 @@ var UnzipInflate = /*#__PURE__*/ (function () { * Creates a DEFLATE decompression that can be used in ZIP archives */ function UnzipInflate() { - var _this_1 = this; + var _this = this; this.i = new Inflate(function (dat, final) { - _this_1.ondata(null, dat, final); + _this.ondata(null, dat, final); }); } UnzipInflate.prototype.push = function (data, final) { @@ -2169,7 +2343,7 @@ var UnzipInflate = /*#__PURE__*/ (function () { this.i.push(data, final); } catch (e) { - this.ondata(e, data, final); + this.ondata(e, null, final); } }; UnzipInflate.compression = 8; @@ -2184,15 +2358,15 @@ var AsyncUnzipInflate = /*#__PURE__*/ (function () { * Creates a DEFLATE decompression that can be used in ZIP archives */ function AsyncUnzipInflate(_, sz) { - var _this_1 = this; + var _this = this; if (sz < 320000) { this.i = new Inflate(function (dat, final) { - _this_1.ondata(null, dat, final); + _this.ondata(null, dat, final); }); } else { this.i = new AsyncInflate(function (err, dat, final) { - _this_1.ondata(err, dat, final); + _this.ondata(err, dat, final); }); this.terminate = this.i.terminate; } @@ -2228,11 +2402,11 @@ var Unzip = /*#__PURE__*/ (function () { * @param final Whether this is the last chunk */ Unzip.prototype.push = function (chunk, final) { - var _this_1 = this; + var _this = this; if (!this.onfile) - throw 'no callback'; + err(5); if (!this.p) - throw 'stream finished'; + err(4); if (this.c > 0) { var len = Math.min(this.c, chunk.length); var toAdd = chunk.subarray(0, len); @@ -2265,8 +2439,8 @@ var Unzip = /*#__PURE__*/ (function () { this_1.c = 0; var bf = b2(buf, i + 6), cmp_1 = b2(buf, i + 8), u = bf & 2048, dd = bf & 8, fnl = b2(buf, i + 26), es = b2(buf, i + 28); if (l > i + 30 + fnl + es) { - var chks_2 = []; - this_1.k.unshift(chks_2); + var chks_3 = []; + this_1.k.unshift(chks_3); f = 2; var sc_1 = b4(buf, i + 18), su_1 = b4(buf, i + 22); var fn_1 = strFromU8(buf.subarray(i + 30, i += 30 + fnl), !u); @@ -2283,21 +2457,21 @@ var Unzip = /*#__PURE__*/ (function () { compression: cmp_1, start: function () { if (!file_1.ondata) - throw 'no callback'; + err(5); if (!sc_1) file_1.ondata(null, et, true); else { - var ctr = _this_1.o[cmp_1]; + var ctr = _this.o[cmp_1]; if (!ctr) - throw 'unknown compression type ' + cmp_1; + file_1.ondata(err(14, 'unknown compression type ' + cmp_1, 1), null, false); d_1 = sc_1 < 0 ? new ctr(fn_1) : new ctr(fn_1, sc_1, su_1); d_1.ondata = function (err, dat, final) { file_1.ondata(err, dat, final); }; - for (var _i = 0, chks_3 = chks_2; _i < chks_3.length; _i++) { - var dat = chks_3[_i]; + for (var _i = 0, chks_4 = chks_3; _i < chks_4.length; _i++) { + var dat = chks_4[_i]; d_1.push(dat, false); } - if (_this_1.k[0] == chks_2 && _this_1.c) - _this_1.d = d_1; + if (_this.k[0] == chks_3 && _this.c) + _this.d = d_1; else d_1.push(et, true); } @@ -2344,7 +2518,7 @@ var Unzip = /*#__PURE__*/ (function () { } if (final) { if (this.c) - throw 'invalid zip file'; + err(13); this.p = null; } }; @@ -2359,116 +2533,140 @@ var Unzip = /*#__PURE__*/ (function () { return Unzip; }()); export { Unzip }; -/** - * Asynchronously decompresses a ZIP archive - * @param data The raw compressed ZIP file - * @param cb The callback to call with the decompressed files - * @returns A function that can be used to immediately terminate the unzipping - */ -export function unzip(data, cb) { +var mt = typeof queueMicrotask == 'function' ? queueMicrotask : typeof setTimeout == 'function' ? setTimeout : function (fn) { fn(); }; +export function unzip(data, opts, cb) { + if (!cb) + cb = opts, opts = {}; if (typeof cb != 'function') - throw 'no callback'; + err(7); var term = []; var tAll = function () { for (var i = 0; i < term.length; ++i) term[i](); }; var files = {}; + var cbd = function (a, b) { + mt(function () { cb(a, b); }); + }; + mt(function () { cbd = cb; }); var e = data.length - 22; for (; b4(data, e) != 0x6054B50; --e) { if (!e || data.length - e > 65558) { - cb('invalid zip file', null); - return; + cbd(err(13, 0, 1), null); + return tAll; } } ; var lft = b2(data, e + 8); - if (!lft) - cb(null, {}); - var c = lft; - var o = b4(data, e + 16); - var z = o == 4294967295; - if (z) { - e = b4(data, e - 12); - if (b4(data, e) != 0x6064B50) { - cb('invalid zip file', null); - return; - } - c = lft = b4(data, e + 32); - o = b4(data, e + 48); - } - var _loop_3 = function (i) { - var _a = zh(data, o, z), c_1 = _a[0], sc = _a[1], su = _a[2], fn = _a[3], no = _a[4], off = _a[5], b = slzh(data, off); - o = no; - var cbl = function (e, d) { - if (e) { - tAll(); - cb(e, null); + if (lft) { + var c = lft; + var o = b4(data, e + 16); + var z = o == 4294967295 || c == 65535; + if (z) { + var ze = b4(data, e - 12); + z = b4(data, ze) == 0x6064B50; + if (z) { + c = lft = b4(data, ze + 32); + o = b4(data, ze + 48); } - else { - files[fn] = d; - if (!--lft) - cb(null, files); - } - }; - if (!c_1) - cbl(null, slc(data, b, b + sc)); - else if (c_1 == 8) { - var infl = data.subarray(b, b + sc); - if (sc < 320000) { - try { - cbl(null, inflateSync(infl, new u8(su))); + } + var fltr = opts && opts.filter; + var _loop_3 = function (i) { + var _a = zh(data, o, z), c_1 = _a[0], sc = _a[1], su = _a[2], fn = _a[3], no = _a[4], off = _a[5], b = slzh(data, off); + o = no; + var cbl = function (e, d) { + if (e) { + tAll(); + cbd(e, null); } - catch (e) { - cbl(e, null); + else { + if (d) + files[fn] = d; + if (!--lft) + cbd(null, files); } + }; + if (!fltr || fltr({ + name: fn, + size: sc, + originalSize: su, + compression: c_1 + })) { + if (!c_1) + cbl(null, slc(data, b, b + sc)); + else if (c_1 == 8) { + var infl = data.subarray(b, b + sc); + // Synchronously decompress under 512KB, or barely-compressed data + if (su < 524288 || sc > 0.8 * su) { + try { + cbl(null, inflateSync(infl, { out: new u8(su) })); + } + catch (e) { + cbl(e, null); + } + } + else + term.push(inflate(infl, { size: su }, cbl)); + } + else + cbl(err(14, 'unknown compression type ' + c_1, 1), null); } else - term.push(inflate(infl, { size: su }, cbl)); + cbl(null, null); + }; + for (var i = 0; i < c; ++i) { + _loop_3(i); } - else - cbl('unknown compression type ' + c_1, null); - }; - for (var i = 0; i < c; ++i) { - _loop_3(i); } + else + cbd(null, {}); return tAll; } /** * Synchronously decompresses a ZIP archive. Prefer using `unzip` for better * performance with more than one file. * @param data The raw compressed ZIP file + * @param opts The ZIP extraction options * @returns The decompressed files */ -export function unzipSync(data) { +export function unzipSync(data, opts) { var files = {}; var e = data.length - 22; for (; b4(data, e) != 0x6054B50; --e) { if (!e || data.length - e > 65558) - throw 'invalid zip file'; + err(13); } ; var c = b2(data, e + 8); if (!c) return {}; var o = b4(data, e + 16); - var z = o == 4294967295; + var z = o == 4294967295 || c == 65535; if (z) { - e = b4(data, e - 12); - if (b4(data, e) != 0x6064B50) - throw 'invalid zip file'; - c = b4(data, e + 32); - o = b4(data, e + 48); + var ze = b4(data, e - 12); + z = b4(data, ze) == 0x6064B50; + if (z) { + c = b4(data, ze + 32); + o = b4(data, ze + 48); + } } + var fltr = opts && opts.filter; for (var i = 0; i < c; ++i) { var _a = zh(data, o, z), c_2 = _a[0], sc = _a[1], su = _a[2], fn = _a[3], no = _a[4], off = _a[5], b = slzh(data, off); o = no; - if (!c_2) - files[fn] = slc(data, b, b + sc); - else if (c_2 == 8) - files[fn] = inflateSync(data.subarray(b, b + sc), new u8(su)); - else - throw 'unknown compression type ' + c_2; + if (!fltr || fltr({ + name: fn, + size: sc, + originalSize: su, + compression: c_2 + })) { + if (!c_2) + files[fn] = slc(data, b, b + sc); + else if (c_2 == 8) + files[fn] = inflateSync(data.subarray(b, b + sc), { out: new u8(su) }); + else + err(14, 'unknown compression type ' + c_2); + } } return files; }