Files
turso/bindings/wasm/web/src/opfs-sync-proxy.js
Elijah Morgan 02e4104932 reorg package structure
src moved under web/ to make it cleaner
build does less moving of files, mostly just moves the wasm-pack
into dist for node and web
2025-01-16 21:29:19 -05:00

137 lines
3.3 KiB
JavaScript

// opfs-sync-proxy.js
let transferBuffer, statusBuffer, statusArray, statusView;
let transferArray;
let rootDir = null;
const handles = new Map();
let nextFd = 1;
self.postMessage("ready");
onmessage = async (e) => {
log("handle message: ", e.data);
if (e.data.cmd === "init") {
log("init");
transferBuffer = e.data.transferBuffer;
statusBuffer = e.data.statusBuffer;
transferArray = new Uint8Array(transferBuffer);
statusArray = new Int32Array(statusBuffer);
statusView = new DataView(statusBuffer);
self.postMessage("done");
return;
}
const result = await handleCommand(e.data);
sendResult(result);
};
self.onerror = (error) => {
console.error("opfssync error: ", error);
// Don't close, keep running
return true; // Prevents default error handling
};
function handleCommand(msg) {
log(`handle message: ${msg.cmd}`);
switch (msg.cmd) {
case "open":
return handleOpen(msg.path);
case "close":
return handleClose(msg.fd);
case "read":
return handleRead(msg.fd, msg.offset, msg.size);
case "write":
return handleWrite(msg.fd, msg.buffer, msg.offset);
case "size":
return handleSize(msg.fd);
case "sync":
return handleSync(msg.fd);
}
}
async function handleOpen(path) {
if (!rootDir) {
rootDir = await navigator.storage.getDirectory();
}
const fd = nextFd++;
const handle = await rootDir.getFileHandle(path, { create: true });
const syncHandle = await handle.createSyncAccessHandle();
handles.set(fd, syncHandle);
return { fd };
}
function handleClose(fd) {
const handle = handles.get(fd);
handle.close();
handles.delete(fd);
return { success: true };
}
function handleRead(fd, offset, size) {
const handle = handles.get(fd);
const readBuffer = new ArrayBuffer(size);
const readSize = handle.read(readBuffer, { at: offset });
log("opfssync read: size: ", readBuffer.byteLength);
const tmp = new Uint8Array(readBuffer);
log("opfssync read buffer: ", [...tmp]);
transferArray.set(tmp);
return { success: true, length: readSize };
}
function handleWrite(fd, buffer, offset) {
log("opfssync buffer size:", buffer.byteLength);
log("opfssync write buffer: ", [...buffer]);
const handle = handles.get(fd);
const size = handle.write(buffer, { at: offset });
return { success: true, length: size };
}
function handleSize(fd) {
const handle = handles.get(fd);
return { success: true, length: handle.getSize() };
}
function handleSync(fd) {
const handle = handles.get(fd);
handle.flush();
return { success: true };
}
function sendResult(result) {
if (result?.fd) {
statusView.setInt32(4, result.fd, true);
} else {
log("opfs-sync-proxy: result.length: ", result.length);
statusView.setInt32(4, result?.length || 0, true);
}
Atomics.store(statusArray, 0, 1);
Atomics.notify(statusArray, 0);
}
// logLevel:
//
// 0 = no logging output
// 1 = only errors
// 2 = warnings and errors
// 3 = debug, warnings, and errors
const logLevel = 1;
const loggers = {
0: console.error.bind(console),
1: console.warn.bind(console),
2: console.log.bind(console),
};
const logImpl = (level, ...args) => {
if (logLevel > level) loggers[level]("OPFS asyncer:", ...args);
};
const log = (...args) => logImpl(2, ...args);
const warn = (...args) => logImpl(1, ...args);
const error = (...args) => logImpl(0, ...args);