From dbab2893efcd498691cea7ca887c36d40a33f615 Mon Sep 17 00:00:00 2001 From: Nitzan Uziely Date: Fri, 26 Mar 2021 17:07:20 +0300 Subject: [PATCH] readline: fix pre-aborted signal question handling fix pre-aborted question handling PR-URL: https://github.com/nodejs/node/pull/37929 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell --- lib/readline.js | 9 +++++++++ test/parallel/test-readline-interface.js | 25 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/lib/readline.js b/lib/readline.js index 41a4a958b11..582fc26baf7 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -59,6 +59,7 @@ const { StringPrototypeStartsWith, StringPrototypeTrim, Promise, + PromiseReject, Symbol, SymbolAsyncIterator, SafeStringIterator, @@ -393,6 +394,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 }); @@ -413,6 +418,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 42de0499976..8afe40efab4 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 });