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.mustSucceed((data) => { 65 assert.deepStrictEqual(data, works); 66})); 67 68// Clear the REPL. 69putIn.run(['.clear']); 70 71// Load the file back in. 72putIn.run([`.load ${saveFileName}`]); 73 74// Make sure that the REPL data is "correct". 75testMe.complete('inner.o', common.mustSucceed((data) => { 76 assert.deepStrictEqual(data, works); 77})); 78 79// Clear the REPL. 80putIn.run(['.clear']); 81 82let loadFile = join(tmpdir.path, 'file.does.not.exist'); 83 84// Should not break. 85putIn.write = common.mustCall(function(data) { 86 // Make sure I get a failed to load message and not some crazy error. 87 assert.strictEqual(data, `Failed to load: ${loadFile}\n`); 88 // Eat me to avoid work. 89 putIn.write = () => {}; 90}); 91putIn.run([`.load ${loadFile}`]); 92 93// Throw error on loading directory. 94loadFile = tmpdir.path; 95putIn.write = common.mustCall(function(data) { 96 assert.strictEqual(data, `Failed to load: ${loadFile} is not a valid file\n`); 97 putIn.write = () => {}; 98}); 99putIn.run([`.load ${loadFile}`]); 100 101// Clear the REPL. 102putIn.run(['.clear']); 103 104// NUL (\0) is disallowed in filenames in UNIX-like operating systems and 105// Windows so we can use that to test failed saves. 106const invalidFileName = join(tmpdir.path, '\0\0\0\0\0'); 107 108// Should not break. 109putIn.write = common.mustCall(function(data) { 110 // Make sure I get a failed to save message and not some other error. 111 assert.strictEqual(data, `Failed to save: ${invalidFileName}\n`); 112 // Reset to no-op. 113 putIn.write = () => {}; 114}); 115 116// Save it to a file. 117putIn.run([`.save ${invalidFileName}`]); 118 119{ 120 // Save .editor mode code. 121 const cmds = [ 122 'function testSave() {', 123 'return "saved";', 124 '}', 125 ]; 126 const putIn = new ArrayStream(); 127 const replServer = repl.start({ terminal: true, stream: putIn }); 128 129 putIn.run(['.editor']); 130 putIn.run(cmds); 131 replServer.write('', { ctrl: true, name: 'd' }); 132 133 putIn.run([`.save ${saveFileName}`]); 134 replServer.close(); 135 assert.strictEqual(fs.readFileSync(saveFileName, 'utf8'), 136 `${cmds.join('\n')}\n`); 137} 138