fix(exec): prevent shared binPaths pollution across workspace runs#9650
fix(exec): prevent shared binPaths pollution across workspace runs#9650arjun-vegeta wants to merge 5 commits into
Conversation
owlstronaut
left a comment
There was a problem hiding this comment.
Thanks for digging into this, but I ran your exact repro on the branch and it still prints A bin / A bin under workspace hoisting only one shared-bin link gets created (→tool-a), so the binPaths change doesn't actually fix #9640
Fixes npm#9640 by preventing fallback to hoisted .bin directories for workspace packages.
Thanks for testing it out. The old I just pushed a complete rewrite. I dropped the The repro now outputs |
|
@owlstronaut I think the issue here is the bin-hoisting collision in hoisted mode. For that, we need only the changes from the earlier version of the PR, a6f9044. Then we can create a separate issue for bin collision. |
|
Thanks for iterating on this. A few concerns with the graph + 1. It assumes every bin is a Node script. Running the resolved bin as 2. It bypasses the hoisted 3. Same-named bins across multiple direct deps resolve non-deterministically. The first matching 4. The tests mock On scope: the |
|
Thanks for the review. I'll revert the graph walk and scope this PR back to just the |
Description:
Fixes #9640
Bug:
When running
npm execacross multiple workspaces, the binary from the first workspace would accidentally bleed into the second one if they shared the same name.Root Cause:
In
libnpmexec, thebinPathsarray was scoped at the module level instead of inside theexec()function. SinceexecWorkspacesruns everything in a single process,binPathsjust kept accumulating paths. When the second workspace ran, the first workspace's.binpath was still sitting at the front ofPATH, so it hijacked the execution.Fix:
Moved
binPathsinsideexec()so it gets a fresh array on every call. I left themanifestsmap at the module level (keyed byspec.raw) because we still want to cache registry specs across calls, and absolute paths won't collide anyway.Testing:
test/local.jswith two workspaces using the exact same local bin name (shared-bin).argsarray to stop@npmcli/run-scriptfrom mutating it and hanging the tests.