Skip to content

Commit d36b60e

Browse files
authored
readline: fix question still called after closed
resolve: #42450 PR-URL: #42464 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
1 parent 0bac547 commit d36b60e

File tree

6 files changed

+73
-1
lines changed

6 files changed

+73
-1
lines changed

‎doc/api/errors.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,6 +2802,14 @@ import 'package-name' // supported
28022802

28032803
`import` with URL schemes other than `file` and `data` is unsupported.
28042804

2805+
<aid="ERR_USE_AFTER_CLOSE"></a>
2806+
2807+
### `ERR_USE_AFTER_CLOSE`
2808+
2809+
> Stability: 1 - Experimental
2810+
2811+
An attempt was made to use something that was already closed.
2812+
28052813
<aid="ERR_VALID_PERFORMANCE_ENTRY_TYPE"></a>
28062814

28072815
### `ERR_VALID_PERFORMANCE_ENTRY_TYPE`

‎doc/api/readline.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ The `callback` function passed to `rl.question()` does not follow the typical
330330
pattern of accepting an `Error` object or `null` as the first argument.
331331
The `callback` is called with the provided answer as the only argument.
332332

333+
An error will be thrown if calling `rl.question()` after `rl.close()`.
334+
333335
Example usage:
334336

335337
```js
@@ -586,6 +588,8 @@ paused.
586588
If the `readlinePromises.Interface` was created with `output` set to `null` or
587589
`undefined` the `query` is not written.
588590

591+
If the question is called after `rl.close()`, it returns a rejected promise.
592+
589593
Example usage:
590594

591595
```mjs
@@ -855,6 +859,8 @@ The `callback` function passed to `rl.question()` does not follow the typical
855859
pattern of accepting an `Error` object or `null` as the first argument.
856860
The `callback` is called with the provided answer as the only argument.
857861

862+
An error will be thrown if calling `rl.question()` after `rl.close()`.
863+
858864
Example usage:
859865

860866
```js

‎lib/internal/errors.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,7 @@ E('ERR_UNSUPPORTED_ESM_URL_SCHEME', (url, supported) =>{
16271627
msg+=`. Received protocol '${url.protocol}'`;
16281628
returnmsg;
16291629
},Error);
1630+
E('ERR_USE_AFTER_CLOSE','%s was closed',Error);
16301631

16311632
// This should probably be a `TypeError`.
16321633
E('ERR_VALID_PERFORMANCE_ENTRY_TYPE',

‎lib/internal/readline/interface.js‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ const{
3838

3939
const{ codes }=require('internal/errors');
4040

41-
const{ERR_INVALID_ARG_VALUE}=codes;
41+
const{
42+
ERR_INVALID_ARG_VALUE,
43+
ERR_USE_AFTER_CLOSE,
44+
}=codes;
4245
const{
4346
validateAbortSignal,
4447
validateArray,
@@ -398,6 +401,9 @@ class Interface extends InterfaceConstructor{
398401
}
399402

400403
question(query,cb){
404+
if(this.closed){
405+
thrownewERR_USE_AFTER_CLOSE('readline');
406+
}
401407
if(this[kQuestionCallback]){
402408
this.prompt();
403409
}else{

‎test/parallel/test-readline-interface.js‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,40 @@ for (let i = 0; i < 12; i++){
10921092
rli.close();
10931093
}
10941094

1095+
// Call question after close
1096+
{
1097+
const[rli,fi]=getInterface({ terminal });
1098+
rli.question('What\'s your name?',common.mustCall((name)=>{
1099+
assert.strictEqual(name,'Node.js');
1100+
rli.close();
1101+
assert.throws(()=>{
1102+
rli.question('How are you?',common.mustNotCall());
1103+
},{
1104+
name: 'Error',
1105+
code: 'ERR_USE_AFTER_CLOSE'
1106+
});
1107+
assert.notStrictEqual(rli.getPrompt(),'How are you?');
1108+
}));
1109+
fi.emit('data','Node.js\n');
1110+
}
1111+
1112+
// Call promisified question after close
1113+
{
1114+
const[rli,fi]=getInterface({ terminal });
1115+
constquestion=util.promisify(rli.question).bind(rli);
1116+
question('What\'s your name?').then(common.mustCall((name)=>{
1117+
assert.strictEqual(name,'Node.js');
1118+
rli.close();
1119+
question('How are you?')
1120+
.then(common.mustNotCall(),common.expectsError({
1121+
code: 'ERR_USE_AFTER_CLOSE',
1122+
name: 'Error'
1123+
}));
1124+
assert.notStrictEqual(rli.getPrompt(),'How are you?');
1125+
}));
1126+
fi.emit('data','Node.js\n');
1127+
}
1128+
10951129
// Can create a new readline Interface with a null output argument
10961130
{
10971131
const[rli,fi]=getInterface({output: null, terminal });

‎test/parallel/test-readline-promises-interface.js‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,23 @@ for (let i = 0; i < 12; i++){
952952
rli.close();
953953
}
954954

955+
// Call question after close
956+
{
957+
const[rli,fi]=getInterface({ terminal });
958+
rli.question('What\'s your name?').then(common.mustCall((name)=>{
959+
assert.strictEqual(name,'Node.js');
960+
rli.close();
961+
rli.question('How are you?')
962+
.then(common.mustNotCall(),common.expectsError({
963+
code: 'ERR_USE_AFTER_CLOSE',
964+
name: 'Error'
965+
}));
966+
assert.notStrictEqual(rli.getPrompt(),'How are you?');
967+
}));
968+
fi.emit('data','Node.js\n');
969+
}
970+
971+
955972
// Can create a new readline Interface with a null output argument
956973
{
957974
const[rli,fi]=getInterface({output: null, terminal });

0 commit comments

Comments
(0)