readline: fix unresolved promise on abortion

Fixes: https://github.com/nodejs/node/issues/53497
PR-URL: https://github.com/nodejs/node/pull/54030
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
Daniel Venable 2024-07-25 02:01:26 +00:00 committed by James M Snell
parent 82ac335bdd
commit 5557ce4aec
3 changed files with 30 additions and 4 deletions

View file

@ -33,10 +33,13 @@ const {
SymbolDispose,
} = primordials;
const { codes: {
const {
AbortError,
codes: {
ERR_INVALID_ARG_VALUE,
ERR_USE_AFTER_CLOSE,
} } = require('internal/errors');
},
} = 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,

View file

@ -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);
});
}

View file

@ -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');