From 7f45abe93cdd8449d3488d110fea895f78565152 Mon Sep 17 00:00:00 2001 From: cnc Date: Fri, 5 Jun 2026 06:06:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=82=E8=80=83=E6=89=80=E6=9C=89=E5=88=86?= =?UTF-8?q?=E7=BB=84=EF=BC=8C=E5=AE=8C=E6=88=90=E5=B0=BD=E9=87=8F=E5=A4=9A?= =?UTF-8?q?=E7=9A=84=E5=86=85=E5=AE=B9=EF=BC=9A=E5=90=8C=E6=AD=A5=20OPFS?= =?UTF-8?q?=20=E4=B8=8E=20smoke=20=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 结论:未扩展 smoke 功能行为,仅收紧 OPFS workspace、directory、policy 浏览器烟测和 source-map 守卫。 LinuxCNC 来源依据:src/emc/rs274ngc/rs274ngc_pre.cc 的 restore_parameters/save_parameters/read_text 参数文件与文件读取语义,以及 interp_internal.hh 的 rs274ngc.var/.bak 常量边界。 检查通过:./check-linuxcnc-opfs-source-map.sh;./check-linuxcnc-wasm-smoke-source-map.sh;./check-linuxcnc-workstreams-source-map.sh;./test-native.sh;./test-linuxcnc-source-link.sh。 --- check-linuxcnc-opfs-source-map.sh | 27 +++++++++++++++++++++++++ check-linuxcnc-wasm-smoke-source-map.sh | 23 +++++++++++++++++++++ docs/linuxcnc-opfs-source-map.md | 6 ++++++ docs/linuxcnc-wasm-smoke-source-map.md | 9 +++++++-- test-web-wasm-browser-smoke.sh | 7 +++++++ 5 files changed, 70 insertions(+), 2 deletions(-) diff --git a/check-linuxcnc-opfs-source-map.sh b/check-linuxcnc-opfs-source-map.sh index b4098e8..859cec5 100755 --- a/check-linuxcnc-opfs-source-map.sh +++ b/check-linuxcnc-opfs-source-map.sh @@ -47,7 +47,10 @@ grep -F '| `web/src/wasm-core.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null grep -F '| `web/src/app.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null grep -F '| `web/test-browser-wasm-smoke-opfs-basic-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null grep -F '| `web/test-browser-wasm-smoke-opfs-parameter-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null +grep -F '| `web/test-browser-wasm-smoke-opfs-workspace-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null grep -F '| `web/test-browser-wasm-smoke-opfs-mirror-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null +grep -F '| `web/test-browser-wasm-smoke-opfs-directory-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null +grep -F '| `web/test-browser-wasm-smoke-opfs-policy-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null grep -F '| `web/test-browser-wasm-smoke-app-sections.js` |' docs/linuxcnc-opfs-source-map.md >/dev/null grep -F 'const LINUXCNC_DEFAULT_PARAMETER_FILE = "rs274ngc.var";' web/src/wasm-core.js >/dev/null @@ -58,9 +61,28 @@ grep -F 'before replacing the main file and managing filename + ".bak".' web/src grep -F 'app frame did not clean up LinuxCNC temporary parameter file in OPFS' \ web/test-browser-wasm-smoke-app-sections.js >/dev/null grep -F 'OPFS cannot be disabled in browser contexts with OPFS support' web/src/wasm-core.js >/dev/null +grep -F 'OPFS path must stay inside the CNC workspace' web/src/wasm-core.js >/dev/null +grep -F 'OPFS mount point must stay inside the Emscripten filesystem' web/src/wasm-core.js >/dev/null +grep -F 'async persistDirectory(path)' web/src/wasm-core.js >/dev/null +grep -F 'async readDirectory(path)' web/src/wasm-core.js >/dev/null grep -F 'const events = await simulator.parseFileWithParameterFile(programPath, parameterPath, "linuxcnc", parseOptions);' \ web/src/app.js >/dev/null grep -F 'OPFS workspace is required for browser program parsing' web/src/app.js >/dev/null +grep -F 'runBrowserOpfsBasicSections(context, simulator)' \ + web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null +grep -F 'runBrowserOpfsParameterSections(context, simulator)' \ + web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null +grep -F 'runBrowserOpfsMirrorSections(context, simulator)' \ + web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null +grep -F 'runBrowserOpfsDirectorySections(context, simulator)' \ + web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null +grep -F 'runBrowserOpfsPolicySections(context)' web/test-browser-wasm-smoke-sections.js >/dev/null +grep -F 'runSection("opfs directory persist and load"' \ + web/test-browser-wasm-smoke-opfs-directory-sections.js >/dev/null +grep -F 'runSection("opfs metadata queries avoid wasm mirror pollution"' \ + web/test-browser-wasm-smoke-opfs-directory-sections.js >/dev/null +grep -F 'runSection("browser opfs policy"' \ + web/test-browser-wasm-smoke-opfs-policy-sections.js >/dev/null grep -F 'runSection("opfs parameter restore in new instance"' test-web-wasm-browser-smoke.sh >/dev/null grep -F 'runSection("opfs invalid parameter restore failures"' test-web-wasm-browser-smoke.sh >/dev/null grep -F 'runSection("opfs stale parameter state cleanup"' test-web-wasm-browser-smoke.sh >/dev/null @@ -81,7 +103,10 @@ coverage_entries = [ "web/src/app.js", "web/test-browser-wasm-smoke-opfs-basic-sections.js", "web/test-browser-wasm-smoke-opfs-parameter-sections.js", + "web/test-browser-wasm-smoke-opfs-workspace-sections.js", "web/test-browser-wasm-smoke-opfs-mirror-sections.js", + "web/test-browser-wasm-smoke-opfs-directory-sections.js", + "web/test-browser-wasm-smoke-opfs-policy-sections.js", "web/test-browser-wasm-smoke-app-sections.js", ] for entry in coverage_entries: @@ -95,6 +120,8 @@ required_phrases = [ "`.new`, `.bak`, failure, and stale-state semantics", 'unlinks `filename + ".bak"`', "OPFS/WASM mirror persistence", + "OPFS directory persistence and WASM mirror refresh", + "OPFS workspace and mount policy", "app-level OPFS program, parameter, backup, and reload behavior", ] for phrase in required_phrases: diff --git a/check-linuxcnc-wasm-smoke-source-map.sh b/check-linuxcnc-wasm-smoke-source-map.sh index 02d9882..49ab87f 100755 --- a/check-linuxcnc-wasm-smoke-source-map.sh +++ b/check-linuxcnc-wasm-smoke-source-map.sh @@ -91,10 +91,21 @@ grep -F 'browser WASM smoke covered $passed_sections sections, expected at least grep -F 'required_browser_sections = {' test-web-wasm-browser-smoke.sh >/dev/null grep -F 'runSection("linuxcnc generated switchkins cases load"' test-web-wasm-browser-smoke.sh >/dev/null grep -F 'runSection("opfs parameter restore in new instance"' test-web-wasm-browser-smoke.sh >/dev/null +grep -F 'runSection("opfs directory persist and load"' test-web-wasm-browser-smoke.sh >/dev/null +grep -F 'runSection("browser opfs policy"' test-web-wasm-browser-smoke.sh >/dev/null grep -F 'runSection("browser app opfs restore"' test-web-wasm-browser-smoke.sh >/dev/null grep -F 'runLinuxCncBrowserSections(context, simulator)' web/test-browser-wasm-smoke-sections.js >/dev/null grep -F 'runBrowserOpfsWorkspaceSections(context, simulator)' web/test-browser-wasm-smoke-sections.js >/dev/null +grep -F 'runBrowserOpfsPolicySections(context)' web/test-browser-wasm-smoke-sections.js >/dev/null grep -F 'runBrowserAppOpfsSections(context)' web/test-browser-wasm-smoke-sections.js >/dev/null +grep -F 'runBrowserOpfsBasicSections(context, simulator)' \ + web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null +grep -F 'runBrowserOpfsParameterSections(context, simulator)' \ + web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null +grep -F 'runBrowserOpfsMirrorSections(context, simulator)' \ + web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null +grep -F 'runBrowserOpfsDirectorySections(context, simulator)' \ + web/test-browser-wasm-smoke-opfs-workspace-sections.js >/dev/null grep -F 'linuxcnc_switchkins_remap_config_cases.json' \ web/test-browser-wasm-smoke-linuxcnc-sections.js >/dev/null grep -F 'missing LinuxCNC switchkins config cases after INI_FILE_NAME remap-load filtering' \ @@ -105,6 +116,12 @@ grep -F 'LinuxCNC source basis: rs274ngc_pre.cc save_parameters()' \ web/test-browser-wasm-smoke-opfs-parameter-sections.js >/dev/null grep -F 'LinuxCNC source basis: rs274ngc_pre.cc read_text() reads' \ web/test-browser-wasm-smoke-opfs-basic-sections.js >/dev/null +grep -F 'runSection("opfs directory persist and load"' \ + web/test-browser-wasm-smoke-opfs-directory-sections.js >/dev/null +grep -F 'runSection("opfs metadata queries avoid wasm mirror pollution"' \ + web/test-browser-wasm-smoke-opfs-directory-sections.js >/dev/null +grep -F 'runSection("browser opfs policy"' \ + web/test-browser-wasm-smoke-opfs-policy-sections.js >/dev/null grep -F 'app frame did not persist current program into OPFS' \ web/test-browser-wasm-smoke-app-sections.js >/dev/null grep -F 'app frame did not persist LinuxCNC parameter backup into OPFS' \ @@ -141,7 +158,12 @@ for path in [ "test-web-wasm-node-smoke.cjs", "test-web-wasm-browser-smoke.sh", "web/test-browser-wasm-smoke-linuxcnc-sections.js", + "web/test-browser-wasm-smoke-opfs-workspace-sections.js", + "web/test-browser-wasm-smoke-opfs-basic-sections.js", "web/test-browser-wasm-smoke-opfs-parameter-sections.js", + "web/test-browser-wasm-smoke-opfs-mirror-sections.js", + "web/test-browser-wasm-smoke-opfs-directory-sections.js", + "web/test-browser-wasm-smoke-opfs-policy-sections.js", "web/test-browser-wasm-smoke-app-sections.js", ]: if f"| `{path}` |" not in source_map: @@ -154,6 +176,7 @@ required_phrases = [ "Node smoke must leave OPFS disabled", "Generated switchkins config smoke cases", "browser smoke shell guard also pins required section names", + "OPFS workspace/policy/directory handling", 'unlinking `filename + ".bak"`', "./check-linuxcnc-wasm-smoke-source-map.sh", ] diff --git a/docs/linuxcnc-opfs-source-map.md b/docs/linuxcnc-opfs-source-map.md index 5810c81..6ed5f89 100644 --- a/docs/linuxcnc-opfs-source-map.md +++ b/docs/linuxcnc-opfs-source-map.md @@ -26,7 +26,10 @@ persistence. It is a policy and bridge map only; it must not add independent fil | `web/src/app.js` | Persists browser programs at `programs/current.ngc` and LinuxCNC parameters at `parameters/rs274ngc.var`. | | `web/test-browser-wasm-smoke-opfs-basic-sections.js` | Verifies OPFS program file reads through LinuxCNC `read_text()` and rejects unsafe paths. | | `web/test-browser-wasm-smoke-opfs-parameter-sections.js` | Verifies OPFS parameter restore, save, `.new`, `.bak`, failure, and stale-state semantics. | +| `web/test-browser-wasm-smoke-opfs-workspace-sections.js` | Aggregates OPFS basic, parameter, mirror, and directory checks under browser OPFS availability. | | `web/test-browser-wasm-smoke-opfs-mirror-sections.js` | Verifies OPFS/WASM mirror persistence used by source-backed file parsing and parameter movement. | +| `web/test-browser-wasm-smoke-opfs-directory-sections.js` | Verifies OPFS directory persistence and WASM mirror refresh without polluting mirrors during metadata queries. | +| `web/test-browser-wasm-smoke-opfs-policy-sections.js` | Verifies OPFS workspace and mount policy, including the browser rule that OPFS cannot be disabled. | | `web/test-browser-wasm-smoke-app-sections.js` | Verifies app-level OPFS program, parameter, backup, and reload behavior. | ## Browser Bridge Boundary @@ -34,6 +37,9 @@ persistence. It is a policy and bridge map only; it must not add independent fil - `web/src/wasm-core.js` must keep LinuxCNC parameter persistence routed through an OPFS workspace. - Browser contexts with OPFS support must not disable OPFS. +- OPFS workspace paths must remain relative paths inside the CNC workspace, and + OPFS mount points must remain absolute paths inside the Emscripten + filesystem. - Browser app and wasm bridge code must not use Local Storage, IndexedDB, File Picker, Directory Picker, WebKit filesystem, or FileReader persistence paths for CNC programs, LinuxCNC parameter files, or mirrored workspace files. diff --git a/docs/linuxcnc-wasm-smoke-source-map.md b/docs/linuxcnc-wasm-smoke-source-map.md index f6a15d5..65a9d8d 100644 --- a/docs/linuxcnc-wasm-smoke-source-map.md +++ b/docs/linuxcnc-wasm-smoke-source-map.md @@ -34,7 +34,12 @@ OPFS-only is the required boundary. | `test-web-wasm-node-smoke.cjs` | Exercises the C ABI, `web/src/wasm-core.js`, generated switchkins config cases, and source-backed kinematics events. | | `test-web-wasm-browser-smoke.sh` | Runs browser checks after verifying copied WASM artifacts and smoke module structure. | | `web/test-browser-wasm-smoke-linuxcnc-sections.js` | Exercises LinuxCNC browser parsing and generated switchkins cases without INI_FILE_NAME remap-load aliases. | +| `web/test-browser-wasm-smoke-opfs-workspace-sections.js` | Aggregates OPFS basic, parameter, mirror, and directory sections under browser OPFS availability. | +| `web/test-browser-wasm-smoke-opfs-basic-sections.js` | Exercises OPFS-backed program file reads through LinuxCNC `read_text()` and rejects unsafe paths. | | `web/test-browser-wasm-smoke-opfs-parameter-sections.js` | Exercises LinuxCNC parameter restore/save/backup semantics through OPFS. | +| `web/test-browser-wasm-smoke-opfs-mirror-sections.js` | Exercises OPFS/WASM mirror persistence used by source-backed program parsing and parameter movement. | +| `web/test-browser-wasm-smoke-opfs-directory-sections.js` | Exercises OPFS directory persistence and WASM mirror refresh without filesystem persistence outside OPFS. | +| `web/test-browser-wasm-smoke-opfs-policy-sections.js` | Exercises browser OPFS workspace and mount policy, including the rule that OPFS cannot be disabled. | | `web/test-browser-wasm-smoke-app-sections.js` | Verifies the browser app uses OPFS program and parameter persistence. | ## Boundaries @@ -46,8 +51,8 @@ OPFS-only is the required boundary. - Generated switchkins config smoke cases must continue to come from `web/public/linuxcnc_switchkins_remap_config_cases.json`. - The browser smoke shell guard also pins required section names for LinuxCNC - browser parsing, OPFS parameter restore/save failure handling, and browser - app OPFS reload coverage. + browser parsing, OPFS workspace/policy/directory handling, OPFS parameter + restore/save failure handling, and browser app OPFS reload coverage. - Smoke wrappers must keep positive minimum coverage thresholds so accidental section loss is visible. diff --git a/test-web-wasm-browser-smoke.sh b/test-web-wasm-browser-smoke.sh index 986e27d..69073a3 100755 --- a/test-web-wasm-browser-smoke.sh +++ b/test-web-wasm-browser-smoke.sh @@ -175,6 +175,13 @@ required_browser_sections = { 'runSection("opfs invalid parameter restore failures"', 'runSection("opfs stale parameter state cleanup"', ), + "web/test-browser-wasm-smoke-opfs-directory-sections.js": ( + 'runSection("opfs directory persist and load"', + 'runSection("opfs metadata queries avoid wasm mirror pollution"', + ), + "web/test-browser-wasm-smoke-opfs-policy-sections.js": ( + 'runSection("browser opfs policy"', + ), "web/test-browser-wasm-smoke-app-sections.js": ( 'runSection("browser app opfs save"', 'runSection("browser app opfs restore"',