-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
repl: Assignment of _ allowed with warning #5535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
6cc2713
1dd5e2a
ca199e2
4062e62
428cef6
1471d13
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Ensures that, when invoking `.clear` in a repl, the underscore assignment behavior is reset, so that its value is again set to the most recently evaluated expression. Additional tests have been added for the behavior of `let` when underscore assignment has been disabled.
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,46 +4,126 @@ require('../common'); | |
| const assert = require('assert'); | ||
| const repl = require('repl'); | ||
| const stream = require('stream'); | ||
| const inputStream = new stream.PassThrough(); | ||
| const outputStream = new stream.PassThrough(); | ||
| let output = ''; | ||
|
|
||
| outputStream.on('data', (data) => { | ||
| output += data; | ||
| var tests = [ | ||
| testSloppyMode, | ||
| testStrictMode, | ||
| testResetContext | ||
| ]; | ||
|
|
||
| tests.forEach(function(test) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems unnecessary. Couldn't you just call the three test cases.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure - I was just modeling this on other tests in the repo. |
||
| test(); | ||
| }); | ||
|
|
||
| process.on('exit', () => { | ||
| const lines = output.trim().split('\n'); | ||
| 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 | ||
| `); | ||
|
|
||
| assert.deepStrictEqual(lines, [ | ||
| assertOutput(r.output, [ | ||
| 'undefined', | ||
| 'undefined', | ||
| 'undefined', | ||
| '10', | ||
| '10', | ||
| 'expression assignment to _ now disabled', | ||
| '20', | ||
| '20', | ||
| '30', | ||
| '20', | ||
| '40', | ||
| '30', | ||
| '40', | ||
| '40' | ||
| '30' | ||
| ]); | ||
| }); | ||
| } | ||
|
|
||
| const r = repl.start({ | ||
| prompt: '', | ||
| input: inputStream, | ||
| output: outputStream | ||
| }); | ||
| 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' | ||
| ]); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Care to explain why
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's complicated in this case. The behavior of let is such that the setter on an object is not called in a scenario like this. Because of the way Notice that a "Setting 'val'..." message is not printed for when a ** EDIT ** |
||
| } | ||
|
|
||
| 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, useGlobal) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why have this
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At one point, I suspected
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think it would be better left out. At some point we may want to lint for unused arguments like this. |
||
| 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: '', | ||
| useGlobal: !!useGlobal, | ||
| replMode: mode | ||
| }); | ||
| } | ||
|
|
||
| r.write('_;\n'); | ||
| r.write('x = 10;\n'); | ||
| r.write('_;\n'); | ||
| r.write('_ = 20;\n'); | ||
| r.write('_;\n'); | ||
| r.write('y = 30;\n'); | ||
| r.write('_;\n'); | ||
| r.write('_ = 40;\n'); | ||
| r.write('_;\n'); | ||
| r.resetContext(); | ||
| r.write('_;\n'); | ||
| function assertOutput(output, expected) { | ||
| const lines = output.accum.trim().split('\n'); | ||
| assert.deepStrictEqual(lines, expected); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest capitalizing this print, it looks to be more in line with other things the REPL prints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a complete sentence, with a period and everything? Or just start with the first word capitalized?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to making it a complete proper sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
The assignment of the last expression's results to _ is now disabled.