@lydell/node-pty 1.0.3 → 1.2.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -47
- package/README.md +17 -7
- package/index.js +39 -42
- package/node-pty.d.ts +20 -3
- package/package.json +10 -8
- package/conpty_console_list_agent.js +0 -13
- package/eventEmitter2.js +0 -45
- package/interfaces.js +0 -6
- package/requireBinary.js +0 -33
- package/shared/conout.js +0 -9
- package/terminal.js +0 -188
- package/types.js +0 -6
- package/unixTerminal.js +0 -265
- package/utils.js +0 -15
- package/windowsConoutConnection.js +0 -120
- package/windowsPtyAgent.js +0 -236
- package/windowsTerminal.js +0 -199
- package/worker/conoutSocketWorker.js +0 -21
package/unixTerminal.js
DELETED
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
extendStatics(d, b);
|
|
11
|
-
function __() { this.constructor = d; }
|
|
12
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
13
|
-
};
|
|
14
|
-
})();
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
var tty = require("tty");
|
|
17
|
-
var terminal_1 = require("./terminal");
|
|
18
|
-
var utils_1 = require("./utils");
|
|
19
|
-
var requireBinary_1 = require("./requireBinary");
|
|
20
|
-
var pty = requireBinary_1.requireBinary('pty.node');
|
|
21
|
-
var helperPath = "@lydell/node-pty-" + process.platform + "-" + process.arch + "/spawn-helper";
|
|
22
|
-
helperPath = process.platform === 'darwin' ? require.resolve(helperPath) : 'spawn-helper-unused';
|
|
23
|
-
helperPath = helperPath.replace('app.asar', 'app.asar.unpacked');
|
|
24
|
-
helperPath = helperPath.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
|
25
|
-
var DEFAULT_FILE = 'sh';
|
|
26
|
-
var DEFAULT_NAME = 'xterm';
|
|
27
|
-
var DESTROY_SOCKET_TIMEOUT_MS = 200;
|
|
28
|
-
var UnixTerminal = /** @class */ (function (_super) {
|
|
29
|
-
__extends(UnixTerminal, _super);
|
|
30
|
-
function UnixTerminal(file, args, opt) {
|
|
31
|
-
var _a, _b;
|
|
32
|
-
var _this = _super.call(this, opt) || this;
|
|
33
|
-
_this._boundClose = false;
|
|
34
|
-
_this._emittedClose = false;
|
|
35
|
-
if (typeof args === 'string') {
|
|
36
|
-
throw new Error('args as a string is not supported on unix.');
|
|
37
|
-
}
|
|
38
|
-
// Initialize arguments
|
|
39
|
-
args = args || [];
|
|
40
|
-
file = file || DEFAULT_FILE;
|
|
41
|
-
opt = opt || {};
|
|
42
|
-
opt.env = opt.env || process.env;
|
|
43
|
-
_this._cols = opt.cols || terminal_1.DEFAULT_COLS;
|
|
44
|
-
_this._rows = opt.rows || terminal_1.DEFAULT_ROWS;
|
|
45
|
-
var uid = (_a = opt.uid) !== null && _a !== void 0 ? _a : -1;
|
|
46
|
-
var gid = (_b = opt.gid) !== null && _b !== void 0 ? _b : -1;
|
|
47
|
-
var env = utils_1.assign({}, opt.env);
|
|
48
|
-
if (opt.env === process.env) {
|
|
49
|
-
_this._sanitizeEnv(env);
|
|
50
|
-
}
|
|
51
|
-
var cwd = opt.cwd || process.cwd();
|
|
52
|
-
env.PWD = cwd;
|
|
53
|
-
var name = opt.name || env.TERM || DEFAULT_NAME;
|
|
54
|
-
env.TERM = name;
|
|
55
|
-
var parsedEnv = _this._parseEnv(env);
|
|
56
|
-
var encoding = (opt.encoding === undefined ? 'utf8' : opt.encoding);
|
|
57
|
-
var onexit = function (code, signal) {
|
|
58
|
-
// XXX Sometimes a data event is emitted after exit. Wait til socket is
|
|
59
|
-
// destroyed.
|
|
60
|
-
if (!_this._emittedClose) {
|
|
61
|
-
if (_this._boundClose) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
_this._boundClose = true;
|
|
65
|
-
// From macOS High Sierra 10.13.2 sometimes the socket never gets
|
|
66
|
-
// closed. A timeout is applied here to avoid the terminal never being
|
|
67
|
-
// destroyed when this occurs.
|
|
68
|
-
var timeout_1 = setTimeout(function () {
|
|
69
|
-
timeout_1 = null;
|
|
70
|
-
// Destroying the socket now will cause the close event to fire
|
|
71
|
-
_this._socket.destroy();
|
|
72
|
-
}, DESTROY_SOCKET_TIMEOUT_MS);
|
|
73
|
-
_this.once('close', function () {
|
|
74
|
-
if (timeout_1 !== null) {
|
|
75
|
-
clearTimeout(timeout_1);
|
|
76
|
-
}
|
|
77
|
-
_this.emit('exit', code, signal);
|
|
78
|
-
});
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
_this.emit('exit', code, signal);
|
|
82
|
-
};
|
|
83
|
-
// fork
|
|
84
|
-
var term = pty.fork(file, args, parsedEnv, cwd, _this._cols, _this._rows, uid, gid, (encoding === 'utf8'), helperPath, onexit);
|
|
85
|
-
_this._socket = new tty.ReadStream(term.fd);
|
|
86
|
-
if (encoding !== null) {
|
|
87
|
-
_this._socket.setEncoding(encoding);
|
|
88
|
-
}
|
|
89
|
-
// setup
|
|
90
|
-
_this._socket.on('error', function (err) {
|
|
91
|
-
// NOTE: fs.ReadStream gets EAGAIN twice at first:
|
|
92
|
-
if (err.code) {
|
|
93
|
-
if (~err.code.indexOf('EAGAIN')) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// close
|
|
98
|
-
_this._close();
|
|
99
|
-
// EIO on exit from fs.ReadStream:
|
|
100
|
-
if (!_this._emittedClose) {
|
|
101
|
-
_this._emittedClose = true;
|
|
102
|
-
_this.emit('close');
|
|
103
|
-
}
|
|
104
|
-
// EIO, happens when someone closes our child process: the only process in
|
|
105
|
-
// the terminal.
|
|
106
|
-
// node < 0.6.14: errno 5
|
|
107
|
-
// node >= 0.6.14: read EIO
|
|
108
|
-
if (err.code) {
|
|
109
|
-
if (~err.code.indexOf('errno 5') || ~err.code.indexOf('EIO')) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// throw anything else
|
|
114
|
-
if (_this.listeners('error').length < 2) {
|
|
115
|
-
throw err;
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
_this._pid = term.pid;
|
|
119
|
-
_this._fd = term.fd;
|
|
120
|
-
_this._pty = term.pty;
|
|
121
|
-
_this._file = file;
|
|
122
|
-
_this._name = name;
|
|
123
|
-
_this._readable = true;
|
|
124
|
-
_this._writable = true;
|
|
125
|
-
_this._socket.on('close', function () {
|
|
126
|
-
if (_this._emittedClose) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
_this._emittedClose = true;
|
|
130
|
-
_this._close();
|
|
131
|
-
_this.emit('close');
|
|
132
|
-
});
|
|
133
|
-
_this._forwardEvents();
|
|
134
|
-
return _this;
|
|
135
|
-
}
|
|
136
|
-
Object.defineProperty(UnixTerminal.prototype, "master", {
|
|
137
|
-
get: function () { return this._master; },
|
|
138
|
-
enumerable: true,
|
|
139
|
-
configurable: true
|
|
140
|
-
});
|
|
141
|
-
Object.defineProperty(UnixTerminal.prototype, "slave", {
|
|
142
|
-
get: function () { return this._slave; },
|
|
143
|
-
enumerable: true,
|
|
144
|
-
configurable: true
|
|
145
|
-
});
|
|
146
|
-
UnixTerminal.prototype._write = function (data) {
|
|
147
|
-
this._socket.write(data);
|
|
148
|
-
};
|
|
149
|
-
Object.defineProperty(UnixTerminal.prototype, "fd", {
|
|
150
|
-
/* Accessors */
|
|
151
|
-
get: function () { return this._fd; },
|
|
152
|
-
enumerable: true,
|
|
153
|
-
configurable: true
|
|
154
|
-
});
|
|
155
|
-
Object.defineProperty(UnixTerminal.prototype, "ptsName", {
|
|
156
|
-
get: function () { return this._pty; },
|
|
157
|
-
enumerable: true,
|
|
158
|
-
configurable: true
|
|
159
|
-
});
|
|
160
|
-
/**
|
|
161
|
-
* openpty
|
|
162
|
-
*/
|
|
163
|
-
UnixTerminal.open = function (opt) {
|
|
164
|
-
var self = Object.create(UnixTerminal.prototype);
|
|
165
|
-
opt = opt || {};
|
|
166
|
-
if (arguments.length > 1) {
|
|
167
|
-
opt = {
|
|
168
|
-
cols: arguments[1],
|
|
169
|
-
rows: arguments[2]
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
var cols = opt.cols || terminal_1.DEFAULT_COLS;
|
|
173
|
-
var rows = opt.rows || terminal_1.DEFAULT_ROWS;
|
|
174
|
-
var encoding = (opt.encoding === undefined ? 'utf8' : opt.encoding);
|
|
175
|
-
// open
|
|
176
|
-
var term = pty.open(cols, rows);
|
|
177
|
-
self._master = new tty.ReadStream(term.master);
|
|
178
|
-
if (encoding !== null) {
|
|
179
|
-
self._master.setEncoding(encoding);
|
|
180
|
-
}
|
|
181
|
-
self._master.resume();
|
|
182
|
-
self._slave = new tty.ReadStream(term.slave);
|
|
183
|
-
if (encoding !== null) {
|
|
184
|
-
self._slave.setEncoding(encoding);
|
|
185
|
-
}
|
|
186
|
-
self._slave.resume();
|
|
187
|
-
self._socket = self._master;
|
|
188
|
-
self._pid = -1;
|
|
189
|
-
self._fd = term.master;
|
|
190
|
-
self._pty = term.pty;
|
|
191
|
-
self._file = process.argv[0] || 'node';
|
|
192
|
-
self._name = process.env.TERM || '';
|
|
193
|
-
self._readable = true;
|
|
194
|
-
self._writable = true;
|
|
195
|
-
self._socket.on('error', function (err) {
|
|
196
|
-
self._close();
|
|
197
|
-
if (self.listeners('error').length < 2) {
|
|
198
|
-
throw err;
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
|
-
self._socket.on('close', function () {
|
|
202
|
-
self._close();
|
|
203
|
-
});
|
|
204
|
-
return self;
|
|
205
|
-
};
|
|
206
|
-
UnixTerminal.prototype.destroy = function () {
|
|
207
|
-
var _this = this;
|
|
208
|
-
this._close();
|
|
209
|
-
// Need to close the read stream so node stops reading a dead file
|
|
210
|
-
// descriptor. Then we can safely SIGHUP the shell.
|
|
211
|
-
this._socket.once('close', function () {
|
|
212
|
-
_this.kill('SIGHUP');
|
|
213
|
-
});
|
|
214
|
-
this._socket.destroy();
|
|
215
|
-
};
|
|
216
|
-
UnixTerminal.prototype.kill = function (signal) {
|
|
217
|
-
try {
|
|
218
|
-
process.kill(this.pid, signal || 'SIGHUP');
|
|
219
|
-
}
|
|
220
|
-
catch (e) { /* swallow */ }
|
|
221
|
-
};
|
|
222
|
-
Object.defineProperty(UnixTerminal.prototype, "process", {
|
|
223
|
-
/**
|
|
224
|
-
* Gets the name of the process.
|
|
225
|
-
*/
|
|
226
|
-
get: function () {
|
|
227
|
-
if (process.platform === 'darwin') {
|
|
228
|
-
var title = pty.process(this._fd);
|
|
229
|
-
return (title !== 'kernel_task') ? title : this._file;
|
|
230
|
-
}
|
|
231
|
-
return pty.process(this._fd, this._pty) || this._file;
|
|
232
|
-
},
|
|
233
|
-
enumerable: true,
|
|
234
|
-
configurable: true
|
|
235
|
-
});
|
|
236
|
-
/**
|
|
237
|
-
* TTY
|
|
238
|
-
*/
|
|
239
|
-
UnixTerminal.prototype.resize = function (cols, rows) {
|
|
240
|
-
if (cols <= 0 || rows <= 0 || isNaN(cols) || isNaN(rows) || cols === Infinity || rows === Infinity) {
|
|
241
|
-
throw new Error('resizing must be done using positive cols and rows');
|
|
242
|
-
}
|
|
243
|
-
pty.resize(this._fd, cols, rows);
|
|
244
|
-
this._cols = cols;
|
|
245
|
-
this._rows = rows;
|
|
246
|
-
};
|
|
247
|
-
UnixTerminal.prototype.clear = function () {
|
|
248
|
-
};
|
|
249
|
-
UnixTerminal.prototype._sanitizeEnv = function (env) {
|
|
250
|
-
// Make sure we didn't start our server from inside tmux.
|
|
251
|
-
delete env['TMUX'];
|
|
252
|
-
delete env['TMUX_PANE'];
|
|
253
|
-
// Make sure we didn't start our server from inside screen.
|
|
254
|
-
// http://web.mit.edu/gnu/doc/html/screen_20.html
|
|
255
|
-
delete env['STY'];
|
|
256
|
-
delete env['WINDOW'];
|
|
257
|
-
// Delete some variables that might confuse our terminal.
|
|
258
|
-
delete env['WINDOWID'];
|
|
259
|
-
delete env['TERMCAP'];
|
|
260
|
-
delete env['COLUMNS'];
|
|
261
|
-
delete env['LINES'];
|
|
262
|
-
};
|
|
263
|
-
return UnixTerminal;
|
|
264
|
-
}(terminal_1.Terminal));
|
|
265
|
-
exports.UnixTerminal = UnixTerminal;
|
package/utils.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Copyright (c) 2017, Daniel Imms (MIT License).
|
|
4
|
-
* Copyright (c) 2018, Microsoft Corporation (MIT License).
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
function assign(target) {
|
|
8
|
-
var sources = [];
|
|
9
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
10
|
-
sources[_i - 1] = arguments[_i];
|
|
11
|
-
}
|
|
12
|
-
sources.forEach(function (source) { return Object.keys(source).forEach(function (key) { return target[key] = source[key]; }); });
|
|
13
|
-
return target;
|
|
14
|
-
}
|
|
15
|
-
exports.assign = assign;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Copyright (c) 2020, Microsoft Corporation (MIT License).
|
|
4
|
-
*/
|
|
5
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
15
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
16
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
17
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
18
|
-
function step(op) {
|
|
19
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
20
|
-
while (_) try {
|
|
21
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
22
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
23
|
-
switch (op[0]) {
|
|
24
|
-
case 0: case 1: t = op; break;
|
|
25
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
26
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
27
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
28
|
-
default:
|
|
29
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
30
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
31
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
32
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
33
|
-
if (t[2]) _.ops.pop();
|
|
34
|
-
_.trys.pop(); continue;
|
|
35
|
-
}
|
|
36
|
-
op = body.call(thisArg, _);
|
|
37
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
38
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
var worker_threads_1 = require("worker_threads");
|
|
43
|
-
var conout_1 = require("./shared/conout");
|
|
44
|
-
var path_1 = require("path");
|
|
45
|
-
var eventEmitter2_1 = require("./eventEmitter2");
|
|
46
|
-
/**
|
|
47
|
-
* The amount of time to wait for additional data after the conpty shell process has exited before
|
|
48
|
-
* shutting down the worker and sockets. The timer will be reset if a new data event comes in after
|
|
49
|
-
* the timer has started.
|
|
50
|
-
*/
|
|
51
|
-
var FLUSH_DATA_INTERVAL = 1000;
|
|
52
|
-
/**
|
|
53
|
-
* Connects to and manages the lifecycle of the conout socket. This socket must be drained on
|
|
54
|
-
* another thread in order to avoid deadlocks where Conpty waits for the out socket to drain
|
|
55
|
-
* when `ClosePseudoConsole` is called. This happens when data is being written to the terminal when
|
|
56
|
-
* the pty is closed.
|
|
57
|
-
*
|
|
58
|
-
* See also:
|
|
59
|
-
* - https://github.com/microsoft/node-pty/issues/375
|
|
60
|
-
* - https://github.com/microsoft/vscode/issues/76548
|
|
61
|
-
* - https://github.com/microsoft/terminal/issues/1810
|
|
62
|
-
* - https://docs.microsoft.com/en-us/windows/console/closepseudoconsole
|
|
63
|
-
*/
|
|
64
|
-
var ConoutConnection = /** @class */ (function () {
|
|
65
|
-
function ConoutConnection(_conoutPipeName) {
|
|
66
|
-
var _this = this;
|
|
67
|
-
this._conoutPipeName = _conoutPipeName;
|
|
68
|
-
this._isDisposed = false;
|
|
69
|
-
this._onReady = new eventEmitter2_1.EventEmitter2();
|
|
70
|
-
var workerData = { conoutPipeName: _conoutPipeName };
|
|
71
|
-
var scriptPath = __dirname.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
|
72
|
-
this._worker = new worker_threads_1.Worker(path_1.join(scriptPath, 'worker/conoutSocketWorker.js'), { workerData: workerData });
|
|
73
|
-
this._worker.on('message', function (message) {
|
|
74
|
-
switch (message) {
|
|
75
|
-
case 1 /* READY */:
|
|
76
|
-
_this._onReady.fire();
|
|
77
|
-
return;
|
|
78
|
-
default:
|
|
79
|
-
console.warn('Unexpected ConoutWorkerMessage', message);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
Object.defineProperty(ConoutConnection.prototype, "onReady", {
|
|
84
|
-
get: function () { return this._onReady.event; },
|
|
85
|
-
enumerable: true,
|
|
86
|
-
configurable: true
|
|
87
|
-
});
|
|
88
|
-
ConoutConnection.prototype.dispose = function () {
|
|
89
|
-
if (this._isDisposed) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
this._isDisposed = true;
|
|
93
|
-
// Drain all data from the socket before closing
|
|
94
|
-
this._drainDataAndClose();
|
|
95
|
-
};
|
|
96
|
-
ConoutConnection.prototype.connectSocket = function (socket) {
|
|
97
|
-
socket.connect(conout_1.getWorkerPipeName(this._conoutPipeName));
|
|
98
|
-
};
|
|
99
|
-
ConoutConnection.prototype._drainDataAndClose = function () {
|
|
100
|
-
var _this = this;
|
|
101
|
-
if (this._drainTimeout) {
|
|
102
|
-
clearTimeout(this._drainTimeout);
|
|
103
|
-
}
|
|
104
|
-
this._drainTimeout = setTimeout(function () { return _this._destroySocket(); }, FLUSH_DATA_INTERVAL);
|
|
105
|
-
};
|
|
106
|
-
ConoutConnection.prototype._destroySocket = function () {
|
|
107
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
108
|
-
return __generator(this, function (_a) {
|
|
109
|
-
switch (_a.label) {
|
|
110
|
-
case 0: return [4 /*yield*/, this._worker.terminate()];
|
|
111
|
-
case 1:
|
|
112
|
-
_a.sent();
|
|
113
|
-
return [2 /*return*/];
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
};
|
|
118
|
-
return ConoutConnection;
|
|
119
|
-
}());
|
|
120
|
-
exports.ConoutConnection = ConoutConnection;
|
package/windowsPtyAgent.js
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Copyright (c) 2012-2015, Christopher Jeffrey, Peter Sunde (MIT License)
|
|
4
|
-
* Copyright (c) 2016, Daniel Imms (MIT License).
|
|
5
|
-
* Copyright (c) 2018, Microsoft Corporation (MIT License).
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
var fs = require("fs");
|
|
9
|
-
var path = require("path");
|
|
10
|
-
var net_1 = require("net");
|
|
11
|
-
var child_process_1 = require("child_process");
|
|
12
|
-
var windowsConoutConnection_1 = require("./windowsConoutConnection");
|
|
13
|
-
var requireBinary_1 = require("./requireBinary");
|
|
14
|
-
var conptyNative;
|
|
15
|
-
/**
|
|
16
|
-
* The amount of time to wait for additional data after the conpty shell process has exited before
|
|
17
|
-
* shutting down the socket. The timer will be reset if a new data event comes in after the timer
|
|
18
|
-
* has started.
|
|
19
|
-
*/
|
|
20
|
-
var FLUSH_DATA_INTERVAL = 1000;
|
|
21
|
-
/**
|
|
22
|
-
* This agent sits between the WindowsTerminal class and provides an interface for both conpty.
|
|
23
|
-
*/
|
|
24
|
-
var WindowsPtyAgent = /** @class */ (function () {
|
|
25
|
-
function WindowsPtyAgent(file, args, env, cwd, cols, rows, debug, conptyInheritCursor) {
|
|
26
|
-
var _this = this;
|
|
27
|
-
if (conptyInheritCursor === void 0) { conptyInheritCursor = false; }
|
|
28
|
-
this._pid = 0;
|
|
29
|
-
this._innerPid = 0;
|
|
30
|
-
if (!conptyNative) {
|
|
31
|
-
conptyNative = requireBinary_1.requireBinary('conpty.node');
|
|
32
|
-
}
|
|
33
|
-
this._ptyNative = conptyNative;
|
|
34
|
-
// Sanitize input variable.
|
|
35
|
-
cwd = path.resolve(cwd);
|
|
36
|
-
// Compose command line
|
|
37
|
-
var commandLine = argsToCommandLine(file, args);
|
|
38
|
-
// Open pty session.
|
|
39
|
-
var term = this._ptyNative.startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor);
|
|
40
|
-
// Not available on windows.
|
|
41
|
-
this._fd = term.fd;
|
|
42
|
-
// Generated incremental number that has no real purpose besides using it
|
|
43
|
-
// as a terminal id.
|
|
44
|
-
this._pty = term.pty;
|
|
45
|
-
// Create terminal pipe IPC channel and forward to a local unix socket.
|
|
46
|
-
this._outSocket = new net_1.Socket();
|
|
47
|
-
this._outSocket.setEncoding('utf8');
|
|
48
|
-
// The conout socket must be ready out on another thread to avoid deadlocks
|
|
49
|
-
this._conoutSocketWorker = new windowsConoutConnection_1.ConoutConnection(term.conout);
|
|
50
|
-
this._conoutSocketWorker.onReady(function () {
|
|
51
|
-
_this._conoutSocketWorker.connectSocket(_this._outSocket);
|
|
52
|
-
});
|
|
53
|
-
this._outSocket.on('connect', function () {
|
|
54
|
-
_this._outSocket.emit('ready_datapipe');
|
|
55
|
-
});
|
|
56
|
-
var inSocketFD = fs.openSync(term.conin, 'w');
|
|
57
|
-
this._inSocket = new net_1.Socket({
|
|
58
|
-
fd: inSocketFD,
|
|
59
|
-
readable: false,
|
|
60
|
-
writable: true
|
|
61
|
-
});
|
|
62
|
-
this._inSocket.setEncoding('utf8');
|
|
63
|
-
var connect = this._ptyNative.connect(this._pty, commandLine, cwd, env, function (c) { return _this._$onProcessExit(c); });
|
|
64
|
-
this._innerPid = connect.pid;
|
|
65
|
-
}
|
|
66
|
-
Object.defineProperty(WindowsPtyAgent.prototype, "inSocket", {
|
|
67
|
-
get: function () { return this._inSocket; },
|
|
68
|
-
enumerable: true,
|
|
69
|
-
configurable: true
|
|
70
|
-
});
|
|
71
|
-
Object.defineProperty(WindowsPtyAgent.prototype, "outSocket", {
|
|
72
|
-
get: function () { return this._outSocket; },
|
|
73
|
-
enumerable: true,
|
|
74
|
-
configurable: true
|
|
75
|
-
});
|
|
76
|
-
Object.defineProperty(WindowsPtyAgent.prototype, "fd", {
|
|
77
|
-
get: function () { return this._fd; },
|
|
78
|
-
enumerable: true,
|
|
79
|
-
configurable: true
|
|
80
|
-
});
|
|
81
|
-
Object.defineProperty(WindowsPtyAgent.prototype, "innerPid", {
|
|
82
|
-
get: function () { return this._innerPid; },
|
|
83
|
-
enumerable: true,
|
|
84
|
-
configurable: true
|
|
85
|
-
});
|
|
86
|
-
Object.defineProperty(WindowsPtyAgent.prototype, "pty", {
|
|
87
|
-
get: function () { return this._pty; },
|
|
88
|
-
enumerable: true,
|
|
89
|
-
configurable: true
|
|
90
|
-
});
|
|
91
|
-
WindowsPtyAgent.prototype.resize = function (cols, rows) {
|
|
92
|
-
if (this._exitCode !== undefined) {
|
|
93
|
-
throw new Error('Cannot resize a pty that has already exited');
|
|
94
|
-
}
|
|
95
|
-
this._ptyNative.resize(this._pty, cols, rows);
|
|
96
|
-
};
|
|
97
|
-
WindowsPtyAgent.prototype.clear = function () {
|
|
98
|
-
this._ptyNative.clear(this._pty);
|
|
99
|
-
};
|
|
100
|
-
WindowsPtyAgent.prototype.kill = function () {
|
|
101
|
-
var _this = this;
|
|
102
|
-
this._inSocket.readable = false;
|
|
103
|
-
this._outSocket.readable = false;
|
|
104
|
-
// Tell the agent to kill the pty, this releases handles to the process
|
|
105
|
-
this._getConsoleProcessList().then(function (consoleProcessList) {
|
|
106
|
-
consoleProcessList.forEach(function (pid) {
|
|
107
|
-
try {
|
|
108
|
-
process.kill(pid);
|
|
109
|
-
}
|
|
110
|
-
catch (e) {
|
|
111
|
-
// Ignore if process cannot be found (kill ESRCH error)
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
_this._ptyNative.kill(_this._pty);
|
|
115
|
-
});
|
|
116
|
-
this._conoutSocketWorker.dispose();
|
|
117
|
-
};
|
|
118
|
-
WindowsPtyAgent.prototype._getConsoleProcessList = function () {
|
|
119
|
-
var _this = this;
|
|
120
|
-
return new Promise(function (resolve) {
|
|
121
|
-
var agent = child_process_1.fork(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()]);
|
|
122
|
-
agent.on('message', function (message) {
|
|
123
|
-
clearTimeout(timeout);
|
|
124
|
-
resolve(message.consoleProcessList);
|
|
125
|
-
});
|
|
126
|
-
var timeout = setTimeout(function () {
|
|
127
|
-
// Something went wrong, just send back the shell PID
|
|
128
|
-
agent.kill();
|
|
129
|
-
resolve([_this._innerPid]);
|
|
130
|
-
}, 5000);
|
|
131
|
-
});
|
|
132
|
-
};
|
|
133
|
-
Object.defineProperty(WindowsPtyAgent.prototype, "exitCode", {
|
|
134
|
-
get: function () {
|
|
135
|
-
return this._exitCode;
|
|
136
|
-
},
|
|
137
|
-
enumerable: true,
|
|
138
|
-
configurable: true
|
|
139
|
-
});
|
|
140
|
-
WindowsPtyAgent.prototype._generatePipeName = function () {
|
|
141
|
-
return "conpty-" + Math.random() * 10000000;
|
|
142
|
-
};
|
|
143
|
-
/**
|
|
144
|
-
* Triggered from the native side when a contpy process exits.
|
|
145
|
-
*/
|
|
146
|
-
WindowsPtyAgent.prototype._$onProcessExit = function (exitCode) {
|
|
147
|
-
var _this = this;
|
|
148
|
-
this._exitCode = exitCode;
|
|
149
|
-
this._flushDataAndCleanUp();
|
|
150
|
-
this._outSocket.on('data', function () { return _this._flushDataAndCleanUp(); });
|
|
151
|
-
};
|
|
152
|
-
WindowsPtyAgent.prototype._flushDataAndCleanUp = function () {
|
|
153
|
-
var _this = this;
|
|
154
|
-
if (this._closeTimeout) {
|
|
155
|
-
clearTimeout(this._closeTimeout);
|
|
156
|
-
}
|
|
157
|
-
this._closeTimeout = setTimeout(function () { return _this._cleanUpProcess(); }, FLUSH_DATA_INTERVAL);
|
|
158
|
-
};
|
|
159
|
-
WindowsPtyAgent.prototype._cleanUpProcess = function () {
|
|
160
|
-
this._inSocket.readable = false;
|
|
161
|
-
this._outSocket.readable = false;
|
|
162
|
-
this._outSocket.destroy();
|
|
163
|
-
};
|
|
164
|
-
return WindowsPtyAgent;
|
|
165
|
-
}());
|
|
166
|
-
exports.WindowsPtyAgent = WindowsPtyAgent;
|
|
167
|
-
// Convert argc/argv into a Win32 command-line following the escaping convention
|
|
168
|
-
// documented on MSDN (e.g. see CommandLineToArgvW documentation). Copied from
|
|
169
|
-
// winpty project.
|
|
170
|
-
function argsToCommandLine(file, args) {
|
|
171
|
-
if (isCommandLine(args)) {
|
|
172
|
-
if (args.length === 0) {
|
|
173
|
-
return file;
|
|
174
|
-
}
|
|
175
|
-
return argsToCommandLine(file, []) + " " + args;
|
|
176
|
-
}
|
|
177
|
-
var argv = [file];
|
|
178
|
-
Array.prototype.push.apply(argv, args);
|
|
179
|
-
var result = '';
|
|
180
|
-
for (var argIndex = 0; argIndex < argv.length; argIndex++) {
|
|
181
|
-
if (argIndex > 0) {
|
|
182
|
-
result += ' ';
|
|
183
|
-
}
|
|
184
|
-
var arg = argv[argIndex];
|
|
185
|
-
// if it is empty or it contains whitespace and is not already quoted
|
|
186
|
-
var hasLopsidedEnclosingQuote = xOr((arg[0] !== '"'), (arg[arg.length - 1] !== '"'));
|
|
187
|
-
var hasNoEnclosingQuotes = ((arg[0] !== '"') && (arg[arg.length - 1] !== '"'));
|
|
188
|
-
var quote = arg === '' ||
|
|
189
|
-
(arg.indexOf(' ') !== -1 ||
|
|
190
|
-
arg.indexOf('\t') !== -1) &&
|
|
191
|
-
((arg.length > 1) &&
|
|
192
|
-
(hasLopsidedEnclosingQuote || hasNoEnclosingQuotes));
|
|
193
|
-
if (quote) {
|
|
194
|
-
result += '\"';
|
|
195
|
-
}
|
|
196
|
-
var bsCount = 0;
|
|
197
|
-
for (var i = 0; i < arg.length; i++) {
|
|
198
|
-
var p = arg[i];
|
|
199
|
-
if (p === '\\') {
|
|
200
|
-
bsCount++;
|
|
201
|
-
}
|
|
202
|
-
else if (p === '"') {
|
|
203
|
-
result += repeatText('\\', bsCount * 2 + 1);
|
|
204
|
-
result += '"';
|
|
205
|
-
bsCount = 0;
|
|
206
|
-
}
|
|
207
|
-
else {
|
|
208
|
-
result += repeatText('\\', bsCount);
|
|
209
|
-
bsCount = 0;
|
|
210
|
-
result += p;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
if (quote) {
|
|
214
|
-
result += repeatText('\\', bsCount * 2);
|
|
215
|
-
result += '\"';
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
result += repeatText('\\', bsCount);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return result;
|
|
222
|
-
}
|
|
223
|
-
exports.argsToCommandLine = argsToCommandLine;
|
|
224
|
-
function isCommandLine(args) {
|
|
225
|
-
return typeof args === 'string';
|
|
226
|
-
}
|
|
227
|
-
function repeatText(text, count) {
|
|
228
|
-
var result = '';
|
|
229
|
-
for (var i = 0; i < count; i++) {
|
|
230
|
-
result += text;
|
|
231
|
-
}
|
|
232
|
-
return result;
|
|
233
|
-
}
|
|
234
|
-
function xOr(arg1, arg2) {
|
|
235
|
-
return ((arg1 && !arg2) || (!arg1 && arg2));
|
|
236
|
-
}
|