psd.js
psd.js copied to clipboard
Onload handlers must contain a reject call inside every Promise.
The problem is, if error is thrown inside onload handler without reject ever called inside a Promise, the outside caller never gets anything and it will just hang there forever.
Context: I stumbled on some PSD files with completely random garbage content left over from HDD corruption 10 years ago.
The loading methods are identical in all forks of psd.js I've seen so far, so the problem is present in all of them.
The fix is wrapping all statements in onload handlers of all public file loading functions into a try-catch with reject on error:
module.exports = {
extended: function(PSD) {
this.fromURL = function(url) {
return new RSVP.Promise(function(resolve, reject) {
var xhr;
xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onload = function() {
try {
var data, psd;
data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
psd = new PSD(data);
psd.parse();
return resolve(psd);
} catch (error) { reject(error); }
};
return xhr.send(null);
});
};
this.fromEvent = function(e) {
return new RSVP.Promise(function(resolve, reject) {
var file, reader;
file = e.dataTransfer.files[0];
reader = new FileReader();
reader.onload = function(e) {
try {
var psd;
psd = new PSD(new Uint8Array(e.target.result));
psd.parse();
return resolve(psd);
} catch (error) { reject(error); }
};
reader.onerror = reject;
return reader.readAsArrayBuffer(file);
});
};
return this.fromDroppedFile = function(file) {
return new RSVP.Promise(function(resolve, reject) {
var reader;
reader = new FileReader();
reader.onload = function(e) {
try {
var psd;
psd = new PSD(new Uint8Array(e.target.result));
psd.parse();
return resolve(psd);
} catch (error) { reject(error); }
};
reader.onerror = reject;
return reader.readAsArrayBuffer(file);
});
};
}
};
I don't know if this is relevant to Node.js or CoffeeScript though.