diff --git a/lib/repl.js b/lib/repl.js index 5ad9e4fbb1506f..2eee3def4e6909 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -73,7 +73,6 @@ const { RegExpPrototypeExec, SafePromiseRace, SafeSet, - SafeWeakSet, StringPrototypeCharAt, StringPrototypeEndsWith, StringPrototypeIncludes, @@ -115,7 +114,7 @@ const { const { Console } = require('console'); const { shouldColorize } = require('internal/util/colors'); const CJSModule = require('internal/modules/cjs/loader').Module; -const domain = require('domain'); +const { AsyncLocalStorage } = require('async_hooks'); let debug = require('internal/util/debuglog').debuglog('repl', (fn) => { debug = fn; }); @@ -123,6 +122,7 @@ const { ErrorPrepareStackTrace, codes: { ERR_CANNOT_WATCH_SIGINT, + ERR_INVALID_ARG_VALUE, ERR_INVALID_REPL_EVAL_CONFIG, ERR_INVALID_REPL_INPUT, ERR_MISSING_ARGS, @@ -178,7 +178,46 @@ const { let processTopLevelAwait; const parentModule = module; -const domainSet = new SafeWeakSet(); + +// AsyncLocalStorage to track which REPL instance owns the current async context +// This replaces the domain-based tracking for error handling +const replContext = new AsyncLocalStorage(); +let exceptionCaptureSetup = false; + +/** + * Sets up the uncaught exception capture callback to route errors + * to the appropriate REPL instance. This replaces domain-based error handling. + * @returns {boolean} true if setup succeeded, false if capture callback already in use + */ +function setupExceptionCapture() { + if (exceptionCaptureSetup) return true; + + if (process.hasUncaughtExceptionCaptureCallback()) { + return false; + } + + process.setUncaughtExceptionCaptureCallback((err) => { + const store = replContext.getStore(); + if (store?.replServer && !store.replServer.closed) { + store.replServer._handleError(err); + return; + } + // No active REPL context - re-emit for normal process handling + process.setUncaughtExceptionCaptureCallback(null); + exceptionCaptureSetup = false; + try { + if (!process.emit('uncaughtException', err, 'uncaughtException')) { + // No handler, rethrow to exit process + throw err; + } + } finally { + setupExceptionCapture(); + } + }); + + exceptionCaptureSetup = true; + return true; +} const kBufferedCommandSymbol = Symbol('bufferedCommand'); const kLoadingSymbol = Symbol('loading'); @@ -313,7 +352,13 @@ class REPLServer extends Interface { this.allowBlockingCompletions = !!options.allowBlockingCompletions; this.useColors = !!options.useColors; - this._domain = options.domain || domain.create(); + this._isStandalone = !!options[kStandaloneREPL]; + + if (options.domain !== undefined) { + throw new ERR_INVALID_ARG_VALUE('options.domain', options.domain, + 'is no longer supported'); + } + this.useGlobal = !!useGlobal; this.ignoreUndefined = !!ignoreUndefined; this.replMode = replMode || module.exports.REPL_MODE_SLOPPY; @@ -338,26 +383,27 @@ class REPLServer extends Interface { // from inside the REPL. This is useful for anyone working on the REPL. module.exports.repl = this; } else if (!addedNewListener) { - // Add this listener only once and use a WeakSet that contains the REPLs - // domains. Otherwise we'd have to add a single listener to each REPL - // instance and that could trigger the `MaxListenersExceededWarning`. + // Add this listener only once. Otherwise we'd have to add a single + // listener to each REPL instance and that could trigger the + // `MaxListenersExceededWarning`. process.prependListener('newListener', (event, listener) => { - if (event === 'uncaughtException' && - process.domain && - listener.name !== 'domainUncaughtExceptionClear' && - domainSet.has(process.domain)) { - // Throw an error so that the event will not be added and the current - // domain takes over. That way the user is notified about the error - // and the current code evaluation is stopped, just as any other code - // that contains an error. - throw new ERR_INVALID_REPL_INPUT( - 'Listeners for `uncaughtException` cannot be used in the REPL'); + if (event === 'uncaughtException') { + const store = replContext.getStore(); + if (store?.replServer) { + // Throw an error so that the event will not be added and the + // current REPL handles it. That way the user is notified about + // the error and the current code evaluation is stopped, just as + // any other code that contains an error. + throw new ERR_INVALID_REPL_INPUT( + 'Listeners for `uncaughtException` cannot be used in the REPL'); + } } }); addedNewListener = true; } - domainSet.add(this._domain); + // Set up exception capture for async error handling + setupExceptionCapture(); const savedRegExMatches = ['', '', '', '', '', '', '', '', '', '']; const sep = '\u0000\u0000\u0000'; @@ -578,13 +624,10 @@ class REPLServer extends Interface { } } catch (e) { err = e; - - if (process.domain) { - debug('not recoverable, send to domain'); - process.domain.emit('error', err); - process.domain.exit(); - return; - } + // Handle non-recoverable errors directly + debug('not recoverable, handle error'); + self._handleError(err); + return; } if (awaitPromise && !err) { @@ -610,13 +653,9 @@ class REPLServer extends Interface { const result = (await promise)?.value; finishExecution(null, result); } catch (err) { - if (err && process.domain) { - debug('not recoverable, send to domain'); - process.domain.emit('error', err); - process.domain.exit(); - return; - } - finishExecution(err); + // Handle non-recoverable async errors directly + debug('not recoverable, handle error'); + self._handleError(err); } finally { // Remove prioritized SIGINT listener if it was not called. prioritizedSigintQueue.delete(sigintListener); @@ -631,124 +670,16 @@ class REPLServer extends Interface { } } - self.eval = self._domain.bind(eval_); - - self._domain.on('error', function debugDomainError(e) { - debug('domain error'); - let errStack = ''; - - if (typeof e === 'object' && e !== null) { - overrideStackTrace.set(e, (error, stackFrames) => { - let frames; - if (typeof stackFrames === 'object') { - // Search from the bottom of the call stack to - // find the first frame with a null function name - const idx = ArrayPrototypeFindLastIndex( - stackFrames, - (frame) => frame.getFunctionName() === null, - ); - // If found, get rid of it and everything below it - frames = ArrayPrototypeSlice(stackFrames, 0, idx); - } else { - frames = stackFrames; - } - // FIXME(devsnek): this is inconsistent with the checks - // that the real prepareStackTrace dispatch uses in - // lib/internal/errors.js. - if (typeof MainContextError.prepareStackTrace === 'function') { - return MainContextError.prepareStackTrace(error, frames); - } - return ErrorPrepareStackTrace(error, frames); - }); - decorateErrorStack(e); - - if (e.domainThrown) { - delete e.domain; - delete e.domainThrown; - } - - if (isError(e)) { - if (e.stack) { - if (e.name === 'SyntaxError') { - // Remove stack trace. - e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( - /^\s+at\s.*\n?/gm, - SideEffectFreeRegExpPrototypeSymbolReplace(/^REPL\d+:\d+\r?\n/, e.stack, ''), - ''); - const importErrorStr = 'Cannot use import statement outside a ' + - 'module'; - if (StringPrototypeIncludes(e.message, importErrorStr)) { - e.message = 'Cannot use import statement inside the Node.js ' + - 'REPL, alternatively use dynamic import: ' + toDynamicImport(ArrayPrototypeAt(self.lines, -1)); - e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( - /SyntaxError:.*\n/, - e.stack, - `SyntaxError: ${e.message}\n`); - } - } else if (self.replMode === module.exports.REPL_MODE_STRICT) { - e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( - /(\s+at\s+REPL\d+:)(\d+)/, - e.stack, - (_, pre, line) => pre + (line - 1), - ); - } - } - errStack = self.writer(e); - - // Remove one line error braces to keep the old style in place. - if (errStack[0] === '[' && errStack[errStack.length - 1] === ']') { - errStack = StringPrototypeSlice(errStack, 1, -1); - } - } - } - - if (!self.underscoreErrAssigned) { - self.lastError = e; - } - - if (options[kStandaloneREPL] && - process.listenerCount('uncaughtException') !== 0) { - process.nextTick(() => { - process.emit('uncaughtException', e); - self.clearBufferedCommand(); - self.lines.level = []; - if (!self.closed) { - self.displayPrompt(); - } - }); - } else { - if (errStack === '') { - errStack = self.writer(e); - } - const lines = SideEffectFreeRegExpPrototypeSymbolSplit(/(?<=\n)/, errStack); - let matched = false; - - errStack = ''; - ArrayPrototypeForEach(lines, (line) => { - if (!matched && - RegExpPrototypeExec(/^\[?([A-Z][a-z0-9_]*)*Error/, line) !== null) { - errStack += writer.options.breakLength >= line.length ? - `Uncaught ${line}` : - `Uncaught:\n${line}`; - matched = true; - } else { - errStack += line; - } - }); - if (!matched) { - const ln = lines.length === 1 ? ' ' : ':\n'; - errStack = `Uncaught${ln}${errStack}`; - } - // Normalize line endings. - errStack += StringPrototypeEndsWith(errStack, '\n') ? '' : '\n'; - self.output.write(errStack); - self.clearBufferedCommand(); - self.lines.level = []; - if (!self.closed) { - self.displayPrompt(); - } - } - }); + // Wrap eval to run within the REPL's async context for error tracking. + // The function names are needed for stack trace filtering - they must not + // be anonymous, but we can't use 'eval' as a name since it's reserved. + const originalEval = eval_; + // eslint-disable-next-line func-name-matching + self.eval = function REPLEval(code, context, file, cb) { + replContext.run({ replServer: self }, function REPLEvalInContext() { + originalEval(code, context, file, cb); + }); + }; self.clearBufferedCommand(); @@ -912,7 +843,7 @@ class REPLServer extends Interface { } if (e) { - self._domain.emit('error', e.err || e); + self._handleError(e.err || e); self[kLastCommandErrored] = true; } @@ -1038,6 +969,117 @@ class REPLServer extends Interface { clearBufferedCommand() { this[kBufferedCommandSymbol] = ''; } + _handleError(e) { + debug('handle error'); + let errStack = ''; + + if (typeof e === 'object' && e !== null) { + overrideStackTrace.set(e, (error, stackFrames) => { + let frames; + if (typeof stackFrames === 'object') { + // Search from the bottom of the call stack to + // find the first frame with a null function name + const idx = ArrayPrototypeFindLastIndex( + stackFrames, + (frame) => frame.getFunctionName() === null, + ); + // If found, get rid of it and everything below it + frames = ArrayPrototypeSlice(stackFrames, 0, idx); + } else { + frames = stackFrames; + } + // FIXME(devsnek): this is inconsistent with the checks + // that the real prepareStackTrace dispatch uses in + // lib/internal/errors.js. + if (typeof MainContextError.prepareStackTrace === 'function') { + return MainContextError.prepareStackTrace(error, frames); + } + return ErrorPrepareStackTrace(error, frames); + }); + decorateErrorStack(e); + + if (isError(e)) { + if (e.stack) { + if (e.name === 'SyntaxError') { + // Remove stack trace. + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /^\s+at\s.*\n?/gm, + SideEffectFreeRegExpPrototypeSymbolReplace(/^REPL\d+:\d+\r?\n/, e.stack, ''), + ''); + const importErrorStr = 'Cannot use import statement outside a ' + + 'module'; + if (StringPrototypeIncludes(e.message, importErrorStr)) { + e.message = 'Cannot use import statement inside the Node.js ' + + 'REPL, alternatively use dynamic import: ' + toDynamicImport(ArrayPrototypeAt(this.lines, -1)); + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /SyntaxError:.*\n/, + e.stack, + `SyntaxError: ${e.message}\n`); + } + } else if (this.replMode === module.exports.REPL_MODE_STRICT) { + e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( + /(\s+at\s+REPL\d+:)(\d+)/, + e.stack, + (_, pre, line) => pre + (line - 1), + ); + } + } + errStack = this.writer(e); + + // Remove one line error braces to keep the old style in place. + if (errStack[0] === '[' && errStack[errStack.length - 1] === ']') { + errStack = StringPrototypeSlice(errStack, 1, -1); + } + } + } + + if (!this.underscoreErrAssigned) { + this.lastError = e; + } + + if (this._isStandalone && + process.listenerCount('uncaughtException') !== 0) { + process.nextTick(() => { + process.emit('uncaughtException', e); + this.clearBufferedCommand(); + this.lines.level = []; + if (!this.closed) { + this.displayPrompt(); + } + }); + } else { + if (errStack === '') { + errStack = this.writer(e); + } + const lines = SideEffectFreeRegExpPrototypeSymbolSplit(/(?<=\n)/, errStack); + let matched = false; + + errStack = ''; + ArrayPrototypeForEach(lines, (line) => { + if (!matched && + RegExpPrototypeExec(/^\[?([A-Z][a-z0-9_]*)*Error/, line) !== null) { + errStack += writer.options.breakLength >= line.length ? + `Uncaught ${line}` : + `Uncaught:\n${line}`; + matched = true; + } else { + errStack += line; + } + }); + if (!matched) { + const ln = lines.length === 1 ? ' ' : ':\n'; + errStack = `Uncaught${ln}${errStack}`; + } + // Normalize line endings. + errStack += StringPrototypeEndsWith(errStack, '\n') ? '' : '\n'; + this.output.write(errStack); + this.clearBufferedCommand(); + this.lines.level = []; + if (!this.closed) { + this.displayPrompt(); + } + } + } close() { if (this.terminal && this.historyManager.isFlushing && !this._closingOnFlush) { this._closingOnFlush = true; diff --git a/test/common/repl.js b/test/common/repl.js index 223050c76e1df0..6ce4d993a4c456 100644 --- a/test/common/repl.js +++ b/test/common/repl.js @@ -2,9 +2,8 @@ const ArrayStream = require('../common/arraystream'); const repl = require('node:repl'); -const assert = require('node:assert'); -function startNewREPLServer(replOpts = {}, testingOpts = {}) { +function startNewREPLServer(replOpts = {}) { const input = new ArrayStream(); const output = new ArrayStream(); @@ -20,11 +19,6 @@ function startNewREPLServer(replOpts = {}, testingOpts = {}) { ...replOpts, }); - if (!testingOpts.disableDomainErrorAssert) { - // Some errors are passed to the domain, but do not callback - replServer._domain.on('error', assert.ifError); - } - return { replServer, input, output }; } diff --git a/test/fixtures/repl-tab-completion-nested-repls.js b/test/fixtures/repl-tab-completion-nested-repls.js index 1d2b154f2b3341..79677491eca55f 100644 --- a/test/fixtures/repl-tab-completion-nested-repls.js +++ b/test/fixtures/repl-tab-completion-nested-repls.js @@ -1,6 +1,5 @@ // Tab completion sometimes uses a separate REPL instance under the hood. -// That REPL instance has its own domain. Make sure domain errors trickle back -// up to the main REPL. +// Make sure errors in completion callbacks are properly thrown. // // Ref: https://github.com/nodejs/node/issues/21586 @@ -31,11 +30,6 @@ const repl = require('repl'); const putIn = new ArrayStream(); const testMe = repl.start('', putIn); -// Some errors are passed to the domain, but do not callback. -testMe._domain.on('error', function(err) { - throw err; -}); - // Nesting of structures causes REPL to use a nested REPL for completion. putIn.run([ 'var top = function() {', diff --git a/test/parallel/test-repl-domain.js b/test/parallel/test-repl-domain.js deleted file mode 100644 index b7c8d95dd26c0e..00000000000000 --- a/test/parallel/test-repl-domain.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; -require('../common'); -const { startNewREPLServer } = require('../common/repl'); -const ArrayStream = require('../common/arraystream'); - -const stream = new ArrayStream(); - -startNewREPLServer({ - input: stream, - output: stream, - terminal: false, -}); - -stream.write = function(data) { - // Don't use assert for this because the domain might catch it, and - // give a false negative. Don't throw, just print and exit. - if (data === 'OK\n') { - console.log('ok'); - } else { - console.error(data); - process.exit(1); - } -}; - -stream.run([ - 'require("domain").create().on("error", function() { console.log("OK") })' + - '.run(function() { throw new Error("threw") })', -]); diff --git a/test/parallel/test-repl-eval-error-after-close.js b/test/parallel/test-repl-eval-error-after-close.js index 8c30a533efba15..0b4683fda4bfda 100644 --- a/test/parallel/test-repl-eval-error-after-close.js +++ b/test/parallel/test-repl-eval-error-after-close.js @@ -20,8 +20,6 @@ const assert = require('node:assert'); eval$.resolve(); }); }, - }, { - disableDomainErrorAssert: true, }); replServer.write('\n'); diff --git a/test/parallel/test-repl-let-process.js b/test/parallel/test-repl-let-process.js index eb6cbc6a472c72..22b57ab5bb977e 100644 --- a/test/parallel/test-repl-let-process.js +++ b/test/parallel/test-repl-let-process.js @@ -3,5 +3,5 @@ require('../common'); const { startNewREPLServer } = require('../common/repl'); // Regression test for https://github.com/nodejs/node/issues/6802 -const { input } = startNewREPLServer({ useGlobal: true }, { disableDomainErrorAssert: true }); +const { input } = startNewREPLServer({ useGlobal: true }); input.run(['let process']); diff --git a/test/parallel/test-repl-mode.js b/test/parallel/test-repl-mode.js index fbc9c18cba4998..0c5d2f70df7ce4 100644 --- a/test/parallel/test-repl-mode.js +++ b/test/parallel/test-repl-mode.js @@ -31,8 +31,8 @@ function testSloppyMode() { } function testStrictMode() { - const { input, output } = startNewREPLServer({ replMode: repl.REPL_MODE_STRICT, terminal: false, prompt: '> ' }, { - disableDomainErrorAssert: true, + const { input, output } = startNewREPLServer({ + replMode: repl.REPL_MODE_STRICT, terminal: false, prompt: '> ' }); input.emit('data', 'x = 3\n'); diff --git a/test/parallel/test-repl-multiple-instances-async-error.js b/test/parallel/test-repl-multiple-instances-async-error.js new file mode 100644 index 00000000000000..ddc8a5eaccdcca --- /dev/null +++ b/test/parallel/test-repl-multiple-instances-async-error.js @@ -0,0 +1,69 @@ +'use strict'; + +// This test verifies that when multiple REPL instances exist concurrently, +// async errors are correctly routed to the REPL instance that created them. + +const common = require('../common'); +const assert = require('assert'); +const repl = require('repl'); +const { Writable, PassThrough } = require('stream'); + +// Create two REPLs with separate inputs and outputs +let output1 = ''; +let output2 = ''; + +const input1 = new PassThrough(); +const input2 = new PassThrough(); + +const writable1 = new Writable({ + write(chunk, encoding, callback) { + output1 += chunk.toString(); + callback(); + } +}); + +const writable2 = new Writable({ + write(chunk, encoding, callback) { + output2 += chunk.toString(); + callback(); + } +}); + +const r1 = repl.start({ + input: input1, + output: writable1, + terminal: false, + prompt: 'R1> ', +}); + +const r2 = repl.start({ + input: input2, + output: writable2, + terminal: false, + prompt: 'R2> ', +}); + +// Create async error in REPL 1 +input1.write('setTimeout(() => { throw new Error("error from repl1") }, 10)\n'); + +// Create async error in REPL 2 +input2.write('setTimeout(() => { throw new Error("error from repl2") }, 20)\n'); + +setTimeout(common.mustCall(() => { + r1.close(); + r2.close(); + + // Verify error from REPL 1 went to REPL 1's output + assert.match(output1, /error from repl1/, + 'REPL 1 should have received its own async error'); + + // Verify error from REPL 2 went to REPL 2's output + assert.match(output2, /error from repl2/, + 'REPL 2 should have received its own async error'); + + // Verify errors did not cross over to wrong REPL + assert.doesNotMatch(output1, /error from repl2/, + 'REPL 1 should not have received REPL 2\'s error'); + assert.doesNotMatch(output2, /error from repl1/, + 'REPL 2 should not have received REPL 1\'s error'); +}), 100); diff --git a/test/parallel/test-repl-pretty-custom-stack.js b/test/parallel/test-repl-pretty-custom-stack.js index 82df8ff4fc6335..0efb814f38d2b5 100644 --- a/test/parallel/test-repl-pretty-custom-stack.js +++ b/test/parallel/test-repl-pretty-custom-stack.js @@ -10,8 +10,6 @@ function run({ command, expected }) { const { replServer, output } = startNewREPLServer({ terminal: false, useColors: false - }, { - disableDomainErrorAssert: true, }); replServer.write(`${command}\n`); diff --git a/test/parallel/test-repl-pretty-stack-custom-writer.js b/test/parallel/test-repl-pretty-stack-custom-writer.js index 2d39633030d775..e31460dbc93efb 100644 --- a/test/parallel/test-repl-pretty-stack-custom-writer.js +++ b/test/parallel/test-repl-pretty-stack-custom-writer.js @@ -5,10 +5,7 @@ const { startNewREPLServer } = require('../common/repl'); const testingReplPrompt = '_REPL_TESTING_PROMPT_>'; -const { replServer, output } = startNewREPLServer( - { prompt: testingReplPrompt }, - { disableDomainErrorAssert: true } -); +const { replServer, output } = startNewREPLServer({ prompt: testingReplPrompt }); replServer.write('throw new Error("foo[a]")\n'); diff --git a/test/parallel/test-repl-pretty-stack.js b/test/parallel/test-repl-pretty-stack.js index a7f13dea75aaea..b2f9cc82c08df0 100644 --- a/test/parallel/test-repl-pretty-stack.js +++ b/test/parallel/test-repl-pretty-stack.js @@ -7,14 +7,11 @@ const { startNewREPLServer } = require('../common/repl'); const stackRegExp = /(at .*REPL\d+:)[0-9]+:[0-9]+/g; function run({ command, expected, ...extraREPLOptions }, i) { - const { replServer, output } = startNewREPLServer( - { - terminal: false, - useColors: false, - ...extraREPLOptions - }, - { disableDomainErrorAssert: true } - ); + const { replServer, output } = startNewREPLServer({ + terminal: false, + useColors: false, + ...extraREPLOptions + }); replServer.write(`${command}\n`); if (typeof expected === 'string') { diff --git a/test/parallel/test-repl-preview-newlines.js b/test/parallel/test-repl-preview-newlines.js index 22ffe0db108590..34a944beb538d7 100644 --- a/test/parallel/test-repl-preview-newlines.js +++ b/test/parallel/test-repl-preview-newlines.js @@ -6,9 +6,7 @@ const { startNewREPLServer } = require('../common/repl'); common.skipIfInspectorDisabled(); -const { input, output } = startNewREPLServer( - { useColors: true }, { disableDomainErrorAssert: true } -); +const { input, output } = startNewREPLServer({ useColors: true }); output.accumulator = ''; diff --git a/test/parallel/test-repl-syntax-error-stack.js b/test/parallel/test-repl-syntax-error-stack.js index 1b6e3fb6e879f2..16bf27d045bc77 100644 --- a/test/parallel/test-repl-syntax-error-stack.js +++ b/test/parallel/test-repl-syntax-error-stack.js @@ -11,7 +11,7 @@ process.on('exit', () => { assert.strictEqual(found, true); }); -const { input, output } = startNewREPLServer({}, { disableDomainErrorAssert: true }); +const { input, output } = startNewREPLServer(); output.write = (data) => { // Matching only on a minimal piece of the stack because the string will vary diff --git a/test/parallel/test-repl-tab-complete-crash.js b/test/parallel/test-repl-tab-complete-crash.js index 58628eb85b2a38..29f75028bdac94 100644 --- a/test/parallel/test-repl-tab-complete-crash.js +++ b/test/parallel/test-repl-tab-complete-crash.js @@ -4,7 +4,7 @@ const common = require('../common'); const assert = require('assert'); const { startNewREPLServer } = require('../common/repl'); -const { replServer, input } = startNewREPLServer({}, { disableDomainErrorAssert: true }); +const { replServer, input } = startNewREPLServer(); // https://github.com/nodejs/node/issues/3346 // Tab-completion should be empty diff --git a/test/parallel/test-repl-tab.js b/test/parallel/test-repl-tab.js index e99f667c4a38f5..710fca9fae2d1e 100644 --- a/test/parallel/test-repl-tab.js +++ b/test/parallel/test-repl-tab.js @@ -10,6 +10,4 @@ const testMe = repl.start('', putIn, function(cmd, context, filename, callback(null, cmd); }); -testMe._domain.on('error', common.mustNotCall()); - testMe.complete('', common.mustSucceed()); diff --git a/test/parallel/test-repl-top-level-await.js b/test/parallel/test-repl-top-level-await.js index 0b35443dbdce14..a94ff8e48984a3 100644 --- a/test/parallel/test-repl-top-level-await.js +++ b/test/parallel/test-repl-top-level-await.js @@ -180,7 +180,7 @@ async function ordinaryTests() { ['k', '234'], ['const k = await Promise.resolve(345)', "Uncaught SyntaxError: Identifier 'k' has already been declared"], // Regression test for https://github.com/nodejs/node/issues/43777. - ['await Promise.resolve(123), Promise.resolve(456)', 'Promise {', { line: 0 }], + ['await Promise.resolve(123), Promise.resolve(456)', 'Promise { 456 }'], ['await Promise.resolve(123), await Promise.resolve(456)', '456'], ['await (Promise.resolve(123), Promise.resolve(456))', '456'], ]; diff --git a/test/parallel/test-repl-uncaught-exception-async.js b/test/parallel/test-repl-uncaught-exception-async.js index f4180080f496f7..e5373cdaca4d8d 100644 --- a/test/parallel/test-repl-uncaught-exception-async.js +++ b/test/parallel/test-repl-uncaught-exception-async.js @@ -8,17 +8,12 @@ const common = require('../common'); const assert = require('assert'); const { startNewREPLServer } = require('../common/repl'); -const { replServer, output } = startNewREPLServer( - { - prompt: '', - terminal: false, - useColors: false, - global: false, - }, - { - disableDomainErrorAssert: true - }, -); +const { replServer, output } = startNewREPLServer({ + prompt: '', + terminal: false, + useColors: false, + global: false, +}); replServer.write( 'process.nextTick(() => {\n' + diff --git a/test/parallel/test-repl-uncaught-exception-evalcallback.js b/test/parallel/test-repl-uncaught-exception-evalcallback.js index 77d03320ee9375..844fce6995aaa6 100644 --- a/test/parallel/test-repl-uncaught-exception-evalcallback.js +++ b/test/parallel/test-repl-uncaught-exception-evalcallback.js @@ -3,21 +3,16 @@ const common = require('../common'); const assert = require('assert'); const { startNewREPLServer } = require('../common/repl'); -const { replServer, output } = startNewREPLServer( - { - prompt: '', - terminal: false, - useColors: false, - global: false, - eval: common.mustCall((code, context, filename, cb) => { - replServer.setPrompt('prompt! '); - cb(new Error('err')); - }) - }, - { - disableDomainErrorAssert: true - }, -); +const { replServer, output } = startNewREPLServer({ + prompt: '', + terminal: false, + useColors: false, + global: false, + eval: common.mustCall((code, context, filename, cb) => { + replServer.setPrompt('prompt! '); + cb(new Error('err')); + }) +}); replServer.write('foo\n'); diff --git a/test/parallel/test-repl-uncaught-exception.js b/test/parallel/test-repl-uncaught-exception.js index 7753fe180b07fd..012c7f59ebc8a8 100644 --- a/test/parallel/test-repl-uncaught-exception.js +++ b/test/parallel/test-repl-uncaught-exception.js @@ -6,16 +6,11 @@ const { startNewREPLServer } = require('../common/repl'); let count = 0; function run({ command, expected, useColors = false }) { - const { replServer, output } = startNewREPLServer( - { - prompt: '', - terminal: false, - useColors, - }, - { - disableDomainErrorAssert: true - }, - ); + const { replServer, output } = startNewREPLServer({ + prompt: '', + terminal: false, + useColors, + }); replServer.write(`${command}\n`); diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js index 52d4cd86e94176..63c63976e2ddd7 100644 --- a/test/parallel/test-repl-underscore.js +++ b/test/parallel/test-repl-underscore.js @@ -176,8 +176,6 @@ function testError() { prompt: testingReplPrompt, replMode: repl.REPL_MODE_STRICT, preview: false, - }, { - disableDomainErrorAssert: true }); replServer.write(`_error; // initial value undefined diff --git a/test/pummel/test-repl-paste-big-data.js b/test/pummel/test-repl-paste-big-data.js index 2265a1af8e393c..46f8415a2b0aae 100644 --- a/test/pummel/test-repl-paste-big-data.js +++ b/test/pummel/test-repl-paste-big-data.js @@ -8,7 +8,7 @@ const { startNewREPLServer } = require('../common/repl'); const cpuUsage = process.cpuUsage(); -const { replServer } = startNewREPLServer({}, { disableDomainErrorAssert: true }); +const { replServer } = startNewREPLServer(); replServer.input.emit('data', '{}'); replServer.input.emit('keypress', '', { name: 'left' }); replServer.input.emit('data', 'node');