summaryrefslogtreecommitdiff
path: root/test/parallel/test-repl-underscore.js
diff options
context:
space:
mode:
authorLance Ball <lball@redhat.com>2016-03-02 16:45:16 -0500
committersilverwind <me@silverwind.io>2016-03-18 21:03:40 +0100
commitad8257fa5b9795d3d79fa4a91d0f18c43f024ab3 (patch)
treeb28a5a76c2c6ba7175b760e6720b7af2a26bd48d /test/parallel/test-repl-underscore.js
parentc67937bebbb8b1de01e8fb878608b8ea5a34cba3 (diff)
downloadandroid-node-v8-ad8257fa5b9795d3d79fa4a91d0f18c43f024ab3.tar.gz
android-node-v8-ad8257fa5b9795d3d79fa4a91d0f18c43f024ab3.tar.bz2
android-node-v8-ad8257fa5b9795d3d79fa4a91d0f18c43f024ab3.zip
repl: Assignment of _ allowed with warning
This commit addresses https://github.com/nodejs/node/issues/5431 by changing the way that the repl handles assignment to the global _ variable. Prior to this commit, node sets the result of the last expression evaluated in the repl to `_`. This causes problems for users of underscore, lodash and other packages where it is common to assign `_` to the package, e.g. `_ = require('lodash');`. Changes in this commit now result in the following behavior. - If unassigned on the repl, `_` continues to refer to the last evaluated expression. - If assigned, the default behavior of assigning `_` to the last evaluated expression is disabled, and `_` now references whatever value was explicitly set. A warning is issued on the repl - 'expression assignment to _ now disabled'. - If `_` is assigned multiple times, the warning is only displayed once. - When `.clear` is executed in the repl, `_` continues to refer to its most recent value, whatever that is (this is per existing behavior). If `_` had been explicitly set prior to `.clear` it will not change again with the evaluation of the next expression. PR-URL: https://github.com/nodejs/node/pull/5535 Fixes: https://github.com/nodejs/node/issues/5431 Reviewed-By: Roman Reiss <me@silverwind.io> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'test/parallel/test-repl-underscore.js')
-rw-r--r--test/parallel/test-repl-underscore.js156
1 files changed, 156 insertions, 0 deletions
diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js
new file mode 100644
index 0000000000..97fc508ad9
--- /dev/null
+++ b/test/parallel/test-repl-underscore.js
@@ -0,0 +1,156 @@
+'use strict';
+
+require('../common');
+const assert = require('assert');
+const repl = require('repl');
+const stream = require('stream');
+
+testSloppyMode();
+testStrictMode();
+testResetContext();
+testMagicMode();
+
+function testSloppyMode() {
+ const r = initRepl(repl.REPL_MODE_SLOPPY);
+
+ // cannot use `let` in sloppy mode
+ r.write(`_; // initial value undefined
+ var x = 10; // evaluates to undefined
+ _; // still undefined
+ y = 10; // evaluates to 10
+ _; // 10 from last eval
+ _ = 20; // explicitly set to 20
+ _; // 20 from user input
+ _ = 30; // make sure we can set it twice and no prompt
+ _; // 30 from user input
+ y = 40; // make sure eval doesn't change _
+ _; // remains 30 from user input
+ `);
+
+ assertOutput(r.output, [
+ 'undefined',
+ 'undefined',
+ 'undefined',
+ '10',
+ '10',
+ 'Expression assignment to _ now disabled.',
+ '20',
+ '20',
+ '30',
+ '30',
+ '40',
+ '30'
+ ]);
+}
+
+function testStrictMode() {
+ const r = initRepl(repl.REPL_MODE_STRICT);
+
+ r.write(`_; // initial value undefined
+ var x = 10; // evaluates to undefined
+ _; // still undefined
+ let _ = 20; // use 'let' only in strict mode - evals to undefined
+ _; // 20 from user input
+ _ = 30; // make sure we can set it twice and no prompt
+ _; // 30 from user input
+ var y = 40; // make sure eval doesn't change _
+ _; // remains 30 from user input
+ function f() { let _ = 50; } // undefined
+ f(); // undefined
+ _; // remains 30 from user input
+ `);
+
+ assertOutput(r.output, [
+ 'undefined',
+ 'undefined',
+ 'undefined',
+ 'undefined',
+ '20',
+ '30',
+ '30',
+ 'undefined',
+ '30',
+ 'undefined',
+ 'undefined',
+ '30'
+ ]);
+}
+
+function testMagicMode() {
+ const r = initRepl(repl.REPL_MODE_MAGIC);
+
+ r.write(`_; // initial value undefined
+ x = 10; //
+ _; // last eval - 10
+ let _ = 20; // undefined
+ _; // 20 from user input
+ _ = 30; // make sure we can set it twice and no prompt
+ _; // 30 from user input
+ var y = 40; // make sure eval doesn't change _
+ _; // remains 30 from user input
+ function f() { let _ = 50; return _; } // undefined
+ f(); // 50
+ _; // remains 30 from user input
+ `);
+
+ assertOutput(r.output, [
+ 'undefined',
+ '10',
+ '10',
+ 'undefined',
+ '20',
+ '30',
+ '30',
+ 'undefined',
+ '30',
+ 'undefined',
+ '50',
+ '30'
+ ]);
+}
+
+function testResetContext() {
+ const r = initRepl(repl.REPL_MODE_SLOPPY);
+
+ r.write(`_ = 10; // explicitly set to 10
+ _; // 10 from user input
+ .clear // Clearing context...
+ _; // remains 10
+ x = 20; // but behavior reverts to last eval
+ _; // expect 20
+ `);
+
+ assertOutput(r.output, [
+ 'Expression assignment to _ now disabled.',
+ '10',
+ '10',
+ 'Clearing context...',
+ '10',
+ '20',
+ '20'
+ ]);
+}
+
+function initRepl(mode) {
+ const inputStream = new stream.PassThrough();
+ const outputStream = new stream.PassThrough();
+ outputStream.accum = '';
+
+ outputStream.on('data', (data) => {
+ outputStream.accum += data;
+ });
+
+ return repl.start({
+ input: inputStream,
+ output: outputStream,
+ useColors: false,
+ terminal: false,
+ prompt: '',
+ replMode: mode
+ });
+}
+
+function assertOutput(output, expected) {
+ const lines = output.accum.trim().split('\n');
+ assert.deepStrictEqual(lines, expected);
+}