From bbd58e61a12c2d67110787e528d1f26904865db0 Mon Sep 17 00:00:00 2001 From: wangdequan Date: Mon, 8 Jun 2026 14:01:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E8=A7=84=E5=88=92=E6=8C=81=E7=BB=AD?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 结论:补强真实浏览器解释器 SDK 对 LinuxCNC 参数文件 restore/save 及非随机/随机工具表 load/save 的直接验证,并通过 host 聚合 smoke。 --- wasm-port/docs/compatibility-validation.md | 45 +++--- wasm-port/tests/browser/interp_smoke.html | 172 +++++++++++++++++++++ 2 files changed, 197 insertions(+), 20 deletions(-) diff --git a/wasm-port/docs/compatibility-validation.md b/wasm-port/docs/compatibility-validation.md index 9abda1a..e0fca6e 100644 --- a/wasm-port/docs/compatibility-validation.md +++ b/wasm-port/docs/compatibility-validation.md @@ -155,14 +155,16 @@ slot readback, and checks the vendored rotary-indexer `G0 A...` execution path for `UNLOCK_ROTARY`/`LOCK_ROTARY` boundary events. It also validates `Interp::init_named_parameters()` and `Interp::find_named_param()` through the same browser SDK/C ABI path for built-in, INI-backed, HAL-backed, and missing -named-parameter lookup. It also uses real browser OPFS -storage plus the interpreter SDK to restore and save a LinuxCNC parameter file -through vendored `Interp::restore_parameters()` and `Interp::save_parameters()`, -and directly checks missing-file success plus out-of-order parameter-file -rejection through the same LinuxCNC `restore_parameters()` C ABI, -to load/save LinuxCNC tool tables through vendored `tooldata_common.cc`, and -to check the random-toolchanger `tooldata_save()` result before OPFS text -writeback, +named-parameter lookup. It also directly checks browser SDK parameter-file +restore/save through vendored `Interp::restore_parameters()` and +`Interp::save_parameters()`, including the LinuxCNC-saved text and `.bak` +backup, and directly checks browser SDK non-random/random tool-table +load/save through vendored `tooldata_common.cc`. The same browser smoke uses +real browser OPFS storage plus the interpreter SDK to restore/save LinuxCNC +parameter files, directly checks missing-file success plus out-of-order +parameter-file rejection through the same LinuxCNC `restore_parameters()` C +ABI, and checks the random-toolchanger `tooldata_save()` result before OPFS +text writeback, to reject invalid INI-derived parameter/tool-table file names through the OPFS path model after the names are parsed by the LinuxCNC-backed INI WASM SDK. It also verifies that explicit session parameter/tool-table file-name options @@ -224,7 +226,7 @@ The validation fails if: | `tests/wasm/node/verify_interp_wasm.sh` | Validates the initial interpreter-core WASM module can be built from vendored LinuxCNC interpreter source, loaded through the interpreter JS SDK, run the first fixture group through `Interp::execute()` and selected file fixtures through `Interp::open()`/`read()`/`execute()`, match the native canonical event plus required state readback fixtures, and run parameter-file restore/save through vendored LinuxCNC `Interp::restore_parameters()` and `Interp::save_parameters()`. | | `tests/opfs/node/verify_file_service.sh` | Validates the host-owned OPFS text-file adapter, path model, session snapshot store including custom filenames and envelope/path rejection paths, machine file store, G-code text store including filename rejection paths, OPFS-to-WASM parameter/tool-table bridges, and grouped machine-session loading without moving file persistence, parameter semantics, or tool-table semantics into the WASM core. | | `tests/browser/verify_ini_panel_browser.sh` | Validates the INI SDK, INI/interpreter WASM module loading, LinuxCNC-backed INI machine-session file-name string lookup, OPFS text-file round trip, generic session snapshot round trip plus custom filename and envelope/path rejection paths, machine file text round trip, G-code text round trip plus filename rejection paths, and the INI panel UI's machine-session load with default OPFS parameter/tool-table file mapping, G-code run, and canonical-event display paths in a real browser runtime. | -| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures through vendored LinuxCNC `Interp::execute()` plus `Interp::open()`/`read()`/`execute()` via the exported C ABI, including OPFS-backed parameter-file restore/save and non-random/random tool-table load/save through vendored LinuxCNC source. | +| `tests/browser/verify_interp_browser.sh` | Validates the interpreter-core WASM module loads through the interpreter JS SDK in a real browser runtime and runs selected positive and negative canonical fixtures through vendored LinuxCNC `Interp::execute()` plus `Interp::open()`/`read()`/`execute()` via the exported C ABI, including direct browser SDK and OPFS-backed parameter-file restore/save plus non-random/random tool-table load/save through vendored LinuxCNC source. | | `tests/host/verify_host_smokes.sh` | Runs the current host-side Node, WASM interpreter-core, OPFS, and browser smoke validation with shared WASM builds. | ## Fixture Coverage @@ -319,17 +321,20 @@ restore/save behavior through the exported C ABI, including out-of-order file rejection, missing-file success, missing required numeric parameter defaulting, required numeric parameter writeback, removal of named-parameter-only lines from saved output, and the `.bak` backup produced by vendored -`save_parameters()`, including browser OPFS readback of the backup text after -the host bridge writes it to persistent storage, plus INI-derived custom and -explicit host override parameter-file paths saved back to OPFS with their -LinuxCNC-produced backup text. It also covers LinuxCNC tool-table -load/save behavior through vendored `tooldata_common.cc`, including the -non-random and random-toolchanger `tooldata_init()` branches, with the SDK -only copying text into the Emscripten filesystem and calling the exported C -ABI; the browser smoke checks the random-toolchanger `tooldata_save()` C ABI -result before OPFS persistence writes the saved table text back, and verifies -that INI-derived custom and explicit host override tool-table OPFS paths can -be saved and read back after the table is loaded through vendored LinuxCNC. The same +`save_parameters()`, including direct browser SDK readback from the +Emscripten filesystem, browser OPFS readback of the backup text after the host +bridge writes it to persistent storage, plus INI-derived custom and explicit +host override parameter-file paths saved back to OPFS with their +LinuxCNC-produced backup text. It also covers LinuxCNC tool-table load/save +behavior through vendored `tooldata_common.cc`, including the non-random and +random-toolchanger `tooldata_init()` branches, with the SDK only copying text +into the Emscripten filesystem and calling the exported C ABI; the browser +smoke directly reads back both non-random and random saved tool-table text +from the Emscripten filesystem, checks the random-toolchanger +`tooldata_save()` C ABI result before OPFS persistence writes the saved table +text back, and verifies that INI-derived custom and explicit host override +tool-table OPFS paths can be saved and read back after the table is loaded +through vendored LinuxCNC. The same Node WASM and browser interpreter smokes now validate the exported `Interp::init()`/`Interp::synch()` probe for initialization canonical events, metric/inch `emcStatus` machine-unit conversion, and current/selected tool diff --git a/wasm-port/tests/browser/interp_smoke.html b/wasm-port/tests/browser/interp_smoke.html index e01e881..a78f4c0 100644 --- a/wasm-port/tests/browser/interp_smoke.html +++ b/wasm-port/tests/browser/interp_smoke.html @@ -338,6 +338,178 @@ ].join("\n"), ); + const browserParameterFilePath = "/work/browser-direct.var"; + interp.writeTextFile( + browserParameterFilePath, + [ + "5161 10.5", + "5162 20.25", + "5220 1", + "5221 2.25", + "5399 44", + "<_named_param> 123", + "", + ].join("\n"), + ); + verifyExpectedOutput( + "restore_parameters_direct", + interp.restoreParameters(browserParameterFilePath), + [ + "restore_parameters=0", + "parameter_5161=10.5", + "parameter_5162=20.25", + "parameter_5221=2.25", + "parameter_5399=44", + ].join("\n"), + ); + verifyExpectedOutput( + "save_parameters_direct", + interp.saveParameters(browserParameterFilePath, { + 5161: 12.34, + 5162: 56.78, + 5220: 1.0, + 5221: 9.87, + 5399: 66.6, + }), + [ + "save_parameters=0", + "parameter_5161=12.34", + "parameter_5162=56.78", + "parameter_5221=9.87", + "parameter_5399=66.6", + ].join("\n"), + ); + verifyExpectedOutput( + "saved_parameters_direct_text", + interp.readTextFile(browserParameterFilePath), + [ + "5161\t12.340000", + "5162\t56.780000", + "5221\t9.870000", + "5399\t66.600000", + "absent=<_named_param>", + ].join("\n"), + ); + verifyExpectedOutput( + "saved_parameters_direct_backup", + interp.readTextFile(`${browserParameterFilePath}.bak`), + [ + "5161 10.5", + "5162 20.25", + "5221 2.25", + "5399 44", + "<_named_param> 123", + ].join("\n"), + ); + + const browserToolTablePath = "/work/browser-direct-tool.tbl"; + interp.writeTextFile( + browserToolTablePath, + [ + "T2 P7 Z3.125 D1.5 I12 J34 Q4 ;browser direct finish tool", + "T5 P9 X1 Y2 Z3 ;browser direct rough tool", + "", + ].join("\n"), + ); + verifyExpectedOutput( + "load_tool_table_direct", + interp.loadToolTable(browserToolTablePath), + [ + "tooldata_load=0", + "tooldata_last_index=2", + "tool_1.toolno=2", + "tool_1.pocketno=7", + "tool_1.z=3.125", + "tool_1.diameter=1.5", + "tool_1.frontangle=12", + "tool_1.backangle=34", + "tool_1.orientation=4", + "tool_1.comment=browser direct finish tool", + "tool_2.toolno=5", + "tool_2.pocketno=9", + "tool_2.comment=browser direct rough tool", + "tool_index_for_tool_2=1", + ].join("\n"), + ); + verifyExpectedOutput( + "save_tool_table_direct", + interp.saveToolTable(browserToolTablePath), + [ + "tooldata_save=0", + "tool_1.toolno=2", + "tool_2.toolno=5", + ].join("\n"), + ); + verifyExpectedOutput( + "saved_tool_table_direct_text", + interp.readTextFile(browserToolTablePath), + [ + "T2", + "P7", + "Z+3.125000", + "D+1.500000", + "I+12.000000", + "J+34.000000", + "Q4", + ";browser direct finish tool", + "T5", + "P9", + ";browser direct rough tool", + ].join("\n"), + ); + + const browserRandomToolTablePath = "/work/browser-direct-random-tool.tbl"; + interp.writeTextFile( + browserRandomToolTablePath, + [ + "T2 P7 Z3.125 D1.5 I12 J34 Q4 ;browser direct random finish tool", + "T5 P9 X1 Y2 Z3 ;browser direct random rough tool", + "", + ].join("\n"), + ); + verifyExpectedOutput( + "load_tool_table_direct_random", + interp.loadToolTable(browserRandomToolTablePath, { randomToolChanger: true }), + [ + "tooldata_random_toolchanger=1", + "tooldata_load=0", + "tooldata_last_index=9", + "tool_pocket_7.toolno=2", + "tool_pocket_7.pocketno=7", + "tool_pocket_7.z=3.125", + "tool_pocket_7.diameter=1.5", + "tool_pocket_7.frontangle=12", + "tool_pocket_7.backangle=34", + "tool_pocket_7.orientation=4", + "tool_pocket_7.comment=browser direct random finish tool", + "tool_pocket_9.toolno=5", + "tool_pocket_9.pocketno=9", + "tool_pocket_9.comment=browser direct random rough tool", + "tool_index_for_tool_2=7", + ].join("\n"), + ); + verifyExpectedOutput( + "save_tool_table_direct_random", + interp.saveToolTable(browserRandomToolTablePath), + [ + "tooldata_save=0", + "tool_pocket_7.toolno=2", + "tool_pocket_9.toolno=5", + ].join("\n"), + ); + verifyExpectedOutput( + "saved_tool_table_direct_random_text", + interp.readTextFile(browserRandomToolTablePath), + [ + "T2", + "P7", + ";browser direct random finish tool", + "T5", + "P9", + ";browser direct random rough tool", + ].join("\n"), + ); + await saveMachineTextFiles("browser-interp", { ini: "[EMC]\nMACHINE = browser-interp\n", toolTable: "T2 P7 Z3.125 D1.5 I12 J34 Q4 ;browser finish tool\n",