#54861: test: use precise GC for utility process observer regression
Description of Change
Make the utility-process stale-observer regression's collection check deterministic with respect to native stack scanning, while retaining the assertions that the first crashed process is collected and a subsequent crash is reported.
- Await the existing precise asynchronous GC helper instead of synchronous GC, which conservatively scans the native stack and can retain an otherwise unreachable wrapper through stale pointers.
- Retain only a
WeakRefto the first child and keep the event-loop boundary before each collection attempt. - Use a unique service name per test attempt so unrelated processes and late notifications from prior attempts cannot satisfy its crash waits.
- Defer removal of crash listeners so a failed or timed-out attempt does not leave them behind.
- Keep the existing timeout and collection-attempt bound, and give collection failures an explicit assertion message.
Only spec/api-utility-process.spec.ts changes; there are no production-code or API changes.
Affected release branches: current upstream 45-x-y, 44-x-y, 43-x-y, and 42-x-y all contain the same synchronous collection loop, shared default service name, and crash-wait helper without teardown cleanup. All four already provide the precise asynchronous GC helper and its TypeScript overload. Backports to 42-x-y and 43-x-y must preserve their existing Windows 32-bit test skip. This assessment is based on source inspection, not release-branch execution.
42-x-y near-EOL scope: This target is retained only for a nearly-zero release/runtime-risk, test-only backport. The regression body and crash-wait helper match pre-fix main, and the precise GC helper, types, and deferred cleanup already exist on 42-x-y. Preserve its Windows 32-bit skip; do not add production changes, new helpers, or broader test cleanup to make this backport work. If those become necessary, drop the 42-x-y target. Release-branch CI is still required before merging a backport.
Validation (Linux, existing local Testing build):
- Unchanged baseline: 11/11 isolated executions passed; the original Windows failure was not reproduced locally.
- Updated exact regression: 100/100 independent executions passed through the normal Vitest/Electron runner, with retries disabled and exactly one passing test verified per repetition.
- Combined neighboring utility-process lifecycle, app crash-notification, and native-heap tests: 31 passed across two spec files.
- Targeted JavaScript lint, formatting, spec TypeScript check, and
git diff --checkpassed. Commit hooks also passed.
Exact regression command, repeated 100 times from the repository root:
env -u CI ELECTRON_OUT_DIR=Testing node script/spec-runner.js \
--skipYarnInstall --files spec/api-utility-process.spec.ts \
-g 'does not keep stale observers for crashed processes without JS references'Neighboring coverage:
env -u CI ELECTRON_OUT_DIR=Testing node script/spec-runner.js \
--skipYarnInstall --files spec/api-utility-process.spec.ts spec/cpp-heap.spec.ts \
-g 'utilityProcess module.*(lifecycle events|child-process-gone|should)'Windows x64/ARM64 validation is still required; Linux success does not establish that the Windows timeout signature is resolved. Native-addon tests gated by --skipYarnInstall were not part of this validation. The full test suite was not run.
Checklist
- I have tested this test-only change against an existing local build; no native rebuild was needed
- I have filled out the PR description
- I have reviewed and verified the changes (human author confirmation)
-
npm testpasses (full suite not run; targeted results above) - tests are changed or added
- PR release notes are omitted because this is a test-only change
Release Notes
Notes: none
Backports
Semver Impact
Semantic Versioning helps users understand the impact of updates:
- Major (X.y.z): Breaking changes that may require code modifications
- Minor (x.Y.z): New features that maintain backward compatibility
- Patch (x.y.Z): Bug fixes that don't change the API
- None: Changes that don't affect using facing parts of Electron