Skip to content

Commit 9dc21a9

Browse files
committed
readline: initialize input before history manager
1 parent 68d7b6f commit 9dc21a9

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

lib/internal/readline/interface.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ function InterfaceConstructor(input, output, completer, terminal) {
215215
input.removeHistoryDuplicates = removeHistoryDuplicates;
216216
}
217217

218-
this.setupHistoryManager(input);
219218

220219
if (completer !== undefined && typeof completer !== 'function') {
221220
throw new ERR_INVALID_ARG_VALUE('completer', completer);
@@ -234,6 +233,7 @@ function InterfaceConstructor(input, output, completer, terminal) {
234233
this[kSubstringSearch] = null;
235234
this.output = output;
236235
this.input = input;
236+
this.setupHistoryManager(input);
237237
this[kUndoStack] = [];
238238
this[kRedoStack] = [];
239239
this[kPreviousCursorCols] = -1;
@@ -384,9 +384,13 @@ class Interface extends InterfaceConstructor {
384384
setupHistoryManager(options) {
385385
this.historyManager = new ReplHistory(this, options);
386386

387-
if (options.onHistoryFileLoaded) {
388-
this.historyManager.initialize(options.onHistoryFileLoaded);
389-
}
387+
// Only initialize REPL history when createInterface()
388+
// was called with an options object (options.input).
389+
// This prevents accidental REPL history init when
390+
// createInterface(input) is used.
391+
if (options?.input && typeof options.onHistoryFileLoaded === 'function') {
392+
this.historyManager.initialize(options.onHistoryFileLoaded);
393+
}
390394

391395
ObjectDefineProperty(this, 'history', {
392396
__proto__: null, configurable: true, enumerable: true,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const readline = require('readline');
5+
const { PassThrough } = require('stream');
6+
7+
assert.doesNotThrow(() => {
8+
const input = new PassThrough();
9+
10+
// This simulates the condition that previously caused
11+
// accidental REPL history initialization.
12+
input.onHistoryFileLoaded = () => {};
13+
14+
readline.createInterface({
15+
input,
16+
output: new PassThrough()
17+
});
18+
});

0 commit comments

Comments
 (0)