node/test/fixtures/repl-tab-completion-nested-repls.js
Matteo Collina a9da9ffc04
repl: remove dependency on domain module
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: https://github.com/nodejs/node/pull/61227
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
2026-03-06 15:38:36 +00:00

44 lines
No EOL
1.2 KiB
JavaScript

// Tab completion sometimes uses a separate REPL instance under the hood.
// Make sure errors in completion callbacks are properly thrown.
//
// Ref: https://github.com/nodejs/node/issues/21586
'use strict';
const { Stream } = require('stream');
function noop() {}
// A stream to push an array into a REPL
function ArrayStream() {
this.run = function(data) {
data.forEach((line) => {
this.emit('data', `${line}\n`);
});
};
}
Object.setPrototypeOf(ArrayStream.prototype, Stream.prototype);
Object.setPrototypeOf(ArrayStream, Stream);
ArrayStream.prototype.readable = true;
ArrayStream.prototype.writable = true;
ArrayStream.prototype.pause = noop;
ArrayStream.prototype.resume = noop;
ArrayStream.prototype.write = noop;
const repl = require('repl');
const putIn = new ArrayStream();
const testMe = repl.start('', putIn);
// Nesting of structures causes REPL to use a nested REPL for completion.
putIn.run([
'var top = function() {',
'r = function test (',
' one, two) {',
'var inner = {',
' one:1',
'};'
]);
// In Node.js 10.11.0, this next line will terminate the repl silently...
testMe.complete('inner.o', () => { throw new Error('fhqwhgads'); });