Commit Graph
2 Commits
Author SHA1 Message Date
吴佳浩Alben 007e181f68 fix(javascript): require exactly one fork IPC channel (#8017)
* fix(javascript): require exactly one fork IPC channel

Node's fork() rejects an explicit stdio array that carries more than one IPC
channel, and the throw is synchronous, before any child process exists:

    if (ArrayPrototypeFilter(options.stdio, ...'ipc').length > 1)
      throw new ERR_IPC_ONE_PIPE()

The analysis already dropped an array with no "ipc" (#7992) but still reported a
resolved fork for an array carrying it twice.

Measured on Node 24.22.1:

    fork({stdio: ["ipc", "ipc"]})                -> THROWS ERR_IPC_ONE_PIPE
    fork({stdio: ["pipe", "ipc", "ipc"]})        -> THROWS ERR_IPC_ONE_PIPE
    fork({stdio: ["ipc"]})                       -> SPAWNED connected=true
    fork({stdio: ["pipe", "ipc"]})               -> SPAWNED connected=true
    fork({stdio: ["pipe", "pipe", "pipe", "ipc"]})-> SPAWNED connected=true

So the required count is exactly one, not at least one. Count the resolved "ipc"
literals and reject the candidate unless the count is one; a spread or an
unreadable element may still change the count and is left alone, as before.

* chore: retrigger title and readiness checks after the title was corrected
2026-11-04 19:11:35 +08:00
吴佳浩Alben 2bfd84b2c8 fix(javascript): emit no fork when a literal stdio array omits the IPC channel (#7992)
* fix(javascript): emit no fork when a literal stdio array omits the IPC channel

Node's fork() requires an explicit stdio array to carry the IPC channel:

    if (!ArrayPrototypeIncludes(options.stdio, 'ipc'))
      throw new ERR_CHILD_PROCESS_IPC_REQUIRED('options.stdio')

The throw is synchronous, before any child process exists, but the analysis
reported a resolved fork with stdioMode "array" — byte-identical to the valid
`[..., "ipc"]` form — which projects to a child-process node, a resolved spawns
relation and resolved connects-stdio.

Measured on Node 24.22.1:

    fork({stdio: ["inherit","inherit","inherit"]}) -> THROWS ERR_CHILD_PROCESS_IPC_REQUIRED
    fork({stdio: ["pipe","pipe","pipe"]})          -> THROWS ERR_CHILD_PROCESS_IPC_REQUIRED
    fork({stdio: ["ipc"]})                         -> SPAWNED connected=true
    fork({stdio: ["inherit","inherit","inherit","ipc"]}) -> SPAWNED connected=true
    fork({stdio: "pipe"})                          -> SPAWNED connected=true
    spawn({stdio: ["inherit","inherit","inherit"]})-> SPAWNED connected=false

A string stdio is normalised with "ipc" appended, so only the array form can omit
it. The same array is valid for spawn, which has no IPC requirement.

Drop a fork candidate only when its stdio array is fully literal and provably
lacks "ipc"; a spread or a non-literal element may still supply the channel and
stays a candidate.

* chore: retrigger title and readiness checks after the title was corrected
2026-10-29 13:38:29 +08:00