Skip to content

Commit 7a8ce5f

Browse files
committed
fix: use private block scope RegExp instead of shared module scope RegExp
1 parent 04b00ba commit 7a8ce5f

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

lib/internal/readline/interface.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const {
2020
MathMaxApply,
2121
NumberIsFinite,
2222
ObjectSetPrototypeOf,
23+
RegExp,
2324
RegExpPrototypeExec,
2425
StringPrototypeCodePointAt,
2526
StringPrototypeEndsWith,
@@ -72,7 +73,7 @@ const kHistorySize = 30;
7273
const kMaxUndoRedoStackSize = 2048;
7374
const kMincrlfDelay = 100;
7475
// \r\n, \n, or \r followed by something other than \n
75-
const lineEnding = /\r?\n|\r(?!\n)/g;
76+
const lineEndingPattern = '\r?\n|\r(?!\n)';
7677

7778
const kLineObjectStream = Symbol('line object stream');
7879
const kQuestionCancel = Symbol('kQuestionCancel');
@@ -585,6 +586,7 @@ class Interface extends InterfaceConstructor {
585586
}
586587

587588
// Run test() on the new string chunk, not on the entire line buffer.
589+
const lineEnding = new RegExp(lineEndingPattern, 'g');
588590
let newPartContainsEnding = RegExpPrototypeExec(lineEnding, string);
589591
if (newPartContainsEnding !== null) {
590592
if (this[kLine_buffer]) {
@@ -1322,18 +1324,24 @@ class Interface extends InterfaceConstructor {
13221324
// falls through
13231325
default:
13241326
if (typeof s === 'string' && s) {
1327+
/**
1328+
* Use Regular Expression scoped to this block, as lastIndex and the state for RegExpPrototypeExec
1329+
* will be overwritten if the same RegEx instance is reused in recursive function calls.
1330+
*/
1331+
const lineEnding = new RegExp(lineEndingPattern, 'g');
13251332
let nextMatch = RegExpPrototypeExec(lineEnding, s);
1326-
if (nextMatch !== null) {
1327-
this[kInsertString](StringPrototypeSlice(s, 0, nextMatch.index));
1328-
let { lastIndex } = lineEnding;
1329-
while ((nextMatch = RegExpPrototypeExec(lineEnding, s)) !== null) {
1330-
this[kLine]();
1333+
1334+
// If no line endings are found, just insert the string as is
1335+
if (nextMatch === null) {
1336+
this[kInsertString](s);
1337+
} else {
1338+
// Keep track of the end of the last match
1339+
let lastIndex = 0;
1340+
do {
13311341
this[kInsertString](StringPrototypeSlice(s, lastIndex, nextMatch.index));
1342+
this[kLine]();
13321343
({ lastIndex } = lineEnding);
1333-
}
1334-
if (lastIndex === s.length) this[kLine]();
1335-
} else {
1336-
this[kInsertString](s);
1344+
} while ((nextMatch = RegExpPrototypeExec(lineEnding, s)) !== null);
13371345
}
13381346
}
13391347
}

lib/repl.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ function REPLServer(prompt,
862862
const matches = self._sawKeyPress ?
863863
RegExpPrototypeExec(/^\s+/, cmd) : null;
864864
// Preserve indentation in editorMode
865-
if (matches && !self.loadMode) {
865+
if (matches) {
866866
const prefix = matches[0];
867867
self.write(prefix);
868868
self.line = prefix;
@@ -1780,11 +1780,9 @@ function defineDefaultCommands(repl) {
17801780
const stats = fs.statSync(file);
17811781
if (stats && stats.isFile()) {
17821782
_turnOnEditorMode(this);
1783-
this.loadMode = true;
17841783
const data = fs.readFileSync(file, 'utf8');
17851784
this.write(data);
17861785
_turnOffEditorMode(this);
1787-
this.loadMode = false;
17881786
this.write('\n');
17891787
} else {
17901788
this.output.write(
@@ -1793,7 +1791,6 @@ function defineDefaultCommands(repl) {
17931791
}
17941792
} catch {
17951793
this.output.write(`Failed to load: ${file}\n`);
1796-
this.loadMode = false;
17971794
}
17981795
this.displayPrompt();
17991796
}

0 commit comments

Comments
 (0)