Skip to content

Commit 88f4523

Browse files
committed
[file_packages] Convert fetchRemotePackage to async. NFC
Part 4 in the sequence following #24882, #24883 and #24885.
1 parent 1956ff0 commit 88f4523

File tree

2 files changed

+81
-85
lines changed

2 files changed

+81
-85
lines changed

test/test_other.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3984,10 +3984,7 @@ def test_file_packager_modularize(self):
39843984

39853985
create_file('post.js', 'MyModule(Module).then(() => console.log("done"));')
39863986

3987-
self.run_process([EMCC, 'main.c', '--extern-pre-js=embed.js', '--extern-post-js=post.js', '-sMODULARIZE', '-sEXPORT_NAME=MyModule', '-sFORCE_FILESYSTEM'])
3988-
3989-
result = self.run_js('a.out.js')
3990-
self.assertContained('|hello world|', result)
3987+
self.do_runf('main.c', '|hello world|', cflags=['--extern-pre-js=embed.js', '--extern-post-js=post.js', '-sMODULARIZE', '-sEXPORT_NAME=MyModule', '-sFORCE_FILESYSTEM'])
39913988

39923989
def test_preprocess(self):
39933990
# Pass -Werror to prevent regressions such as https://github.com/emscripten-core/emscripten/pull/9661

tools/file_packager.py

Lines changed: 80 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -635,11 +635,11 @@ def generate_js(data_target, data_files, metadata):
635635

636636
if options.support_node:
637637
ret += " var isNode = typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string';\n"
638-
ret += ' function loadPackage(metadata) {\n'
638+
ret += ' async function loadPackage(metadata) {\n'
639639

640640
code = '''
641641
function assert(check, msg) {
642-
if (!check) throw msg + new Error().stack;
642+
if (!check) throw new Error(msg);
643643
}\n'''
644644

