From 761e8df55e157fe9303b7f441f9e7ff3c90ee263 Mon Sep 17 00:00:00 2001 From: Prince J Wesley Date: Sat, 9 Jul 2016 04:29:23 +0530 Subject: [PATCH 1/4] repl: Mitigate vm #548 function redefinition issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ```js node 🙈 ₹ git:(upstream ⚡ repl-tmp-548) ./node > function name() { return "node"; }; undefined > name() 'node' > function name() { return "nodejs"; }; undefined > name() 'nodejs' > ``` --- lib/repl.js | 34 +++++++++++++++++++++------------- test/parallel/test-repl.js | 5 +++++ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index ed896552656c51..7b83068e44c979 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -472,19 +472,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); @@ -539,6 +527,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 vm #548 issue + 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() { diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index f321f43174b135..b92709661ed037 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -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: Invalid or unexpected token/ }, + // Mitigate #548 issue + { 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 }, ]); } From db8d80928d3983f6ada91102a76626589d33f2ab Mon Sep 17 00:00:00 2001 From: Prince J Wesley Date: Sat, 9 Jul 2016 05:21:12 +0530 Subject: [PATCH 2/4] Add absolute issue URL --- lib/repl.js | 2 +- test/parallel/test-repl.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 7b83068e44c979..4f9827564afb3a 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -538,7 +538,7 @@ function REPLServer(prompt, cmd = `(${cmd})`; self.wrappedCmd = true; } else { - // Mitigate vm #548 issue + // Mitigate https://github.com/nodejs/node/issues/548 cmd = cmd.replace(/^\s*function\s+([^(]+)/, (_, name) => `var ${name} = function ${name}`); } diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index b92709661ed037..79369672028e05 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -328,7 +328,7 @@ function error_test() { // or block comment. https://github.com/nodejs/node/issues/3611 { client: client_unix, send: 'a = 3.5e', expect: /^SyntaxError: Invalid or unexpected token/ }, - // Mitigate #548 issue + // 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()', From f1eb84e5e49daec11a97a93c26668aa373a221a0 Mon Sep 17 00:00:00 2001 From: Prince J Wesley Date: Sun, 10 Jul 2016 14:12:13 +0530 Subject: [PATCH 3/4] Add known issue test --- ...st-repl-function-redefinition-edge-case.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 test/known_issues/test-repl-function-redefinition-edge-case.js diff --git a/test/known_issues/test-repl-function-redefinition-edge-case.js b/test/known_issues/test-repl-function-redefinition-edge-case.js new file mode 100644 index 00000000000000..68872797c6b177 --- /dev/null +++ b/test/known_issues/test-repl-function-redefinition-edge-case.js @@ -0,0 +1,40 @@ +// 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.equal(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: '' + }); +} + + From 13f8f3aabb5aa7e538d02c08c3023db7e672f392 Mon Sep 17 00:00:00 2001 From: Prince J Wesley Date: Sun, 10 Jul 2016 20:49:31 +0530 Subject: [PATCH 4/4] Use strictEquals assertion --- .../known_issues/test-repl-function-redefinition-edge-case.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/known_issues/test-repl-function-redefinition-edge-case.js b/test/known_issues/test-repl-function-redefinition-edge-case.js index 68872797c6b177..03b721fba7e7d5 100644 --- a/test/known_issues/test-repl-function-redefinition-edge-case.js +++ b/test/known_issues/test-repl-function-redefinition-edge-case.js @@ -15,7 +15,7 @@ r.input.emit('data', '.exit'); const expected = '1\n[Function a]\n'; const got = r.output.accumulator.join(''); -assert.equal(got, expected); +assert.strictEqual(got, expected); function initRepl() { const input = new stream(); @@ -36,5 +36,3 @@ function initRepl() { prompt: '' }); } - -