Skip to content

Commit 831d193

Browse files
committed
repl: fix infinite loop caused by indentation preservation
The editorMode's indentation preservation feature causes an infinite loop in certain cases when using the REPL's .load feature. This commit adds a variable to keep track of whether load is used and disables the indentation preservation in this case.
1 parent 1b87cb6 commit 831d193

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

lib/repl.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,8 @@ function REPLServer(prompt,
855855
cmd = cmd || '';
856856
sawSIGINT = false;
857857

858-
if (self.editorMode) {
858+
// Preserve indentation in editorMode
859+
if (self.editorMode && !self.loadMode) {
859860
self[kBufferedCommandSymbol] += cmd + '\n';
860861

861862
// code alignment
@@ -1779,9 +1780,11 @@ function defineDefaultCommands(repl) {
17791780
const stats = fs.statSync(file);
17801781
if (stats && stats.isFile()) {
17811782
_turnOnEditorMode(this);
1783+
this.loadMode = true;
17821784
const data = fs.readFileSync(file, 'utf8');
17831785
this.write(data);
17841786
_turnOffEditorMode(this);
1787+
this.loadMode = false;
17851788
this.write('\n');
17861789
} else {
17871790
this.output.write(
@@ -1790,6 +1793,7 @@ function defineDefaultCommands(repl) {
17901793
}
17911794
} catch {
17921795
this.output.write(`Failed to load: ${file}\n`);
1796+
this.loadMode = false;
17931797
}
17941798
this.displayPrompt();
17951799
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'use strict';
2+
const common = require('../common');
3+
const ArrayStream = require('../common/arraystream');
4+
const assert = require('assert');
5+
const join = require('path').join;
6+
const fs = require('fs');
7+
8+
common.skipIfDumbTerminal();
9+
10+
const tmpdir = require('../common/tmpdir');
11+
tmpdir.refresh();
12+
13+
const terminalCode = '\u001b[1G\u001b[0J \u001b[1G';
14+
const terminalCodeRegex = new RegExp(terminalCode.replace(/\[/g, '\\['), 'g');
15+
16+
const repl = require('repl');
17+
18+
const inputStream = new ArrayStream();
19+
const outputStream = new ArrayStream();
20+
21+
const r = repl.start({
22+
prompt: '',
23+
input: inputStream,
24+
output: outputStream,
25+
terminal: true,
26+
useColors: false
27+
});
28+
29+
const testFile = 'function a(b) {\n return b }\na(1)\n';
30+
const testFileName = join(tmpdir.path, 'foo.js');
31+
fs.writeFileSync(testFileName, testFile);
32+
33+
const command = `.load ${testFileName}\n`;
34+
let accum = '';
35+
outputStream.write = (data) => accum += data.replace('\r', '');
36+
37+
38+
// load test file.
39+
r.write('.editor\n');
40+
r.write(command);
41+
42+
const expected = command +
43+
'function a(b) {\n' +
44+
' return b }\n' +
45+
'a(1)\n' +
46+
'1\n';
47+
assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected);
48+
r.close();

0 commit comments

Comments
 (0)