From ed1d659074cb83f0d5607cb682fe86604d2afcc1 Mon Sep 17 00:00:00 2001 From: Kevin Buffardi Date: Sat, 1 Aug 2026 14:23:38 -0700 Subject: [PATCH] fix(firefox): require live terminal stdin --- README.md | 8 +-- docs/firefox-stdin-runtime-acceptance.md | 25 +++---- docs/release-playbook.md | 2 +- package.json | 2 +- scripts/e2e-buffered-stdin-ui.test.mjs | 25 ------- scripts/e2e-firefox-compatibility.test.mjs | 6 +- scripts/e2e-firefox-jspi-stdin.test.mjs | 6 +- scripts/e2e-run-request.test.mjs | 19 +----- scripts/e2e-terminal-stop.test.mjs | 69 ++----------------- scripts/e2e-wasi-shim.test.mjs | 66 ++---------------- src/ui/browser-capabilities.mjs | 6 +- src/ui/buffered-stdin-dialog.mjs | 78 ---------------------- src/ui/index.html | 23 ------- src/ui/styles.css | 73 -------------------- src/ui/terminal.js | 34 +++------- src/workers/compiler.worker.js | 3 - src/workers/run-request.mjs | 13 +--- src/workers/wasi-shim.mjs | 20 ------ 18 files changed, 45 insertions(+), 433 deletions(-) delete mode 100644 scripts/e2e-buffered-stdin-ui.test.mjs delete mode 100644 src/ui/buffered-stdin-dialog.mjs diff --git a/README.md b/README.md index f4f4b11..5d8eabd 100644 --- a/README.md +++ b/README.md @@ -220,8 +220,8 @@ different: - compile/run, Monaco, and extension-runtime flows are supported - Firefox 153+ uses WebAssembly JSPI for live, line-buffered `std::cin`, - `std::getline`, and `scanf` input; Firefox 140–152 (or a runtime without - JSPI) retains the pre-supplied buffered stdin fallback (up to 256 KiB) + `std::getline`, and `scanf` input; Firefox runtimes without worker-side JSPI + cannot run stdin-reading programs - file open/save and folder import use fallback browser flows rather than Chromium File System Access APIs - persistent folder write-back and directory-handle session restore may be @@ -464,7 +464,7 @@ manual/GitHub-distributed channel. signed artifact under `release/firefox-unlisted/`. 5. Install the signed XPI in Firefox and complete the manual QA checklist in `docs/firefox-stdin-runtime-acceptance.md`, paying special attention to - JSPI live stdin, its buffered fallback, and the documented + JSPI live stdin and the documented workspace-persistence limitations. ### Manual release QA checklist @@ -530,7 +530,7 @@ Copy the resulting `clang.js` and `clang.wasm` into `dist/clang/`. the UI. - **Browser scope**: Full parity targets desktop Chrome, Edge, Brave, and Chromium. Firefox 153+ supports live canonical (line-buffered) stdin through - JSPI; older supported Firefox versions use buffered stdin. This is not a raw + JSPI; older or no-JSPI Firefox runtimes cannot provide terminal stdin. This is not a raw POSIX PTY, and Firefox workspace-persistence limitations remain. Safari is outside the current release target. - **Managed browsers**: Enterprise policies that block File System Access prompts diff --git a/docs/firefox-stdin-runtime-acceptance.md b/docs/firefox-stdin-runtime-acceptance.md index e6ba980..3d290b4 100644 --- a/docs/firefox-stdin-runtime-acceptance.md +++ b/docs/firefox-stdin-runtime-acceptance.md @@ -4,10 +4,10 @@ Use this procedure to validate live JSPI terminal input from GitHub issue #55 in a real Firefox extension context. `npm run test:browser:firefox` validates packaging and manifest compatibility, but does not execute a compiled program. -Firefox 153+ should use live, canonical (line-buffered) input. Firefox 140–152, -or a runtime where JSPI is unavailable, should keep the pre-supplied buffered -fallback. Persistent folder write-back is outside this test and retains its -documented Firefox limitations. +Firefox 153+ with worker-side JSPI must use live, canonical (line-buffered) +input. A Firefox runtime where JSPI is unavailable must report stdin as +unsupported and must not open a pre-supplied-input dialog. Persistent folder +write-back is outside this test and retains its documented Firefox limitations. ## Setup @@ -55,7 +55,7 @@ int main() { 1. Choose **Compile and Run**. 2. Confirm `Name? ` appears before entering anything and that the - **Pre-supplied stdin** dialog does not open. + pre-supplied-input dialog does not open. 3. Type `Ada`, press Enter, and confirm `Age? ` appears afterward. 4. Type `41` and press Enter. 5. Confirm the final line is `Hello Ada, next year 42` and the process exits @@ -72,19 +72,14 @@ This validates two independent suspend/resume cycles and prompt ordering. 3. Run once more and complete both inputs successfully. Confirm no input from either prior run appears in the new process. -## Buffered fallback test +## Unsupported-runtime test Repeat in Firefox 140–152, or in a controlled environment where the worker does not expose both `WebAssembly.Suspending` and `WebAssembly.promising`. 1. Choose **Compile and Run**. -2. Confirm the **Pre-supplied stdin** dialog opens. -3. Enter `Ada`, a newline, `41`, and a final newline; then choose **Run - program**. -4. Confirm the same successful final output. - -The fallback must not attempt message-interactive stdin merely from the Firefox -version string or main-window capabilities. +2. Confirm no pre-supplied-input dialog opens. +3. Confirm the terminal reports that live stdin is unavailable and posts no run. ## Error exclusions @@ -107,6 +102,6 @@ Record the following in the pull request or follow-up release evidence: - exact observed prompt/output ordering - confirmation that each input was entered only after its prompt appeared - Ctrl+D, Ctrl+C, and clean-rerun results -- confirmation that the buffered dialog was absent on Firefox 153+ JSPI and - present in the no-JSPI fallback test +- confirmation that no pre-supplied-input dialog exists and no-JSPI reports + unsupported stdin - confirmation that stderr and the Browser Console had no unexpected errors diff --git a/docs/release-playbook.md b/docs/release-playbook.md index e6a4838..c230e69 100644 --- a/docs/release-playbook.md +++ b/docs/release-playbook.md @@ -88,7 +88,7 @@ real Firefox desktop build: console/runtime errors. 3. Compile and run the default sample program. 4. Complete `docs/firefox-stdin-runtime-acceptance.md`: confirm Firefox 153+ - JSPI live stdin and the older/no-JSPI buffered fallback both work without + JSPI live stdin works without SharedArrayBuffer/COOP/COEP errors. 5. Open a local source file with Firefox's fallback picker and save changes. 6. Import a folder, compile a multi-file project, and confirm diagnostics appear diff --git a/package.json b/package.json index 8cfaf64..118b91b 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "eslint .", "build": "npm run build:webpack && npm run build:targets", "build:firefox": "npm run build", - "test:e2e": "node --experimental-detect-module --test scripts/e2e-session-persistence.test.mjs scripts/e2e-session-restore-choice.test.mjs scripts/e2e-multifile-build.test.mjs scripts/e2e-workspace-file-tracking.test.mjs scripts/e2e-terminal-mkdir.test.mjs scripts/e2e-terminal-stop.test.mjs scripts/e2e-terminal-git-removal.test.mjs scripts/e2e-terminal-stop-icon.test.mjs scripts/e2e-buffered-stdin-ui.test.mjs scripts/e2e-browser-compatibility.test.mjs scripts/e2e-firefox-compatibility.test.mjs scripts/e2e-firefox-jspi-stdin.test.mjs scripts/e2e-wasi-shim.test.mjs scripts/e2e-run-request.test.mjs scripts/e2e-release-packaging.test.mjs", + "test:e2e": "node --experimental-detect-module --test scripts/e2e-session-persistence.test.mjs scripts/e2e-session-restore-choice.test.mjs scripts/e2e-multifile-build.test.mjs scripts/e2e-workspace-file-tracking.test.mjs scripts/e2e-terminal-mkdir.test.mjs scripts/e2e-terminal-stop.test.mjs scripts/e2e-terminal-git-removal.test.mjs scripts/e2e-terminal-stop-icon.test.mjs scripts/e2e-browser-compatibility.test.mjs scripts/e2e-firefox-compatibility.test.mjs scripts/e2e-firefox-jspi-stdin.test.mjs scripts/e2e-wasi-shim.test.mjs scripts/e2e-run-request.test.mjs scripts/e2e-release-packaging.test.mjs", "test:preflight-clang": "node scripts/preflight-clang-artifacts.js", "test:browser:chrome": "npm run test:preflight-clang && node scripts/smoke-browser.mjs chrome", "test:browser:edge": "npm run test:preflight-clang && node scripts/smoke-browser.mjs edge", diff --git a/scripts/e2e-buffered-stdin-ui.test.mjs b/scripts/e2e-buffered-stdin-ui.test.mjs deleted file mode 100644 index ac89b73..0000000 --- a/scripts/e2e-buffered-stdin-ui.test.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import test from 'node:test'; -import assert from 'node:assert/strict'; -import { readFile } from 'node:fs/promises'; - -test('e2e: buffered stdin dialog has accessible controls and status feedback', async () => { - const html = await readFile('src/ui/index.html', 'utf8'); - const dialog = html.match(//)?.[0]; - - assert.ok(dialog, 'buffered stdin dialog markup should exist'); - assert.match(dialog, /aria-labelledby="buffered-stdin-title"/); - assert.match(dialog, /