jsaddle-terminal: build the runner on Windows; drop the jsaddle-warp fallback - #168
Conversation
The runner was POSIX-only for two reasons: it puts its own terminal into raw mode (termios), and when no IDE answered the handshake it fell back to serving the app over jsaddle-warp. Both are now handled: - Raw mode is abstracted behind withRawMode, with a Windows implementation using the console API (SetConsoleMode: drop line/echo/processed-input, add ENABLE_VIRTUAL_TERMINAL_INPUT; enable ENABLE_VIRTUAL_TERMINAL_PROCESSING on output) — the direct analog of the termios bracket. getRunPid likewise wraps getProcessID / getCurrentProcessId. - The jsaddle-warp fallback is removed. It was the only user of jsaddle-warp / warp / websockets (and forced aeson<2.3); without an IDE there is now nothing to tunnel to, so the runner just reports that and stops. So the whole library (runner included) builds on every platform, letting an IDE like leksah host jsaddle apps in a terminal window on Windows too. Deps: aeson/stm move to the unconditional set; unix on POSIX, Win32 on Windows.
There was a problem hiding this comment.
Pull request overview
This PR makes the jsaddle-terminal runner (Language.Javascript.JSaddle.Terminal) build cross-platform by introducing a Windows console raw-mode implementation (via Win32) alongside the existing POSIX termios path, and removes the previous jsaddle-warp fallback behavior/dependency chain.
Changes:
- Add CPP-gated raw terminal mode handling: POSIX (
unix/termios) vs Windows (Win32console mode + VT input/output). - Remove the “serve via jsaddle-warp on a free port” fallback and instead report “no IDE answered” and exit.
- Update
jsaddle-terminal.cabalto expose the runner unconditionally and adjust dependencies (aeson/stmunconditional;unixvsWin32platform split).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| jsaddle-terminal/src/Language/Javascript/JSaddle/Terminal.hs | Adds cross-platform raw-mode support and removes the jsaddle-warp fallback path. |
| jsaddle-terminal/jsaddle-terminal.cabal | Exposes the runner module on all platforms and updates dependency conditionals (unix vs Win32). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| rawOut = outSaved .|. eNABLE_VIRTUAL_TERMINAL_PROCESSING | ||
| bracket_ | ||
| (setConsoleMode hIn rawIn >> setConsoleMode hOut rawOut) | ||
| (setConsoleMode hIn inSaved >> setConsoleMode hOut outSaved) | ||
| act |
There was a problem hiding this comment.
Fixed in 71c7dc2 — one bracket_ per handle, nested, so the input mode is restored even if setting the output mode throws.
| (atomically, newTChanIO, readTChan, writeTChan, TChan) | ||
| import Control.Exception (bracket_, catch, SomeException, try) | ||
| import Control.Monad (forever, void, when) | ||
| import Control.Exception (bracket_, catch, SomeException) |
There was a problem hiding this comment.
Not needed: the nested-bracket_ fix in 71c7dc2 gets the same guarantee without onException, so the import list is unchanged.
| -- The runner puts its own terminal into raw mode. On POSIX that is termios | ||
| -- (unix); on Windows it is the console API (SetConsoleMode with VT flags), | ||
| -- from Win32. The IDE-tunnel transport itself opens no sockets, so the | ||
| -- runner builds on every platform now (it used to fall back to jsaddle-warp | ||
| -- when no IDE answered — dropped, so the aeson<2.3 cap it carried is gone). | ||
| if os(windows) | ||
| build-depends: Win32 >=2.13.0.0 && <2.15 | ||
| else | ||
| build-depends: unix |
There was a problem hiding this comment.
Good catch — the description: text now says the runner reports on stderr and stops, and notes the jsaddle-warp fallback was removed (71c7dc2).
…ription Two review points from the PR: * The Windows raw-mode bracket set both console modes in one acquire action. If the second call (output mode) threw, bracket_ would not run the release action at all, leaving the user's console in raw input mode. Use one bracket per handle, nested, so the input mode is always restored. * The package description still advertised the jsaddle-warp fallback this branch removes.
|
Addressed the review in 71c7dc2:
Verification: |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (1)
jsaddle-terminal/src/Language/Javascript/JSaddle/Terminal.hs:172
- This comment still refers specifically to a "raw-termios bracket", but the raw-mode wrapper is now cross-platform (termios on POSIX, console mode on Windows). Updating this wording avoids misleading readers about what
tunnelassumes.
-- | The tunnel session, inside the raw-termios bracket.
|
Also took the suppressed nit from the second pass: |
Follow-up to #167. Makes the
jsaddle-terminalrunner (Language.Javascript.JSaddle.Terminal) build on every platform, so an IDE like leksah can host jsaddle apps in a terminal window on Windows too — not just link the pureProtocol/Bootstrapmodules there.The runner was POSIX-only for two reasons; both are addressed:
Raw terminal mode → cross-platform
The runner puts its own controlling terminal into raw mode to read keystrokes byte-by-byte (no echo/line-buffering,
ISIGoff so Ctrl-C arrives as raw0x03). That was termios (unix). It's now behindwithRawMode, with a Windows implementation using the console API —SetConsoleModeclearingENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUTand settingENABLE_VIRTUAL_TERMINAL_INPUT(keys arrive as VT escape sequences, matching the existing reader), plusENABLE_VIRTUAL_TERMINAL_PROCESSINGon output. Both modes are saved and restored.getRunPidlikewise wrapsgetProcessID/getCurrentProcessId. All from theWin32package — no C shim.Drop the jsaddle-warp fallback
When no IDE answered the handshake the runner used to serve the app over
jsaddle-warpon a free port. That was the only user ofjsaddle-warp/warp/websockets, and it forcedaeson < 2.3. It's removed: without an IDE there's now nothing to tunnel to, so the runner reports that and stops. Dropping it frees theaesonbound and is what lets the runner build on Windows without dragging that dependency tree onto the mingw cross.cabal
The runner module and
aeson/stmmove to the unconditional set; the platform split is justunix(POSIX) vsWin32 >=2.13(Windows). Demo/test stanzas are unchanged (still off by default / non-Windows).Testing
x86_64-w64-mingw32via haskell.nix —jsaddle-terminallibrary (runner included) and, as a consumer, leksah'sleksah-webview2.exelink cleanly.