diff --git a/lib/readline.js b/lib/readline.js index cd1bfb8b6aaa51..113314affc3a29 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -59,6 +59,7 @@ const { StringPrototypeStartsWith, StringPrototypeTrim, Promise, + PromiseReject, Symbol, SymbolAsyncIterator, SafeStringIterator, @@ -376,6 +377,10 @@ Interface.prototype.question = function(query, options, cb) { options = typeof options === 'object' && options !== null ? options : {}; if (options.signal) { + if (options.signal.aborted) { + return; + } + options.signal.addEventListener('abort', () => { this[kQuestionCancel](); }, { once: true }); @@ -396,6 +401,10 @@ Interface.prototype.question = function(query, options, cb) { Interface.prototype.question[promisify.custom] = function(query, options) { options = typeof options === 'object' && options !== null ? options : {}; + if (options.signal && options.signal.aborted) { + return PromiseReject(new AbortError()); + } + return new Promise((resolve, reject) => { this.question(query, options, resolve); diff --git a/test/parallel/test-readline-interface.js b/test/parallel/test-readline-interface.js index 4660e5b9f56937..e9bf8142b82dd0 100644 --- a/test/parallel/test-readline-interface.js +++ b/test/parallel/test-readline-interface.js @@ -968,6 +968,31 @@ for (let i = 0; i < 12; i++) { rli.close(); } + // pre-aborted signal + { + const signal = AbortSignal.abort(); + const [rli] = getInterface({ terminal }); + rli.pause(); + rli.on('resume', common.mustNotCall()); + rli.question('hello?', { signal }, common.mustNotCall()); + rli.close(); + } + + // pre-aborted signal promisified question + { + const signal = AbortSignal.abort(); + const [rli] = getInterface({ terminal }); + const question = util.promisify(rli.question).bind(rli); + rli.on('resume', common.mustNotCall()); + rli.pause(); + question('hello?', { signal }) + .then(common.mustNotCall()) + .catch(common.mustCall((error) => { + assert.strictEqual(error.name, 'AbortError'); + })); + rli.close(); + } + // Can create a new readline Interface with a null output argument { const [rli, fi] = getInterface({ output: null, terminal });