1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23const common = require('../common'); 24const ArrayStream = require('../common/arraystream'); 25const assert = require('assert'); 26const join = require('path').join; 27const fs = require('fs'); 28 29const tmpdir = require('../common/tmpdir'); 30tmpdir.refresh(); 31 32const repl = require('repl'); 33 34const works = [['inner.one'], 'inner.o']; 35 36const putIn = new ArrayStream(); 37const testMe = repl.start('', putIn); 38 39// Some errors might be passed to the domain. 40testMe._domain.on('error', function(reason) { 41 const err = new Error('Test failed'); 42 err.reason = reason; 43 throw err; 44}); 45 46const testFile = [ 47 'let inner = (function() {', 48 ' return {one:1};', 49 '})()' 50]; 51const saveFileName = join(tmpdir.path, 'test.save.js'); 52 53// Add some data. 54putIn.run(testFile); 55 56// Save it to a file. 57putIn.run([`.save ${saveFileName}`]); 58 59// The file should have what I wrote. 60assert.strictEqual(fs.readFileSync(saveFileName, 'utf8'), 61 testFile.join('\n')); 62 63// Make sure that the REPL data is "correct". 64testMe.complete('inner.o', common.mustCall(function(error, data) { 65 assert.ifError(error); 66 assert.deepStrictEqual(data, works); 67})); 68 69// Clear the REPL. 70putIn.run(['.clear']); 71 72// Load the file back in. 73putIn.run([`.load ${saveFileName}`]); 74 75// Make sure that the REPL data is "correct". 76testMe.complete('inner.o', common.mustCall(function(error, data) { 77 assert.ifError(error); 78 assert.deepStrictEqual(data, works); 79})); 80 81// Clear the REPL. 82putIn.run(['.clear']); 83 84let loadFile = join(tmpdir.path, 'file.does.not.exist'); 85 86// Should not break. 87putIn.write = common.mustCall(function(data) { 88 // Make sure I get a failed to load message and not some crazy error. 89 assert.strictEqual(data, `Failed to load: ${loadFile}\n`); 90 // Eat me to avoid work. 91 putIn.write = () => {}; 92}); 93putIn.run([`.load ${loadFile}`]); 94 95// Throw error on loading directory. 96loadFile = tmpdir.path; 97putIn.write = common.mustCall(function(data) { 98 assert.strictEqual(data, `Failed to load: ${loadFile} is not a valid file\n`); 99 putIn.write = () => {}; 100}); 101putIn.run([`.load ${loadFile}`]); 102 103// Clear the REPL. 104putIn.run(['.clear']); 105 106// NUL (\0) is disallowed in filenames in UNIX-like operating systems and 107// Windows so we can use that to test failed saves. 108const invalidFileName = join(tmpdir.path, '\0\0\0\0\0'); 109 110// Should not break. 111putIn.write = common.mustCall(function(data) { 112 // Make sure I get a failed to save message and not some other error. 113 assert.strictEqual(data, `Failed to save: ${invalidFileName}\n`); 114 // Reset to no-op. 115 putIn.write = () => {}; 116}); 117 118// Save it to a file. 119putIn.run([`.save ${invalidFileName}`]); 120 121{ 122 // Save .editor mode code. 123 const cmds = [ 124 'function testSave() {', 125 'return "saved";', 126 '}' 127 ]; 128 const putIn = new ArrayStream(); 129 const replServer = repl.start({ terminal: true, stream: putIn }); 130 131 putIn.run(['.editor']); 132 putIn.run(cmds); 133 replServer.write('', { ctrl: true, name: 'd' }); 134 135 putIn.run([`.save ${saveFileName}`]); 136 replServer.close(); 137 assert.strictEqual(fs.readFileSync(saveFileName, 'utf8'), 138 `${cmds.join('\n')}\n`); 139} 140