fix(trace): make ?trace= work by merging Module.ENV in the glue
The emscripten glue's `var ENV = {};` never merged Module.ENV, so boot.ts's
Module.ENV.KICAD_TRACE was a silent no-op — and since environ_get on a pthread
proxies to the main thread, the app/UI thread's getenv read the (empty) main
ENV. Net: KICAD_TRACE never arrived and every KI_TRACE was a no-op.
scripts/common/patch-env-shim.mjs post-processes each generated <app>.js to
merge Module.ENV into ENV (idempotent; runtime no-op when unset), wired into
docker/build.sh's per-app host post-process next to the dyncall-shim inject.
Replaces a fragile manual glue edit re-applied after every build. Verified:
symbol-editor eager load now emits KI_TRACE_SYM_CHOOSER fatLoad timing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
88aaba99c9
commit
89a433fda9
3 changed files with 69 additions and 3 deletions
|
|
@ -266,6 +266,13 @@ postprocess_app() {
|
|||
kw_stage dyncall-shims
|
||||
./scripts/common/inject-dyncall-shims.sh "${out_dir}/${app}.js"
|
||||
|
||||
# Merge Module.ENV into the runtime ENV: the emscripten glue never merges it,
|
||||
# so ?trace= (boot.ts sets Module.ENV.KICAD_TRACE) was a silent no-op —
|
||||
# environ_get on the app pthread proxies to the main thread, whose ENV stayed
|
||||
# empty. Replaces a manual per-build glue edit. Idempotent; runtime no-op when
|
||||
# Module.ENV is unset. See docs/features/libs/0013.
|
||||
node ./scripts/common/patch-env-shim.mjs "${out_dir}/${app}.js"
|
||||
|
||||
# Apply wasm-emscripten-finalize on host (skipped in Docker due to memory limits)
|
||||
kw_stage finalize
|
||||
./scripts/common/apply-finalize.sh "${out_dir}/${app}.wasm" "${out_dir}/${app}.wasm"
|
||||
|
|
|
|||
56
scripts/common/patch-env-shim.mjs
Normal file
56
scripts/common/patch-env-shim.mjs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// Patch an emscripten glue `<app>.js` so the runtime `ENV` merges `Module.ENV`.
|
||||
//
|
||||
// Why: emscripten's generated glue does `var ENV = {};` and (in this toolchain)
|
||||
// never merges the caller's `Module.ENV`, so setting `Module.ENV` from JS is a
|
||||
// silent no-op. The standalone's boot.ts uses `Module.ENV.KICAD_TRACE` to drive
|
||||
// the `?trace=` profiling harness. Crucially, `_environ_get` on a pthread PROXIES
|
||||
// TO THE MAIN THREAD, so `getenv()` on the app pthread reads the MAIN thread's
|
||||
// `ENV` via `getEnvStrings()` — which stays empty without this merge. Result:
|
||||
// `KICAD_TRACE` never reaches `TRACE_MANAGER`, and every `KI_TRACE(...)` is a
|
||||
// silent no-op. Merging `Module.ENV` makes `?trace=` (and any future Module.ENV
|
||||
// use) actually work. Safe no-op when `Module.ENV` is unset (normal boots).
|
||||
//
|
||||
// This replaces a fragile manual edit that had to be re-applied to the generated
|
||||
// glue after every build (docs/features/libs/0013). Idempotent; run per app in
|
||||
// the build's host post-process. Usage: node patch-env-shim.mjs <file.js> [...]
|
||||
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
|
||||
// Guard on `typeof Module` (glue-local on main; undefined in some worker realms —
|
||||
// harmless there, since environ_get proxies to main anyway). Marker keeps it
|
||||
// idempotent and lets the region-replace below re-normalize a prior insert.
|
||||
const SHIM =
|
||||
'try { if (typeof Module !== "undefined" && Module && Module.ENV)' +
|
||||
" for (var _k in Module.ENV) ENV[_k] = Module.ENV[_k]; }" +
|
||||
" catch (e) {} /*PCBJAM_ENV_SHIM*/";
|
||||
|
||||
// Match `var ENV = {};` plus whatever sits between it and the next glue function
|
||||
// (`var getExecutableName`), so re-running normalizes an earlier insert instead
|
||||
// of stacking. The `getExecutableName` anchor is stable across emscripten builds.
|
||||
const REGION = /var ENV = \{\};[\s\S]*?\n(?=var getExecutableName)/;
|
||||
|
||||
let failed = 0;
|
||||
for (const file of process.argv.slice(2)) {
|
||||
let src;
|
||||
try {
|
||||
src = readFileSync(file, "utf8");
|
||||
} catch (e) {
|
||||
console.error(`[env-shim] cannot read ${file}: ${e.message}`);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
if (!REGION.test(src)) {
|
||||
console.error(`[env-shim] no \`var ENV = {};\` anchor in ${file} — skipped`);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
const patched = src.replace(REGION, `var ENV = {};\n${SHIM}\n\n`);
|
||||
if (patched === src) {
|
||||
console.log(`[env-shim] ${file} already current`);
|
||||
continue;
|
||||
}
|
||||
writeFileSync(file, patched);
|
||||
console.log(`[env-shim] patched ${file}`);
|
||||
}
|
||||
|
||||
process.exit(failed ? 1 : 0);
|
||||
|
|
@ -190,9 +190,12 @@ async function doBoot(opts: BootOptions): Promise<void> {
|
|||
|
||||
// Dev/diagnostics: ?trace=<KICAD_TRACE mask> turns on a KiCad trace channel for
|
||||
// this boot (e.g. ?trace=KI_TRACE_SYM_CHOOSER for symbol-chooser timing). Set on
|
||||
// the page's Module.ENV (main thread) AND seeded into each pthread worker via
|
||||
// pthreadWorkerScript (the app/UI thread under PROXY_TO_PTHREAD); the glue's
|
||||
// ENV-merge shim feeds it into the C environ that wxGetEnv reads.
|
||||
// the page's Module.ENV (main thread). Under PROXY_TO_PTHREAD the app/UI thread
|
||||
// is a pthread, but `environ_get` on a pthread proxies to the MAIN thread — so
|
||||
// the main thread's ENV is what `getenv("KICAD_TRACE")` reads. The build's
|
||||
// patch-env-shim.mjs makes the glue merge Module.ENV into that ENV (emscripten's
|
||||
// glue otherwise ignores Module.ENV); the per-worker seed below is a harmless
|
||||
// belt-and-suspenders. See docs/features/libs/0013.
|
||||
const traceMask = new URLSearchParams(window.location.search).get("trace");
|
||||
|
||||
// libs: install the provider (must exist before any plugin call can suspend
|
||||
|
|
|
|||
Loading…
Reference in a new issue