101arrowz / fflate

High performance (de)compression in an 8kB package
https://101arrowz.github.io/fflate
MIT License
2.29k stars 80 forks source link

Uncaught SyntaxError: Unexpected end of input #226

Open Booteille opened 1 week ago

Booteille commented 1 week ago

Hi!

I am trying to use the async version of zip function, using deno runtime. Unfortunately, my code returns an error when trying to upload a file higher than 150kb (but works perfectly fine when using files lower in size).

Here are the test files: fakefile_150KB.txt fakefile_151KB.txt

Have you any clue on how to solve this issue?

Thanks.

How to reproduce The code used:

import * as fs from "node:fs";
import mime from "mime";
import * as fflate from "fflate";

const filePath = "./bench/fakefile_151KB.txt";
const file = new File([fs.readFileSync(filePath)], filePath, {
  type: mime.getType(filePath) as string,
});
const fileBytes = await file.bytes();

fflate.zip({
  [file.name]: fileBytes,
}, (err, _data) => {
  if (err) console.error(err);
});

The problem

error: Uncaught (in worker "[worker eval]") SyntaxError: Unexpected end of input
Warning Couldn't format source line: Column 149 is out of bounds (source may have changed at runtime)
    at <anonymous> (data:text/javascript,;u8=Uint8Array;u16=U......u16 "map": index -> :1:149)
