node-pty 1.2.0-beta.12 → 1.2.0-beta.14
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/lib/conpty_console_list_agent.js +1 -1
- package/lib/index.js +6 -6
- package/lib/shared/conout.js +2 -3
- package/lib/terminal.js +2 -2
- package/lib/unixTerminal.js +5 -3
- package/lib/utils.js +6 -7
- package/lib/windowsConoutConnection.js +6 -6
- package/lib/windowsPtyAgent.js +35 -10
- package/lib/windowsTerminal.js +10 -2
- package/lib/worker/conoutSocketWorker.js +3 -3
- package/package.json +7 -6
- package/prebuilds/darwin-arm64/pty.node +0 -0
- package/prebuilds/darwin-arm64/spawn-helper +0 -0
- package/prebuilds/darwin-x64/pty.node +0 -0
- package/prebuilds/darwin-x64/spawn-helper +0 -0
- package/prebuilds/linux-arm64/pty.node +0 -0
- package/prebuilds/linux-x64/pty.node +0 -0
- package/prebuilds/win32-arm64/conpty.node +0 -0
- package/prebuilds/win32-arm64/conpty.pdb +0 -0
- package/prebuilds/win32-arm64/conpty_console_list.node +0 -0
- package/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
- package/prebuilds/win32-x64/conpty.node +0 -0
- package/prebuilds/win32-x64/conpty.pdb +0 -0
- package/prebuilds/win32-x64/conpty_console_list.node +0 -0
- package/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
- package/src/unix/pty.cc +1 -0
- package/src/win/conpty.cc +71 -37
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
var utils_1 = require("./utils");
|
|
11
|
-
var getConsoleProcessList = utils_1.loadNativeModule('conpty_console_list').module.getConsoleProcessList;
|
|
11
|
+
var getConsoleProcessList = (0, utils_1.loadNativeModule)('conpty_console_list').module.getConsoleProcessList;
|
|
12
12
|
var shellPid = parseInt(process.argv[2], 10);
|
|
13
13
|
var consoleProcessList = [];
|
|
14
14
|
if (shellPid > 0) {
|
package/lib/index.js
CHANGED
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
* Copyright (c) 2018, Microsoft Corporation (MIT License).
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.native =
|
|
8
|
+
exports.native = void 0;
|
|
9
|
+
exports.spawn = spawn;
|
|
10
|
+
exports.fork = fork;
|
|
11
|
+
exports.createTerminal = createTerminal;
|
|
12
|
+
exports.open = open;
|
|
9
13
|
var utils_1 = require("./utils");
|
|
10
14
|
var terminalCtor;
|
|
11
15
|
if (process.platform === 'win32') {
|
|
@@ -29,24 +33,20 @@ else {
|
|
|
29
33
|
function spawn(file, args, opt) {
|
|
30
34
|
return new terminalCtor(file, args, opt);
|
|
31
35
|
}
|
|
32
|
-
exports.spawn = spawn;
|
|
33
36
|
/** @deprecated */
|
|
34
37
|
function fork(file, args, opt) {
|
|
35
38
|
return new terminalCtor(file, args, opt);
|
|
36
39
|
}
|
|
37
|
-
exports.fork = fork;
|
|
38
40
|
/** @deprecated */
|
|
39
41
|
function createTerminal(file, args, opt) {
|
|
40
42
|
return new terminalCtor(file, args, opt);
|
|
41
43
|
}
|
|
42
|
-
exports.createTerminal = createTerminal;
|
|
43
44
|
function open(options) {
|
|
44
45
|
return terminalCtor.open(options);
|
|
45
46
|
}
|
|
46
|
-
exports.open = open;
|
|
47
47
|
/**
|
|
48
48
|
* Expose the native API when not Windows, note that this is not public API and
|
|
49
49
|
* could be removed at any time.
|
|
50
50
|
*/
|
|
51
|
-
exports.native = (process.platform !== 'win32' ? utils_1.loadNativeModule('pty').module : null);
|
|
51
|
+
exports.native = (process.platform !== 'win32' ? (0, utils_1.loadNativeModule)('pty').module : null);
|
|
52
52
|
//# sourceMappingURL=index.js.map
|
package/lib/shared/conout.js
CHANGED
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
* Copyright (c) 2020, Microsoft Corporation (MIT License).
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getWorkerPipeName =
|
|
6
|
+
exports.getWorkerPipeName = getWorkerPipeName;
|
|
7
7
|
function getWorkerPipeName(conoutPipeName) {
|
|
8
|
-
return conoutPipeName
|
|
8
|
+
return "".concat(conoutPipeName, "-worker");
|
|
9
9
|
}
|
|
10
|
-
exports.getWorkerPipeName = getWorkerPipeName;
|
|
11
10
|
//# sourceMappingURL=conout.js.map
|
package/lib/terminal.js
CHANGED
|
@@ -101,14 +101,14 @@ var Terminal = /** @class */ (function () {
|
|
|
101
101
|
if (Array.isArray(value)) {
|
|
102
102
|
value.forEach(function (v, i) {
|
|
103
103
|
if (typeof v !== type) {
|
|
104
|
-
throw new Error(name
|
|
104
|
+
throw new Error("".concat(name, "[").concat(i, "] must be a ").concat(type, " (not a ").concat(typeof v[i], ")"));
|
|
105
105
|
}
|
|
106
106
|
});
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
if (typeof value !== type) {
|
|
111
|
-
throw new Error(name
|
|
111
|
+
throw new Error("".concat(name, " must be a ").concat(type, " (not a ").concat(typeof value, ")"));
|
|
112
112
|
}
|
|
113
113
|
};
|
|
114
114
|
/** See net.Socket.end */
|
package/lib/unixTerminal.js
CHANGED
|
@@ -3,10 +3,12 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
3
3
|
var extendStatics = function (d, b) {
|
|
4
4
|
extendStatics = Object.setPrototypeOf ||
|
|
5
5
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (
|
|
6
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
7
|
return extendStatics(d, b);
|
|
8
8
|
};
|
|
9
9
|
return function (d, b) {
|
|
10
|
+
if (typeof b !== "function" && b !== null)
|
|
11
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
10
12
|
extendStatics(d, b);
|
|
11
13
|
function __() { this.constructor = d; }
|
|
12
14
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
@@ -24,7 +26,7 @@ var path = require("path");
|
|
|
24
26
|
var tty = require("tty");
|
|
25
27
|
var terminal_1 = require("./terminal");
|
|
26
28
|
var utils_1 = require("./utils");
|
|
27
|
-
var native = utils_1.loadNativeModule('pty');
|
|
29
|
+
var native = (0, utils_1.loadNativeModule)('pty');
|
|
28
30
|
var pty = native.module;
|
|
29
31
|
var helperPath = native.dir + '/spawn-helper';
|
|
30
32
|
helperPath = path.resolve(__dirname, helperPath);
|
|
@@ -52,7 +54,7 @@ var UnixTerminal = /** @class */ (function (_super) {
|
|
|
52
54
|
_this._rows = opt.rows || terminal_1.DEFAULT_ROWS;
|
|
53
55
|
var uid = (_a = opt.uid) !== null && _a !== void 0 ? _a : -1;
|
|
54
56
|
var gid = (_b = opt.gid) !== null && _b !== void 0 ? _b : -1;
|
|
55
|
-
var env = utils_1.assign({}, opt.env);
|
|
57
|
+
var env = (0, utils_1.assign)({}, opt.env);
|
|
56
58
|
if (opt.env === process.env) {
|
|
57
59
|
_this._sanitizeEnv(env);
|
|
58
60
|
}
|
package/lib/utils.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Copyright (c) 2018, Microsoft Corporation (MIT License).
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
7
|
+
exports.assign = assign;
|
|
8
|
+
exports.loadNativeModule = loadNativeModule;
|
|
8
9
|
function assign(target) {
|
|
9
10
|
var sources = [];
|
|
10
11
|
for (var _i = 1; _i < arguments.length; _i++) {
|
|
@@ -13,10 +14,9 @@ function assign(target) {
|
|
|
13
14
|
sources.forEach(function (source) { return Object.keys(source).forEach(function (key) { return target[key] = source[key]; }); });
|
|
14
15
|
return target;
|
|
15
16
|
}
|
|
16
|
-
exports.assign = assign;
|
|
17
17
|
function loadNativeModule(name) {
|
|
18
18
|
// Check build, debug, and then prebuilds.
|
|
19
|
-
var dirs = ['build/Release', 'build/Debug', "prebuilds/"
|
|
19
|
+
var dirs = ['build/Release', 'build/Debug', "prebuilds/".concat(process.platform, "-").concat(process.arch)];
|
|
20
20
|
// Check relative to the parent dir for unbundled and then the current dir for bundled
|
|
21
21
|
var relative = ['..', '.'];
|
|
22
22
|
var lastError;
|
|
@@ -24,16 +24,15 @@ function loadNativeModule(name) {
|
|
|
24
24
|
var d = dirs_1[_i];
|
|
25
25
|
for (var _a = 0, relative_1 = relative; _a < relative_1.length; _a++) {
|
|
26
26
|
var r = relative_1[_a];
|
|
27
|
-
var dir = r
|
|
27
|
+
var dir = "".concat(r, "/").concat(d);
|
|
28
28
|
try {
|
|
29
|
-
return { dir: dir, module: require(dir
|
|
29
|
+
return { dir: dir, module: require("".concat(dir, "/").concat(name, ".node")) };
|
|
30
30
|
}
|
|
31
31
|
catch (e) {
|
|
32
32
|
lastError = e;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
throw new Error("Failed to load native module: "
|
|
36
|
+
throw new Error("Failed to load native module: ".concat(name, ".node, checked: ").concat(dirs.join(', '), ": ").concat(lastError));
|
|
37
37
|
}
|
|
38
|
-
exports.loadNativeModule = loadNativeModule;
|
|
39
38
|
//# sourceMappingURL=utils.js.map
|
|
@@ -12,12 +12,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
12
12
|
});
|
|
13
13
|
};
|
|
14
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 =
|
|
15
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
16
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
17
17
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
18
18
|
function step(op) {
|
|
19
19
|
if (f) throw new TypeError("Generator is already executing.");
|
|
20
|
-
while (_) try {
|
|
20
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
21
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
22
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
23
23
|
switch (op[0]) {
|
|
@@ -73,10 +73,10 @@ var ConoutConnection = /** @class */ (function () {
|
|
|
73
73
|
conoutPipeName: _conoutPipeName
|
|
74
74
|
};
|
|
75
75
|
var scriptPath = __dirname.replace('node_modules.asar', 'node_modules.asar.unpacked');
|
|
76
|
-
this._worker = new worker_threads_1.Worker(path_1.join(scriptPath, 'worker/conoutSocketWorker.js'), { workerData: workerData });
|
|
76
|
+
this._worker = new worker_threads_1.Worker((0, path_1.join)(scriptPath, 'worker/conoutSocketWorker.js'), { workerData: workerData });
|
|
77
77
|
this._worker.on('message', function (message) {
|
|
78
78
|
switch (message) {
|
|
79
|
-
case 1 /* READY */:
|
|
79
|
+
case 1 /* ConoutWorkerMessage.READY */:
|
|
80
80
|
_this._onReady.fire();
|
|
81
81
|
return;
|
|
82
82
|
default:
|
|
@@ -98,7 +98,7 @@ var ConoutConnection = /** @class */ (function () {
|
|
|
98
98
|
this._drainDataAndClose();
|
|
99
99
|
};
|
|
100
100
|
ConoutConnection.prototype.connectSocket = function (socket) {
|
|
101
|
-
socket.connect(conout_1.getWorkerPipeName(this._conoutPipeName));
|
|
101
|
+
socket.connect((0, conout_1.getWorkerPipeName)(this._conoutPipeName));
|
|
102
102
|
};
|
|
103
103
|
ConoutConnection.prototype._drainDataAndClose = function () {
|
|
104
104
|
var _this = this;
|
package/lib/windowsPtyAgent.js
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
* Copyright (c) 2018, Microsoft Corporation (MIT License).
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.
|
|
8
|
+
exports.WindowsPtyAgent = void 0;
|
|
9
|
+
exports.argsToCommandLine = argsToCommandLine;
|
|
9
10
|
var fs = require("fs");
|
|
10
11
|
var path = require("path");
|
|
11
12
|
var child_process_1 = require("child_process");
|
|
12
13
|
var net_1 = require("net");
|
|
13
14
|
var windowsConoutConnection_1 = require("./windowsConoutConnection");
|
|
15
|
+
var eventEmitter2_1 = require("./eventEmitter2");
|
|
14
16
|
var utils_1 = require("./utils");
|
|
15
17
|
var conptyNative;
|
|
16
18
|
/**
|
|
@@ -24,13 +26,14 @@ var FLUSH_DATA_INTERVAL = 1000;
|
|
|
24
26
|
*/
|
|
25
27
|
var WindowsPtyAgent = /** @class */ (function () {
|
|
26
28
|
function WindowsPtyAgent(file, args, env, cwd, cols, rows, debug, _useConptyDll, conptyInheritCursor) {
|
|
27
|
-
var _this = this;
|
|
28
29
|
if (_useConptyDll === void 0) { _useConptyDll = false; }
|
|
29
30
|
if (conptyInheritCursor === void 0) { conptyInheritCursor = false; }
|
|
31
|
+
var _this = this;
|
|
30
32
|
this._useConptyDll = _useConptyDll;
|
|
31
33
|
this._innerPid = 0;
|
|
34
|
+
this._onError = new eventEmitter2_1.EventEmitter2();
|
|
32
35
|
if (!conptyNative) {
|
|
33
|
-
conptyNative = utils_1.loadNativeModule('conpty').module;
|
|
36
|
+
conptyNative = (0, utils_1.loadNativeModule)('conpty').module;
|
|
34
37
|
}
|
|
35
38
|
this._ptyNative = conptyNative;
|
|
36
39
|
// Sanitize input variable.
|
|
@@ -80,6 +83,11 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
80
83
|
});
|
|
81
84
|
this._inSocket.setEncoding('utf8');
|
|
82
85
|
}
|
|
86
|
+
Object.defineProperty(WindowsPtyAgent.prototype, "onError", {
|
|
87
|
+
get: function () { return this._onError.event; },
|
|
88
|
+
enumerable: false,
|
|
89
|
+
configurable: true
|
|
90
|
+
});
|
|
83
91
|
Object.defineProperty(WindowsPtyAgent.prototype, "inSocket", {
|
|
84
92
|
get: function () { return this._inSocket; },
|
|
85
93
|
enumerable: false,
|
|
@@ -107,13 +115,31 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
107
115
|
});
|
|
108
116
|
WindowsPtyAgent.prototype._completePtyConnection = function () {
|
|
109
117
|
var _this = this;
|
|
118
|
+
var _a;
|
|
110
119
|
if (!this._pendingPtyInfo) {
|
|
111
120
|
return;
|
|
112
121
|
}
|
|
113
|
-
var
|
|
122
|
+
var _b = this._pendingPtyInfo, pty = _b.pty, commandLine = _b.commandLine, cwd = _b.cwd, env = _b.env;
|
|
114
123
|
this._pendingPtyInfo = undefined;
|
|
115
|
-
|
|
116
|
-
|
|
124
|
+
try {
|
|
125
|
+
var connect = conptyNative.connect(pty, commandLine, cwd, env, this._useConptyDll, function (c) { return _this._$onProcessExit(c); });
|
|
126
|
+
this._innerPid = connect.pid;
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
// connect() runs from the conout worker's onReady callback (or its
|
|
130
|
+
// timeout fallback), so a throw here would otherwise surface as an
|
|
131
|
+
// uncaughtException with no way for the consumer to observe it.
|
|
132
|
+
var code = (_a = /error code: (\d+)/.exec(err.message)) === null || _a === void 0 ? void 0 : _a[1];
|
|
133
|
+
this._exitCode = code ? parseInt(code, 10) : -1;
|
|
134
|
+
try {
|
|
135
|
+
this._ptyNative.kill(this._pty, this._useConptyDll);
|
|
136
|
+
}
|
|
137
|
+
catch ( /* already gone */_c) { /* already gone */ }
|
|
138
|
+
this._conoutSocketWorker.dispose();
|
|
139
|
+
this._inSocket.destroy();
|
|
140
|
+
this._outSocket.destroy();
|
|
141
|
+
this._onError.fire(err);
|
|
142
|
+
}
|
|
117
143
|
};
|
|
118
144
|
WindowsPtyAgent.prototype.resize = function (cols, rows) {
|
|
119
145
|
if (this._exitCode !== undefined) {
|
|
@@ -160,7 +186,7 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
160
186
|
return Promise.resolve([]);
|
|
161
187
|
}
|
|
162
188
|
return new Promise(function (resolve) {
|
|
163
|
-
var agent = child_process_1.fork(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()]);
|
|
189
|
+
var agent = (0, child_process_1.fork)(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()]);
|
|
164
190
|
agent.on('message', function (message) {
|
|
165
191
|
clearTimeout(timeout);
|
|
166
192
|
resolve(message.consoleProcessList);
|
|
@@ -180,7 +206,7 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
180
206
|
configurable: true
|
|
181
207
|
});
|
|
182
208
|
WindowsPtyAgent.prototype._generatePipeName = function () {
|
|
183
|
-
return "conpty-"
|
|
209
|
+
return "conpty-".concat(Math.random() * 10000000);
|
|
184
210
|
};
|
|
185
211
|
/**
|
|
186
212
|
* Triggered from the native side when a contpy process exits.
|
|
@@ -222,7 +248,7 @@ function argsToCommandLine(file, args) {
|
|
|
222
248
|
if (args.length === 0) {
|
|
223
249
|
return file;
|
|
224
250
|
}
|
|
225
|
-
return argsToCommandLine(file, [])
|
|
251
|
+
return "".concat(argsToCommandLine(file, []), " ").concat(args);
|
|
226
252
|
}
|
|
227
253
|
var argv = [file];
|
|
228
254
|
Array.prototype.push.apply(argv, args);
|
|
@@ -270,7 +296,6 @@ function argsToCommandLine(file, args) {
|
|
|
270
296
|
}
|
|
271
297
|
return result;
|
|
272
298
|
}
|
|
273
|
-
exports.argsToCommandLine = argsToCommandLine;
|
|
274
299
|
function isCommandLine(args) {
|
|
275
300
|
return typeof args === 'string';
|
|
276
301
|
}
|
package/lib/windowsTerminal.js
CHANGED
|
@@ -8,10 +8,12 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
8
8
|
var extendStatics = function (d, b) {
|
|
9
9
|
extendStatics = Object.setPrototypeOf ||
|
|
10
10
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
11
|
-
function (d, b) { for (var p in b) if (
|
|
11
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
12
12
|
return extendStatics(d, b);
|
|
13
13
|
};
|
|
14
14
|
return function (d, b) {
|
|
15
|
+
if (typeof b !== "function" && b !== null)
|
|
16
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
15
17
|
extendStatics(d, b);
|
|
16
18
|
function __() { this.constructor = d; }
|
|
17
19
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
@@ -37,7 +39,7 @@ var WindowsTerminal = /** @class */ (function (_super) {
|
|
|
37
39
|
if (opt.encoding) {
|
|
38
40
|
console.warn('Setting encoding on Windows is not supported');
|
|
39
41
|
}
|
|
40
|
-
var env = utils_1.assign({}, opt.env);
|
|
42
|
+
var env = (0, utils_1.assign)({}, opt.env);
|
|
41
43
|
_this._cols = opt.cols || terminal_1.DEFAULT_COLS;
|
|
42
44
|
_this._rows = opt.rows || terminal_1.DEFAULT_ROWS;
|
|
43
45
|
var cwd = opt.cwd || process.cwd();
|
|
@@ -50,6 +52,12 @@ var WindowsTerminal = /** @class */ (function (_super) {
|
|
|
50
52
|
// Create new termal.
|
|
51
53
|
_this._agent = new windowsPtyAgent_1.WindowsPtyAgent(file, args, parsedEnv, cwd, _this._cols, _this._rows, false, opt.useConptyDll, opt.conptyInheritCursor);
|
|
52
54
|
_this._socket = _this._agent.outSocket;
|
|
55
|
+
// The socket 'close' handler that drives 'exit' is only attached after
|
|
56
|
+
// ready_datapipe, which never fires when connect() fails.
|
|
57
|
+
_this._agent.onError(function () {
|
|
58
|
+
_this._close();
|
|
59
|
+
_this.emit('exit', _this._agent.exitCode);
|
|
60
|
+
});
|
|
53
61
|
// Not available until `ready` event emitted.
|
|
54
62
|
_this._pid = _this._agent.innerPid;
|
|
55
63
|
_this._fd = _this._agent.fd;
|
|
@@ -10,13 +10,13 @@ var conoutPipeName = worker_threads_1.workerData.conoutPipeName;
|
|
|
10
10
|
var conoutSocket = new net_1.Socket();
|
|
11
11
|
conoutSocket.setEncoding('utf8');
|
|
12
12
|
conoutSocket.connect(conoutPipeName, function () {
|
|
13
|
-
var server = net_1.createServer(function (workerSocket) {
|
|
13
|
+
var server = (0, net_1.createServer)(function (workerSocket) {
|
|
14
14
|
conoutSocket.pipe(workerSocket);
|
|
15
15
|
});
|
|
16
|
-
server.listen(conout_1.getWorkerPipeName(conoutPipeName));
|
|
16
|
+
server.listen((0, conout_1.getWorkerPipeName)(conoutPipeName));
|
|
17
17
|
if (!worker_threads_1.parentPort) {
|
|
18
18
|
throw new Error('worker_threads parentPort is null');
|
|
19
19
|
}
|
|
20
|
-
worker_threads_1.parentPort.postMessage(1 /* READY */);
|
|
20
|
+
worker_threads_1.parentPort.postMessage(1 /* ConoutWorkerMessage.READY */);
|
|
21
21
|
});
|
|
22
22
|
//# sourceMappingURL=conoutSocketWorker.js.map
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Microsoft Corporation"
|
|
6
6
|
},
|
|
7
|
-
"version": "1.2.0-beta.
|
|
7
|
+
"version": "1.2.0-beta.14",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"main": "./lib/index.js",
|
|
10
10
|
"types": "./typings/node-pty.d.ts",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsc -b ./src/tsconfig.json",
|
|
40
40
|
"watch": "tsc -b -w ./src/tsconfig.json",
|
|
41
|
-
"lint": "eslint
|
|
41
|
+
"lint": "eslint src/",
|
|
42
42
|
"install": "node scripts/prebuild.js || node-gyp rebuild",
|
|
43
43
|
"postinstall": "node scripts/post-install.js",
|
|
44
44
|
"compileCommands": "node scripts/gen-compile-commands.js",
|
|
@@ -53,13 +53,14 @@
|
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/mocha": "^7.0.2",
|
|
55
55
|
"@types/node": "12",
|
|
56
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
57
|
-
"@typescript-eslint/parser": "^
|
|
56
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
57
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
58
58
|
"cross-env": "^5.1.4",
|
|
59
|
-
"eslint": "^
|
|
59
|
+
"eslint": "^10.4.0",
|
|
60
|
+
"globals": "^14.0.0",
|
|
60
61
|
"mocha": "10",
|
|
61
62
|
"node-gyp": "^11.4.2",
|
|
62
63
|
"ps-list": "^6.0.0",
|
|
63
|
-
"typescript": "^
|
|
64
|
+
"typescript": "^5.0.0"
|
|
64
65
|
}
|
|
65
66
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/unix/pty.cc
CHANGED
package/src/win/conpty.cc
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
#include <node_api.h>
|
|
15
15
|
#include <assert.h>
|
|
16
16
|
#include <Shlwapi.h> // PathCombine, PathIsRelative
|
|
17
|
+
#include <atomic>
|
|
18
|
+
#include <mutex>
|
|
17
19
|
#include <sstream>
|
|
18
20
|
#include <iostream>
|
|
19
21
|
#include <string>
|
|
@@ -44,15 +46,18 @@ struct pty_baton {
|
|
|
44
46
|
HANDLE hOut;
|
|
45
47
|
HPCON hpc;
|
|
46
48
|
|
|
47
|
-
HANDLE hShell;
|
|
49
|
+
HANDLE hShell = nullptr;
|
|
48
50
|
|
|
49
51
|
pty_baton(int _id, HANDLE _hIn, HANDLE _hOut, HPCON _hpc) : id(_id), hIn(_hIn), hOut(_hOut), hpc(_hpc) {};
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
static std::vector<std::unique_ptr<pty_baton>> ptyHandles;
|
|
53
|
-
static
|
|
55
|
+
static std::mutex g_ptyHandlesMutex;
|
|
56
|
+
static std::atomic<int> ptyCounter{0};
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
// The leading scoped-lock parameter encodes the precondition that the caller
|
|
59
|
+
// holds g_ptyHandlesMutex.
|
|
60
|
+
static pty_baton* get_pty_baton(const std::lock_guard<std::mutex>&, int id) {
|
|
56
61
|
auto it = std::find_if(ptyHandles.begin(), ptyHandles.end(), [id](const auto& ptyHandle) {
|
|
57
62
|
return ptyHandle->id == id;
|
|
58
63
|
});
|
|
@@ -62,17 +67,6 @@ static pty_baton* get_pty_baton(int id) {
|
|
|
62
67
|
return nullptr;
|
|
63
68
|
}
|
|
64
69
|
|
|
65
|
-
static bool remove_pty_baton(int id) {
|
|
66
|
-
auto it = std::remove_if(ptyHandles.begin(), ptyHandles.end(), [id](const auto& ptyHandle) {
|
|
67
|
-
return ptyHandle->id == id;
|
|
68
|
-
});
|
|
69
|
-
if (it != ptyHandles.end()) {
|
|
70
|
-
ptyHandles.erase(it);
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
70
|
struct ExitEvent {
|
|
77
71
|
int exit_code = 0;
|
|
78
72
|
};
|
|
@@ -99,11 +93,15 @@ void SetupExitCallback(Napi::Env env, Napi::Function cb, pty_baton* baton) {
|
|
|
99
93
|
ExitEvent *exit_event = new ExitEvent;
|
|
100
94
|
// Wait for process to complete.
|
|
101
95
|
WaitForSingleObject(baton->hShell, INFINITE);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
{
|
|
97
|
+
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
98
|
+
GetExitCodeProcess(baton->hShell, (LPDWORD)(&exit_event->exit_code));
|
|
99
|
+
CloseHandle(baton->hShell);
|
|
100
|
+
const int id = baton->id;
|
|
101
|
+
std::erase_if(ptyHandles, [id](const auto& ptyHandle) {
|
|
102
|
+
return ptyHandle->id == id;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
107
105
|
|
|
108
106
|
auto status = tsfn.BlockingCall(exit_event, callback); // In main thread
|
|
109
107
|
switch (status) {
|
|
@@ -298,10 +296,13 @@ static Napi::Value PtyStartProcess(const Napi::CallbackInfo& info) {
|
|
|
298
296
|
|
|
299
297
|
if (SUCCEEDED(hr)) {
|
|
300
298
|
// We were able to instantiate a conpty
|
|
301
|
-
const int ptyId =
|
|
299
|
+
const int ptyId = ++ptyCounter;
|
|
302
300
|
marshal.Set("pty", Napi::Number::New(env, ptyId));
|
|
303
|
-
|
|
304
|
-
|
|
301
|
+
{
|
|
302
|
+
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
303
|
+
ptyHandles.emplace_back(
|
|
304
|
+
std::make_unique<pty_baton>(ptyId, hIn, hOut, hpc));
|
|
305
|
+
}
|
|
305
306
|
} else {
|
|
306
307
|
throw Napi::Error::New(env, "Cannot launch conpty");
|
|
307
308
|
}
|
|
@@ -349,10 +350,13 @@ static Napi::Value PtyConnect(const Napi::CallbackInfo& info) {
|
|
|
349
350
|
const bool useConptyDll = info[4].As<Napi::Boolean>().Value();
|
|
350
351
|
Napi::Function exitCallback = info[5].As<Napi::Function>();
|
|
351
352
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
353
|
+
pty_baton* handle;
|
|
354
|
+
{
|
|
355
|
+
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
356
|
+
handle = get_pty_baton(lock, id);
|
|
357
|
+
if (!handle) {
|
|
358
|
+
throw Napi::Error::New(env, "Invalid pty handle");
|
|
359
|
+
}
|
|
356
360
|
}
|
|
357
361
|
|
|
358
362
|
// Prepare command line
|
|
@@ -380,6 +384,14 @@ static Napi::Value PtyConnect(const Napi::CallbackInfo& info) {
|
|
|
380
384
|
ConnectNamedPipe(handle->hIn, nullptr);
|
|
381
385
|
ConnectNamedPipe(handle->hOut, nullptr);
|
|
382
386
|
|
|
387
|
+
// Close hIn/hOut on every exit so a throw doesn't leak the named-pipe server handles.
|
|
388
|
+
auto closePipeHandles = [handle]() {
|
|
389
|
+
CloseHandle(handle->hIn);
|
|
390
|
+
CloseHandle(handle->hOut);
|
|
391
|
+
handle->hIn = nullptr;
|
|
392
|
+
handle->hOut = nullptr;
|
|
393
|
+
};
|
|
394
|
+
|
|
383
395
|
// Attach the pseudoconsole to the client application we're creating
|
|
384
396
|
STARTUPINFOEXW siEx{0};
|
|
385
397
|
siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);
|
|
@@ -390,12 +402,14 @@ static Napi::Value PtyConnect(const Napi::CallbackInfo& info) {
|
|
|
390
402
|
|
|
391
403
|
SIZE_T size = 0;
|
|
392
404
|
InitializeProcThreadAttributeList(NULL, 1, 0, &size);
|
|
393
|
-
BYTE
|
|
394
|
-
siEx.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList);
|
|
405
|
+
std::unique_ptr<BYTE[]> attrList = std::make_unique<BYTE[]>(size);
|
|
406
|
+
siEx.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList.get());
|
|
395
407
|
|
|
396
408
|
fSuccess = InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, &size);
|
|
397
409
|
if (!fSuccess) {
|
|
398
|
-
|
|
410
|
+
Napi::Error error = errorWithCode(info, "InitializeProcThreadAttributeList failed");
|
|
411
|
+
closePipeHandles();
|
|
412
|
+
throw error;
|
|
399
413
|
}
|
|
400
414
|
fSuccess = UpdateProcThreadAttribute(siEx.lpAttributeList,
|
|
401
415
|
0,
|
|
@@ -405,7 +419,10 @@ static Napi::Value PtyConnect(const Napi::CallbackInfo& info) {
|
|
|
405
419
|
NULL,
|
|
406
420
|
NULL);
|
|
407
421
|
if (!fSuccess) {
|
|
408
|
-
|
|
422
|
+
Napi::Error error = errorWithCode(info, "UpdateProcThreadAttribute failed");
|
|
423
|
+
DeleteProcThreadAttributeList(siEx.lpAttributeList);
|
|
424
|
+
closePipeHandles();
|
|
425
|
+
throw error;
|
|
409
426
|
}
|
|
410
427
|
|
|
411
428
|
PROCESS_INFORMATION piClient{};
|
|
@@ -422,9 +439,14 @@ static Napi::Value PtyConnect(const Napi::CallbackInfo& info) {
|
|
|
422
439
|
&piClient // lpProcessInformation
|
|
423
440
|
);
|
|
424
441
|
if (!fSuccess) {
|
|
425
|
-
|
|
442
|
+
Napi::Error error = errorWithCode(info, "Cannot create process");
|
|
443
|
+
DeleteProcThreadAttributeList(siEx.lpAttributeList);
|
|
444
|
+
closePipeHandles();
|
|
445
|
+
throw error;
|
|
426
446
|
}
|
|
427
447
|
|
|
448
|
+
DeleteProcThreadAttributeList(siEx.lpAttributeList);
|
|
449
|
+
|
|
428
450
|
HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
|
|
429
451
|
bool fLoadedDll = hLibrary != nullptr;
|
|
430
452
|
if (useConptyDll && fLoadedDll)
|
|
@@ -443,8 +465,7 @@ static Napi::Value PtyConnect(const Napi::CallbackInfo& info) {
|
|
|
443
465
|
// Close the thread handle to avoid resource leak
|
|
444
466
|
CloseHandle(piClient.hThread);
|
|
445
467
|
// Close the input read and output write handle of the pseudoconsole
|
|
446
|
-
|
|
447
|
-
CloseHandle(handle->hOut);
|
|
468
|
+
closePipeHandles();
|
|
448
469
|
|
|
449
470
|
SetupExitCallback(env, exitCallback, handle);
|
|
450
471
|
|
|
@@ -471,7 +492,8 @@ static Napi::Value PtyResize(const Napi::CallbackInfo& info) {
|
|
|
471
492
|
SHORT rows = static_cast<SHORT>(info[2].As<Napi::Number>().Uint32Value());
|
|
472
493
|
const bool useConptyDll = info[3].As<Napi::Boolean>().Value();
|
|
473
494
|
|
|
474
|
-
|
|
495
|
+
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
496
|
+
const pty_baton* handle = get_pty_baton(lock, id);
|
|
475
497
|
|
|
476
498
|
if (handle != nullptr) {
|
|
477
499
|
HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
|
|
@@ -512,7 +534,8 @@ static Napi::Value PtyClear(const Napi::CallbackInfo& info) {
|
|
|
512
534
|
return env.Undefined();
|
|
513
535
|
}
|
|
514
536
|
|
|
515
|
-
|
|
537
|
+
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
538
|
+
const pty_baton* handle = get_pty_baton(lock, id);
|
|
516
539
|
|
|
517
540
|
if (handle != nullptr) {
|
|
518
541
|
HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
|
|
@@ -543,7 +566,8 @@ static Napi::Value PtyKill(const Napi::CallbackInfo& info) {
|
|
|
543
566
|
int id = info[0].As<Napi::Number>().Int32Value();
|
|
544
567
|
const bool useConptyDll = info[1].As<Napi::Boolean>().Value();
|
|
545
568
|
|
|
546
|
-
|
|
569
|
+
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
570
|
+
pty_baton* handle = get_pty_baton(lock, id);
|
|
547
571
|
|
|
548
572
|
if (handle != nullptr) {
|
|
549
573
|
HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
|
|
@@ -558,7 +582,17 @@ static Napi::Value PtyKill(const Napi::CallbackInfo& info) {
|
|
|
558
582
|
pfnClosePseudoConsole(handle->hpc);
|
|
559
583
|
}
|
|
560
584
|
}
|
|
561
|
-
if (
|
|
585
|
+
// Defensive: if PtyConnect was never called (or failed before closing the
|
|
586
|
+
// pipe handles), release the named pipe server handles here.
|
|
587
|
+
if (handle->hIn != nullptr) {
|
|
588
|
+
CloseHandle(handle->hIn);
|
|
589
|
+
handle->hIn = nullptr;
|
|
590
|
+
}
|
|
591
|
+
if (handle->hOut != nullptr) {
|
|
592
|
+
CloseHandle(handle->hOut);
|
|
593
|
+
handle->hOut = nullptr;
|
|
594
|
+
}
|
|
595
|
+
if (useConptyDll && handle->hShell != nullptr) {
|
|
562
596
|
TerminateProcess(handle->hShell, 1);
|
|
563
597
|
}
|
|
564
598
|
}
|