645645
# Set up folders
@@ -808,7 +808,7 @@ def generate_js(data_target, data_files, metadata):
808808
809809
async function openDatabase() {
810810
if (typeof indexedDB == 'undefined') {
811-
throw 'using IndexedDB to cache data can only be done on a web page or in a web worker';
811+
throw new Error('using IndexedDB to cache data can only be done on a web page or in a web worker');
812812
}
813813
return new Promise((resolve, reject) => {
814814
var openRequest = indexedDB.open(DB_NAME, DB_VERSION);
@@ -953,62 +953,58 @@ def generate_js(data_target, data_files, metadata):
953953
if options.support_node:
954954
node_support_code = '''
955955
if (isNode) {
956-
require('fs/promises').readFile(packageName).then((contents) => callback(contents.buffer));
957-
return;
956+
var fsPromises = require('fs/promises');
957+
var contents = await fsPromises.readFile(packageName);
958+
return contents.buffer;
958959
}'''.strip()
959960

960961
ret += '''
961-
function fetchRemotePackage(packageName, packageSize, callback) {
962+
async function fetchRemotePackage(packageName, packageSize) {
962963
%(node_support_code)s
963964
Module['dataFileDownloads'] ??= {};
964-
fetch(packageName)
965-
.catch((cause) => Promise.reject(new Error(`Network Error: ${packageName}`, {cause}))) // If fetch fails, rewrite the error to include the failing URL & the cause.
966-
.then((response) => {
967-
if (!response.ok) {
968-
return Promise.reject(new Error(`${response.status}: ${response.url}`));
969-
}
965+
try {
966+
var response = await fetch(packageName);
967+
} catch (e) {
968+
throw new Error(`Network Error: ${packageName}`, {e});
969+
}
970+
if (!response.ok) {
971+
throw new Error(`${response.status}: ${response.url}`);
972+
}
970973
971-
const reader = response.body.getReader();
972-
const iterate = () => reader.read().then(handleChunk).catch((cause) => {
973-
return Promise.reject(new Error(`Unexpected error while handling : ${response.url} ${cause}`, {cause}));
974-
});
974+
const chunks = [];
975+
const headers = response.headers;
976+
const total = Number(headers.get('Content-Length') ?? packageSize);
977+
let loaded = 0;
975978
976-
const chunks = [];
977-
const headers = response.headers;
978-
const total = Number(headers.get('Content-Length') ?? packageSize);
979-
let loaded = 0;
979+
Module['setStatus']?.('Downloading data...');
980+
const reader = response.body.getReader();
980981
981-
const handleChunk = ({done, value}) => {
982-
if (!done) {
983-
chunks.push(value);
984-
loaded += value.length;
985-
Module['dataFileDownloads'][packageName] = {loaded, total};
982+
while (1) {
983+
var {done, value} = await reader.read();
984+
if (done) break;
985+
chunks.push(value);
986+
loaded += value.length;
987+
Module['dataFileDownloads'][packageName] = {loaded, total};
986988
987-
let totalLoaded = 0;
988-
let totalSize = 0;
989+
let totalLoaded = 0;
990+
let totalSize = 0;
989991
990-
for (const download of Object.values(Module['dataFileDownloads'])) {
991-
totalLoaded += download.loaded;
992-
totalSize += download.total;
993-
}
992+
for (const download of Object.values(Module['dataFileDownloads'])) {
993+
totalLoaded += download.loaded;
994+
totalSize += download.total;
995+
}
994996
995-
Module['setStatus']?.(`Downloading data... (${totalLoaded}/${totalSize})`);
996-
return iterate();
997-
} else {
998-
const packageData = new Uint8Array(chunks.map((c) => c.length).reduce((a, b) => a + b, 0));
999-
let offset = 0;
1000-
for (const chunk of chunks) {
1001-
packageData.set(chunk, offset);
1002-
offset += chunk.length;
1003-
}
1004-
callback(packageData.buffer);
1005-
}
1006-
};
997+
Module['setStatus']?.(`Downloading data... (${totalLoaded}/${totalSize})`);
998+
}
1007999
1008-
Module['setStatus']?.('Downloading data...');
1009-
return iterate();
1010-
});
1011-
};\n''' % {'node_support_code': node_support_code}
1000+
const packageData = new Uint8Array(chunks.map((c) => c.length).reduce((a, b) => a + b, 0));
1001+
let offset = 0;
1002+
for (const chunk of chunks) {
1003+
packageData.set(chunk, offset);
1004+
offset += chunk.length;
1005+
}
1006+
return packageData.buffer;
1007+
}\n''' % {'node_support_code': node_support_code}
10121008

10131009
code += '''
10141010
function processPackageData(arrayBuffer) {
@@ -1017,7 +1013,7 @@ def generate_js(data_target, data_files, metadata):
10171013
var byteArray = new Uint8Array(arrayBuffer);
10181014
var curr;
10191015
%s
1020-
};
1016+
}
10211017
Module['addRunDependency']('datafile_%s');\n''' % (use_data, js_manipulation.escape_for_js_string(data_target))
10221018
# use basename because from the browser's point of view,
10231019
# we need to find the datafile in the same dir as the html file
@@ -1027,32 +1023,31 @@ def generate_js(data_target, data_files, metadata):
10271023

10281024
if options.use_preload_cache:
10291025
code += '''
1030-
function preloadFallback(error) {
1026+
async function preloadFallback(error) {
10311027
console.error(error);
10321028
console.error('falling back to default preload behavior');
1033-
fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, processPackageData);
1034-
};
1035-
1036-
openDatabase()
1037-
.then((db) => {
1038-
checkCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME)
1039-
.then((cachedData) => {
1040-
Module['preloadResults'][PACKAGE_NAME] = {fromCache: !!cachedData};
1041-
if (cachedData) {
1042-
fetchCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME, cachedData).then(processPackageData);
1043-
} else {
1044-
fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE,
1045-
(packageData) => {
1046-
cacheRemotePackage(db, PACKAGE_PATH + PACKAGE_NAME, packageData, {uuid:PACKAGE_UUID})
1047-
.then(processPackageData)
1048-
.catch((error) => {
1049-
console.error(error);
1050-
processPackageData(packageData);
1051-
});
1052-
});
1053-
}
1054-
})
1055-
}).catch(preloadFallback);
1029+
processPackageData(await fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE));
1030+
}
1031+
1032+
try {
1033+
var db = await openDatabase();
1034+
var pkgMetadata = await checkCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME);
1035+
var useCached = !!pkgMetadata;
1036+
Module['preloadResults'][PACKAGE_NAME] = {fromCache: useCached};
1037+
if (useCached) {
1038+
processPackageData(await fetchCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME, pkgMetadata));
1039+
} else {
1040+
var packageData = await fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE);
1041+
try {
1042+
processPackageData(await cacheRemotePackage(db, PACKAGE_PATH + PACKAGE_NAME, packageData, {uuid:PACKAGE_UUID}))
1043+
} catch (error) {
1044+
console.error(error);
1045+
processPackageData(packageData);
1046+
}
1047+
}
1048+
} catch(e) {
1049+
await preloadFallback(e);
1050+
}
10561051
10571052
Module['setStatus']?.('Downloading...');\n'''
10581053
else:
@@ -1064,14 +1059,18 @@ def generate_js(data_target, data_files, metadata):
10641059
var fetchedCallback = null;
10651060
var fetched = Module['getPreloadedPackage'] ? Module['getPreloadedPackage'](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
10661061
1067-
if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, (data) => {
1068-
if (fetchedCallback) {
1069-
fetchedCallback(data);
1070-
fetchedCallback = null;
1071-
} else {
1072-
fetched = data;
1073-
}
1074-
});\n'''
1062+
if (!fetched) {
1063+
// Note that we don't use await here because we want to execute the
1064+
// the rest of this function immediately.
1065+
fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE).then((data) => {
1066+
if (fetchedCallback) {
1067+
fetchedCallback(data);
1068+
fetchedCallback = null;
1069+
} else {
1070+
fetched = data;
1071+
}
1072+
})
1073+
}\n'''
10751074

10761075
code += '''
10771076
Module['preloadResults'][PACKAGE_NAME] = {fromCache: false};
@@ -1083,7 +1082,7 @@ def generate_js(data_target, data_files, metadata):
10831082
}\n'''
10841083

10851084
ret += '''
1086-
function runWithFS(Module) {\n'''
1085+
async function runWithFS(Module) {\n'''
10871086
ret += code
10881087
ret += '''
10891088
}

0 commit comments

Comments
 (0)