node-pty 1.2.0-beta.14 → 1.2.0-beta.16
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/unixTerminal.js +4 -0
- package/lib/windowsConoutConnection.js +18 -12
- package/lib/windowsPtyAgent.js +53 -12
- package/lib/windowsTerminal.js +5 -0
- package/package.json +15 -4
- 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/win/conpty.cc +69 -3
- package/typings/node-pty.d.ts +17 -0
package/lib/unixTerminal.js
CHANGED
|
@@ -261,6 +261,10 @@ var UnixTerminal = /** @class */ (function (_super) {
|
|
|
261
261
|
};
|
|
262
262
|
UnixTerminal.prototype.clear = function () {
|
|
263
263
|
};
|
|
264
|
+
UnixTerminal.prototype.setParentWindow = function (handle) {
|
|
265
|
+
// Windows only
|
|
266
|
+
return false;
|
|
267
|
+
};
|
|
264
268
|
UnixTerminal.prototype._sanitizeEnv = function (env) {
|
|
265
269
|
// Make sure we didn't start our server from inside tmux.
|
|
266
270
|
delete env['TMUX'];
|
|
@@ -50,25 +50,15 @@ var eventEmitter2_1 = require("./eventEmitter2");
|
|
|
50
50
|
* the timer has started.
|
|
51
51
|
*/
|
|
52
52
|
var FLUSH_DATA_INTERVAL = 1000;
|
|
53
|
-
/**
|
|
54
|
-
* Connects to and manages the lifecycle of the conout socket. This socket must be drained on
|
|
55
|
-
* another thread in order to avoid deadlocks where Conpty waits for the out socket to drain
|
|
56
|
-
* when `ClosePseudoConsole` is called. This happens when data is being written to the terminal when
|
|
57
|
-
* the pty is closed.
|
|
58
|
-
*
|
|
59
|
-
* See also:
|
|
60
|
-
* - https://github.com/microsoft/node-pty/issues/375
|
|
61
|
-
* - https://github.com/microsoft/vscode/issues/76548
|
|
62
|
-
* - https://github.com/microsoft/terminal/issues/1810
|
|
63
|
-
* - https://docs.microsoft.com/en-us/windows/console/closepseudoconsole
|
|
64
|
-
*/
|
|
65
53
|
var ConoutConnection = /** @class */ (function () {
|
|
66
54
|
function ConoutConnection(_conoutPipeName, _useConptyDll) {
|
|
67
55
|
var _this = this;
|
|
68
56
|
this._conoutPipeName = _conoutPipeName;
|
|
69
57
|
this._useConptyDll = _useConptyDll;
|
|
70
58
|
this._isDisposed = false;
|
|
59
|
+
this._isReady = false;
|
|
71
60
|
this._onReady = new eventEmitter2_1.EventEmitter2();
|
|
61
|
+
this._onError = new eventEmitter2_1.EventEmitter2();
|
|
72
62
|
var workerData = {
|
|
73
63
|
conoutPipeName: _conoutPipeName
|
|
74
64
|
};
|
|
@@ -77,18 +67,34 @@ var ConoutConnection = /** @class */ (function () {
|
|
|
77
67
|
this._worker.on('message', function (message) {
|
|
78
68
|
switch (message) {
|
|
79
69
|
case 1 /* ConoutWorkerMessage.READY */:
|
|
70
|
+
_this._isReady = true;
|
|
80
71
|
_this._onReady.fire();
|
|
81
72
|
return;
|
|
82
73
|
default:
|
|
83
74
|
console.warn('Unexpected ConoutWorkerMessage', message);
|
|
84
75
|
}
|
|
85
76
|
});
|
|
77
|
+
this._worker.on('error', function (error) {
|
|
78
|
+
if (!_this._isDisposed && !_this._isReady) {
|
|
79
|
+
_this._onError.fire(error);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
this._worker.on('exit', function (code) {
|
|
83
|
+
if (!_this._isDisposed && !_this._isReady) {
|
|
84
|
+
_this._onError.fire(new Error("Conout worker exited before connecting (code ".concat(code, ")")));
|
|
85
|
+
}
|
|
86
|
+
});
|
|
86
87
|
}
|
|
87
88
|
Object.defineProperty(ConoutConnection.prototype, "onReady", {
|
|
88
89
|
get: function () { return this._onReady.event; },
|
|
89
90
|
enumerable: false,
|
|
90
91
|
configurable: true
|
|
91
92
|
});
|
|
93
|
+
Object.defineProperty(ConoutConnection.prototype, "onError", {
|
|
94
|
+
get: function () { return this._onError.event; },
|
|
95
|
+
enumerable: false,
|
|
96
|
+
configurable: true
|
|
97
|
+
});
|
|
92
98
|
ConoutConnection.prototype.dispose = function () {
|
|
93
99
|
if (!this._useConptyDll && this._isDisposed) {
|
|
94
100
|
return;
|
package/lib/windowsPtyAgent.js
CHANGED
|
@@ -21,13 +21,19 @@ var conptyNative;
|
|
|
21
21
|
* has started.
|
|
22
22
|
*/
|
|
23
23
|
var FLUSH_DATA_INTERVAL = 1000;
|
|
24
|
+
var CONNECTION_TIMEOUT = 5000;
|
|
25
|
+
var defaultWindowsPtyAgentOptions = {
|
|
26
|
+
connectionTimeout: CONNECTION_TIMEOUT,
|
|
27
|
+
conoutConnectionFactory: function (conoutPipeName, useConptyDll) { return new windowsConoutConnection_1.ConoutConnection(conoutPipeName, useConptyDll); }
|
|
28
|
+
};
|
|
24
29
|
/**
|
|
25
30
|
* This agent sits between the WindowsTerminal class and provides an interface for conpty.
|
|
26
31
|
*/
|
|
27
32
|
var WindowsPtyAgent = /** @class */ (function () {
|
|
28
|
-
function WindowsPtyAgent(file, args, env, cwd, cols, rows, debug, _useConptyDll, conptyInheritCursor) {
|
|
33
|
+
function WindowsPtyAgent(file, args, env, cwd, cols, rows, debug, _useConptyDll, conptyInheritCursor, options) {
|
|
29
34
|
if (_useConptyDll === void 0) { _useConptyDll = false; }
|
|
30
35
|
if (conptyInheritCursor === void 0) { conptyInheritCursor = false; }
|
|
36
|
+
if (options === void 0) { options = defaultWindowsPtyAgentOptions; }
|
|
31
37
|
var _this = this;
|
|
32
38
|
this._useConptyDll = _useConptyDll;
|
|
33
39
|
this._innerPid = 0;
|
|
@@ -54,24 +60,26 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
54
60
|
// We must wait for the worker to connect before calling conptyNative.connect()
|
|
55
61
|
// to avoid blocking the Node.js event loop in ConnectNamedPipe.
|
|
56
62
|
// See https://github.com/microsoft/node-pty/issues/763
|
|
57
|
-
this._conoutSocketWorker =
|
|
63
|
+
this._conoutSocketWorker = options.conoutConnectionFactory(term.conout, this._useConptyDll);
|
|
58
64
|
// Store pending connection info - we'll complete the connection when worker is ready
|
|
59
65
|
this._pendingPtyInfo = { pty: this._pty, commandLine: commandLine, cwd: cwd, env: env };
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
}, 5000);
|
|
66
|
+
// Never call connect() before the worker is ready, as ConnectNamedPipe
|
|
67
|
+
// would block the Node.js event loop while waiting for the output client.
|
|
68
|
+
this._connectionTimeout = setTimeout(function () {
|
|
69
|
+
_this._failPtyConnection(new Error('Timed out waiting for ConPTY output worker'));
|
|
70
|
+
}, options.connectionTimeout);
|
|
67
71
|
this._conoutSocketWorker.onReady(function () {
|
|
68
|
-
|
|
72
|
+
if (!_this._pendingPtyInfo) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
_this._clearConnectionTimeout();
|
|
69
76
|
_this._conoutSocketWorker.connectSocket(_this._outSocket);
|
|
70
77
|
// Now that the worker has connected to the output pipe, we can safely call
|
|
71
78
|
// conptyNative.connect() which calls ConnectNamedPipe - it won't block because
|
|
72
79
|
// the client (worker) is already connected
|
|
73
80
|
_this._completePtyConnection();
|
|
74
81
|
});
|
|
82
|
+
this._conoutSocketWorker.onError(function (error) { return _this._failPtyConnection(error); });
|
|
75
83
|
this._outSocket.on('connect', function () {
|
|
76
84
|
_this._outSocket.emit('ready_datapipe');
|
|
77
85
|
});
|
|
@@ -119,6 +127,7 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
119
127
|
if (!this._pendingPtyInfo) {
|
|
120
128
|
return;
|
|
121
129
|
}
|
|
130
|
+
this._clearConnectionTimeout();
|
|
122
131
|
var _b = this._pendingPtyInfo, pty = _b.pty, commandLine = _b.commandLine, cwd = _b.cwd, env = _b.env;
|
|
123
132
|
this._pendingPtyInfo = undefined;
|
|
124
133
|
try {
|
|
@@ -126,8 +135,8 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
126
135
|
this._innerPid = connect.pid;
|
|
127
136
|
}
|
|
128
137
|
catch (err) {
|
|
129
|
-
// connect() runs from the conout worker's onReady callback
|
|
130
|
-
//
|
|
138
|
+
// connect() runs from the conout worker's onReady callback, so a throw
|
|
139
|
+
// here would otherwise surface as an
|
|
131
140
|
// uncaughtException with no way for the consumer to observe it.
|
|
132
141
|
var code = (_a = /error code: (\d+)/.exec(err.message)) === null || _a === void 0 ? void 0 : _a[1];
|
|
133
142
|
this._exitCode = code ? parseInt(code, 10) : -1;
|
|
@@ -141,6 +150,28 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
141
150
|
this._onError.fire(err);
|
|
142
151
|
}
|
|
143
152
|
};
|
|
153
|
+
WindowsPtyAgent.prototype._failPtyConnection = function (error) {
|
|
154
|
+
if (!this._pendingPtyInfo) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this._clearConnectionTimeout();
|
|
158
|
+
this._pendingPtyInfo = undefined;
|
|
159
|
+
this._exitCode = -1;
|
|
160
|
+
try {
|
|
161
|
+
this._ptyNative.kill(this._pty, this._useConptyDll);
|
|
162
|
+
}
|
|
163
|
+
catch ( /* already gone */_a) { /* already gone */ }
|
|
164
|
+
this._conoutSocketWorker.dispose();
|
|
165
|
+
this._inSocket.destroy();
|
|
166
|
+
this._outSocket.destroy();
|
|
167
|
+
this._onError.fire(error);
|
|
168
|
+
};
|
|
169
|
+
WindowsPtyAgent.prototype._clearConnectionTimeout = function () {
|
|
170
|
+
if (this._connectionTimeout) {
|
|
171
|
+
clearTimeout(this._connectionTimeout);
|
|
172
|
+
this._connectionTimeout = undefined;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
144
175
|
WindowsPtyAgent.prototype.resize = function (cols, rows) {
|
|
145
176
|
if (this._exitCode !== undefined) {
|
|
146
177
|
throw new Error('Cannot resize a pty that has already exited');
|
|
@@ -150,9 +181,19 @@ var WindowsPtyAgent = /** @class */ (function () {
|
|
|
150
181
|
WindowsPtyAgent.prototype.clear = function () {
|
|
151
182
|
this._ptyNative.clear(this._pty, this._useConptyDll);
|
|
152
183
|
};
|
|
184
|
+
/**
|
|
185
|
+
* Tells ConPTY which top-level window hosts the terminal (ConptyReparentPseudoConsole). The
|
|
186
|
+
* window becomes the owner of the console window returned by GetConsoleWindow(), so dialogs
|
|
187
|
+
* that console apps parent to it (e.g. WAM sign-in) stack above the host window. Returns
|
|
188
|
+
* whether the request was sent to ConPTY, which applies it asynchronously.
|
|
189
|
+
*/
|
|
190
|
+
WindowsPtyAgent.prototype.setParentWindow = function (handle) {
|
|
191
|
+
return this._ptyNative.reparent(this._pty, handle, this._useConptyDll);
|
|
192
|
+
};
|
|
153
193
|
WindowsPtyAgent.prototype.kill = function () {
|
|
154
194
|
var _this = this;
|
|
155
195
|
// Prevent deferred connection from completing after kill
|
|
196
|
+
this._clearConnectionTimeout();
|
|
156
197
|
this._pendingPtyInfo = undefined;
|
|
157
198
|
// Tell the agent to kill the pty, this releases handles to the process
|
|
158
199
|
if (!this._useConptyDll) {
|
package/lib/windowsTerminal.js
CHANGED
|
@@ -148,6 +148,11 @@ var WindowsTerminal = /** @class */ (function (_super) {
|
|
|
148
148
|
_this._agent.clear();
|
|
149
149
|
});
|
|
150
150
|
};
|
|
151
|
+
WindowsTerminal.prototype.setParentWindow = function (handle) {
|
|
152
|
+
// Not deferred: the pseudoconsole exists as soon as the agent is created, and the owner
|
|
153
|
+
// should be requested before the shell starts asking for it.
|
|
154
|
+
return this._agent.setParentWindow(handle);
|
|
155
|
+
};
|
|
151
156
|
WindowsTerminal.prototype.destroy = function () {
|
|
152
157
|
var _this = this;
|
|
153
158
|
this._deferNoArgs(function () {
|
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.16",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"main": "./lib/index.js",
|
|
10
10
|
"types": "./typings/node-pty.d.ts",
|
|
@@ -27,6 +27,18 @@
|
|
|
27
27
|
"bugs": {
|
|
28
28
|
"url": "https://github.com/microsoft/node-pty/issues"
|
|
29
29
|
},
|
|
30
|
+
"devEngines": {
|
|
31
|
+
"runtime": {
|
|
32
|
+
"name": "node",
|
|
33
|
+
"version": ">=24",
|
|
34
|
+
"onFail": "error"
|
|
35
|
+
},
|
|
36
|
+
"packageManager": {
|
|
37
|
+
"name": "npm",
|
|
38
|
+
"version": ">=11.6.3",
|
|
39
|
+
"onFail": "error"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
30
42
|
"keywords": [
|
|
31
43
|
"pty",
|
|
32
44
|
"tty",
|
|
@@ -51,15 +63,14 @@
|
|
|
51
63
|
"node-addon-api": "^7.1.0"
|
|
52
64
|
},
|
|
53
65
|
"devDependencies": {
|
|
54
|
-
"@types/mocha": "^
|
|
66
|
+
"@types/mocha": "^10.0.10",
|
|
55
67
|
"@types/node": "12",
|
|
56
68
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
57
69
|
"@typescript-eslint/parser": "^8.0.0",
|
|
58
70
|
"cross-env": "^5.1.4",
|
|
59
71
|
"eslint": "^10.4.0",
|
|
60
72
|
"globals": "^14.0.0",
|
|
61
|
-
"mocha": "
|
|
62
|
-
"node-gyp": "^11.4.2",
|
|
73
|
+
"mocha": "12.0.2",
|
|
63
74
|
"ps-list": "^6.0.0",
|
|
64
75
|
"typescript": "^5.0.0"
|
|
65
76
|
}
|
|
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/win/conpty.cc
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
#include <assert.h>
|
|
16
16
|
#include <Shlwapi.h> // PathCombine, PathIsRelative
|
|
17
17
|
#include <atomic>
|
|
18
|
+
#include <cstring>
|
|
18
19
|
#include <mutex>
|
|
19
20
|
#include <sstream>
|
|
20
21
|
#include <iostream>
|
|
@@ -40,6 +41,9 @@ typedef void (__stdcall *PFNRELEASEPSEUDOCONSOLE)(HPCON hpc);
|
|
|
40
41
|
|
|
41
42
|
#endif
|
|
42
43
|
|
|
44
|
+
// Only exported by the bundled conpty.dll; kernel32 has no equivalent.
|
|
45
|
+
typedef HRESULT (__stdcall *PFNREPARENTPSEUDOCONSOLE)(HPCON hpc, HWND newParent);
|
|
46
|
+
|
|
43
47
|
struct pty_baton {
|
|
44
48
|
int id;
|
|
45
49
|
HANDLE hIn;
|
|
@@ -495,7 +499,7 @@ static Napi::Value PtyResize(const Napi::CallbackInfo& info) {
|
|
|
495
499
|
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
496
500
|
const pty_baton* handle = get_pty_baton(lock, id);
|
|
497
501
|
|
|
498
|
-
if (handle != nullptr) {
|
|
502
|
+
if (handle != nullptr && handle->hpc != nullptr) {
|
|
499
503
|
HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
|
|
500
504
|
bool fLoadedDll = hLibrary != nullptr;
|
|
501
505
|
if (fLoadedDll)
|
|
@@ -537,7 +541,7 @@ static Napi::Value PtyClear(const Napi::CallbackInfo& info) {
|
|
|
537
541
|
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
538
542
|
const pty_baton* handle = get_pty_baton(lock, id);
|
|
539
543
|
|
|
540
|
-
if (handle != nullptr) {
|
|
544
|
+
if (handle != nullptr && handle->hpc != nullptr) {
|
|
541
545
|
HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
|
|
542
546
|
bool fLoadedDll = hLibrary != nullptr;
|
|
543
547
|
if (fLoadedDll)
|
|
@@ -553,6 +557,65 @@ static Napi::Value PtyClear(const Napi::CallbackInfo& info) {
|
|
|
553
557
|
return env.Undefined();
|
|
554
558
|
}
|
|
555
559
|
|
|
560
|
+
// The handle is the bytes of an HWND in native byte order, which is how Electron's
|
|
561
|
+
// BrowserWindow.getNativeWindowHandle() returns it.
|
|
562
|
+
static bool TryGetWindowHandle(const Napi::Value& value, HWND* hwnd) {
|
|
563
|
+
if (!value.IsBuffer()) {
|
|
564
|
+
return false;
|
|
565
|
+
}
|
|
566
|
+
const auto buffer = value.As<Napi::Buffer<uint8_t>>();
|
|
567
|
+
if (buffer.Length() != sizeof(HWND)) {
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
std::memcpy(hwnd, buffer.Data(), sizeof(*hwnd));
|
|
571
|
+
return true;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
static Napi::Value PtyReparent(const Napi::CallbackInfo& info) {
|
|
575
|
+
Napi::Env env(info.Env());
|
|
576
|
+
Napi::HandleScope scope(env);
|
|
577
|
+
|
|
578
|
+
if (info.Length() != 3 ||
|
|
579
|
+
!info[0].IsNumber() ||
|
|
580
|
+
!info[2].IsBoolean()) {
|
|
581
|
+
throw Napi::Error::New(env, "Usage: pty.reparent(id, hwnd, useConptyDll)");
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
int id = info[0].As<Napi::Number>().Int32Value();
|
|
585
|
+
HWND newParent;
|
|
586
|
+
if (!TryGetWindowHandle(info[1], &newParent)) {
|
|
587
|
+
throw Napi::Error::New(env, "pty.reparent: hwnd must be a Buffer the size of an HWND");
|
|
588
|
+
}
|
|
589
|
+
const bool useConptyDll = info[2].As<Napi::Boolean>().Value();
|
|
590
|
+
|
|
591
|
+
// ConptyReparentPseudoConsole only exists in the bundled conpty.dll.
|
|
592
|
+
if (!useConptyDll) {
|
|
593
|
+
return Napi::Boolean::New(env, false);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
|
|
597
|
+
const pty_baton* handle = get_pty_baton(lock, id);
|
|
598
|
+
|
|
599
|
+
bool sent = false;
|
|
600
|
+
if (handle != nullptr && handle->hpc != nullptr) {
|
|
601
|
+
HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
|
|
602
|
+
bool fLoadedDll = hLibrary != nullptr;
|
|
603
|
+
if (fLoadedDll)
|
|
604
|
+
{
|
|
605
|
+
PFNREPARENTPSEUDOCONSOLE const pfnReparentPseudoConsole = (PFNREPARENTPSEUDOCONSOLE)GetProcAddress(
|
|
606
|
+
(HMODULE)hLibrary, "ConptyReparentPseudoConsole");
|
|
607
|
+
if (pfnReparentPseudoConsole)
|
|
608
|
+
{
|
|
609
|
+
// Asks ConPTY to make newParent the owner of the console window returned by
|
|
610
|
+
// GetConsoleWindow(); ConPTY applies it asynchronously.
|
|
611
|
+
sent = SUCCEEDED(pfnReparentPseudoConsole(handle->hpc, newParent));
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
return Napi::Boolean::New(env, sent);
|
|
617
|
+
}
|
|
618
|
+
|
|
556
619
|
static Napi::Value PtyKill(const Napi::CallbackInfo& info) {
|
|
557
620
|
Napi::Env env(info.Env());
|
|
558
621
|
Napi::HandleScope scope(env);
|
|
@@ -577,9 +640,11 @@ static Napi::Value PtyKill(const Napi::CallbackInfo& info) {
|
|
|
577
640
|
PFNCLOSEPSEUDOCONSOLE const pfnClosePseudoConsole = (PFNCLOSEPSEUDOCONSOLE)GetProcAddress(
|
|
578
641
|
(HMODULE)hLibrary,
|
|
579
642
|
useConptyDll ? "ConptyClosePseudoConsole" : "ClosePseudoConsole");
|
|
580
|
-
if (pfnClosePseudoConsole)
|
|
643
|
+
if (pfnClosePseudoConsole && handle->hpc != nullptr)
|
|
581
644
|
{
|
|
582
645
|
pfnClosePseudoConsole(handle->hpc);
|
|
646
|
+
// Closing frees the pseudoconsole, but the baton lives until the exit thread erases it.
|
|
647
|
+
handle->hpc = nullptr;
|
|
583
648
|
}
|
|
584
649
|
}
|
|
585
650
|
// Defensive: if PtyConnect was never called (or failed before closing the
|
|
@@ -609,6 +674,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
|
|
|
609
674
|
exports.Set("connect", Napi::Function::New(env, PtyConnect));
|
|
610
675
|
exports.Set("resize", Napi::Function::New(env, PtyResize));
|
|
611
676
|
exports.Set("clear", Napi::Function::New(env, PtyClear));
|
|
677
|
+
exports.Set("reparent", Napi::Function::New(env, PtyReparent));
|
|
612
678
|
exports.Set("kill", Napi::Function::New(env, PtyKill));
|
|
613
679
|
return exports;
|
|
614
680
|
};
|
package/typings/node-pty.d.ts
CHANGED
|
@@ -173,6 +173,23 @@ declare module 'node-pty' {
|
|
|
173
173
|
*/
|
|
174
174
|
clear(): void;
|
|
175
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Sets the handle (HWND) of the top-level window that hosts this terminal. ConPTY makes it the
|
|
178
|
+
* owner of the console window returned by `GetConsoleWindow()`, so windows that console
|
|
179
|
+
* applications parent to it (for example `GetAncestor(GetConsoleWindow(), GA_ROOTOWNER)`, which
|
|
180
|
+
* MSAL/WAM sign-in uses) open on top of the host window instead of behind it. Calling it right
|
|
181
|
+
* after spawning sends the request before the process is launched. Call it again whenever the
|
|
182
|
+
* terminal moves to a different window. Optional so existing implementations of `IPty` keep
|
|
183
|
+
* compiling.
|
|
184
|
+
* @param handle The window handle (HWND) as its bytes in native byte order, the way Electron's
|
|
185
|
+
* `BrowserWindow.getNativeWindowHandle()` returns it. Throws unless it's a Buffer the size of
|
|
186
|
+
* an HWND (8 bytes in a 64-bit process).
|
|
187
|
+
* @returns Whether the request was sent to ConPTY, which applies it asynchronously. This is
|
|
188
|
+
* always false unless on Windows with `useConptyDll`, and false once the pseudoconsole is
|
|
189
|
+
* closed.
|
|
190
|
+
*/
|
|
191
|
+
setParentWindow?(handle: Buffer): boolean;
|
|
192
|
+
|
|
176
193
|
/**
|
|
177
194
|
* Writes data to the pty.
|
|
178
195
|
* @param data The data to write.
|