Skip to content

node:child_process largely stubbed — 52 radar tests fail with 'value is not a function' #1780

Closed

Description

@proggeramlug

Summary

node:child_process is largely stubbed — 52 of ~74 judged tests fail at runtime with value is not a function (Perry resolves a child_process method to a non-callable stub, then the test calls it).

Examples: test-child-process-default-options.js, test-child-process-destroy.js, test-child-process-advanced-serialization-*.js.

What to do

Audit the child_process surface (spawn/exec/execFile/fork/spawnSync/...) — the 52 failures indicate most entry points return stubs rather than working implementations. File sub-tickets per method family once the surface is mapped, or implement the core spawn/exec path first (most tests bottom out there).

Note: some child_process tests are also in the feature-link-artifact bucket (#1778) — confirm linkage before attributing a failure to a missing impl.

Context: full #800 radar sweep (1300 judged), perry 0.5.1028.

Activity

  1. added
    bugConfirmed defect or regression
    parityCompatibility gap with Node.js, ECMAScript, or the supported ecosystem
    on May 25, 2026
  2. proggeramlug commented on May 26, 2026

    @proggeramlug
    ContributorAuthor

    Partial fix in #1827 (PR), plus scope mapping:

    Fixed: child_process.exec(cmd[, options], callback) — js_child_process_exec was a null stub and the codegen lowered the callback then discarded it, so exec(cmd, cb) never fired its callback. exec now runs the command (shell, like execSync) and invokes the callback with (err, stdout, stderr) (immediate-callback model, same as the async fs wrappers). The callback is located whether it sits in the options slot (exec(cmd, cb)) or the third slot (exec(cmd, options, cb)); non-zero exit yields an Error; the no-callback form still returns the stdout string. execSync / spawnSync already worked.

    Still open — the larger part of this ticket: the dominant node-core child_process pattern is the streaming API:

    const child = spawn(cmd, args);
    child.stdout.on('data', d => …);   // child.stdout is currently a string → "(string).on is not a function"
    child.on('exit'|'close'|'error', …);

    js_child_process_spawn / exec (the streaming forms) are explicit null-returning stubs ("needs event loop integration"). A real ChildProcess object — stdout/stderr as Readable streams, stdin Writable, EventEmitter (spawn/exit/close/error/message), pid/kill(), and IPC for fork — is a sizeable feature requiring subprocess + event-loop integration. Most of the 52 radar fails bottom out there. Suggest splitting that into its own ticket (spawn-with-streams) and keeping this for the audit.

  3. proggeramlug commented on May 27, 2026

    @proggeramlug
    ContributorAuthor

    Knocked out the remaining easy stubs in PR #1926 (runtime-only):

    • Options were ignored — spawn/exec/execFile/execFileSync/spawnSync/execSync now honor { cwd, env, shell } (the options pointer was already threaded to js_child_process_spawn_streams, just never read). env replaces the environment wholesale per Node semantics; shell:true/shell:"<path>" joins command+args into a <shell> -c line.
    • Listener removal was a no-op — removeListener/off now rebuild the listener array without the matching closure; removeAllListeners([event]) clears one event or all.

    New test_issue_1780_options.ts is byte-identical to node --experimental-strip-types. The follow-ups #1856 (ChildProcess/Stream exports) and #1857 (promisify exec/execFile) closed via #1861.

    Still open (the large remaining piece): fork + IPC (send/disconnect/'message', channel/connected semantics). Perry has no async subprocess reactor, so a real fork needs subprocess + event-loop integration — worth its own ticket rather than folding into this one. Leaving #1780 open to track that.

  4. proggeramlug commented on May 27, 2026

    @proggeramlug
    ContributorAuthor

    The original failure cluster here — 52 radar tests failing with value is not a function because spawn()'s .stdout was a string — is fixed: streaming spawn() (#1858), exec callback (#1828), execFile/execFileSync (#1858), ChildProcess/Stream exports + promisify(exec/execFile) (#1861, closing #1856/#1857), and cwd/env/shell options + listener removal (#1926). test_parity_child_process is byte-identical to Node and out of known_failures.json.

    The remaining surface is split into granular tickets (per the "no umbrella issues" preference) and this umbrella is closed:

    Closing in favor of those.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regressionparityCompatibility gap with Node.js, ECMAScript, or the supported ecosystem

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions