From 9366b8d90a479777c362774fb53ab15b16d07bad Mon Sep 17 00:00:00 2001 From: Prince J Wesley Date: Wed, 23 Nov 2016 03:46:25 +0530 Subject: [PATCH] repl: preprocess only for defaultEval Code preprocessing is applicable only for default eval function. Therefore, Moved `preprocess` function invocation inside `defaultEval` function. Fixes: https://github.com/nodejs/node/issues/9743 PR-URL: https://github.com/nodejs/node/pull/9752 Reviewed-By: Anna Henningsen --- lib/repl.js | 51 +++++++++++++++++---------------- test/parallel/test-repl-eval.js | 10 +++++-- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 8bddfb5e3a..9c58105655 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -238,7 +238,33 @@ function REPLServer(prompt, eval_ = eval_ || defaultEval; + 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*(\*)\s*|\s+)([^(]+)/, + (_, genStar, name) => `var ${name} = function ${genStar || ''}${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`; + } + function defaultEval(code, context, file, cb) { + // Remove trailing new line + code = code.replace(/\n$/, ''); + code = preprocess(code); + var err, result, retry = false, input = code, wrappedErr; // first, create the Script object to check the syntax @@ -499,8 +525,7 @@ function REPLServer(prompt, } } - var evalCmd = self.bufferedCommand + cmd; - evalCmd = preprocess(evalCmd); + const evalCmd = self.bufferedCommand + cmd + '\n'; debug('eval %j', evalCmd); self.eval(evalCmd, self.context, 'repl', finish); @@ -557,28 +582,6 @@ 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*(\*)\s*|\s+)([^(]+)/, - (_, genStar, name) => `var ${name} = function ${genStar || ''}${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 onSigCont() { diff --git a/test/parallel/test-repl-eval.js b/test/parallel/test-repl-eval.js index 7e5c7d3994..1eb4e2371c 100644 --- a/test/parallel/test-repl-eval.js +++ b/test/parallel/test-repl-eval.js @@ -10,7 +10,8 @@ const repl = require('repl'); eval: common.mustCall((cmd, context) => { // Assertions here will not cause the test to exit with an error code // so set a boolean that is checked in process.on('exit',...) instead. - evalCalledWithExpectedArgs = (cmd === 'foo\n' && context.foo === 'bar'); + evalCalledWithExpectedArgs = (cmd === 'function f() {}\n' && + context.foo === 'bar'); }) }; @@ -18,7 +19,12 @@ const repl = require('repl'); r.context = {foo: 'bar'}; try { - r.write('foo\n'); + // Default preprocessor transforms + // function f() {} to + // var f = function f() {} + // Test to ensure that original input is preserved. + // Reference: https://github.com/nodejs/node/issues/9743 + r.write('function f() {}\n'); } finally { r.write('.exit\n'); }