Skip to content

Commit 7660103

Browse files
authored
WasmFS: Fix file packager use after startup (#19615)
During startup if we run file packager code then the createDataFile etc. calls are turned into code that caches the info for later, as we can't call into WasmFS during startup. Then when WasmFS is running, it reads the cached info and creates the files. But we also need to handle the case where file packager code is run after startup, which is easier to support even if it is more rare - just create the file or directory.
1 parent 4abedb8 commit 7660103

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

src/library_wasmfs.js

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,20 @@
77
mergeInto(LibraryManager.library, {
88
$wasmFSPreloadedFiles: [],
99
$wasmFSPreloadedDirs: [],
10+
// We must note when preloading has been "flushed", that is, the time at which
11+
// WasmFS has started up and read the preloaded data. After that time, no more
12+
// data needs to be preloaded (and it would be invalid to do so, as any
13+
// further additions to wasmFSPreloadedFiles|Dirs would be ignored).
14+
$wasmFSPreloadingFlushed: false,
15+
1016
$FS__postset: `
1117
FS.init();
1218
FS.createPreloadedFile = FS_createPreloadedFile;
1319
`,
1420
$FS__deps: [
1521
'$wasmFSPreloadedFiles',
1622
'$wasmFSPreloadedDirs',
23+
'$wasmFSPreloadingFlushed',
1724
'$PATH',
1825
'$stringToUTF8OnStack',
1926
'$withStackSave',
@@ -55,10 +62,19 @@ FS.createPreloadedFile = FS_createPreloadedFile;
5562
FS.ErrnoError.prototype.constructor = FS.ErrnoError;
5663
},
5764
createDataFile: (parent, name, fileData, canRead, canWrite, canOwn) => {
58-
// Data files must be cached until the file system itself has been initialized.
59-
var mode = FS_getMode(canRead, canWrite);
6065
var pathName = name ? parent + '/' + name : parent;
61-
wasmFSPreloadedFiles.push({pathName, fileData, mode});
66+
var mode = FS_getMode(canRead, canWrite);
67+
68+
if (!wasmFSPreloadingFlushed) {
69+
// WasmFS code in the wasm is not ready to be called yet. Cache the
70+
// files we want to create here in JS, and WasmFS will read them
71+
// later.
72+
wasmFSPreloadedFiles.push({pathName, fileData, mode});
73+
} else {
74+
// WasmFS is already running, so create the file normally.
75+
FS.create(pathName, mode);
76+
FS.writeFile(pathName, fileData);
77+
}
6278
},
6379
createPath: (parent, path, canRead, canWrite) => {
6480
// Cache file path directory names.
@@ -67,7 +83,11 @@ FS.createPreloadedFile = FS_createPreloadedFile;
6783
var part = parts.pop();
6884
if (!part) continue;
6985
var current = PATH.join2(parent, part);
70-
wasmFSPreloadedDirs.push({parentPath: parent, childName: part});
86+
if (!wasmFSPreloadingFlushed) {
87+
wasmFSPreloadedDirs.push({parentPath: parent, childName: part});
88+
} else {
89+
FS.mkdir(current);
90+
}
7191
parent = current;
7292
}
7393
return current;
@@ -322,8 +342,17 @@ FS.createPreloadedFile = FS_createPreloadedFile;
322342

323343
#endif
324344
},
325-
_wasmfs_get_num_preloaded_files__deps: ['$wasmFSPreloadedFiles'],
345+
346+
_wasmfs_get_num_preloaded_files__deps: [
347+
'$wasmFSPreloadedFiles',
348+
'$wasmFSPreloadingFlushed'],
326349
_wasmfs_get_num_preloaded_files: function() {
350+
// When this method is called from WasmFS it means that we are about to
351+
// flush all the preloaded data, so mark that. (There is no call that
352+
// occurs at the end of that flushing, which would be more natural, but it
353+
// is fine to mark the flushing here as during the flushing itself no user
354+
// code can run, so nothing will check whether we have flushed or not.)
355+
wasmFSPreloadingFlushed = true;
327356
return wasmFSPreloadedFiles.length;
328357
},
329358
_wasmfs_get_num_preloaded_dirs__deps: ['$wasmFSPreloadedDirs'],

test/test_browser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,6 +1884,7 @@ def test_clientside_vertex_arrays_es3(self):
18841884
def test_emscripten_api(self):
18851885
self.btest_exit('emscripten_api_browser.c', args=['-sEXPORTED_FUNCTIONS=_main,_third', '-lSDL'])
18861886

1887+
@also_with_wasmfs
18871888
def test_emscripten_async_load_script(self):
18881889
def setup():
18891890
create_file('script1.js', '''

0 commit comments

Comments
 (0)