From 8544872198facb8b0e7ad457605fffdc390c343f Mon Sep 17 00:00:00 2001 From: cnc Date: Sat, 6 Jun 2026 06:06:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E6=BA=90=E4=BF=9D=E6=8A=A4=20OPFS=20?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=A4=87=E4=BB=BD=E5=A4=B1=E8=B4=A5=E8=BE=B9?= =?UTF-8?q?=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/wasm-core.js | 7 ++++- ...browser-wasm-smoke-opfs-mirror-sections.js | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/web/src/wasm-core.js b/web/src/wasm-core.js index 14e0526..c5ce82e 100644 --- a/web/src/wasm-core.js +++ b/web/src/wasm-core.js @@ -529,7 +529,12 @@ function installOpfsWorkspace(module, options) { const backupPath = `${LINUXCNC_DEFAULT_PARAMETER_FILE}.bak`; const backupData = readFirstExistingWasmFile(module, [backupPath, `/${backupPath}`]); if (backupData !== null) { - await writeOpfsFile(workspacePath, `${path}.bak`, backupData); + try { + await writeOpfsFile(workspacePath, `${path}.bak`, backupData); + } catch (_backupError) { + // LinuxCNC reports link(filename, filename + ".bak") failures + // with perror() and still renames filename + ".new" over filename. + } } else { await removeOpfsFileEntry(workspacePath, `${path}.bak`); } diff --git a/web/test-browser-wasm-smoke-opfs-mirror-sections.js b/web/test-browser-wasm-smoke-opfs-mirror-sections.js index 803faa9..e8b91b3 100644 --- a/web/test-browser-wasm-smoke-opfs-mirror-sections.js +++ b/web/test-browser-wasm-smoke-opfs-mirror-sections.js @@ -1,9 +1,13 @@ export async function runBrowserOpfsMirrorSections(context, simulator) { const { expectEvent, + expectIncludes, + expectOpfsDirectoryStat, expectMissingWasmPath, expectText, + expectWasmFilesMissing, near, + readOpfsText, runSection, withSmokeSimulator, } = context; @@ -123,4 +127,27 @@ export async function runBrowserOpfsMirrorSections(context, simulator) { const truncatedWasmProgram = new TextDecoder().decode(simulator.fs.module.FS.readFile(truncatedWasmPath)); expectText(truncatedWasmProgram, "G21\n", "OPFS writeFile did not truncate the WASM mirror"); }); + + await runSection("opfs parameter backup bridge failure is non-fatal", async () => { + // LinuxCNC source basis: rs274ngc_pre.cc save_parameters() + // reports link(filename, filename + ".bak") failure with perror() + // but still renames filename + ".new" over the parameter file. + simulator.fs.module.FS.writeFile("rs274ngc.var", "5161\t12.000000\n"); + simulator.fs.module.FS.writeFile("rs274ngc.var.bak", "5161\t11.000000\n"); + const backupBridgeDirectory = simulator.fs.opfs.resolvePath("parameters/backup-bridge-directory.var.bak"); + simulator.fs.module.FS.mkdir(backupBridgeDirectory); + await simulator.fs.opfs.persistDirectory("parameters/backup-bridge-directory.var.bak"); + await simulator.fs.opfs.persistParameterFile("parameters/backup-bridge-directory.var"); + expectIncludes( + await readOpfsText(simulator, "parameters/backup-bridge-directory.var"), + "5161\t12.000000", + "LinuxCNC parameter bridge did not persist the main file when backup link failed", + ); + await expectOpfsDirectoryStat( + simulator, + "parameters/backup-bridge-directory.var.bak", + "LinuxCNC parameter backup bridge removed an existing OPFS backup directory", + ); + expectWasmFilesMissing(simulator.fs.module.FS, ["rs274ngc.var", "rs274ngc.var.new", "rs274ngc.var.bak"], (parameterPath) => `LinuxCNC parameter scratch file remained outside OPFS after non-fatal backup bridge failure: ${parameterPath}`); + }); }