Skip to content

Commit

Permalink
repl: fix infinite loop caused by indentation preservation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Theo-Steiner committed Feb 20, 2023
1 parent 1b87cb6 commit 831d193
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
6 changes: 5 additions & 1 deletion lib/repl.js
Expand Up @@ -855,7 +855,8 @@ function REPLServer(prompt,
cmd = cmd || '';
sawSIGINT = false;

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

// code alignment
Expand Down Expand Up @@ -1779,9 +1780,11 @@ function defineDefaultCommands(repl) {
const stats = fs.statSync(file);
if (stats && stats.isFile()) {
_turnOnEditorMode(this);
this.loadMode = true;
const data = fs.readFileSync(file, 'utf8');
this.write(data);
_turnOffEditorMode(this);
this.loadMode = false;
this.write('\n');
} else {
this.output.write(
Expand All @@ -1790,6 +1793,7 @@ function defineDefaultCommands(repl) {
}
} catch {
this.output.write(`Failed to load: ${file}\n`);
this.loadMode = false;
}
this.displayPrompt();
}
Expand Down
48 changes: 48 additions & 0 deletions test/parallel/test-repl-load-and-execute.js
@@ -0,0 +1,48 @@
'use strict';
const common = require('../common');
const ArrayStream = require('../common/arraystream');
const assert = require('assert');
const join = require('path').join;
const fs = require('fs');

common.skipIfDumbTerminal();

const tmpdir = require('../common/tmpdir');
tmpdir.refresh();

const terminalCode = '\u001b[1G\u001b[0J \u001b[1G';
const terminalCodeRegex = new RegExp(terminalCode.replace(/\[/g, '\\['), 'g');

const repl = require('repl');

const inputStream = new ArrayStream();
const outputStream = new ArrayStream();

const r = repl.start({
prompt: '',
input: inputStream,
output: outputStream,
terminal: true,
useColors: false
});

const testFile = 'function a(b) {\n return b }\na(1)\n';
const testFileName = join(tmpdir.path, 'foo.js');
fs.writeFileSync(testFileName, testFile);

const command = `.load ${testFileName}\n`;
let accum = '';
outputStream.write = (data) => accum += data.replace('\r', '');


// load test file.
r.write('.editor\n');
r.write(command);

const expected = command +
'function a(b) {\n' +
' return b }\n' +
'a(1)\n' +
'1\n';
assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected);
r.close();

0 comments on commit 831d193

Please sign in to comment.