[Object: null prototype] {
  message: "Uncaught SyntaxError: Unexpected end of input",
  fileName: 'data:text/javascript,;u8=Uint8Array;u16=Uint16Array;i32=Int32Array;hMap=function (cd, mb, r) {    var s = cd.length;    // index    var i = 0;    // u16 "map": index -> #%20of%20codes%20with%20bit%20length%20=%20index%20%20%20%20var%20l%20=%20new%20u16(mb);%20%20%20%20//%20length%20of%20cd%20must%20be%20288%20(total%20#%20of%20codes)%20%20%20%20for%20(;%20i%20%3C%20s;%20++i)%20{%20%20%20%20%20%20%20%20if%20(cd[i])%20%20%20%20%20%20%20%20%20%20%20%20++l[cd[i]%20-%201];%20%20%20%20}%20%20%20%20//%20u16%20%22map%22:%20index%20-%3E%20minimum%20code%20for%20bit%20length%20=%20index%20%20%20%20var%20le%20=%20new%20u16(mb);%20%20%20%20for%20(i%20=%201;%20i%20%3C%20mb;%20++i)%20{%20%20%20%20%20%20%20%20le[i]%20=%20(le[i%20-%201]%20+%20l[i%20-%201])%20%3C%3C%201;%20%20%20%20}%20%20%20%20var%20co;%20%20%20%20if%20(r)%20{%20%20%20%20%20%20%20%20//%20u16%20%22map%22:%20index%20-%3E%20number%20of%20actual%20bits,%20symbol%20for%20code%20%20%20%20%20%20%20%20co%20=%20new%20u16(1%20%3C%3C%20mb);%20%20%20%20%20%20%20%20//%20bits%20to%20remove%20for%20reverser%20%20%20%20%20%20%20%20var%20rvb%20=%2015%20-%20mb;%20%20%20%20%20%20%20%20for%20(i%20=%200;%20i%20%3C%20s;%20++i)%20{%20%20%20%20%20%20%20%20%20%20%20%20//%20ignore%200%20lengths%20%20%20%20%20%20%20%20%20%20%20%20if%20(cd[i])%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20num%20encoding%20both%20symbol%20and%20bits%20read%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20sv%20=%20(i%20%3C%3C%204)%20|%20cd[i];%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20free%20bits%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20r_1%20=%20mb%20-%20cd[i];%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20start%20value%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20v%20=%20le[cd[i]%20-%201]++%20%3C%3C%20r_1;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20m%20is%20end%20value%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(var%20m%20=%20v%20|%20((1%20%3C%3C%20r_1)%20-%201);%20v%20%3C=%20m;%20++v)%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20every%2016%20bit%20value%20starting%20with%20the%20code%20yields%20the%20same%20result%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20co[rev[v]%20%3E%3E%20rvb]%20=%20sv;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20}%20%20%20%20}%20%20%20%20else%20{%20%20%20%20%20%20%20%20co%20=%20new%20u16(s);%20%20%20%20%20%20%20%20for%20(i%20=%200;%20i%20%3C%20s;%20++i)%20{%20%20%20%20%20%20%20%20%20%20%20%20if%20(cd[i])%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20co[i]%20=%20rev[le[cd[i]%20-%201]++]%20%3E%3E%20(15%20-%20cd[i]);%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20}%20%20%20%20}%20%20%20%20return%20co;};wbits=function%20(d,%20p,%20v)%20{%20%20%20%20v%20%3C%3C=%20p%20&%207;%20%20%20%20var%20o%20=%20(p%20/%208)%20|%200;%20%20%20%20d[o]%20|=%20v;%20%20%20%20d[o%20+%201]%20|=%20v%20%3E%3E%208;};wbits16=function%20(d,%20p,%20v)%20{%20%20%20%20v%20%3C%3C=%20p%20&%207;%20%20%20%20var%20o%20=%20(p%20/%208)%20|%200;%20%20%20%20d[o]%20|=%20v;%20%20%20%20d[o%20+%201]%20|=%20v%20%3E%3E%208;%20%20%20%20d[o%20+%202]%20|=%20v%20%3E%3E%2016;};hTree=function%20(d,%20mb)%20{%20%20%20%20//%20Need%20extra%20info%20to%20make%20a%20tree%20%20%20%20var%20t%20=%20[];%20%20%20%20for%20(var%20i%20=%200;%20i%20%3C%20d.length;%20++i)%20{%20%20%20%20%20%20%20%20if%20(d[i])%20%20%20%20%20%20%20%20%20%20%20%20t.push({%20s:%20i,%20f:%20d[i]%20});%20%20%20%20}%20%20%20%20var%20s%20=%20t.length;%20%20%20%20var%20t2%20=%20t.slice();%20%20%20%20if%20(!s)%20%20%20%20%20%20%20%20return%20{%20t:%20et,%20l:%200%20};%20%20%20%20if%20(s%20==%201)%20{%20%20%20%20%20%20%20%20var%20v%20=%20new%20u8(t[0].s%20+%201);%20%20%20%20%20%20%20%20v[t[0].s]%20=%201;%20%20%20%20%20%20%20%20return%20{%20t:%20v,%20l:%201%20};%20%20%20%20}%20%20%20%20t.sort(function%20(a,%20b)%20{%20return%20a.f%20-%20b.f;%20});%20%20%20%20//%20after%20i2%20reaches%20last%20ind,%20will%20be%20stopped%20%20%20%20//%20freq%20must%20be%20greater%20than%20largest%20possible%20number%20of%20symbols%20%20%20%20t.push({%20s:%20-1,%20f:%2025001%20});%20%20%20%20var%20l%20=%20t[0],%20r%20=%20t[1],%20i0%20=%200,%20i1%20=%201,%20i2%20=%202;%20%20%20%20t[0]%20=%20{%20s:%20-1,%20f:%20l.f%20+%20r.f,%20l:%20l,%20r:%20r%20};%20%20%20%20//%20efficient%20algorithm%20from%20UZIP.js%20%20%20%20//%20i0%20is%20lookbehind,%20i2%20is%20lookahead%20-%20after%20processing%20two%20low-freq%20%20%20%20//%20symbols%20that%20combined%20have%20high%20freq,%20will%20start%20processing%20i2%20(high-freq,%20%20%20%20//%20non-composite)%20symbols%20instead%20%20%20%20//%20see%20https://reddit.com/r/photopea/comments/ikekht/uzipjs_questions/%20%20%20%20while%20(i1%20!=%20s%20-%201)%20{%20%20%20%20%20%20%20%20l%20=%20t[t[i0].f%20%3C%20t[i2].f%20?%20i0++%20:%20i2++];%20%20%20%20%20%20%20%20r%20=%20t[i0%20!=%20i1%20&&%20t[i0].f%20%3C%20t[i2].f%20?%20i0++%20:%20i2++];%20%20%20%20%20%20%20%20t[i1++]%20=%20{%20s:%20-1,%20f:%20l.f%20+%20r.f,%20l:%20l,%20r:%20r%20};%20%20%20%20}%20%20%20%20var%20maxSym%20=%20t2[0].s;%20%20%20%20for%20(var%20i%20=%201;%20i%20%3C%20s;%20++i)%20{%20%20%20%20%20%20%20%20if%20(t2[i].s%20%3E%20maxSym)%20%20%20%20%20%20%20%20%20%20%20%20maxSym%20=%20t2[i].s;%20%20%20%20}%20%20%20%20//%20code%20lengths%20%20%20%20var%20tr%20=%20new%20u16(maxSym%20+%201);%20%20%20%20//%20max%20bits%20in%20tree%20%20%20%20var%20mbt%20=%20ln(t[i1%20-%201],%20tr,%200);%20%20%20%20if%20(mbt%20%3E%20mb)%20{%20%20%20%20%20%20%20%20//%20more%20algorithms%20from%20UZIP.js%20%20%20%20%20%20%20%20//%20TODO:%20find%20out%20how%20this%20code%20works%20(debt)%20%20%20%20%20%20%20%20//%20%20ind%20%20%20%20debt%20%20%20%20%20%20%20%20var%20i%20=%200,%20dt%20=%200;%20%20%20%20%20%20%20%20//%20%20%20%20left%20%20%20%20%20%20%20%20%20%20%20%20cost%20%20%20%20%20%20%20%20var%20lft%20=%20mbt%20-%20mb,%20cst%20=%201%20%3C%3C%20lft;%20%20%20%20%20%20%20%20t2.sort(function%20(a,%20b)%20{%20return%20tr[b.s]%20-%20tr[a.s]%20||%20a.f%20-%20b.f;%20});%20%20%20%20%20%20%20%20for%20(;%20i%20%3C%20s;%20++i)%20{%20%20%20%20%20%20%20%20%20%20%20%20var%20i2_1%20=%20t2[i].s;%20%20%20%20%20%20%20%20%20%20%20%20if%20(tr[i2_1]%20%3E%20mb)%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20dt%20+=%20cst%20-%20(1%20%3C%3C%20(mbt%20-%20tr[i2_1]));%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tr[i2_1]%20=%20mb;%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20%20%20%20%20else%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break;%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20dt%20%3E%3E=%20lft;%20%20%20%20%20%20%20%20while%20(dt%20%3E%200)%20{%20%20%20%20%20%20%20%20%20%20%20%20var%20i2_2%20=%20t2[i].s;%20%20%20%20%20%20%20%20%20%20%20%20if%20(tr[i2_2]%20%3C%20mb)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20dt%20-=%201%20%3C%3C%20(mb%20-%20tr[i2_2]++%20-%201);%20%20%20%20%20%20%20%20%20%20%20%20else%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20++i;%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20for%20(;%20i%20%3E=%200%20&&%20dt;%20--i)%20{%20%20%20%20%20%20%20%20%20%20%20%20var%20i2_3%20=%20t2[i].s;%20%20%20%20%20%20%20%20%20%20%20%20if%20(tr[i2_3]%20==%20mb)%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20--tr[i2_3];%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20++dt;%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20mbt%20=%20mb;%20%20%20%20}%20%20%20%20return%20{%20t:%20new%20u8(tr),%20l:%20mbt%20};};ln=function%20(n,%20l,%20d)%20{%20%20%20%20return%20n.s%20==%20-1%20%20%20%20%20%20%20%20?%20Math.max(ln(n.l,%20l,%20d%20+%201),%20ln(n.r,%20l,%20d%20+%201))%20%20%20%20%20%20%20%20:%20(l[n.s]%20=%20d);};lc=function%20(c)%20{%20%20%20%20var%20s%20=%20c.length;%20%20%20%20//%20Note%20that%20the%20semicolon%20was%20intentional%20%20%20%20while%20(s%20&&%20!c[--s])%20%20%20%20%20%20%20%20;%20%20%20%20var%20cl%20=%20new%20u16(++s);%20%20%20%20//%20%20ind%20%20%20%20%20%20num%20%20%20%20%20%20%20%20%20streak%20%20%20%20var%20cli%20=%200,%20cln%20=%20c[0],%20cls%20=%201;%20%20%20%20var%20w%20=%20function%20(v)%20{%20cl[cli++]%20=%20v;%20};%20%20%20%20for%20(var%20i%20=%201;%20i%20%3C=%20s;%20++i)%20{%20%20%20%20%20%20%20%20if%20(c[i]%20==%20cln%20&&%20i%20!=%20s)%20%20%20%20%20%20%20%20%20%20%20%20++cls;%20%20%20%20%20%20%20%20else%20{%20%20%20%20%20%20%20%20%20%20%20%20if%20(!cln%20&&%20cls%20%3E%202)%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(;%20cls%20%3E%20138;%20cls%20-=%20138)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w(32754);%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(cls%20%3E%202)%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w(cls%20%3E%2010%20?%20((cls%20-%2011)%20%3C%3C%205)%20|%2028690%20:%20((cls%20-%203)%20%3C%3C%205)%20|%2012305);%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cls%20=%200;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20%20%20%20%20else%20if%20(cls%20%3E%203)%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w(cln),%20--cls;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(;%20cls%20%3E%206;%20cls%20-=%206)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w(8304);%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(cls%20%3E%202)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w(((cls%20-%203)%20%3C%3C%205)%20|%208208),%20cls%20=%200;%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20%20%20%20%20while%20(cls--)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w(cln);%20%20%20%20%20%20%20%20%20%20%20%20cls%20=%201;%20%20%20%20%20%20%20%20%20%20%20%20cln%20=%20c[i];%20%20%20%20%20%20%20%20}%20%20%20%20}%20%20%20%20return%20{%20c:%20cl.subarray(0,%20cli),%20n:%20s%20};};clen=function%20(cf,%20cl)%20{%20%20%20%20var%20l%20=%200;%20%20%20%20for%20(var%20i%20=%200;%20i%20%3C%20cl.length;%20++i)%20%20%20%20%20%20%20%20l%20+=%20cf[i]%20*%20cl[i];%20%20%20%20return%20l;};wfblk=function%20(out,%20pos,%20da'... 17699 more characters,
  lineNumber: 1,
  columnNumber: 149
}

I am on Linux Pop!_OS, using deno 2.0.4 runtime. fflate is in version 0.8.2.

101arrowz commented 1 week ago

This is an interesting bug. It seems like a bug in Deno rather than fflate if I'm being honest, but I'll have a look.

The reason you're seeing the 150kB switch point is likely due to the main-thread vs. workerized compression heuristics fflate uses; files are compressed on the main thread below a certain size (so workers aren't used at all), but use separate threads at larger sizes. It seems like there's an issue with fflate's worker generation strategy when running on Deno, which is why it seems to break above 150kB.

Thanks for reporting this!

Booteille commented 1 week ago

Thanks a lot for your answer! I truly appreciate the fact you take the time to think about the issue.

I'll report this issue to deno devs as soon as I've time!