125 lines
6.4 KiB
Bash
Executable File
125 lines
6.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")"
|
|
|
|
# LinuxCNC source basis: this guard ties the browser app entry point to
|
|
# LinuxCNC RS274 parameter-file defaults, rs274ngc_pre.cc restore/save/read
|
|
# file semantics, and the existing OPFS-backed wasm-core bridge. It validates
|
|
# app integration policy only; it does not add CNC behavior or expand smoke
|
|
# parsing, or interpret G-code.
|
|
linuxcnc_root=${LINUXCNC_ROOT:-../linuxcnc}
|
|
linuxcnc_root=$(cd "$linuxcnc_root" && pwd)
|
|
|
|
grep -F '#define RS274NGC_PARAMETER_FILE_NAME_DEFAULT "rs274ngc.var"' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
|
grep -F '#define RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX ".bak"' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/interp_internal.hh" >/dev/null
|
|
grep -F 'int Interp::restore_parameters(const char *filename)' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
|
grep -F 'int Interp::save_parameters(const char *filename,' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
|
grep -F 'std::string tempfile = std::string(filename) + ".new";' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
|
grep -F '+ RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX;' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
|
grep -F 'unlink(bakfile.c_str());' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
|
grep -F 'if(link(filename, bakfile.c_str()) < 0)' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
|
grep -F 'if(rename(tempfile.c_str(), filename) < 0)' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
|
grep -F 'read_text(command, _setup.file_pointer, _setup.linetext,' \
|
|
"$linuxcnc_root/src/emc/rs274ngc/rs274ngc_pre.cc" >/dev/null
|
|
|
|
grep -F 'LinuxCNC browser app source map' docs/linuxcnc-browser-app-source-map.md >/dev/null
|
|
grep -F 'must not add CNC behavior' docs/linuxcnc-browser-app-source-map.md >/dev/null
|
|
grep -F 'must not expand the temporary smoke parser' docs/linuxcnc-browser-app-source-map.md >/dev/null
|
|
grep -F '`RS274NGC_PARAMETER_FILE_NAME_DEFAULT` as `rs274ngc.var`' \
|
|
docs/linuxcnc-browser-app-source-map.md >/dev/null
|
|
grep -F '`parseFileWithParameterFile(programPath, parameterPath, "linuxcnc", ...)`' \
|
|
docs/linuxcnc-browser-app-source-map.md >/dev/null
|
|
grep -F 'orders parameter saves as backup unlink' \
|
|
docs/linuxcnc-browser-app-source-map.md >/dev/null
|
|
|
|
grep -F '<script type="module" src="/src/app.js"></script>' web/index.html >/dev/null
|
|
grep -F '<option value="linuxcnc-rs274">LINUXCNC</option>' web/index.html >/dev/null
|
|
if [[ "$(grep -Fc '<option value=' web/index.html)" -ne 1 ]]; then
|
|
echo "browser app backend selector must expose only the LinuxCNC RS274 backend" >&2
|
|
exit 1
|
|
fi
|
|
|
|
grep -F 'import { createWasmSimulator } from "./wasm-core.js";' web/src/app.js >/dev/null
|
|
grep -F 'const programPath = "programs/current.ngc";' web/src/app.js >/dev/null
|
|
grep -F 'const linuxCncParameterFileName = "rs274ngc.var";' web/src/app.js >/dev/null
|
|
grep -F 'const parameterPath = `parameters/${linuxCncParameterFileName}`;' web/src/app.js >/dev/null
|
|
grep -F 'const linuxCncBackend = "linuxcnc-rs274";' web/src/app.js >/dev/null
|
|
grep -F 'const opfsOptions = { required: true, mountPoint: "/cnc", workspacePath: "cnc-simulator" };' \
|
|
web/src/app.js >/dev/null
|
|
grep -F 'simulatorPromise = createWasmSimulator({' web/src/app.js >/dev/null
|
|
grep -F 'opfs: opfsOptions,' web/src/app.js >/dev/null
|
|
grep -F 'OPFS workspace is required for browser program parsing' web/src/app.js >/dev/null
|
|
grep -F 'await simulator.fs.opfs.writeFile(programPath, elements.input.value);' web/src/app.js >/dev/null
|
|
grep -F 'const events = await simulator.parseFileWithParameterFile(programPath, parameterPath, "linuxcnc", parseOptions);' \
|
|
web/src/app.js >/dev/null
|
|
grep -F 'elements.backendSelect.value = linuxCncBackend;' web/src/app.js >/dev/null
|
|
grep -F 'globalThis.__cncSimulatorForTest = simulatorPromise;' web/src/app.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 state into OPFS' \
|
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
|
grep -F 'app frame did not persist LinuxCNC parameter backup into OPFS' \
|
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
|
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 PROGRAM RESTORED' web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
|
grep -F 'app frame did not reload LinuxCNC parameter state from OPFS after reload' \
|
|
web/test-browser-wasm-smoke-app-sections.js >/dev/null
|
|
grep -F 'runSection("browser app opfs save"' test-web-wasm-browser-smoke.sh >/dev/null
|
|
grep -F 'runSection("browser app opfs restore"' test-web-wasm-browser-smoke.sh >/dev/null
|
|
|
|
if grep -R -n -E 'localStorage|sessionStorage|indexedDB|showOpenFilePicker|showSaveFilePicker|showDirectoryPicker|webkitRequestFileSystem|FileReader' web/src; then
|
|
echo "browser app/wasm code must not add filesystem persistence outside OPFS" >&2
|
|
exit 1
|
|
fi
|
|
|
|
python3 - <<'PY'
|
|
from pathlib import Path
|
|
|
|
source_map = Path("docs/linuxcnc-browser-app-source-map.md").read_text(encoding="utf-8")
|
|
for entry in [
|
|
"web/index.html",
|
|
"web/src/app.js",
|
|
"web/test-browser-wasm-smoke-app-sections.js",
|
|
]:
|
|
if f"| `{entry}` |" not in source_map:
|
|
raise SystemExit(f"docs/linuxcnc-browser-app-source-map.md missing app entry: {entry}")
|
|
|
|
for phrase in [
|
|
"must not add CNC behavior",
|
|
"must not expand the temporary smoke parser",
|
|
"existing `createWasmSimulator()` OPFS API",
|
|
"programs/current.ngc",
|
|
"parameters/rs274ngc.var",
|
|
"visible backend selector must stay limited",
|
|
"./check-linuxcnc-browser-app-source-map.sh",
|
|
"does not interpret G-code",
|
|
]:
|
|
if phrase not in source_map:
|
|
raise SystemExit(f"docs/linuxcnc-browser-app-source-map.md missing boundary phrase: {phrase}")
|
|
|
|
for entry in [
|
|
"test-native.sh",
|
|
"test-linuxcnc-source-link.sh",
|
|
"build-wasm.sh",
|
|
]:
|
|
text = Path(entry).read_text(encoding="utf-8")
|
|
if "./check-linuxcnc-browser-app-source-map.sh" not in text:
|
|
raise SystemExit(f"{entry} must run ./check-linuxcnc-browser-app-source-map.sh")
|
|
|
|
app = Path("web/src/app.js").read_text(encoding="utf-8")
|
|
if "parse(" in app.replace("parseProgram", ""):
|
|
raise SystemExit("browser app should route program execution through parseFileWithParameterFile, not direct parse")
|
|
PY
|