Comments (27)
Check v0.4.8 on NPM, which should have fixed the issue for your Chrome extension. Thanks for the bug report and especially for your continued help in debugging!
from fflate.
Sure, that's fine. I know the files are minified, but I'm still able to (and want to) debug the minified builds with JSBeautifier, searching for function names, etc. This is mainly because I can't reproduce the error locally; I'd like to see exactly where the bug is appearing.
from fflate.
Sure, that's fine. I know the files are minified, but I'm still able to (and want to) debug the minified builds with JSBeautifier, searching for function names, etc. This is mainly because I can't reproduce the error locally; I'd like to see exactly where the bug is appearing.
Mail sent!
from fflate.
I've looked at the minified source and it seems that you're using
zipSync
there because I cannot find the asynchronous zipping function. However, your stack trace and previous issue indicate the use ofzip
. Could you verify that you've sent the same version of the file you created the error log with?
Sorry, I've replaced the zip
function with zipSync
in non minified production build, I've mailed you the correct files now.
from fflate.
I've extracted the minified version of fflate
from your build and run my test suite on it, but everything seems to be working fine. Therefore, the failure must be a difference in environment. Could you describe your operating system and browser (name and version)? If only a specific set of files causes the error, could you send those over too?
from fflate.
Yeah that would probably be issue, you can send it to me and I'll take a look.
from fflate.
I managed to force the exact same error to appear by making the data that the Worker receives null. The question remains why exactly the worker receives the null value. I'm afraid I'll need to take a look at your source code just to kill this bug once and for all.
By the way, the file you sent seems to still work with the minified Webpack build, the unminified Node build, and the minified Parcel build on https://101arrowz.github.io/fflate. Argh!
it's strange because it will not work in my production envoirment. Are you used vue 3? I've sent to you an invitation to the repo with the source code. Let me know
from fflate.
Well, I finally was able to recreate the bug. I'll try my best to find what exactly your code does differently from mine that causes fflate
to fail.
from fflate.
The problem was with the library, not your code, although you did have an unusual use case. The Content Security Policy (CSP) is used to prevent arbitrary code injection and execution from untrusted sources, which can somewhat improve security. Most of the time, I test with a very loose Content Security Policy, which is the default for most environments. However, Chrome extensions are not really allowed to execute anything but their own code, so I had to rewrite one function that used dynamic evaluation to make everything work. I hope the library works well for your codebase!
from fflate.
The problem was with the library, not your code, although you did have an unusual use case. The Content Security Policy (CSP) is used to prevent arbitrary code injection and execution from untrusted sources, which can somewhat improve security. Most of the time, I test with a very loose Content Security Policy, which is the default for most environments. However, Chrome extensions are not really allowed to execute anything but their own code, so I had to rewrite one function that used dynamic evaluation to make everything work. I hope the library works well for your codebase!
Not so unusual to see a strict CSP on certain websites nowdays, the update to support CSP is a great think trust me. I will link to the extension repo in my app where this project is used. You did a great job. Thank you!
from fflate.
I'd like to have access to the code in write-zip.896bce5d.js
and chunk-vendors.64883a9e.js
for debugging purposes; could you send/pastebin them? Otherwise it's hard to tell what exactly went wrong.
from fflate.
I'd like to have access to the code in
write-zip.896bce5d.js
andchunk-vendors.64883a9e.js
for debugging purposes; could you send/pastebin them? Otherwise it's hard to tell what exactly went wrong.
Unfortunately the files that cause the error are minified so I don't know if it can be useful for debug. I can mail you the files since pastebin will not accept it's content and mark them as potentially offensive
from fflate.
I've looked at the minified source and it seems that you're using zipSync
there because I cannot find the asynchronous zipping function. However, your stack trace and previous issue indicate the use of zip
. Could you verify that you've sent the same version of the file you created the error log with?
from fflate.
I've extracted the minified version of
fflate
from your build and run my test suite on it, but everything seems to be working fine. Therefore, the failure must be a difference in environment. Could you describe your operating system, browser (name and version), and the version offflate
you are using?
No, I haven't used any specific file, I've tested the app I'm working on with some random images and files I have on the pc.
I'm on macOS 10.13.6 and the library is used inside a vue 3 powered browser extension. I'm creating the build using vue ui and all the test that give the error are done on chrome 87 and firefox developer edition 85.0b4. The fflate version is 0.4.6
from fflate.
That's frustrating; my environment is virtually identical: operating system, chrome version, and fflate version are all the same. I think the only possible error could be in your loading script. Have you tried running a production build with a hardcoded input to zip
? Instead of passing in the result from your FileReader
, try this:
zip({
// this is "hello world"
'test-file.txt': new Uint8Array([
104, 101, 108, 108,
111, 32, 119, 111,
114, 108, 100
])
}, (err, dat) => ...)
If the error persists, I have no idea what's going on and will need a day or two to look into it further. Otherwise, it's a bug in the FileReader
script (though I'm totally lost as to how switching from development to production could cause that).
from fflate.
That's frustrating; my environment is virtually identical: operating system, chrome version, and fflate version are all the same. I think the only possible error could be in your loading script. Have you tried running a production build with a hardcoded input to
zip
? Instead of passing in the result from yourFileReader
, try this:zip({ // this is "hello world" 'test-file.txt': new Uint8Array([ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 ]) }, (err, dat) => ...)If the error persists, I have no idea what's going on and will need a day or two to look into it further. Otherwise, it's a bug in the
FileReader
script (though I'm totally lost as to how switching from development to production could cause that).
I will try and let you know
from fflate.
Tested with the Unit8Array suggested from you and no error occur, I'm able to download the zip file with the test-file.txt
iniside.
from fflate.
OK, the error is coming from the loading script then. Try copy-pasting this code line-for-line, since it works in my environment:
import { zip } from 'fflate';
function readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(new Uint8Array(reader.result));
};
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
}
async function createZip() {
// You can replace this with what you need, but it needs to be a
// FileList object or an array of File objects.
const files = document.querySelectorAll('input[type="file"]')[1].files;
const toZip = {};
for (const file of files) {
toZip[file.name] = await readFile(file);
}
return new Promise((res, rej) => {
zip(toZip, { consume: true, level: 9 }, (err, dat) => err ? rej(err) : res(dat))
});
}
from fflate.
OK, the error is coming from the loading script then. Try copy-pasting this code line-for-line, since it works in my environment:
import { zip } from 'fflate'; function readFile(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => { resolve(new Uint8Array(reader.result)); }; reader.onerror = reject; reader.readAsArrayBuffer(file); }); } async function createZip() { // You can replace this with what you need, but it needs to be a // FileList object or an array of File objects. const files = document.querySelectorAll('input[type="file"]')[1].files; const toZip = {}; for (const file of files) { toZip[file.name] = await readFile(file); } return new Promise((res, rej) => { zip(toZip, { consume: true, level: 9 }, (err, dat) => err ? rej(err) : res(dat)) }); }
What do you mean with loading script? I see that you have called the reader.readAsArrayBuffer()
after the loadend, I'm calling it before loadendin my readFile
function
readFile(file) {
return new Promise( (resolve, reject) => {
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onerror = reject;
reader.onloadend = () => {
resolve(new Uint8Array(reader.result));
}
});
}
Also the zip function is wrapped inside a promise, can you explain me why this choice? I have a single function to create the zip and save it, if I wrap the zip
inside a Promise I will need to create a dedicated method to generate the zip? I'm editing my code now, I will update you after test in production :)
from fflate.
You should be able to make whatever changes you think will work, but just to rule out all the possibilities, it's best to see if this works, then start shifting closer to what you wrote originally. I have a feeling the readFile
method was at fault, but I can't be sure so I suggest copying as closely as possible to avoid whatever bug caused the failure in the first place.
from fflate.
I've modified the code in this way, like you've suggested, inside vue methods:
handleFiles(e) {
e.dataTransfer.files.forEach( (file) => {
this.filesList.push(file.name);
this.files.push(file);
});
},
readFile(file) {
return new Promise( (resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(new Uint8Array(reader.result));
}
reader.readAsArrayBuffer(file);
reader.onerror = reject;
});
},
async processFiles() {
this.isProcessing = true;
let archiveContent = {};
for(const file of this.files){
let fileBuffer = await this.readFile(file);
archiveContent[file.name] = fileBuffer;
}
//debug
const zipFile = await this.createZip(archiveContent);
console.log(zipFile);
//production
// const data = zipSync(archiveContent, {consume: true, level: 9});
// const chance = new Chance();
// saveAs(new Blob([data.buffer]), `${chance.hash({length: 6})}.zip`);
// this.isProcessing = false;
// this.$router.push({path: '/'});
},
//debug
createZip(fileBuffer) {
return new Promise((resolve, reject) => {
zip(fileBuffer, { consume: true, level: 9 }, (err, dat) => err ? reject(err) : resolve(dat));
});
}
The error still remain
chunk-vendors.080bcd71.js:6 Uncaught TypeError: Cannot read property 'length' of null
at A (chunk-vendors.080bcd71.js:6)
at chunk-vendors.080bcd71.js:6
at Worker.s.onerror (chunk-vendors.080bcd71.js:6)
A @ chunk-vendors.080bcd71.js:6
(anonymous) @ chunk-vendors.080bcd71.js:6
s.onerror @ chunk-vendors.080bcd71.js:6
error (async)
r @ chunk-vendors.080bcd71.js:6
X @ chunk-vendors.080bcd71.js:6
re @ chunk-vendors.080bcd71.js:6
ce @ chunk-vendors.080bcd71.js:6
h @ chunk-vendors.080bcd71.js:6
Ae @ chunk-vendors.080bcd71.js:6
(anonymous) @ write-zip.547e918f.js:1
createZip @ write-zip.547e918f.js:1
(anonymous) @ write-zip.547e918f.js:1
u @ chunk-vendors.080bcd71.js:8
(anonymous) @ chunk-vendors.080bcd71.js:8
(anonymous) @ chunk-vendors.080bcd71.js:8
a @ chunk-vendors.080bcd71.js:1
s @ chunk-vendors.080bcd71.js:1
Promise.then (async)
a @ chunk-vendors.080bcd71.js:1
s @ chunk-vendors.080bcd71.js:1
Promise.then (async)
a @ chunk-vendors.080bcd71.js:1
s @ chunk-vendors.080bcd71.js:1
Promise.then (async)
a @ chunk-vendors.080bcd71.js:1
s @ chunk-vendors.080bcd71.js:1
Promise.then (async)
a @ chunk-vendors.080bcd71.js:1
s @ chunk-vendors.080bcd71.js:1
(anonymous) @ chunk-vendors.080bcd71.js:1
(anonymous) @ chunk-vendors.080bcd71.js:1
processFiles @ write-zip.547e918f.js:1
(anonymous) @ write-zip.547e918f.js:1
(anonymous) @ chunk-vendors.080bcd71.js:6
Ee @ chunk-vendors.080bcd71.js:6
Re @ chunk-vendors.080bcd71.js:6
t @ chunk-vendors.080bcd71.js:6
from fflate.
This is the strangest bug I've seen in a while, especially since it doesn't appear for me. Try removing consume: true
from the ZIP options; if that still fails, just share the source code and I'll try my best to recreate the bug.
from fflate.
@101arrowz I've done some test with the consume: true
and without it, with some single files that vary from pdf and text documents to images and I've noticed that the error will occur when I try to zip a particular file, a screen taken with macOS that is a PNG. All the tested files were read with success and the zip Unit8Array
is logged in console correctly. I assume that the file is causing the error? I can send it to you if want to give a try and investigate about ?
from fflate.
I managed to force the exact same error to appear by making the data that the Worker receives null. The question remains why exactly the worker receives the null value. I'm afraid I'll need to take a look at your source code just to kill this bug once and for all.
By the way, the file you sent seems to still work with the minified Webpack build, the unminified Node build, and the minified Parcel build on https://101arrowz.github.io/fflate. Argh!
from fflate.
Well, I finally was able to recreate the bug. I'll try my best to find what exactly your code does differently from mine that causes
fflate
to fail.
Ok, send me a mail with details if you find something wrong in the code. For curiosity, do you have used the same image that give me the problem or another file? Thank you for the help.
from fflate.
Whew, that was quite the debugging experience! I finally found that the bug was the use of new Function()
in fflate
to dynamically create the web workers in the asynchronous version. Although this works in most situations, Chrome extensions block this kind of call by default due to the content security policy, which bans unsafe-eval
. I'm going to update fflate
to no longer need new Function
.
The reason some files worked and others didn't was that fflate
only uses the worker version for larger files. The problem occurred for all files that were sufficiently large, and only appeared in production because the Content Security Policy is loosened in development.
from fflate.
Check v0.4.8 on NPM, which should have fixed the issue for your Chrome extension. Thanks for the bug report and especially for your continued help in debugging!
You are welcome!If you want to collaborate for some projects it will be nice. What caused the bug, is an error inside my code or other things?
from fflate.
Related Issues (20)
- Compression Streams ponyfill for browser HOT 1
- Deflate/Inflate does not work with zlib/gzip c++ HOT 7
- Add Bzip2?
- Hangs on gunzipSync of compressed content with invalid dictionary HOT 3
- Option to shorten output as much as possible HOT 3
- Incorrect argument order in AsyncFlateStreamHandler HOT 5
- Truncated output of gunzip if SIZE footer is incorrect HOT 5
- return uncompressed size instead of resized output buffer HOT 4
- Improve zip documentation HOT 1
- The encoded data was not valid for encoding utf-8 HOT 1
- Streams onData do not work as expected anymore HOT 8
- CDN bundle for 0.8.1 is broken HOT 2
- Async unzip maxing out CPU and memory for some files HOT 3
- fflate.decompressSync is not a function when using `nifti-reader-js` (React) HOT 7
- Occasional CRC Errors When Streaming Data into Zip using AsyncZipDeflate HOT 7
- `zipSync` can get order of ZIP entries wrong, due to how objects work HOT 3
- delete the rust code
- The 2nd+ JPG images in a zip stream being created are corrupt for some reason? HOT 9
- `gunzipSync` failing (0 gzip length) on some npm package tarballs HOT 1
- Unexpected EOF when inflating ZIP HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fflate.