Skip to content

Commit c575cee

Browse files
readline: add stricter validation called after closed
1 parent e57841f commit c575cee

File tree

5 files changed

+59
-4
lines changed

5 files changed

+59
-4
lines changed

lib/internal/readline/interface.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,9 @@ class Interface extends InterfaceConstructor {
536536
* @returns {void | Interface}
537537
*/
538538
pause() {
539+
if (this.closed) {
540+
throw new ERR_USE_AFTER_CLOSE('readline');
541+
}
539542
if (this.paused) return;
540543
this.input.pause();
541544
this.paused = true;
@@ -548,6 +551,9 @@ class Interface extends InterfaceConstructor {
548551
* @returns {void | Interface}
549552
*/
550553
resume() {
554+
if (this.closed) {
555+
throw new ERR_USE_AFTER_CLOSE('readline');
556+
}
551557
if (!this.paused) return;
552558
this.input.resume();
553559
this.paused = false;
@@ -568,6 +574,9 @@ class Interface extends InterfaceConstructor {
568574
* @returns {void}
569575
*/
570576
write(d, key) {
577+
if (this.closed) {
578+
throw new ERR_USE_AFTER_CLOSE('readline');
579+
}
571580
if (this.paused) this.resume();
572581
if (this.terminal) {
573582
this[kTtyWrite](d, key);

test/parallel/test-readline-interface.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,44 @@ for (let i = 0; i < 12; i++) {
12021202
fi.emit('data', 'Node.js\n');
12031203
}
12041204

1205+
// Call write after close
1206+
{
1207+
const [rli, fi] = getInterface({ terminal });
1208+
rli.question('What\'s your name?', common.mustCall((name) => {
1209+
assert.strictEqual(name, 'Node.js');
1210+
rli.close();
1211+
assert.throws(() => {
1212+
rli.write('I said Node.js');
1213+
}, {
1214+
name: 'Error',
1215+
code: 'ERR_USE_AFTER_CLOSE'
1216+
});
1217+
}));
1218+
fi.emit('data', 'Node.js\n');
1219+
}
1220+
1221+
// Call pause/resume after close
1222+
{
1223+
const [rli, fi] = getInterface({ terminal });
1224+
rli.question('What\'s your name?', common.mustCall((name) => {
1225+
assert.strictEqual(name, 'Node.js');
1226+
rli.close();
1227+
assert.throws(() => {
1228+
rli.pause();
1229+
}, {
1230+
name: 'Error',
1231+
code: 'ERR_USE_AFTER_CLOSE'
1232+
});
1233+
assert.throws(() => {
1234+
rli.resume();
1235+
}, {
1236+
name: 'Error',
1237+
code: 'ERR_USE_AFTER_CLOSE'
1238+
});
1239+
}));
1240+
fi.emit('data', 'Node.js\n');
1241+
}
1242+
12051243
// Can create a new readline Interface with a null output argument
12061244
{
12071245
const [rli, fi] = getInterface({ output: null, terminal });

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,9 @@ function assertCursorRowsAndCols(rli, rows, cols) {
204204
fi.emit('data', character);
205205
}
206206
fi.emit('data', '\n');
207-
rli.close();
207+
setTimeout(() => {
208+
rli.close();
209+
});
208210
}
209211

210212
// \t when there is no completer function should behave like an ordinary

test/parallel/test-readline-promises-tab-complete.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ if (process.env.TERM === 'dumb') {
8080
output = '';
8181
});
8282
}
83-
rli.close();
83+
setTimeout(() => {
84+
rli.close();
85+
})
8486
});
8587
});
8688
});
@@ -114,5 +116,7 @@ if (process.env.TERM === 'dumb') {
114116
assert.match(output, /^Tab completion error: Error: message/);
115117
output = '';
116118
});
117-
rli.close();
119+
setTimeout(() => {
120+
rli.close();
121+
});
118122
}

test/parallel/test-repl-import-referrer.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ child.on('exit', common.mustCall(() => {
2424

2525
child.stdin.write('await import(\'./message.mjs\');\n');
2626
child.stdin.write('.exit');
27-
child.stdin.end();
27+
setTimeout(() => {
28+
child.stdin.end();
29+
}, 100);

0 commit comments

Comments
 (0)