Skip to content

Commit

Permalink
repl: Mitigate vm #548 function redefinition issue
Browse files Browse the repository at this point in the history
```js
node 🙈 ₹ git:(upstream ⚡ repl-tmp-548) ./node
> function name() { return "node"; };
undefined
> name()
'node'
> function name() { return "nodejs"; };
undefined
> name()
'nodejs'
>
```

PR-URL: #7794
Reviewed-By: Evan Lucas <evanlucas@me.com>
  • Loading branch information
princejwesley authored and evanlucas committed Jul 21, 2016
1 parent d3f0a6a commit 72fc4eb
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 13 deletions.
34 changes: 21 additions & 13 deletions lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,19 +471,7 @@ function REPLServer(prompt,
}

var evalCmd = self.bufferedCommand + cmd;
if (/^\s*\{/.test(evalCmd) && /\}\s*$/.test(evalCmd)) {
// It's confusing for `{ a : 1 }` to be interpreted as a block
// statement rather than an object literal. So, we first try
// to wrap it in parentheses, so that it will be interpreted as
// an expression.
evalCmd = '(' + evalCmd + ')\n';
self.wrappedCmd = true;
} else {
// otherwise we just append a \n so that it will be either
// terminated, or continued onto the next expression if it's an
// unexpected end of input.
evalCmd = evalCmd + '\n';
}
evalCmd = preprocess(evalCmd);

debug('eval %j', evalCmd);
self.eval(evalCmd, self.context, 'repl', finish);
Expand Down Expand Up @@ -538,6 +526,26 @@ function REPLServer(prompt,
// Display prompt again
self.displayPrompt();
}

function preprocess(code) {
let cmd = code;
if (/^\s*\{/.test(cmd) && /\}\s*$/.test(cmd)) {
// It's confusing for `{ a : 1 }` to be interpreted as a block
// statement rather than an object literal. So, we first try
// to wrap it in parentheses, so that it will be interpreted as
// an expression.
cmd = `(${cmd})`;
self.wrappedCmd = true;
} else {
// Mitigate https://github.com/nodejs/node/issues/548
cmd = cmd.replace(/^\s*function\s+([^(]+)/,
(_, name) => `var ${name} = function ${name}`);
}
// Append a \n so that it will be either
// terminated, or continued onto the next expression if it's an
// unexpected end of input.
return `${cmd}\n`;
}
});

self.on('SIGCONT', function() {
Expand Down
38 changes: 38 additions & 0 deletions test/known_issues/test-repl-function-redefinition-edge-case.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Reference: https://github.com/nodejs/node/pull/7624
'use strict';
const common = require('../common');
const assert = require('assert');
const repl = require('repl');
const stream = require('stream');

common.globalCheck = false;

const r = initRepl();

r.input.emit('data', 'function a() { return 42; } (1)\n');
r.input.emit('data', 'a\n');
r.input.emit('data', '.exit');

const expected = '1\n[Function a]\n';
const got = r.output.accumulator.join('');
assert.strictEqual(got, expected);

function initRepl() {
const input = new stream();
input.write = input.pause = input.resume = () => {};
input.readable = true;

const output = new stream();
output.writable = true;
output.accumulator = [];

output.write = (data) => output.accumulator.push(data);

return repl.start({
input,
output,
useColors: false,
terminal: false,
prompt: ''
});
}
5 changes: 5 additions & 0 deletions test/parallel/test-repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,11 @@ function error_test() {
// or block comment. https://github.com/nodejs/node/issues/3611
{ client: client_unix, send: 'a = 3.5e',
expect: /^SyntaxError: Unexpected token ILLEGAL/ },
// Mitigate https://github.com/nodejs/node/issues/548
{ client: client_unix, send: 'function name(){ return "node"; };name()',
expect: "'node'\n" + prompt_unix },
{ client: client_unix, send: 'function name(){ return "nodejs"; };name()',
expect: "'nodejs'\n" + prompt_unix },
]);
}

Expand Down

0 comments on commit 72fc4eb

Please sign in to comment.