mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 16:59:27 +08:00
132 lines
4.8 KiB
JavaScript
132 lines
4.8 KiB
JavaScript
importScripts("./wasm_exec.js");
|
|
|
|
let pending = Promise.resolve();
|
|
const operations = new Map();
|
|
self.onmessage = ({ data }) => {
|
|
if (data.type === "cancel") {
|
|
operations.get(data.id)?.abort();
|
|
return;
|
|
}
|
|
if (data.name === "ofdgoConvertPDF" || data.name === "ofdgoExportPage" || data.name === "ofdgoExportDocument" || data.name === "ofdgoExportAttachment" || data.name === "ofdgoSaveDocument" || data.name === "ofdgoSaveEncrypted" || data.name === "ofdgoSaveSigned" || data.name === "ofdgoImportPages") {
|
|
operations.set(data.id, new AbortController());
|
|
}
|
|
pending = pending.then(() => handleMessage(data));
|
|
};
|
|
async function handleMessage({ id, name, args }) {
|
|
let output;
|
|
let channel;
|
|
const signal = operations.get(id)?.signal;
|
|
const importing = name === "ofdgoImportPages";
|
|
const converting = name === "ofdgoConvertPDF";
|
|
const saving = name === "ofdgoSaveDocument" || name === "ofdgoSaveEncrypted" || name === "ofdgoSaveSigned";
|
|
const key = name === "ofdgoOpen" ? args[3]?.key : name === "ofdgoSaveSigned" || name === "ofdgoLoadImport" ? args[1]?.key : null;
|
|
const keyPassword = name === "ofdgoOpen" ? args[3]?.keyPassword : name === "ofdgoSaveSigned" || name === "ofdgoLoadImport" ? args[1]?.keyPassword : null;
|
|
const password = name === "ofdgoOpen" ? args[3]?.password : name === "ofdgoSaveEncrypted" || name === "ofdgoLoadImport" ? args[1]?.password : null;
|
|
try {
|
|
signal?.throwIfAborted();
|
|
const chunks = [];
|
|
let size = 0;
|
|
if (signal) {
|
|
channel = new MessageChannel();
|
|
const finish = (done, err, commit = false) => {
|
|
channel.port1.onmessage = () => {
|
|
if (commit && !signal.aborted && !err) operations.delete(id);
|
|
done(err?.message || "", signal.aborted);
|
|
};
|
|
channel.port2.postMessage(null);
|
|
};
|
|
if (importing || converting) {
|
|
args.push((phase, completed, total, done) => {
|
|
self.postMessage({ id, type: importing ? "import" : "conversion", phase, completed, total });
|
|
finish(done, null, importing && phase === "commit");
|
|
});
|
|
} else {
|
|
const file = args.pop();
|
|
const indices = saving ? args.shift() : null;
|
|
if (file) output = await file.createWritable();
|
|
signal.throwIfAborted();
|
|
args.push((bytes, done) => {
|
|
if (signal.aborted) {
|
|
finish(done);
|
|
return;
|
|
}
|
|
size += bytes.length;
|
|
if (output) {
|
|
output.write(bytes).then(() => finish(done), (err) => finish(done, err));
|
|
} else {
|
|
chunks.push(new Blob([bytes]));
|
|
finish(done);
|
|
}
|
|
});
|
|
if (name === "ofdgoExportDocument") {
|
|
args.push((completed, total, done) => {
|
|
self.postMessage({ id, type: "export", stage: "pages", completed, total });
|
|
finish(done);
|
|
});
|
|
} else if (saving) {
|
|
args.push((phase, completed, total, done) => {
|
|
self.postMessage({ id, type: "export", stage: "prepare", phase, completed, total });
|
|
finish(done);
|
|
});
|
|
if (indices != null) args.push(indices);
|
|
}
|
|
}
|
|
}
|
|
const payload = await globalThis[name](...args);
|
|
signal?.throwIfAborted();
|
|
const result = typeof payload === "string" ? JSON.parse(payload) : payload;
|
|
if (signal && !importing && !converting && result.ok) {
|
|
operations.delete(id);
|
|
result.data.size = size;
|
|
self.postMessage({ id, type: "export", stage: "save" });
|
|
if (output) {
|
|
await output.close();
|
|
} else {
|
|
result.data.blob = new Blob(chunks, { type: result.data.mime });
|
|
}
|
|
} else if (output) {
|
|
await output.abort();
|
|
}
|
|
output = null;
|
|
const transfer = result.data?.bytes ? [result.data.bytes.buffer] : (result.data?.images || []).map((image) => image.bytes.buffer);
|
|
self.postMessage({ id, ...result }, transfer);
|
|
} catch (err) {
|
|
await output?.abort().catch(() => {});
|
|
const result = { id, ok: false, error: err.message };
|
|
if (signal?.aborted) {
|
|
result.error = importing ? "导入已取消" : converting ? "转换已取消" : "导出已取消";
|
|
result.canceled = true;
|
|
}
|
|
self.postMessage(result);
|
|
} finally {
|
|
password?.fill(0);
|
|
key?.fill(0);
|
|
keyPassword?.fill(0);
|
|
channel?.port1.close();
|
|
channel?.port2.close();
|
|
operations.delete(id);
|
|
}
|
|
}
|
|
|
|
function exitWASM(err) {
|
|
self.postMessage({ type: "exit", error: err?.message || "引擎运行中断" });
|
|
self.close();
|
|
}
|
|
|
|
async function loadWASM() {
|
|
const go = new Go();
|
|
self.postMessage({ type: "progress", text: "正在下载引擎", percent: 16 });
|
|
const response = await fetch("./ofdgo.wasm");
|
|
self.postMessage({ type: "progress", text: "正在编译引擎", percent: 35 });
|
|
const { instance } = await WebAssembly.instantiateStreaming(response, go.importObject);
|
|
self.postMessage({ type: "progress", text: "正在启动引擎", percent: 58 });
|
|
go.run(instance).then(exitWASM, exitWASM);
|
|
if (!go.exited) {
|
|
const backends = JSON.parse(globalThis.ofdgoRenderBackends());
|
|
if (!backends.ok) throw new Error(backends.error);
|
|
self.postMessage({ type: "ready", backends: backends.data });
|
|
}
|
|
}
|
|
|
|
loadWASM().catch(exitWASM);
|