|
1 | 1 | 'use strict';
|
2 | 2 |
|
3 |
| -const { Interface } = require('readline'); |
4 | 3 | const REPL = require('repl');
|
5 |
| -const path = require('path'); |
6 |
| -const fs = require('fs'); |
7 |
| -const os = require('os'); |
8 |
| -const util = require('util'); |
9 |
| -const debug = util.debuglog('repl'); |
| 4 | + |
10 | 5 | module.exports = Object.create(REPL);
|
11 | 6 | module.exports.createInternalRepl = createRepl;
|
12 | 7 |
|
13 |
| -// XXX(chrisdickinson): The 15ms debounce value is somewhat arbitrary. |
14 |
| -// The debounce is to guard against code pasted into the REPL. |
15 |
| -const kDebounceHistoryMS = 15; |
16 |
| - |
17 |
| -function _writeToOutput(repl, message) { |
18 |
| - repl._writeToOutput(message); |
19 |
| - repl._refreshLine(); |
20 |
| -} |
21 |
| - |
22 | 8 | function createRepl(env, opts, cb) {
|
23 | 9 | if (typeof opts === 'function') {
|
24 | 10 | cb = opts;
|
@@ -55,151 +41,9 @@ function createRepl(env, opts, cb) {
|
55 | 41 | if (!Number.isNaN(historySize) && historySize > 0) {
|
56 | 42 | opts.historySize = historySize;
|
57 | 43 | } else {
|
58 |
| - // XXX(chrisdickinson): set here to avoid affecting existing applications |
59 |
| - // using repl instances. |
60 | 44 | opts.historySize = 1000;
|
61 | 45 | }
|
62 | 46 |
|
63 | 47 | const repl = REPL.start(opts);
|
64 |
| - if (opts.terminal) { |
65 |
| - return setupHistory(repl, env.NODE_REPL_HISTORY, cb); |
66 |
| - } |
67 |
| - |
68 |
| - repl._historyPrev = _replHistoryMessage; |
69 |
| - cb(null, repl); |
70 |
| -} |
71 |
| - |
72 |
| -function setupHistory(repl, historyPath, ready) { |
73 |
| - // Empty string disables persistent history |
74 |
| - if (typeof historyPath === 'string') |
75 |
| - historyPath = historyPath.trim(); |
76 |
| - |
77 |
| - if (historyPath === '') { |
78 |
| - repl._historyPrev = _replHistoryMessage; |
79 |
| - return ready(null, repl); |
80 |
| - } |
81 |
| - |
82 |
| - if (!historyPath) { |
83 |
| - try { |
84 |
| - historyPath = path.join(os.homedir(), '.node_repl_history'); |
85 |
| - } catch (err) { |
86 |
| - _writeToOutput(repl, '\nError: Could not get the home directory.\n' + |
87 |
| - 'REPL session history will not be persisted.\n'); |
88 |
| - |
89 |
| - debug(err.stack); |
90 |
| - repl._historyPrev = _replHistoryMessage; |
91 |
| - return ready(null, repl); |
92 |
| - } |
93 |
| - } |
94 |
| - |
95 |
| - var timer = null; |
96 |
| - var writing = false; |
97 |
| - var pending = false; |
98 |
| - repl.pause(); |
99 |
| - // History files are conventionally not readable by others: |
100 |
| - // https://github.com/nodejs/node/issues/3392 |
101 |
| - // https://github.com/nodejs/node/pull/3394 |
102 |
| - fs.open(historyPath, 'a+', 0o0600, oninit); |
103 |
| - |
104 |
| - function oninit(err, hnd) { |
105 |
| - if (err) { |
106 |
| - // Cannot open history file. |
107 |
| - // Don't crash, just don't persist history. |
108 |
| - _writeToOutput(repl, '\nError: Could not open history file.\n' + |
109 |
| - 'REPL session history will not be persisted.\n'); |
110 |
| - debug(err.stack); |
111 |
| - |
112 |
| - repl._historyPrev = _replHistoryMessage; |
113 |
| - repl.resume(); |
114 |
| - return ready(null, repl); |
115 |
| - } |
116 |
| - fs.close(hnd, onclose); |
117 |
| - } |
118 |
| - |
119 |
| - function onclose(err) { |
120 |
| - if (err) { |
121 |
| - return ready(err); |
122 |
| - } |
123 |
| - fs.readFile(historyPath, 'utf8', onread); |
124 |
| - } |
125 |
| - |
126 |
| - function onread(err, data) { |
127 |
| - if (err) { |
128 |
| - return ready(err); |
129 |
| - } |
130 |
| - |
131 |
| - if (data) { |
132 |
| - repl.history = data.split(/[\n\r]+/, repl.historySize); |
133 |
| - } else { |
134 |
| - repl.history = []; |
135 |
| - } |
136 |
| - |
137 |
| - fs.open(historyPath, 'r+', onhandle); |
138 |
| - } |
139 |
| - |
140 |
| - function onhandle(err, hnd) { |
141 |
| - if (err) { |
142 |
| - return ready(err); |
143 |
| - } |
144 |
| - fs.ftruncate(hnd, 0, (err) => { |
145 |
| - repl._historyHandle = hnd; |
146 |
| - repl.on('line', online); |
147 |
| - |
148 |
| - // Reading the file data out erases it |
149 |
| - repl.once('flushHistory', function() { |
150 |
| - repl.resume(); |
151 |
| - ready(null, repl); |
152 |
| - }); |
153 |
| - flushHistory(); |
154 |
| - }); |
155 |
| - } |
156 |
| - |
157 |
| - // ------ history listeners ------ |
158 |
| - function online() { |
159 |
| - repl._flushing = true; |
160 |
| - |
161 |
| - if (timer) { |
162 |
| - clearTimeout(timer); |
163 |
| - } |
164 |
| - |
165 |
| - timer = setTimeout(flushHistory, kDebounceHistoryMS); |
166 |
| - } |
167 |
| - |
168 |
| - function flushHistory() { |
169 |
| - timer = null; |
170 |
| - if (writing) { |
171 |
| - pending = true; |
172 |
| - return; |
173 |
| - } |
174 |
| - writing = true; |
175 |
| - const historyData = repl.history.join(os.EOL); |
176 |
| - fs.write(repl._historyHandle, historyData, 0, 'utf8', onwritten); |
177 |
| - } |
178 |
| - |
179 |
| - function onwritten(err, data) { |
180 |
| - writing = false; |
181 |
| - if (pending) { |
182 |
| - pending = false; |
183 |
| - online(); |
184 |
| - } else { |
185 |
| - repl._flushing = Boolean(timer); |
186 |
| - if (!repl._flushing) { |
187 |
| - repl.emit('flushHistory'); |
188 |
| - } |
189 |
| - } |
190 |
| - } |
191 |
| -} |
192 |
| - |
193 |
| - |
194 |
| -function _replHistoryMessage() { |
195 |
| - if (this.history.length === 0) { |
196 |
| - _writeToOutput( |
197 |
| - this, |
198 |
| - '\nPersistent history support disabled. ' + |
199 |
| - 'Set the NODE_REPL_HISTORY environment\nvariable to ' + |
200 |
| - 'a valid, user-writable path to enable.\n' |
201 |
| - ); |
202 |
| - } |
203 |
| - this._historyPrev = Interface.prototype._historyPrev; |
204 |
| - return this._historyPrev(); |
| 48 | + repl.setupHistory(opts.terminal ? env.NODE_REPL_HISTORY : '', cb); |
205 | 49 | }
|
0 commit comments