node-pty 1.1.0-beta9 → 1.2.0-beta.1
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/README.md +2 -0
- package/binding.gyp +7 -4
- package/deps/winpty/src/agent/Agent.cc +11 -3
- package/deps/winpty/src/winpty.gyp +29 -1
- package/lib/conpty_console_list_agent.js +3 -7
- package/lib/conpty_console_list_agent.js.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/terminal.js.map +1 -1
- package/lib/terminal.test.js.map +1 -1
- package/lib/unixTerminal.js +78 -37
- package/lib/unixTerminal.js.map +1 -1
- package/lib/unixTerminal.test.js +3 -5
- package/lib/unixTerminal.test.js.map +1 -1
- package/lib/utils.js +23 -1
- package/lib/utils.js.map +1 -1
- package/lib/windowsConoutConnection.js +6 -3
- package/lib/windowsConoutConnection.js.map +1 -1
- package/lib/windowsPtyAgent.js +45 -48
- package/lib/windowsPtyAgent.js.map +1 -1
- package/lib/windowsTerminal.js +19 -21
- package/lib/windowsTerminal.js.map +1 -1
- package/lib/windowsTerminal.test.js +40 -26
- package/lib/windowsTerminal.test.js.map +1 -1
- package/lib/worker/conoutSocketWorker.js.map +1 -1
- package/package.json +6 -2
- 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/win32-arm64/conpty/OpenConsole.exe +0 -0
- package/prebuilds/win32-arm64/conpty/conpty.dll +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-arm64/pty.node +0 -0
- package/prebuilds/win32-arm64/pty.pdb +0 -0
- package/prebuilds/win32-arm64/winpty-agent.exe +0 -0
- package/prebuilds/win32-arm64/winpty-agent.pdb +0 -0
- package/prebuilds/win32-arm64/winpty.dll +0 -0
- package/prebuilds/win32-arm64/winpty.pdb +0 -0
- package/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
- package/prebuilds/win32-x64/conpty/conpty.dll +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/prebuilds/win32-x64/pty.node +0 -0
- package/prebuilds/win32-x64/pty.pdb +0 -0
- package/prebuilds/win32-x64/winpty-agent.exe +0 -0
- package/prebuilds/win32-x64/winpty-agent.pdb +0 -0
- package/prebuilds/win32-x64/winpty.dll +0 -0
- package/prebuilds/win32-x64/winpty.pdb +0 -0
- package/scripts/gen-compile-commands.js +8 -0
- package/scripts/{publish.js → increment-version.js} +10 -18
- package/scripts/post-install.js +48 -10
- package/scripts/prebuild.js +34 -0
- package/src/conpty_console_list_agent.ts +2 -6
- package/src/index.ts +2 -1
- package/src/interfaces.ts +2 -1
- package/src/native.d.ts +5 -5
- package/src/terminal.test.ts +1 -1
- package/src/terminal.ts +2 -2
- package/src/unix/pty.cc +28 -11
- package/src/unixTerminal.test.ts +3 -6
- package/src/unixTerminal.ts +101 -34
- package/src/utils.ts +20 -0
- package/src/win/conpty.cc +141 -55
- package/src/win/conpty.h +41 -0
- package/src/win/path_util.cc +23 -24
- package/src/windowsConoutConnection.ts +6 -3
- package/src/windowsPtyAgent.ts +42 -43
- package/src/windowsTerminal.test.ts +46 -33
- package/src/windowsTerminal.ts +24 -29
- package/src/worker/conoutSocketWorker.ts +2 -2
- package/third_party/conpty/1.23.251008001/win10-arm64/OpenConsole.exe +0 -0
- package/third_party/conpty/1.23.251008001/win10-arm64/conpty.dll +0 -0
- package/third_party/conpty/1.23.251008001/win10-x64/OpenConsole.exe +0 -0
- package/third_party/conpty/1.23.251008001/win10-x64/conpty.dll +0 -0
- package/typings/node-pty.d.ts +9 -1
package/src/windowsPtyAgent.ts
CHANGED
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
import * as os from 'os';
|
|
9
9
|
import * as path from 'path';
|
|
10
|
+
import { fork } from 'child_process';
|
|
10
11
|
import { Socket } from 'net';
|
|
11
12
|
import { ArgvOrCommandLine } from './types';
|
|
12
|
-
import { fork } from 'child_process';
|
|
13
13
|
import { ConoutConnection } from './windowsConoutConnection';
|
|
14
|
+
import { loadNativeModule } from './utils';
|
|
14
15
|
|
|
15
16
|
let conptyNative: IConptyNative;
|
|
16
17
|
let winptyNative: IWinptyNative;
|
|
@@ -54,6 +55,7 @@ export class WindowsPtyAgent {
|
|
|
54
55
|
rows: number,
|
|
55
56
|
debug: boolean,
|
|
56
57
|
private _useConpty: boolean | undefined,
|
|
58
|
+
private _useConptyDll: boolean = false,
|
|
57
59
|
conptyInheritCursor: boolean = false
|
|
58
60
|
) {
|
|
59
61
|
if (this._useConpty === undefined || this._useConpty === true) {
|
|
@@ -61,31 +63,11 @@ export class WindowsPtyAgent {
|
|
|
61
63
|
}
|
|
62
64
|
if (this._useConpty) {
|
|
63
65
|
if (!conptyNative) {
|
|
64
|
-
|
|
65
|
-
conptyNative = require('../build/Release/conpty.node');
|
|
66
|
-
} catch (outerError) {
|
|
67
|
-
try {
|
|
68
|
-
conptyNative = require('../build/Debug/conpty.node');
|
|
69
|
-
} catch (innerError) {
|
|
70
|
-
console.error('innerError', innerError);
|
|
71
|
-
// Re-throw the exception from the Release require if the Debug require fails as well
|
|
72
|
-
throw outerError;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
66
|
+
conptyNative = loadNativeModule('conpty').module;
|
|
75
67
|
}
|
|
76
68
|
} else {
|
|
77
69
|
if (!winptyNative) {
|
|
78
|
-
|
|
79
|
-
winptyNative = require('../build/Release/pty.node');
|
|
80
|
-
} catch (outerError) {
|
|
81
|
-
try {
|
|
82
|
-
winptyNative = require('../build/Debug/pty.node');
|
|
83
|
-
} catch (innerError) {
|
|
84
|
-
console.error('innerError', innerError);
|
|
85
|
-
// Re-throw the exception from the Release require if the Debug require fails as well
|
|
86
|
-
throw outerError;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
70
|
+
winptyNative = loadNativeModule('pty').module;
|
|
89
71
|
}
|
|
90
72
|
}
|
|
91
73
|
this._ptyNative = this._useConpty ? conptyNative : winptyNative;
|
|
@@ -99,7 +81,7 @@ export class WindowsPtyAgent {
|
|
|
99
81
|
// Open pty session.
|
|
100
82
|
let term: IConptyProcess | IWinptyProcess;
|
|
101
83
|
if (this._useConpty) {
|
|
102
|
-
term = (this._ptyNative as IConptyNative).startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor);
|
|
84
|
+
term = (this._ptyNative as IConptyNative).startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor, this._useConptyDll);
|
|
103
85
|
} else {
|
|
104
86
|
term = (this._ptyNative as IWinptyNative).startProcess(file, commandLine, env, cwd, cols, rows, debug);
|
|
105
87
|
this._pid = (term as IWinptyProcess).pid;
|
|
@@ -117,7 +99,7 @@ export class WindowsPtyAgent {
|
|
|
117
99
|
this._outSocket = new Socket();
|
|
118
100
|
this._outSocket.setEncoding('utf8');
|
|
119
101
|
// The conout socket must be ready out on another thread to avoid deadlocks
|
|
120
|
-
this._conoutSocketWorker = new ConoutConnection(term.conout);
|
|
102
|
+
this._conoutSocketWorker = new ConoutConnection(term.conout, this._useConptyDll);
|
|
121
103
|
this._conoutSocketWorker.onReady(() => {
|
|
122
104
|
this._conoutSocketWorker.connectSocket(this._outSocket);
|
|
123
105
|
});
|
|
@@ -134,7 +116,7 @@ export class WindowsPtyAgent {
|
|
|
134
116
|
this._inSocket.setEncoding('utf8');
|
|
135
117
|
|
|
136
118
|
if (this._useConpty) {
|
|
137
|
-
const connect = (this._ptyNative as IConptyNative).connect(this._pty, commandLine, cwd, env, c => this._$onProcessExit(c));
|
|
119
|
+
const connect = (this._ptyNative as IConptyNative).connect(this._pty, commandLine, cwd, env, this._useConptyDll, c => this._$onProcessExit(c));
|
|
138
120
|
this._innerPid = connect.pid;
|
|
139
121
|
}
|
|
140
122
|
}
|
|
@@ -144,33 +126,43 @@ export class WindowsPtyAgent {
|
|
|
144
126
|
if (this._exitCode !== undefined) {
|
|
145
127
|
throw new Error('Cannot resize a pty that has already exited');
|
|
146
128
|
}
|
|
147
|
-
this._ptyNative.resize(this._pty, cols, rows);
|
|
129
|
+
(this._ptyNative as IConptyNative).resize(this._pty, cols, rows, this._useConptyDll);
|
|
148
130
|
return;
|
|
149
131
|
}
|
|
150
|
-
this._ptyNative.resize(this._pid, cols, rows);
|
|
132
|
+
(this._ptyNative as IWinptyNative).resize(this._pid, cols, rows);
|
|
151
133
|
}
|
|
152
134
|
|
|
153
135
|
public clear(): void {
|
|
154
136
|
if (this._useConpty) {
|
|
155
|
-
(this._ptyNative as IConptyNative).clear(this._pty);
|
|
137
|
+
(this._ptyNative as IConptyNative).clear(this._pty, this._useConptyDll);
|
|
156
138
|
}
|
|
157
139
|
}
|
|
158
140
|
|
|
159
141
|
public kill(): void {
|
|
160
|
-
this._inSocket.readable = false;
|
|
161
|
-
this._outSocket.readable = false;
|
|
162
142
|
// Tell the agent to kill the pty, this releases handles to the process
|
|
163
143
|
if (this._useConpty) {
|
|
164
|
-
this.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
144
|
+
if (!this._useConptyDll) {
|
|
145
|
+
this._inSocket.readable = false;
|
|
146
|
+
this._outSocket.readable = false;
|
|
147
|
+
this._getConsoleProcessList().then(consoleProcessList => {
|
|
148
|
+
consoleProcessList.forEach((pid: number) => {
|
|
149
|
+
try {
|
|
150
|
+
process.kill(pid);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
// Ignore if process cannot be found (kill ESRCH error)
|
|
153
|
+
}
|
|
154
|
+
});
|
|
171
155
|
});
|
|
172
|
-
(this._ptyNative as IConptyNative).kill(this._pty);
|
|
173
|
-
|
|
156
|
+
(this._ptyNative as IConptyNative).kill(this._pty, this._useConptyDll);
|
|
157
|
+
this._conoutSocketWorker.dispose();
|
|
158
|
+
} else {
|
|
159
|
+
// Close the input write handle to signal the end of session.
|
|
160
|
+
this._inSocket.destroy();
|
|
161
|
+
(this._ptyNative as IConptyNative).kill(this._pty, this._useConptyDll);
|
|
162
|
+
this._outSocket.on('data', () => {
|
|
163
|
+
this._conoutSocketWorker.dispose();
|
|
164
|
+
});
|
|
165
|
+
}
|
|
174
166
|
} else {
|
|
175
167
|
// Because pty.kill closes the handle, it will kill most processes by itself.
|
|
176
168
|
// Process IDs can be reused as soon as all handles to them are
|
|
@@ -188,7 +180,6 @@ export class WindowsPtyAgent {
|
|
|
188
180
|
}
|
|
189
181
|
});
|
|
190
182
|
}
|
|
191
|
-
this._conoutSocketWorker.dispose();
|
|
192
183
|
}
|
|
193
184
|
|
|
194
185
|
private _getConsoleProcessList(): Promise<number[]> {
|
|
@@ -232,11 +223,16 @@ export class WindowsPtyAgent {
|
|
|
232
223
|
*/
|
|
233
224
|
private _$onProcessExit(exitCode: number): void {
|
|
234
225
|
this._exitCode = exitCode;
|
|
235
|
-
this.
|
|
236
|
-
|
|
226
|
+
if (!this._useConptyDll) {
|
|
227
|
+
this._flushDataAndCleanUp();
|
|
228
|
+
this._outSocket.on('data', () => this._flushDataAndCleanUp());
|
|
229
|
+
}
|
|
237
230
|
}
|
|
238
231
|
|
|
239
232
|
private _flushDataAndCleanUp(): void {
|
|
233
|
+
if (this._useConptyDll) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
240
236
|
if (this._closeTimeout) {
|
|
241
237
|
clearTimeout(this._closeTimeout);
|
|
242
238
|
}
|
|
@@ -244,6 +240,9 @@ export class WindowsPtyAgent {
|
|
|
244
240
|
}
|
|
245
241
|
|
|
246
242
|
private _cleanUpProcess(): void {
|
|
243
|
+
if (this._useConptyDll) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
247
246
|
this._inSocket.readable = false;
|
|
248
247
|
this._outSocket.readable = false;
|
|
249
248
|
this._outSocket.destroy();
|
|
@@ -26,13 +26,16 @@ function pollForProcessState(desiredState: IProcessState, intervalMs: number = 1
|
|
|
26
26
|
psList({ all: true }).then(ps => {
|
|
27
27
|
let success = true;
|
|
28
28
|
const pids = Object.keys(desiredState).map(k => parseInt(k, 10));
|
|
29
|
+
console.log('expected pids', JSON.stringify(pids));
|
|
29
30
|
pids.forEach(pid => {
|
|
30
31
|
if (desiredState[pid]) {
|
|
31
32
|
if (!ps.some(p => p.pid === pid)) {
|
|
33
|
+
console.log(`pid ${pid} does not exist`);
|
|
32
34
|
success = false;
|
|
33
35
|
}
|
|
34
36
|
} else {
|
|
35
37
|
if (ps.some(p => p.pid === pid)) {
|
|
38
|
+
console.log(`pid ${pid} still exists`);
|
|
36
39
|
success = false;
|
|
37
40
|
}
|
|
38
41
|
}
|
|
@@ -71,6 +74,7 @@ function pollForProcessTreeSize(pid: number, size: number, intervalMs: number =
|
|
|
71
74
|
}).forEach(p => openList.push(p));
|
|
72
75
|
list.push(current);
|
|
73
76
|
}
|
|
77
|
+
console.log('list', JSON.stringify(list));
|
|
74
78
|
const success = list.length === size;
|
|
75
79
|
if (success) {
|
|
76
80
|
clearInterval(interval);
|
|
@@ -88,53 +92,57 @@ function pollForProcessTreeSize(pid: number, size: number, intervalMs: number =
|
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
if (process.platform === 'win32') {
|
|
91
|
-
[true, false].forEach((useConpty) => {
|
|
92
|
-
describe(`WindowsTerminal (useConpty = ${useConpty})`, () => {
|
|
95
|
+
[[false, false], [true, false], [true, true]].forEach(([useConpty, useConptyDll]) => {
|
|
96
|
+
describe(`WindowsTerminal (useConpty = ${useConpty}, useConptyDll = ${useConptyDll})`, () => {
|
|
93
97
|
describe('kill', () => {
|
|
94
|
-
it('should not crash parent process', (done)
|
|
95
|
-
|
|
98
|
+
it('should not crash parent process', function (done) {
|
|
99
|
+
this.timeout(20000);
|
|
100
|
+
const term = new WindowsTerminal('cmd.exe', [], { useConpty, useConptyDll });
|
|
101
|
+
term.on('exit', () => done());
|
|
96
102
|
term.kill();
|
|
97
|
-
// Add done call to deferred function queue to ensure the kill call has completed
|
|
98
|
-
(<any>term)._defer(done);
|
|
99
103
|
});
|
|
100
104
|
it('should kill the process tree', function (done: Mocha.Done): void {
|
|
101
|
-
this.timeout(
|
|
102
|
-
const term = new WindowsTerminal('cmd.exe', [], { useConpty });
|
|
105
|
+
this.timeout(20000);
|
|
106
|
+
const term = new WindowsTerminal('cmd.exe', [], { useConpty, useConptyDll });
|
|
103
107
|
// Start sub-processes
|
|
104
108
|
term.write('powershell.exe\r');
|
|
105
|
-
term.write('notepad.exe\r');
|
|
106
109
|
term.write('node.exe\r');
|
|
107
|
-
|
|
110
|
+
console.log('start poll for tree size');
|
|
111
|
+
pollForProcessTreeSize(term.pid, 3, 500, 5000).then(list => {
|
|
108
112
|
assert.strictEqual(list[0].name.toLowerCase(), 'cmd.exe');
|
|
109
113
|
assert.strictEqual(list[1].name.toLowerCase(), 'powershell.exe');
|
|
110
|
-
assert.strictEqual(list[2].name.toLowerCase(), '
|
|
111
|
-
assert.strictEqual(list[3].name.toLowerCase(), 'node.exe');
|
|
114
|
+
assert.strictEqual(list[2].name.toLowerCase(), 'node.exe');
|
|
112
115
|
term.kill();
|
|
113
116
|
const desiredState: IProcessState = {};
|
|
114
117
|
desiredState[list[0].pid] = false;
|
|
115
118
|
desiredState[list[1].pid] = false;
|
|
116
|
-
desiredState[list[2].pid] =
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
done();
|
|
119
|
+
desiredState[list[2].pid] = false;
|
|
120
|
+
term.on('exit', () => {
|
|
121
|
+
pollForProcessState(desiredState, 1000, 5000).then(() => {
|
|
122
|
+
done();
|
|
123
|
+
});
|
|
122
124
|
});
|
|
123
125
|
});
|
|
124
126
|
});
|
|
125
127
|
});
|
|
126
128
|
|
|
127
129
|
describe('resize', () => {
|
|
128
|
-
it('should throw a non-native exception when resizing an invalid value', ()
|
|
129
|
-
|
|
130
|
+
it('should throw a non-native exception when resizing an invalid value', function(done) {
|
|
131
|
+
this.timeout(20000);
|
|
132
|
+
const term = new WindowsTerminal('cmd.exe', [], { useConpty, useConptyDll });
|
|
130
133
|
assert.throws(() => term.resize(-1, -1));
|
|
131
134
|
assert.throws(() => term.resize(0, 0));
|
|
132
135
|
assert.doesNotThrow(() => term.resize(1, 1));
|
|
136
|
+
term.on('exit', () => {
|
|
137
|
+
done();
|
|
138
|
+
});
|
|
139
|
+
term.kill();
|
|
133
140
|
});
|
|
134
|
-
it('should throw a non-native exception when resizing a killed terminal', (done)
|
|
135
|
-
|
|
141
|
+
it('should throw a non-native exception when resizing a killed terminal', function(done) {
|
|
142
|
+
this.timeout(20000);
|
|
143
|
+
const term = new WindowsTerminal('cmd.exe', [], { useConpty, useConptyDll });
|
|
136
144
|
(<any>term)._defer(() => {
|
|
137
|
-
term.
|
|
145
|
+
term.once('exit', () => {
|
|
138
146
|
assert.throws(() => term.resize(1, 1));
|
|
139
147
|
done();
|
|
140
148
|
});
|
|
@@ -144,7 +152,8 @@ if (process.platform === 'win32') {
|
|
|
144
152
|
});
|
|
145
153
|
|
|
146
154
|
describe('Args as CommandLine', () => {
|
|
147
|
-
it('should not fail running a file containing a space in the path', (done)
|
|
155
|
+
it('should not fail running a file containing a space in the path', function (done) {
|
|
156
|
+
this.timeout(10000);
|
|
148
157
|
const spaceFolder = path.resolve(__dirname, '..', 'fixtures', 'space folder');
|
|
149
158
|
if (!fs.existsSync(spaceFolder)) {
|
|
150
159
|
fs.mkdirSync(spaceFolder);
|
|
@@ -158,7 +167,7 @@ if (process.platform === 'win32') {
|
|
|
158
167
|
// Skip test if git bash isn't installed
|
|
159
168
|
return;
|
|
160
169
|
}
|
|
161
|
-
const term = new WindowsTerminal(cmdCopiedPath, '/c echo "hello world"', { useConpty });
|
|
170
|
+
const term = new WindowsTerminal(cmdCopiedPath, '/c echo "hello world"', { useConpty, useConptyDll });
|
|
162
171
|
let result = '';
|
|
163
172
|
term.on('data', (data) => {
|
|
164
173
|
result += data;
|
|
@@ -171,8 +180,9 @@ if (process.platform === 'win32') {
|
|
|
171
180
|
});
|
|
172
181
|
|
|
173
182
|
describe('env', () => {
|
|
174
|
-
it('should set environment variables of the shell', (done)
|
|
175
|
-
|
|
183
|
+
it('should set environment variables of the shell', function (done) {
|
|
184
|
+
this.timeout(10000);
|
|
185
|
+
const term = new WindowsTerminal('cmd.exe', '/C echo %FOO%', { useConpty, useConptyDll, env: { FOO: 'BAR' }});
|
|
176
186
|
let result = '';
|
|
177
187
|
term.on('data', (data) => {
|
|
178
188
|
result += data;
|
|
@@ -185,16 +195,18 @@ if (process.platform === 'win32') {
|
|
|
185
195
|
});
|
|
186
196
|
|
|
187
197
|
describe('On close', () => {
|
|
188
|
-
it('should return process zero exit codes', (done)
|
|
189
|
-
|
|
198
|
+
it('should return process zero exit codes', function (done) {
|
|
199
|
+
this.timeout(10000);
|
|
200
|
+
const term = new WindowsTerminal('cmd.exe', '/C exit', { useConpty, useConptyDll });
|
|
190
201
|
term.on('exit', (code) => {
|
|
191
202
|
assert.strictEqual(code, 0);
|
|
192
203
|
done();
|
|
193
204
|
});
|
|
194
205
|
});
|
|
195
206
|
|
|
196
|
-
it('should return process non-zero exit codes', (done)
|
|
197
|
-
|
|
207
|
+
it('should return process non-zero exit codes', function (done) {
|
|
208
|
+
this.timeout(10000);
|
|
209
|
+
const term = new WindowsTerminal('cmd.exe', '/C exit 2', { useConpty, useConptyDll });
|
|
198
210
|
term.on('exit', (code) => {
|
|
199
211
|
assert.strictEqual(code, 2);
|
|
200
212
|
done();
|
|
@@ -203,8 +215,9 @@ if (process.platform === 'win32') {
|
|
|
203
215
|
});
|
|
204
216
|
|
|
205
217
|
describe('Write', () => {
|
|
206
|
-
it('should accept input', (done)
|
|
207
|
-
|
|
218
|
+
it('should accept input', function (done) {
|
|
219
|
+
this.timeout(10000);
|
|
220
|
+
const term = new WindowsTerminal('cmd.exe', '', { useConpty, useConptyDll });
|
|
208
221
|
term.write('exit\r');
|
|
209
222
|
term.on('exit', () => {
|
|
210
223
|
done();
|
package/src/windowsTerminal.ts
CHANGED
|
@@ -16,7 +16,7 @@ const DEFAULT_NAME = 'Windows Shell';
|
|
|
16
16
|
|
|
17
17
|
export class WindowsTerminal extends Terminal {
|
|
18
18
|
private _isReady: boolean;
|
|
19
|
-
private _deferreds:
|
|
19
|
+
private _deferreds: { run: () => void }[];
|
|
20
20
|
private _agent: WindowsPtyAgent;
|
|
21
21
|
|
|
22
22
|
constructor(file?: string, args?: ArgvOrCommandLine, opt?: IWindowsPtyForkOptions) {
|
|
@@ -48,7 +48,7 @@ export class WindowsTerminal extends Terminal {
|
|
|
48
48
|
this._deferreds = [];
|
|
49
49
|
|
|
50
50
|
// Create new termal.
|
|
51
|
-
this._agent = new WindowsPtyAgent(file, args, parsedEnv, cwd, this._cols, this._rows, false, opt.useConpty, opt.conptyInheritCursor);
|
|
51
|
+
this._agent = new WindowsPtyAgent(file, args, parsedEnv, cwd, this._cols, this._rows, false, opt.useConpty, opt.useConptyDll, opt.conptyInheritCursor);
|
|
52
52
|
this._socket = this._agent.outSocket;
|
|
53
53
|
|
|
54
54
|
// Not available until `ready` event emitted.
|
|
@@ -60,31 +60,26 @@ export class WindowsTerminal extends Terminal {
|
|
|
60
60
|
// emitted.
|
|
61
61
|
this._socket.on('ready_datapipe', () => {
|
|
62
62
|
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
//
|
|
75
|
-
this
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// Reset
|
|
84
|
-
this._deferreds = [];
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
});
|
|
63
|
+
// Run deferreds and set ready state once the first data event is received.
|
|
64
|
+
this._socket.once('data', () => {
|
|
65
|
+
// Wait until the first data event is fired then we can run deferreds.
|
|
66
|
+
if (!this._isReady) {
|
|
67
|
+
// Terminal is now ready and we can avoid having to defer method
|
|
68
|
+
// calls.
|
|
69
|
+
this._isReady = true;
|
|
70
|
+
|
|
71
|
+
// Execute all deferred methods
|
|
72
|
+
this._deferreds.forEach(fn => {
|
|
73
|
+
// NB! In order to ensure that `this` has all its references
|
|
74
|
+
// updated any variable that need to be available in `this` before
|
|
75
|
+
// the deferred is run has to be declared above this forEach
|
|
76
|
+
// statement.
|
|
77
|
+
fn.run();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Reset
|
|
81
|
+
this._deferreds = [];
|
|
82
|
+
}
|
|
88
83
|
});
|
|
89
84
|
|
|
90
85
|
// Shutdown if `error` event is emitted.
|
|
@@ -123,11 +118,11 @@ export class WindowsTerminal extends Terminal {
|
|
|
123
118
|
this._forwardEvents();
|
|
124
119
|
}
|
|
125
120
|
|
|
126
|
-
protected _write(data: string): void {
|
|
121
|
+
protected _write(data: string | Buffer): void {
|
|
127
122
|
this._defer(this._doWrite, data);
|
|
128
123
|
}
|
|
129
124
|
|
|
130
|
-
private _doWrite(data: string): void {
|
|
125
|
+
private _doWrite(data: string | Buffer): void {
|
|
131
126
|
this._agent.inSocket.write(data);
|
|
132
127
|
}
|
|
133
128
|
|
|
@@ -6,7 +6,8 @@ import { parentPort, workerData } from 'worker_threads';
|
|
|
6
6
|
import { Socket, createServer } from 'net';
|
|
7
7
|
import { ConoutWorkerMessage, IWorkerData, getWorkerPipeName } from '../shared/conout';
|
|
8
8
|
|
|
9
|
-
const conoutPipeName = (workerData as IWorkerData)
|
|
9
|
+
const { conoutPipeName } = (workerData as IWorkerData);
|
|
10
|
+
|
|
10
11
|
const conoutSocket = new Socket();
|
|
11
12
|
conoutSocket.setEncoding('utf8');
|
|
12
13
|
conoutSocket.connect(conoutPipeName, () => {
|
|
@@ -14,7 +15,6 @@ conoutSocket.connect(conoutPipeName, () => {
|
|
|
14
15
|
conoutSocket.pipe(workerSocket);
|
|
15
16
|
});
|
|
16
17
|
server.listen(getWorkerPipeName(conoutPipeName));
|
|
17
|
-
|
|
18
18
|
if (!parentPort) {
|
|
19
19
|
throw new Error('worker_threads parentPort is null');
|
|
20
20
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/typings/node-pty.d.ts
CHANGED
|
@@ -95,6 +95,14 @@ declare module 'node-pty' {
|
|
|
95
95
|
*/
|
|
96
96
|
useConpty?: boolean;
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* (EXPERIMENTAL)
|
|
100
|
+
*
|
|
101
|
+
* Whether to use the conpty.dll shipped with the node-pty package instead of the one built into
|
|
102
|
+
* Windows. Defaults to false.
|
|
103
|
+
*/
|
|
104
|
+
useConptyDll?: boolean;
|
|
105
|
+
|
|
98
106
|
/**
|
|
99
107
|
* Whether to use PSEUDOCONSOLE_INHERIT_CURSOR in conpty.
|
|
100
108
|
* @see https://docs.microsoft.com/en-us/windows/console/createpseudoconsole
|
|
@@ -165,7 +173,7 @@ declare module 'node-pty' {
|
|
|
165
173
|
* Writes data to the pty.
|
|
166
174
|
* @param data The data to write.
|
|
167
175
|
*/
|
|
168
|
-
write(data: string): void;
|
|
176
|
+
write(data: string | Buffer): void;
|
|
169
177
|
|
|
170
178
|
/**
|
|
171
179
|
* Kills the pty.
|