Skip to content

Upgrade bufout to v1.0.0 and remove EventEmitter listener limits - #438

Merged
kraenhansen merged 2 commits into
nextfrom
claude/bufout-1-0-0-upgrade-ey2dje
Aug 13, 2026
Merged

Upgrade bufout to v1.0.0 and remove EventEmitter listener limits#438
kraenhansen merged 2 commits into
nextfrom
claude/bufout-1-0-0-upgrade-ey2dje

Conversation

@kraenhansen

Copy link
Copy Markdown
Collaborator

Summary

Upgrades bufout to v1.0.0, which implements efficient listener management for concurrent child process spawning. This eliminates the need to raise EventEmitter.defaultMaxListeners to 100 across the CLI packages.

Changes

  • Dependency upgrade: Updated bufout from ^0.3.2 to ^1.0.0 in @react-native-node-api/cli-utils
  • Removed EventEmitter configuration: Deleted EventEmitter.defaultMaxListeners = 100 assignments from:
    • packages/ferric/src/run.ts
    • packages/cmake-rn/src/cli.ts
    • packages/host/src/node/cli/program.ts
  • Removed unused imports: Cleaned up now-unnecessary EventEmitter imports from the above files

Implementation Details

The new version of bufout uses a shared pass-through stream per destination and attaches a single shared exit/SIGINT listener only while children are running. This keeps the number of listeners constant regardless of concurrent child process count, restoring Node's default listener limit and re-enabling the leak detection warning it provides.

https://claude.ai/code/session_01BAjP89a9VA9EtQsVBxGcto

@kraenhansen kraenhansen added Apple 🍎 Anything related to the Apple platform (iOS, macOS, Cocoapods, Xcode, XCFrameworks, etc.) Android 🤖 Anything related to the Android platform (Gradle, NDK, Android SDK) Ferric 🦀 labels Aug 13, 2026 — with Claude
@kraenhansen kraenhansen self-assigned this Aug 13, 2026

Copy link
Copy Markdown
Collaborator Author

Merged next in to pick up #432 — the iOS run on the previous head failed for a reason unrelated to this diff.

What failed: Test app (iOS) built fine and got through buffers and async, then the app hard-crashed right after loading threadsafe-function-test--addon (DISCONNECTION for no particular reason (code = 1006)).

Why it isn't this PR: bufout is host-side build tooling — it spawns cmake/xcodebuild on the runner and never ends up in the app binary, so it can't affect simulator runtime behaviour. The build itself succeeded and every addon loaded.

What it actually is: this branch was based on c73d30c, four commits behind next. #432 (715a24e), merged since, describes precisely this symptom:

node-addon-api's tsfn error path (which calls napi_fatal_exception whenever an exception escapes a thread-safe-function callback) [had] no chance of being observed or handled — a single throwing tsfn callback hard-killed the app

That PR notes it wasn't exercised on-device, so this run is likely the first device coverage it gets. Treating the merge as the fix is a hypothesis, not a confirmed one — if iOS stays red on the new head, the failure is pre-existing on next and belongs in its own issue rather than in a dependency bump.

Labels Apple 🍎 / Android 🤖 / Ferric 🦀 are attached deliberately: those jobs are the only place the changed spawn machinery runs real concurrent builds.


Generated by Claude Code

claude added 2 commits August 13, 2026 11:44
bufout v1.0.0 keeps the number of listeners on the process and on the
output streams constant regardless of how many children are spawned
concurrently: a single shared exit/SIGINT listener is attached only while
children are running, and every child pipes into one shared pass-through
per destination stream.

That removes the reason the CLIs raised EventEmitter.defaultMaxListeners
to 100, so those assignments (and the now-unused node:events /
node:stream imports) are gone and Node's default limit applies again,
restoring the leak warning it exists to give.

Verified with 80 concurrent children in both "inherit" and "buffered"
mode, plus the SpawnFailure flush path, at the default limit of 10: no
MaxListenersExceededWarning, and process listener counts return to zero.

The public API is unchanged from 0.3.x — the major bump reflects the
1.0.0 milestone, not a breaking change to spawn/SpawnFailure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAjP89a9VA9EtQsVBxGcto
The Check workflow only runs on opened/synchronize/reopened, so the
Apple/Android/Ferric jobs gated on labels never evaluated the labels
added after the pull request was opened. This empty commit fires a
synchronize event so they run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BAjP89a9VA9EtQsVBxGcto
@kraenhansen
kraenhansen force-pushed the claude/bufout-1-0-0-upgrade-ey2dje branch from cc78aee to debfe4c Compare August 13, 2026 11:44
@kraenhansen
kraenhansen merged commit 48fa7fc into next Aug 13, 2026
16 checks passed
@kraenhansen
kraenhansen deleted the claude/bufout-1-0-0-upgrade-ey2dje branch August 13, 2026 12:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Android 🤖 Anything related to the Android platform (Gradle, NDK, Android SDK) Apple 🍎 Anything related to the Apple platform (iOS, macOS, Cocoapods, Xcode, XCFrameworks, etc.) Ferric 🦀

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants