diff --git a/lib/repl.js b/lib/repl.js index 12461d67de481b..85692d718f75ea 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -1535,10 +1535,10 @@ function defineDefaultCommands(repl) { help: 'Save all evaluated commands in this REPL session to a file', action: function(file) { try { - fs.writeFileSync(file, this.lines.join('\n') + '\n'); - this.outputStream.write('Session saved to: ' + file + '\n'); + fs.writeFileSync(file, this.lines.join('\n')); + this.outputStream.write(`Session saved to: ${file}\n`); } catch { - this.outputStream.write('Failed to save: ' + file + '\n'); + this.outputStream.write(`Failed to save: ${file}\n`); } this.displayPrompt(); } @@ -1548,23 +1548,20 @@ function defineDefaultCommands(repl) { help: 'Load JS from a file into the REPL session', action: function(file) { try { - var stats = fs.statSync(file); + const stats = fs.statSync(file); if (stats && stats.isFile()) { _turnOnEditorMode(this); - var data = fs.readFileSync(file, 'utf8'); - var lines = data.split('\n'); - for (var n = 0; n < lines.length; n++) { - if (lines[n]) - this.write(`${lines[n]}\n`); - } + const data = fs.readFileSync(file, 'utf8'); + this.write(data); _turnOffEditorMode(this); this.write('\n'); } else { - this.outputStream.write('Failed to load: ' + file + - ' is not a valid file\n'); + this.outputStream.write( + `Failed to load: ${file} is not a valid file\n` + ); } } catch { - this.outputStream.write('Failed to load: ' + file + '\n'); + this.outputStream.write(`Failed to load: ${file}\n`); } this.displayPrompt(); } diff --git a/test/parallel/test-repl-load-multiline.js b/test/parallel/test-repl-load-multiline.js index 87b866c01be165..b2bee8d6e4647e 100644 --- a/test/parallel/test-repl-load-multiline.js +++ b/test/parallel/test-repl-load-multiline.js @@ -13,6 +13,7 @@ const expected = `${command} const getLunch = () => placeOrder('tacos') .then(eat); + const placeOrder = (order) => Promise.resolve(order); const eat = (food) => ''; diff --git a/test/parallel/test-repl-pretty-custom-stack.js b/test/parallel/test-repl-pretty-custom-stack.js index b65287c5f55b1f..0d2ada134fe2f8 100644 --- a/test/parallel/test-repl-pretty-custom-stack.js +++ b/test/parallel/test-repl-pretty-custom-stack.js @@ -5,6 +5,7 @@ const fixtures = require('../common/fixtures'); const assert = require('assert'); const repl = require('repl'); +const stackRegExp = /repl:[0-9]+:[0-9]+/g; function run({ command, expected }) { let accum = ''; @@ -23,7 +24,10 @@ function run({ command, expected }) { }); r.write(`${command}\n`); - assert.strictEqual(accum, expected); + assert.strictEqual( + accum.replace(stackRegExp, 'repl:*:*'), + expected.replace(stackRegExp, 'repl:*:*') + ); r.close(); } @@ -44,8 +48,8 @@ const tests = [ { // test .load for a file that throws command: `.load ${fixtures.path('repl-pretty-stack.js')}`, - expected: 'Thrown:\nError: Whoops!--->\nrepl:9:24--->\nd (repl:12:3)' + - '--->\nc (repl:9:3)--->\nb (repl:6:3)--->\na (repl:3:3)\n' + expected: 'Thrown:\nError: Whoops!--->\nrepl:*:*--->\nd (repl:*:*)' + + '--->\nc (repl:*:*)--->\nb (repl:*:*)--->\na (repl:*:*)\n' }, { command: 'let x y;', @@ -63,7 +67,7 @@ const tests = [ // test anonymous IIFE { command: '(function() { throw new Error(\'Whoops!\'); })()', - expected: 'Thrown:\nError: Whoops!--->\nrepl:1:21\n' + expected: 'Thrown:\nError: Whoops!--->\nrepl:*:*\n' } ]; diff --git a/test/parallel/test-repl-pretty-stack.js b/test/parallel/test-repl-pretty-stack.js index 8beb48fd689dc7..9f307c4f430b8c 100644 --- a/test/parallel/test-repl-pretty-stack.js +++ b/test/parallel/test-repl-pretty-stack.js @@ -5,6 +5,7 @@ const fixtures = require('../common/fixtures'); const assert = require('assert'); const repl = require('repl'); +const stackRegExp = /(at .*repl:)[0-9]+:[0-9]+/g; function run({ command, expected, ...extraREPLOptions }) { let accum = ''; @@ -24,7 +25,10 @@ function run({ command, expected, ...extraREPLOptions }) { }); r.write(`${command}\n`); - assert.strictEqual(accum, expected); + assert.strictEqual( + accum.replace(stackRegExp, '$1*:*'), + expected.replace(stackRegExp, '$1*:*') + ); r.close(); } @@ -32,9 +36,9 @@ const tests = [ { // Test .load for a file that throws. command: `.load ${fixtures.path('repl-pretty-stack.js')}`, - expected: 'Thrown:\nError: Whoops!\n at repl:9:24\n' + - ' at d (repl:12:3)\n at c (repl:9:3)\n' + - ' at b (repl:6:3)\n at a (repl:3:3)\n' + expected: 'Thrown:\nError: Whoops!\n at repl:*:*\n' + + ' at d (repl:*:*)\n at c (repl:*:*)\n' + + ' at b (repl:*:*)\n at a (repl:*:*)\n' }, { command: 'let x y;', @@ -48,12 +52,12 @@ const tests = [ { command: '(() => { const err = Error(\'Whoops!\'); ' + 'err.foo = \'bar\'; throw err; })()', - expected: "Thrown:\nError: Whoops!\n at repl:1:22 {\n foo: 'bar'\n}\n", + expected: "Thrown:\nError: Whoops!\n at repl:*:* {\n foo: 'bar'\n}\n", }, { command: '(() => { const err = Error(\'Whoops!\'); ' + 'err.foo = \'bar\'; throw err; })()', - expected: 'Thrown:\nError: Whoops!\n at repl:1:22 {\n foo: ' + + expected: 'Thrown:\nError: Whoops!\n at repl:*:* {\n foo: ' + "\u001b[32m'bar'\u001b[39m\n}\n", useColors: true }, @@ -64,7 +68,7 @@ const tests = [ // Test anonymous IIFE. { command: '(function() { throw new Error(\'Whoops!\'); })()', - expected: 'Thrown:\nError: Whoops!\n at repl:1:21\n' + expected: 'Thrown:\nError: Whoops!\n at repl:*:*\n' } ]; diff --git a/test/parallel/test-repl-save-load.js b/test/parallel/test-repl-save-load.js index d36a2b74d4373a..66b0f400a91764 100644 --- a/test/parallel/test-repl-save-load.js +++ b/test/parallel/test-repl-save-load.js @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -require('../common'); +const common = require('../common'); const ArrayStream = require('../common/arraystream'); const assert = require('assert'); const join = require('path').join; @@ -36,6 +36,12 @@ const works = [['inner.one'], 'inner.o']; const putIn = new ArrayStream(); const testMe = repl.start('', putIn); +// Some errors might be passed to the domain. +testMe._domain.on('error', function(reason) { + const err = new Error('Test failed'); + err.reason = reason; + throw err; +}); const testFile = [ 'var top = function() {', @@ -43,89 +49,90 @@ const testFile = [ ]; const saveFileName = join(tmpdir.path, 'test.save.js'); -// input some data +// Add some data. putIn.run(testFile); -// save it to a file +// Save it to a file. putIn.run([`.save ${saveFileName}`]); -// The file should have what I wrote +// The file should have what I wrote. assert.strictEqual(fs.readFileSync(saveFileName, 'utf8'), - `${testFile.join('\n')}\n`); + testFile.join('\n')); -{ - // save .editor mode code - const cmds = [ - 'function testSave() {', - 'return "saved";', - '}' - ]; - const putIn = new ArrayStream(); - const replServer = repl.start({ terminal: true, stream: putIn }); - - putIn.run(['.editor']); - putIn.run(cmds); - replServer.write('', { ctrl: true, name: 'd' }); - - putIn.run([`.save ${saveFileName}`]); - replServer.close(); - assert.strictEqual(fs.readFileSync(saveFileName, 'utf8'), - `${cmds.join('\n')}\n\n`); -} - -// Make sure that the REPL data is "correct" -// so when I load it back I know I'm good -testMe.complete('inner.o', function(error, data) { +// Make sure that the REPL data is "correct". +testMe.complete('inner.o', common.mustCall(function(error, data) { + assert.ifError(error); assert.deepStrictEqual(data, works); -}); +})); -// clear the REPL +// Clear the REPL. putIn.run(['.clear']); -// Load the file back in +// Load the file back in. putIn.run([`.load ${saveFileName}`]); -// Make sure that the REPL data is "correct" -testMe.complete('inner.o', function(error, data) { +// Make sure that the REPL data is "correct". +testMe.complete('inner.o', common.mustCall(function(error, data) { + assert.ifError(error); assert.deepStrictEqual(data, works); -}); +})); -// clear the REPL +// Clear the REPL. putIn.run(['.clear']); let loadFile = join(tmpdir.path, 'file.does.not.exist'); -// should not break -putIn.write = function(data) { - // Make sure I get a failed to load message and not some crazy error - assert.strictEqual(data, `Failed to load:${loadFile}\n`); - // Eat me to avoid work +// Should not break. +putIn.write = common.mustCall(function(data) { + // Make sure I get a failed to load message and not some crazy error. + assert.strictEqual(data, `Failed to load: ${loadFile}\n`); + // Eat me to avoid work. putIn.write = () => {}; -}; +}); putIn.run([`.load ${loadFile}`]); -// Throw error on loading directory +// Throw error on loading directory. loadFile = tmpdir.path; -putIn.write = function(data) { - assert.strictEqual(data, `Failed to load:${loadFile} is not a valid file\n`); +putIn.write = common.mustCall(function(data) { + assert.strictEqual(data, `Failed to load: ${loadFile} is not a valid file\n`); putIn.write = () => {}; -}; +}); putIn.run([`.load ${loadFile}`]); -// clear the REPL +// Clear the REPL. putIn.run(['.clear']); // NUL (\0) is disallowed in filenames in UNIX-like operating systems and -// Windows so we can use that to test failed saves +// Windows so we can use that to test failed saves. const invalidFileName = join(tmpdir.path, '\0\0\0\0\0'); -// should not break -putIn.write = function(data) { - // Make sure I get a failed to save message and not some other error - assert.strictEqual(data, `Failed to save:${invalidFileName}\n`); - // reset to no-op +// Should not break. +putIn.write = common.mustCall(function(data) { + // Make sure I get a failed to save message and not some other error. + assert.strictEqual(data, `Failed to save: ${invalidFileName}\n`); + // Reset to no-op. putIn.write = () => {}; -}; +}); -// save it to a file +// Save it to a file. putIn.run([`.save ${invalidFileName}`]); + +{ + // Save .editor mode code. + const cmds = [ + 'function testSave() {', + 'return "saved";', + '}' + ]; + const putIn = new ArrayStream(); + const replServer = repl.start({ terminal: true, stream: putIn }); + + putIn.run(['.editor']); + putIn.run(cmds); + replServer.write('', { ctrl: true, name: 'd' }); + + putIn.run([`.save ${saveFileName}`]); + replServer.close(); + assert.strictEqual(fs.readFileSync(saveFileName, 'utf8'), + `${cmds.join('\n')}\n`); +}