Skip to content

Commit

Permalink
repl: give repl entries unique names
Browse files Browse the repository at this point in the history
This is a workaround for the REPL for a problem when multiple of the
entries have the same source text

Fixes: nodejs#1337
Refs: https://bugs.chromium.org/p/v8/issues/detail?id=10284

PR-URL: nodejs#34372
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
  • Loading branch information
bmeck committed Aug 3, 2020
1 parent 54746bb commit ca26eae
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 deletions.
14 changes: 10 additions & 4 deletions lib/repl.js
Expand Up @@ -128,6 +128,12 @@ const {
} = internalBinding('contextify');

const history = require('internal/repl/history');
let nextREPLResourceNumber = 1;
// This prevents v8 code cache from getting confused and using a different
// cache from a resource of the same name
function getREPLResourceName() {
return `REPL${nextREPLResourceNumber++}`;
}

// Lazy-loaded.
let processTopLevelAwait;
Expand Down Expand Up @@ -568,10 +574,10 @@ function REPLServer(prompt,
if (e.name === 'SyntaxError') {
// Remove stack trace.
e.stack = e.stack
.replace(/^repl:\d+\r?\n/, '')
.replace(/^REPL\d+:\d+\r?\n/, '')
.replace(/^\s+at\s.*\n?/gm, '');
} else if (self.replMode === module.exports.REPL_MODE_STRICT) {
e.stack = e.stack.replace(/(\s+at\s+repl:)(\d+)/,
e.stack = e.stack.replace(/(\s+at\s+REPL\d+:)(\d+)/,
(_, pre, line) => pre + (line - 1));
}
}
Expand Down Expand Up @@ -767,7 +773,7 @@ function REPLServer(prompt,
const evalCmd = self[kBufferedCommandSymbol] + cmd + '\n';

debug('eval %j', evalCmd);
self.eval(evalCmd, self.context, 'repl', finish);
self.eval(evalCmd, self.context, getREPLResourceName(), finish);

function finish(e, ret) {
debug('finish', e, ret);
Expand Down Expand Up @@ -1248,7 +1254,7 @@ function complete(line, callback) {

const memberGroups = [];
const evalExpr = `try { ${expr} } catch {}`;
this.eval(evalExpr, this.context, 'repl', (e, obj) => {
this.eval(evalExpr, this.context, getREPLResourceName(), (e, obj) => {
try {
let p;
if ((typeof obj === 'object' && obj !== null) ||
Expand Down
20 changes: 20 additions & 0 deletions test/parallel/test-repl-dynamic-import.js
@@ -0,0 +1,20 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const child_process = require('child_process');
const child = child_process.spawn(process.execPath, [
'--interactive',
'--expose-gc'
], {
stdio: 'pipe'
});
child.stdin.write('\nimport("fs");\n_.then(gc);\n');
// Wait for concurrent GC to finish
setTimeout(() => {
child.stdin.write('\nimport("fs");\n');
child.stdin.write('\nprocess.exit(0);\n');
}, common.platformTimeout(50));
child.on('exit', (code, signal) => {
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
});
12 changes: 6 additions & 6 deletions test/parallel/test-repl-pretty-custom-stack.js
Expand Up @@ -5,7 +5,7 @@ const fixtures = require('../common/fixtures');
const assert = require('assert');
const repl = require('repl');

const stackRegExp = /repl:[0-9]+:[0-9]+/g;
const stackRegExp = /(REPL\d+):[0-9]+:[0-9]+/g;

function run({ command, expected }) {
let accum = '';
Expand All @@ -25,8 +25,8 @@ function run({ command, expected }) {

r.write(`${command}\n`);
assert.strictEqual(
accum.replace(stackRegExp, 'repl:*:*'),
expected.replace(stackRegExp, 'repl:*:*')
accum.replace(stackRegExp, '$1:*:*'),
expected.replace(stackRegExp, '$1:*:*')
);
r.close();
}
Expand All @@ -48,8 +48,8 @@ const tests = [
{
// test .load for a file that throws
command: `.load ${fixtures.path('repl-pretty-stack.js')}`,
expected: 'Uncaught Error: Whoops!--->\nrepl:*:*--->\nd (repl:*:*)' +
'--->\nc (repl:*:*)--->\nb (repl:*:*)--->\na (repl:*:*)\n'
expected: 'Uncaught Error: Whoops!--->\nREPL1:*:*--->\nd (REPL1:*:*)' +
'--->\nc (REPL1:*:*)--->\nb (REPL1:*:*)--->\na (REPL1:*:*)\n'
},
{
command: 'let x y;',
Expand All @@ -67,7 +67,7 @@ const tests = [
// test anonymous IIFE
{
command: '(function() { throw new Error(\'Whoops!\'); })()',
expected: 'Uncaught Error: Whoops!--->\nrepl:*:*\n'
expected: 'Uncaught Error: Whoops!--->\nREPL5:*:*\n'
}
];

Expand Down
14 changes: 7 additions & 7 deletions test/parallel/test-repl-pretty-stack.js
Expand Up @@ -5,7 +5,7 @@ const fixtures = require('../common/fixtures');
const assert = require('assert');
const repl = require('repl');

const stackRegExp = /(at .*repl:)[0-9]+:[0-9]+/g;
const stackRegExp = /(at .*REPL\d+:)[0-9]+:[0-9]+/g;

function run({ command, expected, ...extraREPLOptions }, i) {
let accum = '';
Expand Down Expand Up @@ -37,9 +37,9 @@ const tests = [
{
// Test .load for a file that throws.
command: `.load ${fixtures.path('repl-pretty-stack.js')}`,
expected: 'Uncaught Error: Whoops!\n at repl:*:*\n' +
' at d (repl:*:*)\n at c (repl:*:*)\n' +
' at b (repl:*:*)\n at a (repl:*:*)\n'
expected: 'Uncaught Error: Whoops!\n at REPL1:*:*\n' +
' at d (REPL1:*:*)\n at c (REPL1:*:*)\n' +
' at b (REPL1:*:*)\n at a (REPL1:*:*)\n'
},
{
command: 'let x y;',
Expand All @@ -53,12 +53,12 @@ const tests = [
{
command: '(() => { const err = Error(\'Whoops!\'); ' +
'err.foo = \'bar\'; throw err; })()',
expected: "Uncaught Error: Whoops!\n at repl:*:* {\n foo: 'bar'\n}\n",
expected: "Uncaught Error: Whoops!\n at REPL4:*:* {\n foo: 'bar'\n}\n",
},
{
command: '(() => { const err = Error(\'Whoops!\'); ' +
'err.foo = \'bar\'; throw err; })()',
expected: 'Uncaught Error: Whoops!\n at repl:*:* {\n foo: ' +
expected: 'Uncaught Error: Whoops!\n at REPL5:*:* {\n foo: ' +
"\u001b[32m'bar'\u001b[39m\n}\n",
useColors: true
},
Expand All @@ -69,7 +69,7 @@ const tests = [
// Test anonymous IIFE.
{
command: '(function() { throw new Error(\'Whoops!\'); })()',
expected: 'Uncaught Error: Whoops!\n at repl:*:*\n'
expected: 'Uncaught Error: Whoops!\n at REPL7:*:*\n'
}
];

Expand Down

0 comments on commit ca26eae

Please sign in to comment.