-
Notifications
You must be signed in to change notification settings - Fork 3.4k
[file_packager.py] Fix errback
call in fetchRemotePackage
#24871
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
By the way it looks like this code was added in #22016, but the code in replaced also did Also, it looks like errback is just doing This change does seem perfectly good, but I'm wondoring how it solves your issue if the result is just to call |
I will now have one place where I can reject the promise returned by function. Other thing that comes to my mind is changing console.errors in whole script to Module.printErr to enable filtering or guard the logs with some flag |
@sbc100 I think that I have more proposal as part of this mr |
tools/file_packager.py
Outdated
ret += ''' | ||
function handleError(error) { | ||
console.error('package error:', error); | ||
return error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why add return error
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think think about it now again it is really unnecessary
tools/file_packager.py
Outdated
@@ -1117,7 +1119,7 @@ def generate_js(data_target, data_files, metadata): | |||
if (isNode) { | |||
require('fs').readFile(metadataUrl, 'utf8', (err, contents) => { | |||
if (err) { | |||
return Promise.reject(err); | |||
return handleError(err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can delete the return
keyword here.
Should I merge when the pipeline passes now? |
Head branch was pushed to by a user without write access
d9001d8
to
f566133
Compare
@sbc100 I have fixed the pipeline, some returns where neccessary since errback had different meaning, I wonder if we should modify catch statement in fetchRemotePackage now |
tools/file_packager.py
Outdated
@@ -984,7 +989,7 @@ def generate_js(data_target, data_files, metadata): | |||
|
|||
const reader = response.body.getReader(); | |||
const iterate = () => reader.read().then(handleChunk).catch((cause) => { | |||
return Promise.reject(new Error(`Unexpected error while handling : ${response.url} ${cause}`, {cause})); | |||
return errback(new Error(`Unexpected error while handling : ${response.url} ${cause}`, {cause})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this return
is needed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree,
@@ -1138,8 +1139,10 @@ def generate_js(data_target, data_files, metadata): | |||
if (response.ok) { | |||
return response.json(); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you still need to do something here when the response is not ok
... you either need the throw
or return a rejected promise object I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actaully I think just doing throwPackageError
here on this line is probably what you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder now, if we take this code:
function preloadFallback(error) {
console.error(error);
console.error('falling back to default preload behavior');
fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, processPackageData, throwPackageError);
};
openDatabase(
(db) => checkCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME,
(useCached, metadata) => {
Module['preloadResults'][PACKAGE_NAME] = {fromCache: useCached};
if (useCached) {
fetchCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME, metadata, processPackageData, preloadFallback);
} else {
fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE,
(packageData) => {
cacheRemotePackage(db, PACKAGE_PATH + PACKAGE_NAME, packageData, {uuid:PACKAGE_UUID}, processPackageData,
(error) => {
console.error(error);
processPackageData(packageData);
});
}
, preloadFallback);
}
}, preloadFallback)
, preloadFallback);
then this catch in fetchRemotePackage will not fail
Module['dataFileDownloads'] ??= {};
fetch(packageName)
.catch((cause) => errback(new Error(`Network Error: ${packageName}`, {cause}))) // If fetch fails, rewrite the error to include the failing URL & the cause.
.then((response) => {
I think that just adding promise Rejsect here for security iss what we want
errback(new Error(`Network Error: ${packageName}`, {cause})); | ||
// We want to be sure to cancel promise chain because we sometimes call this function with method | ||
// which doesn't throw error hance promise chain is not broken | ||
return Promise.reject(new Error(`Network Error: ${packageName}`, {cause})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is starting to look pretty ugly because we mixing callbacks and promises .. I think converting to using async
await
is ultimately what we we probably want to do here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have prototyped something, but maybe it deservse separate PR...
function fetchRemotePackage(packageName, packageSize) {
return new Promise((fetchPackageResolve, fetchPackageReject) => {
if (isNode) {
require('fs').readFile(packageName, (err, contents) => {
if (err) {
fetchPackageReject(err);
} else {
fetchPackageResolve(contents.buffer);
}
});
return;
}
Module['dataFileDownloads'] ??= {};
fetch(packageName)
.catch((cause) => {
err = new Error(`Network Error: ${packageName}`, {cause});
fetchPackageReject(err);
return Promise.reject(err);
}) // If fetch fails, rewrite the error to include the failing URL & the cause.
.then((response) => {
if (!response.ok) {
fetchPackageReject(new Error(`${response.status}: ${response.url}`));
return;
}
if (!response.body && response.arrayBuffer) { // If we're using the polyfill, readers won't be available...
return response.arrayBuffer().then(fetchPackageResolve);
}
const reader = response.body.getReader();
const iterate = () => reader.read().then(handleChunk).catch((cause) => {
fetchPackageReject(new Error(`Unexpected error while handling : ${response.url} ${cause}`, {cause}));
return;
});
const chunks = [];
const headers = response.headers;
const total = Number(headers.get('Content-Length') ?? packageSize);
let loaded = 0;
const handleChunk = ({done, value}) => {
if (!done) {
chunks.push(value);
loaded += value.length;
Module['dataFileDownloads'][packageName] = {loaded, total};
let totalLoaded = 0;
let totalSize = 0;
for (const download of Object.values(Module['dataFileDownloads'])) {
totalLoaded += download.loaded;
totalSize += download.total;
}
Module['setStatus']?.(`Downloading data... (${totalLoaded}/${totalSize})`);
return iterate();
} else {
const packageData = new Uint8Array(chunks.map((c) => c.length).reduce((a, b) => a + b, 0));
let offset = 0;
for (const chunk of chunks) {
packageData.set(chunk, offset);
offset += chunk.length;
}
fetchPackageResolve(packageData.buffer);
}
};
Module['setStatus']?.('Downloading data...');
return iterate();
});
});
};
```
I took as stab as converting part of the file_packager output to async/await: #24871. Its not the relevant part .. but its a start. |
So should I fix that now ? |
I've made some progress on it, so can do this part if you like? |
Not right now for sure, but feel free to take and use my prototype, I have changed it now after some tests, at least happy path should pass with current version pasted in my comment. |
I think I'm going to go for full conversion to async/await which should make your change much simpler (I hope) |
Part 2: #24883 |
So we wait with this PR and the export_es6 one for the conversion to async? |
Yes I think the async conversion work will supersede this PR |
@sbc100 to be honest I don't see the point of this PR anymore after your changes. I think it will be possible to Reject main functions promise from just one or two places without the need of handleError |
That sounds reasonable to me. The non-es6 case I think the point of handleError is to show something on the console to the user so they know the package loading has failed. For the es6 case i don't think that is necessary, so I think you could just do |
So I think I can close that |
Yes, I think this PR can be closed. Is that what you are asking? I think the conversion async removed the need for this fix. |
errback
argument was ignored infetchRemotePackage
,Promise.reject
was called instead