diff --git a/lib/internal/readline/interface.js b/lib/internal/readline/interface.js index bd63420a1ea3f7..aa2f46123a9e55 100644 --- a/lib/internal/readline/interface.js +++ b/lib/internal/readline/interface.js @@ -33,10 +33,13 @@ const { SymbolDispose, } = primordials; -const { codes: { - ERR_INVALID_ARG_VALUE, - ERR_USE_AFTER_CLOSE, -} } = require('internal/errors'); +const { + AbortError, + codes: { + ERR_INVALID_ARG_VALUE, + ERR_USE_AFTER_CLOSE, + }, +} = require('internal/errors'); const { validateAbortSignal, @@ -111,6 +114,7 @@ const kPrompt = Symbol('_prompt'); const kPushToKillRing = Symbol('_pushToKillRing'); const kPushToUndoStack = Symbol('_pushToUndoStack'); const kQuestionCallback = Symbol('_questionCallback'); +const kQuestionReject = Symbol('_questionReject'); const kRedo = Symbol('_redo'); const kRedoStack = Symbol('_redoStack'); const kRefreshLine = Symbol('_refreshLine'); @@ -1126,6 +1130,7 @@ class Interface extends InterfaceConstructor { } else { // This readline instance is finished this.close(); + this[kQuestionReject]?.(new AbortError('Aborted with Ctrl+C')); } break; @@ -1137,6 +1142,7 @@ class Interface extends InterfaceConstructor { if (this.cursor === 0 && this.line.length === 0) { // This readline instance is finished this.close(); + this[kQuestionReject]?.(new AbortError('Aborted with Ctrl+D')); } else if (this.cursor < this.line.length) { this[kDeleteRight](); } @@ -1392,6 +1398,7 @@ module.exports = { kQuestion, kQuestionCallback, kQuestionCancel, + kQuestionReject, kRefreshLine, kSawKeyPress, kSawReturnAt, diff --git a/lib/readline/promises.js b/lib/readline/promises.js index ccd0745a33f941..a4ad0adabaf228 100644 --- a/lib/readline/promises.js +++ b/lib/readline/promises.js @@ -13,6 +13,7 @@ const { Interface: _Interface, kQuestion, kQuestionCancel, + kQuestionReject, } = require('internal/readline/interface'); const { @@ -54,6 +55,8 @@ class Interface extends _Interface { }; } + this[kQuestionReject] = reject; + this[kQuestion](query, cb); }); } diff --git a/test/parallel/test-readline-promises-interface.js b/test/parallel/test-readline-promises-interface.js index 97424c1372629c..32aab1b60c2ee5 100644 --- a/test/parallel/test-readline-promises-interface.js +++ b/test/parallel/test-readline-promises-interface.js @@ -951,6 +951,22 @@ for (let i = 0; i < 12; i++) { rli.close(); } + // Aborting a question with ctrl+C + { + const [rli, fi] = getInterface({ terminal: true }); + assert.rejects(rli.question('hello?'), { name: 'AbortError' }) + .then(common.mustCall()); + fi.emit('keypress', '.', { ctrl: true, name: 'c' }); + } + + // Aborting a question with ctrl+D + { + const [rli, fi] = getInterface({ terminal: true }); + assert.rejects(rli.question('hello?'), { name: 'AbortError' }) + .then(common.mustCall()); + fi.emit('keypress', '.', { ctrl: true, name: 'd' }); + } + (async () => { const [rli] = getInterface({ terminal }); const signal = AbortSignal.abort('boom');