Joe Osborn c413bcc626
Threaded emscripten fixes (#17614)
* Actually read CLI args in emscripten

* Fix fetchfs manifest parsing, increase download chunk size

The chunk size should probably be made a parameter in the future.  The
larger chunk size trades longer hitches for fewer hitches.

* Add exec command driver and API functions for emscripten.

Under WASMFS, stdin/stdout can't be customized the way they can with
the JS FS implementation.  Also, this approach frees up stdin/stdout
and simplifies interaction with the command interface for web embedders.

* fixup upload paths, show use of new emscripten cmd interface

* Add JS library function names to EXPORTS as well as EXPORTED_FUNCTIONS for older emsdk versions
2025-02-24 09:25:05 -08:00

67 lines
2.1 KiB
JavaScript

importScripts("zip-no-worker.min.js");
async function writeFile(path, data) {
const root = await navigator.storage.getDirectory();
const dir_end = path.lastIndexOf("/");
const parent = path.substr(0, dir_end);
const child = path.substr(dir_end+1);
const parent_dir = await mkdirTree(parent);
const file = await parent_dir.getFileHandle(child,{create:true});
const stream = await file.createSyncAccessHandle();
const written = stream.write(data);
stream.close();
}
async function mkdirTree(path) {
const root = await navigator.storage.getDirectory();
const parts = path.split("/");
let here = root;
for (const part of parts) {
if (part == "") { continue; }
here = await here.getDirectoryHandle(part, {create:true});
}
return here;
}
async function setupZipFS(zipBuf) {
const root = await navigator.storage.getDirectory();
const zipReader = new zip.ZipReader(new zip.Uint8ArrayReader(zipBuf), {useWebWorkers:false});
const entries = await zipReader.getEntries();
for(const file of entries) {
if (file.getData && !file.directory) {
const writer = new zip.Uint8ArrayWriter();
const data = await file.getData(writer);
await writeFile(file.filename, data);
} else if (file.directory) {
await mkdirTree(file.filename);
}
}
await zipReader.close();
}
onmessage = async (msg) => {
if(msg.data.command == "load_bundle") {
let old_timestamp = msg.data.time;
try {
const root = await navigator.storage.getDirectory();
const _bundle = await root.getDirectoryHandle("bundle");
} catch (_e) {
old_timestamp = "";
}
let resp = await fetch("assets/frontend/bundle-minimal.zip", {
headers: {
"If-Modified-Since": old_timestamp
}
});
if (resp.status == 200) {
await setupZipFS(new Uint8Array(await resp.arrayBuffer()));
} else {
await resp.text();
}
postMessage({command:"loaded_bundle", time:resp.headers.get("last-modified")});
} else if(msg.data.command == "upload_file") {
await writeFile("userdata/content/"+msg.data.name, new Uint8Array(msg.data.data));
postMessage({command:"uploaded_file",name:msg.data.name});
}
}