node-pty 1.1.0-beta41 → 1.1.0-beta42
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 +111 -1
- package/lib/unixTerminal.js.map +1 -1
- package/package.json +1 -1
- package/src/unix/pty.cc +8 -8
- package/src/unixTerminal.ts +71 -1
package/lib/unixTerminal.js
CHANGED
|
@@ -12,8 +12,50 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
12
12
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
13
13
|
};
|
|
14
14
|
})();
|
|
15
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
16
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
17
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
18
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
19
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
20
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
21
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
25
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
26
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
27
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
28
|
+
function step(op) {
|
|
29
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
30
|
+
while (_) try {
|
|
31
|
+
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;
|
|
32
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
33
|
+
switch (op[0]) {
|
|
34
|
+
case 0: case 1: t = op; break;
|
|
35
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
36
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
37
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
38
|
+
default:
|
|
39
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
40
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
41
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
42
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
43
|
+
if (t[2]) _.ops.pop();
|
|
44
|
+
_.trys.pop(); continue;
|
|
45
|
+
}
|
|
46
|
+
op = body.call(thisArg, _);
|
|
47
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
48
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
49
|
+
}
|
|
50
|
+
};
|
|
15
51
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
52
|
exports.UnixTerminal = void 0;
|
|
53
|
+
/**
|
|
54
|
+
* Copyright (c) 2012-2015, Christopher Jeffrey (MIT License)
|
|
55
|
+
* Copyright (c) 2016, Daniel Imms (MIT License).
|
|
56
|
+
* Copyright (c) 2018, Microsoft Corporation (MIT License).
|
|
57
|
+
*/
|
|
58
|
+
var fs = require("fs");
|
|
17
59
|
var path = require("path");
|
|
18
60
|
var tty = require("tty");
|
|
19
61
|
var terminal_1 = require("./terminal");
|
|
@@ -34,6 +76,8 @@ var UnixTerminal = /** @class */ (function (_super) {
|
|
|
34
76
|
var _this = _super.call(this, opt) || this;
|
|
35
77
|
_this._boundClose = false;
|
|
36
78
|
_this._emittedClose = false;
|
|
79
|
+
_this._writeQueue = [];
|
|
80
|
+
_this._writeInProgress = false;
|
|
37
81
|
if (typeof args === 'string') {
|
|
38
82
|
throw new Error('args as a string is not supported on unix.');
|
|
39
83
|
}
|
|
@@ -146,7 +190,72 @@ var UnixTerminal = /** @class */ (function (_super) {
|
|
|
146
190
|
configurable: true
|
|
147
191
|
});
|
|
148
192
|
UnixTerminal.prototype._write = function (data) {
|
|
149
|
-
|
|
193
|
+
// Writes are put in a queue and processed asynchronously in order to handle
|
|
194
|
+
// backpressure from the kernel buffer.
|
|
195
|
+
this._writeQueue.push(data);
|
|
196
|
+
if (this._writeInProgress) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
this._writeInProgress = true;
|
|
200
|
+
this._processWriteQueue();
|
|
201
|
+
};
|
|
202
|
+
UnixTerminal.prototype._processWriteQueue = function () {
|
|
203
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
204
|
+
var data;
|
|
205
|
+
var _this = this;
|
|
206
|
+
return __generator(this, function (_a) {
|
|
207
|
+
data = this._writeQueue.shift();
|
|
208
|
+
if (!data) {
|
|
209
|
+
this._writeInProgress = false;
|
|
210
|
+
return [2 /*return*/];
|
|
211
|
+
}
|
|
212
|
+
// Write to the underlying file descriptor and handle it directly, rather
|
|
213
|
+
// than using the `net.Socket`/`tty.WriteStream` wrappers which swallow the
|
|
214
|
+
// errors and cause the thread to block indefinitely.
|
|
215
|
+
fs.write(this._fd, data, function (err, written) {
|
|
216
|
+
// Requeue any partial writes
|
|
217
|
+
if (written < data.length) {
|
|
218
|
+
_this._writeQueue.unshift(data.slice(written));
|
|
219
|
+
}
|
|
220
|
+
if (err) {
|
|
221
|
+
var errno = err.errno;
|
|
222
|
+
switch (errno) {
|
|
223
|
+
case -35: // EAGAIN (macOS)
|
|
224
|
+
case -11: // EAGAIN (Linux)
|
|
225
|
+
// This error appears to get swallowed and translated into
|
|
226
|
+
// `ERR_SYSTEM_ERROR` when using tty.WriteStream and not fs.write
|
|
227
|
+
// directly.
|
|
228
|
+
// This can happen during a regular partial write, but the most
|
|
229
|
+
// reliable way to test this is to run `sleep 10` in the shell and
|
|
230
|
+
// paste enough data to fill the kernel-level buffer. Once the sleep
|
|
231
|
+
// ends, the pty should accept the data again. Re-process after a
|
|
232
|
+
// short break.
|
|
233
|
+
_this._writeTimeout = setTimeout(function () { return _this._processWriteQueue(); }, 5);
|
|
234
|
+
return;
|
|
235
|
+
case -5: // EIO
|
|
236
|
+
case -32: // EPIPE
|
|
237
|
+
// Stop processing writes immediately as the pty is closed.
|
|
238
|
+
_this._writeInProgress = false;
|
|
239
|
+
return;
|
|
240
|
+
default:
|
|
241
|
+
console.error('Unhandled pty write error', errno, err);
|
|
242
|
+
// Fall through as it's important to finish processing the queue
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Using `setImmediate` here appears to corrupt the data, this may be what
|
|
247
|
+
// the interleaving/dropped data comment is about in Node.js' tty module:
|
|
248
|
+
// https://github.com/nodejs/node/blob/4cac2b94bed4bf02810be054e8f63c0048c66564/lib/tty.js#L106C1-L111C34
|
|
249
|
+
//
|
|
250
|
+
// Yielding via `setImmediate` also doesn't seem to drain the buffer much
|
|
251
|
+
// anyway, so use a short timeout when this happens instead. Note that the `drain`
|
|
252
|
+
// event does not appear to happen on `net.Socket`/`tty.WriteStream` when
|
|
253
|
+
// writing to ptys.
|
|
254
|
+
_this._writeTimeout = setTimeout(function () { return _this._processWriteQueue(); }, 5);
|
|
255
|
+
});
|
|
256
|
+
return [2 /*return*/];
|
|
257
|
+
});
|
|
258
|
+
});
|
|
150
259
|
};
|
|
151
260
|
Object.defineProperty(UnixTerminal.prototype, "fd", {
|
|
152
261
|
/* Accessors */
|
|
@@ -214,6 +323,7 @@ var UnixTerminal = /** @class */ (function (_super) {
|
|
|
214
323
|
_this.kill('SIGHUP');
|
|
215
324
|
});
|
|
216
325
|
this._socket.destroy();
|
|
326
|
+
clearTimeout(this._writeTimeout);
|
|
217
327
|
};
|
|
218
328
|
UnixTerminal.prototype.kill = function (signal) {
|
|
219
329
|
try {
|
package/lib/unixTerminal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unixTerminal.js","sourceRoot":"","sources":["../src/unixTerminal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"unixTerminal.js","sourceRoot":"","sources":["../src/unixTerminal.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/unix/pty.cc
CHANGED
|
@@ -448,10 +448,10 @@ Napi::Value PtyFork(const Napi::CallbackInfo& info) {
|
|
|
448
448
|
}
|
|
449
449
|
#endif
|
|
450
450
|
|
|
451
|
-
Napi::Object obj = Napi::Object::New(napiEnv);
|
|
452
|
-
obj.Set("fd", Napi::Number::New(napiEnv, master));
|
|
453
|
-
obj.Set("pid", Napi::Number::New(napiEnv, pid));
|
|
454
|
-
obj.Set("pty", Napi::String::New(napiEnv, ptsname(master)));
|
|
451
|
+
Napi::Object obj = Napi::Object::New(napiEnv);
|
|
452
|
+
obj.Set("fd", Napi::Number::New(napiEnv, master));
|
|
453
|
+
obj.Set("pid", Napi::Number::New(napiEnv, pid));
|
|
454
|
+
obj.Set("pty", Napi::String::New(napiEnv, ptsname(master)));
|
|
455
455
|
|
|
456
456
|
// Set up process exit callback.
|
|
457
457
|
Napi::Function cb = info[10].As<Napi::Function>();
|
|
@@ -492,10 +492,10 @@ Napi::Value PtyOpen(const Napi::CallbackInfo& info) {
|
|
|
492
492
|
throw Napi::Error::New(env, "Could not set slave fd to nonblocking.");
|
|
493
493
|
}
|
|
494
494
|
|
|
495
|
-
Napi::Object obj = Napi::Object::New(env);
|
|
496
|
-
obj.Set("master", Napi::Number::New(env, master));
|
|
497
|
-
obj.Set("slave", Napi::Number::New(env, slave));
|
|
498
|
-
obj.Set("pty", Napi::String::New(env, ptsname(master)));
|
|
495
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
496
|
+
obj.Set("master", Napi::Number::New(env, master));
|
|
497
|
+
obj.Set("slave", Napi::Number::New(env, slave));
|
|
498
|
+
obj.Set("pty", Napi::String::New(env, ptsname(master)));
|
|
499
499
|
|
|
500
500
|
return obj;
|
|
501
501
|
}
|
package/src/unixTerminal.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Copyright (c) 2016, Daniel Imms (MIT License).
|
|
4
4
|
* Copyright (c) 2018, Microsoft Corporation (MIT License).
|
|
5
5
|
*/
|
|
6
|
+
import * as fs from 'fs';
|
|
6
7
|
import * as net from 'net';
|
|
7
8
|
import * as path from 'path';
|
|
8
9
|
import * as tty from 'tty';
|
|
@@ -34,6 +35,11 @@ export class UnixTerminal extends Terminal {
|
|
|
34
35
|
|
|
35
36
|
private _boundClose: boolean = false;
|
|
36
37
|
private _emittedClose: boolean = false;
|
|
38
|
+
|
|
39
|
+
private readonly _writeQueue: (string | Buffer)[] = [];
|
|
40
|
+
private _writeInProgress: boolean = false;
|
|
41
|
+
private _writeTimeout: NodeJS.Timeout | undefined;
|
|
42
|
+
|
|
37
43
|
private _master: net.Socket | undefined;
|
|
38
44
|
private _slave: net.Socket | undefined;
|
|
39
45
|
|
|
@@ -162,7 +168,69 @@ export class UnixTerminal extends Terminal {
|
|
|
162
168
|
}
|
|
163
169
|
|
|
164
170
|
protected _write(data: string | Buffer): void {
|
|
165
|
-
|
|
171
|
+
// Writes are put in a queue and processed asynchronously in order to handle
|
|
172
|
+
// backpressure from the kernel buffer.
|
|
173
|
+
this._writeQueue.push(data);
|
|
174
|
+
if (this._writeInProgress) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
this._writeInProgress = true;
|
|
178
|
+
this._processWriteQueue();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private async _processWriteQueue(): Promise<void> {
|
|
182
|
+
const data = this._writeQueue.shift();
|
|
183
|
+
if (!data) {
|
|
184
|
+
this._writeInProgress = false;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Write to the underlying file descriptor and handle it directly, rather
|
|
189
|
+
// than using the `net.Socket`/`tty.WriteStream` wrappers which swallow the
|
|
190
|
+
// errors and cause the thread to block indefinitely.
|
|
191
|
+
fs.write(this._fd, data, (err, written) => {
|
|
192
|
+
// Requeue any partial writes
|
|
193
|
+
if (written < data.length) {
|
|
194
|
+
this._writeQueue.unshift(data.slice(written));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (err) {
|
|
198
|
+
const errno = (err as any).errno;
|
|
199
|
+
switch (errno) {
|
|
200
|
+
case -35: // EAGAIN (macOS)
|
|
201
|
+
case -11: // EAGAIN (Linux)
|
|
202
|
+
// This error appears to get swallowed and translated into
|
|
203
|
+
// `ERR_SYSTEM_ERROR` when using tty.WriteStream and not fs.write
|
|
204
|
+
// directly.
|
|
205
|
+
// This can happen during a regular partial write, but the most
|
|
206
|
+
// reliable way to test this is to run `sleep 10` in the shell and
|
|
207
|
+
// paste enough data to fill the kernel-level buffer. Once the sleep
|
|
208
|
+
// ends, the pty should accept the data again. Re-process after a
|
|
209
|
+
// short break.
|
|
210
|
+
this._writeTimeout = setTimeout(() => this._processWriteQueue(), 5);
|
|
211
|
+
return;
|
|
212
|
+
case -5: // EIO
|
|
213
|
+
case -32: // EPIPE
|
|
214
|
+
// Stop processing writes immediately as the pty is closed.
|
|
215
|
+
this._writeInProgress = false;
|
|
216
|
+
return;
|
|
217
|
+
default:
|
|
218
|
+
console.error('Unhandled pty write error', errno, err);
|
|
219
|
+
// Fall through as it's important to finish processing the queue
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Using `setImmediate` here appears to corrupt the data, this may be what
|
|
225
|
+
// the interleaving/dropped data comment is about in Node.js' tty module:
|
|
226
|
+
// https://github.com/nodejs/node/blob/4cac2b94bed4bf02810be054e8f63c0048c66564/lib/tty.js#L106C1-L111C34
|
|
227
|
+
//
|
|
228
|
+
// Yielding via `setImmediate` also doesn't seem to drain the buffer much
|
|
229
|
+
// anyway, so use a short timeout when this happens instead. Note that the `drain`
|
|
230
|
+
// event does not appear to happen on `net.Socket`/`tty.WriteStream` when
|
|
231
|
+
// writing to ptys.
|
|
232
|
+
this._writeTimeout = setTimeout(() => this._processWriteQueue(), 5);
|
|
233
|
+
});
|
|
166
234
|
}
|
|
167
235
|
|
|
168
236
|
/* Accessors */
|
|
@@ -238,6 +306,8 @@ export class UnixTerminal extends Terminal {
|
|
|
238
306
|
});
|
|
239
307
|
|
|
240
308
|
this._socket.destroy();
|
|
309
|
+
|
|
310
|
+
clearTimeout(this._writeTimeout);
|
|
241
311
|
}
|
|
242
312
|
|
|
243
313
|
public kill(signal?: string): void {
|