-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
repl: Assignment of _ allowed with warning
This commit addresses #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: #5535 Fixes: #5431 Reviewed-By: Roman Reiss <me@silverwind.io> Reviewed-By: James M Snell <jasnell@gmail.com>
- Loading branch information
1 parent
c67937b
commit ad8257f
Showing
3 changed files
with
183 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |