repl: remove dependency on domain module#61227
Conversation
Replace the domain-based error handling with AsyncLocalStorage and setUncaughtExceptionCaptureCallback. This removes the REPL's dependency on the deprecated domain module while preserving all existing behavior: - Synchronous errors during eval are caught and displayed - Async errors (setTimeout, promises, etc.) are caught via the uncaught exception capture callback - Top-level await errors are caught and displayed - The REPL continues operating after errors - Multiple REPL instances can coexist with errors routed correctly Changes: - Use AsyncLocalStorage to track which REPL instance owns an async context, replacing domain's automatic async tracking - Add setupExceptionCapture() to install setUncaughtExceptionCaptureCallback for catching async errors and routing them to the correct REPL - Extract error handling logic into REPLServer.prototype._handleError() - Wrap eval execution in replContext.run() for async context tracking - Update newListener protection to check AsyncLocalStorage context - Throw ERR_INVALID_ARG_VALUE if options.domain is passed PR-URL: nodejs#61227
6ef82e6 to
e86555a
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #61227 +/- ##
==========================================
+ Coverage 89.64% 89.66% +0.01%
==========================================
Files 676 676
Lines 206330 206390 +60
Branches 39518 39531 +13
==========================================
+ Hits 184973 185052 +79
+ Misses 13480 13464 -16
+ Partials 7877 7874 -3
🚀 New features to boost your workflow:
|
|
@nodejs/tsc this needs more reviews |
|
There are linter and test failures to address |
Replace the domain-based error handling with AsyncLocalStorage and setUncaughtExceptionCaptureCallback. This removes the REPL's dependency on the deprecated domain module while preserving all existing behavior: - Synchronous errors during eval are caught and displayed - Async errors (setTimeout, promises, etc.) are caught via the uncaught exception capture callback - Top-level await errors are caught and displayed - The REPL continues operating after errors - Multiple REPL instances can coexist with errors routed correctly Changes: - Use AsyncLocalStorage to track which REPL instance owns an async context, replacing domain's automatic async tracking - Add setupExceptionCapture() to install setUncaughtExceptionCaptureCallback for catching async errors and routing them to the correct REPL - Extract error handling logic into REPLServer.prototype._handleError() - Wrap eval execution in replContext.run() for async context tracking - Update newListener protection to check AsyncLocalStorage context - Throw ERR_INVALID_ARG_VALUE if options.domain is passed PR-URL: nodejs#61227
e86555a to
855468d
Compare
|
@aduh95 done |
Failed to start CI⚠ Commits were pushed since the last approving review: ⚠ - repl: remove dependency on domain module ✘ Refusing to run CI on potentially unsafe PRhttps://github.com/nodejs/node/actions/runs/20913460585 |
|
I’ve updated this PR and made it minor by adding a new API and make it backward compatible with using domain. I would wait for backporting this. |
Replace the domain-based error handling with AsyncLocalStorage and setUncaughtExceptionCaptureCallback. This removes the REPL's dependency on the deprecated domain module while preserving all existing behavior: - Synchronous errors during eval are caught and displayed - Async errors (setTimeout, promises, etc.) are caught via the uncaught exception capture callback - Top-level await errors are caught and displayed - The REPL continues operating after errors - Multiple REPL instances can coexist with errors routed correctly Changes: - Use AsyncLocalStorage to track which REPL instance owns an async context, replacing domain's automatic async tracking - Add setupExceptionCapture() to install setUncaughtExceptionCaptureCallback for catching async errors and routing them to the correct REPL - Extract error handling logic into REPLServer.prototype._handleError() - Wrap eval execution in replContext.run() for async context tracking - Update newListener protection to check AsyncLocalStorage context - Throw ERR_INVALID_ARG_VALUE if options.domain is passed PR-URL: nodejs#61227
90dda43 to
045d98f
Compare
| ```mjs | ||
| import process from 'node:process'; | ||
|
|
||
| process.addUncaughtExceptionCaptureCallback((err) => { |
There was a problem hiding this comment.
Won't it be available on global process?
|
|
||
| This feature is not available in [`Worker`][] threads. | ||
|
|
||
| ## `process.addUncaughtExceptionCaptureCallback(fn)` |
There was a problem hiding this comment.
Should we land it as experimental first?
| method with a non-`null` argument while another capture function is set will | ||
| throw an error. | ||
|
|
||
| Using this function is mutually exclusive with using the deprecated |
There was a problem hiding this comment.
I guess we should add this to changes: at the top of this function documentation
lib/internal/process/execution.js
Outdated
| // Otherwise, the primary callback (if set) is called. | ||
| function addUncaughtExceptionCaptureCallback(fn) { | ||
| if (typeof fn !== 'function') { | ||
| throw new ERR_INVALID_ARG_TYPE('fn', 'Function', fn); |
There was a problem hiding this comment.
| throw new ERR_INVALID_ARG_TYPE('fn', 'Function', fn); | |
| validateFunction(fn, 'fn'); |
6f50f41 to
6125d23
Compare
|
@RafaelGSS ping |
|
@mcollina conflicts |
Replace the domain-based error handling with AsyncLocalStorage and setUncaughtExceptionCaptureCallback. This removes the REPL's dependency on the deprecated domain module while preserving all existing behavior: - Synchronous errors during eval are caught and displayed - Async errors (setTimeout, promises, etc.) are caught via the uncaught exception capture callback - Top-level await errors are caught and displayed - The REPL continues operating after errors - Multiple REPL instances can coexist with errors routed correctly Changes: - Use AsyncLocalStorage to track which REPL instance owns an async context, replacing domain's automatic async tracking - Add setupExceptionCapture() to install setUncaughtExceptionCaptureCallback for catching async errors and routing them to the correct REPL - Extract error handling logic into REPLServer.prototype._handleError() - Wrap eval execution in replContext.run() for async context tracking - Update newListener protection to check AsyncLocalStorage context - Throw ERR_INVALID_ARG_VALUE if options.domain is passed PR-URL: nodejs#61227
Add auxiliary callback mechanism to setUncaughtExceptionCaptureCallback to allow REPL and domain module to coexist. The REPL uses the new addUncaughtExceptionCaptureCallback API which doesn't conflict with domain's use of the primary callback. - Add addUncaughtExceptionCaptureCallback for non-exclusive callbacks - Update REPL to check for active domain before handling errors - Remove mutual exclusivity checks from domain module - Restore test-repl-domain.js test - Update domain coexistence tests
- Mark addUncaughtExceptionCaptureCallback as experimental - Add changes entry to setUncaughtExceptionCaptureCallback docs - Use validateFunction instead of manual type check
6125d23 to
f80a221
Compare
|
Rebased on top of main and adapted the conflict resolution to use the new ref-counted @RafaelGSS @anonrig @marco-ippolito could you re-approve? The only change from the previous version is adapting the |
Replace domain-based error handling with AsyncLocalStorage and setUncaughtExceptionCaptureCallback. This removes REPL's dependency on the deprecated domain module while preserving existing behavior and allowing the domain module to still be used within REPL sessions.
Changes
addUncaughtExceptionCaptureCallbackAPI for auxiliary callbacks, allowing REPL and domain to coexist