Skip to content

Spawn vp-managed package managers via node <pm>.cjs directly to remove the Windows .cmd/.ps1 shim hazards #1971

Description

@fengmk2

Summary

Proposal: invoke vp-managed package managers (and npm/npx) by spawning the real JS entry with the managed Node directly (node <pm>.cjs <args>), instead of resolving to the Windows .cmd shim and then routing through PowerShell. This removes the root cause behind both the Ctrl+C terminal corruption and the CI stdin hang in every stdio configuration, and drops the PowerShell dependency.

Background

Why the current approach has structural limits

  • It couples two unrelated concerns through a heuristic: terminal Ctrl+C corruption is a console property, but it is gated on stdin TTY-ness.
  • It keeps a hard dependency on PowerShell being present plus -ExecutionPolicy Bypass for the interactive path.
  • It still leaves the cmd.exe corruption in place for non-TTY-but-console cases (e.g. vp install < input.txt from a real terminal).

Proposal: bypass the shims for vp-managed binaries

vp already has everything needed to skip the shim layer for the binaries it manages:

  • The installer writes the real JS entry next to the shims (crates/vite_install/src/package_manager.rs, crates/vite_install/src/shim.rs): <pm>.cjs, <pm>.cmd, and <pm>.ps1 all just run node <pm>.cjs, e.g. $VP_HOME/package_manager/pnpm/<ver>/pnpm/bin/pnpm.cjs.
  • vp ships its own Node: $VP_HOME/js_runtime/node/<ver>/node(.exe).

So for the managed scope, spawn:

$VP_HOME/js_runtime/node/<ver>/node(.exe)   .../pnpm/bin/pnpm.cjs   <args>

This is byte-for-byte what the shims do internally, minus the wrapper.

Benefits:

  • No cmd.exe, so no Ctrl+C "Terminate batch job (Y/N)?" corruption, in every stdio config.
  • No .ps1, so no $MyInvocation.ExpectingInput stdin hang, in every stdio config.
  • No PowerShell dependency or execution-policy concerns.
  • Removes the TTY heuristic for this path; identical behavior in CI and interactive. vp keeps full control of stdio inheritance and signal handling (execute_with_terminal_guard, fix_stdio_streams).

Scope and fallback

Apply this only to what vp owns (the $VP_HOME managed shims: package managers plus npm/npx under js_runtime), where the .cjs target is known. For arbitrary third-party node_modules/.bin/*.cmd, parsing the shim to find the node target is more involved, so the existing TTY-gated PowerShell rewrite in ps1_shim.rs can stay as the fallback there. Net result: the highest-value path (the package-manager invocation that caused the CI hang) becomes bulletproof, and the general case keeps today's behavior.

Implementation sketch

  • In crates/vite_command/src/lib.rs resolve_program (or a layer above it): when the resolved bin is a vp-managed PM / npm / npx shim, resolve to the sibling <name>.cjs plus the managed node, and return (node_path, [cjs_path, ...args]) instead of the .cmd / PowerShell rewrite.
  • Keep ps1_shim::rewrite_cmd_to_powershell for the node_modules/.bin/* fallback.

Notes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Fields

Priority

None yet

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions