Skip to content

node:child_process: expose _forkChild IPC bootstrap helper #2717

Closed

Description

@andrewtdiz

Summary

Node exposes child_process._forkChild(fd, serializationMode) as an enumerable function on the node:child_process namespace. Perry's child-process surface now includes fork() and IPC-related work, but _forkChild itself is absent from the manifest, generated declarations, and native namespace callable list.

This is an internal/legacy export, but it is part of Node's observable Object.keys(require("node:child_process")) surface and is used by Node's child-process IPC bootstrap path to install process.send() / channel handling in forked children.

Expected Node behavior

With Node v25.9.0:

const cp = require("node:child_process");

console.log(Object.keys(cp)); // includes "_forkChild"
console.log(Object.prototype.propertyIsEnumerable.call(cp, "_forkChild")); // true
console.log(typeof cp._forkChild); // "function"
console.log(cp._forkChild.length); // 2
console.log(cp._forkChild.name); // "_forkChild"

Calling the helper participates in Node's IPC child bootstrap and expects an IPC fd plus serialization mode; invalid direct calls throw from that bootstrap path rather than resolving to undefined.

Current Perry evidence

On origin/main:

I did not use a current-tree target/release/perry binary for this check; this is Node-probe plus current source evidence.

Suggested test surface

Add a small shape fixture under test-parity/node-suite/child_process/:

import * as cp from "node:child_process";

console.log("_forkChild enumerable:", Object.prototype.propertyIsEnumerable.call(cp, "_forkChild"));
console.log("_forkChild type:", typeof cp._forkChild);
console.log("_forkChild length:", cp._forkChild?.length);
console.log("_forkChild name:", cp._forkChild?.name);

If a minimal implementation is added before full IPC bootstrap behavior, the fixture can stay shape-only and a follow-up can cover valid fd/serialization behavior.

Scope / non-goals

  • Scope: expose the enumerable _forkChild function shape on the child_process namespace, generated declarations/reference docs, and captured-property reads.
  • Scope: eventually route valid calls into the child IPC bootstrap path if Perry needs parity for Node forked-child startup.
  • Non-goal: changing child_process.fork() lifecycle behavior or spawn/exec option semantics (node:child_process: honor spawn and exec option semantics beyond cwd/env/shell #2555).
  • Non-goal: reintroducing child_process.Stream; current source comments correctly note Node returns undefined for that name in current Node.

Activity

  1. andrewtdiz commented on Jun 2, 2026

    @andrewtdiz
    ContributorAuthor

    Taking this with #2556 and #3316 as a focused node:child_process lifecycle/IPC surface PR cut. Planned scope: ChildProcess Symbol.dispose dispatch, _forkChild enumerable export shape, and subprocess.send callback/closed-channel observable semantics. Non-goals: broad spawn/exec option semantics (#2555), setup arg validation (#3079), and child-side process IPC surface (#2529) unless a minimal helper is required for the selected tests.

  2. andrewtdiz commented on Jun 2, 2026

    @andrewtdiz
    ContributorAuthor

    Implemented in draft PR #4110.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions