Files
cnc_wams/wasm-port/runtime/opfs/file-service.js
wangdequan 9a9fb5d4c1 按建议,继续完成后续工作
结论:已将 INI 面板的 OPFS 文本文件读写抽为 host-side file-service,并新增 Node mock 验证,确认 OPFS 边界不进入 WASM core 且可覆盖保存、读取、缺失路径和非法路径行为。
2026-06-08 00:19:52 +08:00

53 lines
1.6 KiB
JavaScript

function splitPath(path) {
if (typeof path !== "string" || path.length === 0) {
throw new Error("OPFS path must be a non-empty relative path.");
}
if (path.startsWith("/") || path.includes("//")) {
throw new Error(`Invalid OPFS path: ${path}`);
}
const parts = path.split("/");
if (parts.some((part) => part === "." || part === ".." || part === "")) {
throw new Error(`Invalid OPFS path: ${path}`);
}
return parts;
}
export async function getOpfsRoot(storage = globalThis.navigator?.storage) {
if (!storage?.getDirectory) {
throw new Error("OPFS is not available in this browser.");
}
return storage.getDirectory();
}
export async function ensureParentDir(root, path) {
const parts = splitPath(path);
let current = root;
for (const part of parts.slice(0, -1)) {
current = await current.getDirectoryHandle(part, { create: true });
}
return current;
}
export async function saveTextFile(path, text, storage) {
const root = await getOpfsRoot(storage);
const dir = await ensureParentDir(root, path);
const filename = splitPath(path).at(-1);
const fileHandle = await dir.getFileHandle(filename, { create: true });
const writable = await fileHandle.createWritable();
await writable.write(text);
await writable.close();
}
export async function loadTextFile(path, storage) {
const root = await getOpfsRoot(storage);
const parts = splitPath(path);
let current = root;
for (const part of parts.slice(0, -1)) {
current = await current.getDirectoryHandle(part);
}
const fileHandle = await current.getFileHandle(parts.at(-1));
const file = await fileHandle.getFile();
return file.text();
}