node-pty 1.2.0-beta.11 → 1.2.0-beta.13

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.
Files changed (38) hide show
  1. package/lib/conpty_console_list_agent.js +1 -1
  2. package/lib/index.js +6 -6
  3. package/lib/shared/conout.js +2 -3
  4. package/lib/terminal.js +2 -2
  5. package/lib/unixTerminal.js +5 -3
  6. package/lib/utils.js +6 -7
  7. package/lib/windowsConoutConnection.js +6 -6
  8. package/lib/windowsPtyAgent.js +7 -7
  9. package/lib/windowsTerminal.js +4 -2
  10. package/lib/worker/conoutSocketWorker.js +3 -3
  11. package/package.json +6 -6
  12. package/prebuilds/darwin-arm64/pty.node +0 -0
  13. package/prebuilds/darwin-arm64/spawn-helper +0 -0
  14. package/prebuilds/darwin-x64/pty.node +0 -0
  15. package/prebuilds/darwin-x64/spawn-helper +0 -0
  16. package/prebuilds/linux-arm64/pty.node +0 -0
  17. package/prebuilds/linux-x64/pty.node +0 -0
  18. package/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  19. package/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  20. package/prebuilds/win32-arm64/conpty.node +0 -0
  21. package/prebuilds/win32-arm64/conpty.pdb +0 -0
  22. package/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  23. package/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
  24. package/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  25. package/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  26. package/prebuilds/win32-x64/conpty.node +0 -0
  27. package/prebuilds/win32-x64/conpty.pdb +0 -0
  28. package/prebuilds/win32-x64/conpty_console_list.node +0 -0
  29. package/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
  30. package/src/win/conpty.cc +35 -28
  31. package/third_party/conpty/1.25.260303002/win10-arm64/OpenConsole.exe +0 -0
  32. package/third_party/conpty/{1.23.251008001 → 1.25.260303002}/win10-arm64/conpty.dll +0 -0
  33. package/third_party/conpty/1.25.260303002/win10-x64/OpenConsole.exe +0 -0
  34. package/third_party/conpty/1.25.260303002/win10-x64/conpty.dll +0 -0
  35. package/typings/node-pty.d.ts +1 -1
  36. package/third_party/conpty/1.23.251008001/win10-arm64/OpenConsole.exe +0 -0
  37. package/third_party/conpty/1.23.251008001/win10-x64/OpenConsole.exe +0 -0
  38. package/third_party/conpty/1.23.251008001/win10-x64/conpty.dll +0 -0
@@ -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 = exports.open = exports.createTerminal = exports.fork = exports.spawn = void 0;
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
@@ -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 = void 0;
6
+ exports.getWorkerPipeName = getWorkerPipeName;
7
7
  function getWorkerPipeName(conoutPipeName) {
8
- return conoutPipeName + "-worker";
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 + "[" + i + "] must be a " + type + " (not a " + typeof v[i] + ")");
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 + " must be a " + type + " (not a " + typeof value + ")");
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 */
@@ -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 (b.hasOwnProperty(p)) d[p] = b[p]; };
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.loadNativeModule = exports.assign = void 0;
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/" + process.platform + "-" + process.arch];
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 + "/" + d;
27
+ var dir = "".concat(r, "/").concat(d);
28
28
  try {
29
- return { dir: dir, module: require(dir + "/" + name + ".node") };
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: " + name + ".node, checked: " + dirs.join(', ') + ": " + lastError);
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 = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), 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;
@@ -5,7 +5,8 @@
5
5
  * Copyright (c) 2018, Microsoft Corporation (MIT License).
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.argsToCommandLine = exports.WindowsPtyAgent = void 0;
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");
@@ -24,13 +25,13 @@ var FLUSH_DATA_INTERVAL = 1000;
24
25
  */
25
26
  var WindowsPtyAgent = /** @class */ (function () {
26
27
  function WindowsPtyAgent(file, args, env, cwd, cols, rows, debug, _useConptyDll, conptyInheritCursor) {
27
- var _this = this;
28
28
  if (_useConptyDll === void 0) { _useConptyDll = false; }
29
29
  if (conptyInheritCursor === void 0) { conptyInheritCursor = false; }
30
+ var _this = this;
30
31
  this._useConptyDll = _useConptyDll;
31
32
  this._innerPid = 0;
32
33
  if (!conptyNative) {
33
- conptyNative = utils_1.loadNativeModule('conpty').module;
34
+ conptyNative = (0, utils_1.loadNativeModule)('conpty').module;
34
35
  }
35
36
  this._ptyNative = conptyNative;
36
37
  // Sanitize input variable.
@@ -160,7 +161,7 @@ var WindowsPtyAgent = /** @class */ (function () {
160
161
  return Promise.resolve([]);
161
162
  }
162
163
  return new Promise(function (resolve) {
163
- var agent = child_process_1.fork(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()]);
164
+ var agent = (0, child_process_1.fork)(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()]);
164
165
  agent.on('message', function (message) {
165
166
  clearTimeout(timeout);
166
167
  resolve(message.consoleProcessList);
@@ -180,7 +181,7 @@ var WindowsPtyAgent = /** @class */ (function () {
180
181
  configurable: true
181
182
  });
182
183
  WindowsPtyAgent.prototype._generatePipeName = function () {
183
- return "conpty-" + Math.random() * 10000000;
184
+ return "conpty-".concat(Math.random() * 10000000);
184
185
  };
185
186
  /**
186
187
  * Triggered from the native side when a contpy process exits.
@@ -222,7 +223,7 @@ function argsToCommandLine(file, args) {
222
223
  if (args.length === 0) {
223
224
  return file;
224
225
  }
225
- return argsToCommandLine(file, []) + " " + args;
226
+ return "".concat(argsToCommandLine(file, []), " ").concat(args);
226
227
  }
227
228
  var argv = [file];
228
229
  Array.prototype.push.apply(argv, args);
@@ -270,7 +271,6 @@ function argsToCommandLine(file, args) {
270
271
  }
271
272
  return result;
272
273
  }
273
- exports.argsToCommandLine = argsToCommandLine;
274
274
  function isCommandLine(args) {
275
275
  return typeof args === 'string';
276
276
  }
@@ -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 (b.hasOwnProperty(p)) d[p] = b[p]; };
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();
@@ -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.11",
7
+ "version": "1.2.0-beta.13",
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 -c .eslintrc.js --ext .ts src/",
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,13 @@
53
53
  "devDependencies": {
54
54
  "@types/mocha": "^7.0.2",
55
55
  "@types/node": "12",
56
- "@typescript-eslint/eslint-plugin": "^2.27.0",
57
- "@typescript-eslint/parser": "^2.27.0",
56
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
57
+ "@typescript-eslint/parser": "^8.0.0",
58
58
  "cross-env": "^5.1.4",
59
- "eslint": "^6.8.0",
59
+ "eslint": "^9.0.0",
60
60
  "mocha": "10",
61
61
  "node-gyp": "^11.4.2",
62
62
  "ps-list": "^6.0.0",
63
- "typescript": "^3.8.3"
63
+ "typescript": "^5.0.0"
64
64
  }
65
65
  }
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
@@ -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>
@@ -50,9 +52,12 @@ struct pty_baton {
50
52
  };
51
53
 
52
54
  static std::vector<std::unique_ptr<pty_baton>> ptyHandles;
53
- static volatile LONG ptyCounter;
55
+ static std::mutex g_ptyHandlesMutex;
56
+ static std::atomic<int> ptyCounter{0};
54
57
 
55
- static pty_baton* get_pty_baton(int id) {
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
- // Get process exit code.
103
- GetExitCodeProcess(baton->hShell, (LPDWORD)(&exit_event->exit_code));
104
- // Clean up handles
105
- CloseHandle(baton->hShell);
106
- assert(remove_pty_baton(baton->id));
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 = InterlockedIncrement(&ptyCounter);
299
+ const int ptyId = ++ptyCounter;
302
300
  marshal.Set("pty", Napi::Number::New(env, ptyId));
303
- ptyHandles.emplace_back(
304
- std::make_unique<pty_baton>(ptyId, hIn, hOut, hpc));
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
- // Fetch pty handle from ID and start process
353
- pty_baton* handle = get_pty_baton(id);
354
- if (!handle) {
355
- throw Napi::Error::New(env, "Invalid pty handle");
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
@@ -471,7 +475,8 @@ static Napi::Value PtyResize(const Napi::CallbackInfo& info) {
471
475
  SHORT rows = static_cast<SHORT>(info[2].As<Napi::Number>().Uint32Value());
472
476
  const bool useConptyDll = info[3].As<Napi::Boolean>().Value();
473
477
 
474
- const pty_baton* handle = get_pty_baton(id);
478
+ std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
479
+ const pty_baton* handle = get_pty_baton(lock, id);
475
480
 
476
481
  if (handle != nullptr) {
477
482
  HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
@@ -512,7 +517,8 @@ static Napi::Value PtyClear(const Napi::CallbackInfo& info) {
512
517
  return env.Undefined();
513
518
  }
514
519
 
515
- const pty_baton* handle = get_pty_baton(id);
520
+ std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
521
+ const pty_baton* handle = get_pty_baton(lock, id);
516
522
 
517
523
  if (handle != nullptr) {
518
524
  HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
@@ -543,7 +549,8 @@ static Napi::Value PtyKill(const Napi::CallbackInfo& info) {
543
549
  int id = info[0].As<Napi::Number>().Int32Value();
544
550
  const bool useConptyDll = info[1].As<Napi::Boolean>().Value();
545
551
 
546
- const pty_baton* handle = get_pty_baton(id);
552
+ std::lock_guard<std::mutex> lock(g_ptyHandlesMutex);
553
+ const pty_baton* handle = get_pty_baton(lock, id);
547
554
 
548
555
  if (handle != nullptr) {
549
556
  HANDLE hLibrary = LoadConptyDll(info, useConptyDll);
@@ -12,7 +12,7 @@ declare module 'node-pty' {
12
12
  * escaped properly.
13
13
  * @param options The options of the terminal.
14
14
  * @see CommandLineToArgvW https://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
15
- * @see Parsing C++ Comamnd-Line Arguments https://msdn.microsoft.com/en-us/library/17w5ykft.aspx
15
+ * @see Parsing C++ Command-Line Arguments https://msdn.microsoft.com/en-us/library/17w5ykft.aspx
16
16
  * @see GetCommandLine https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156.aspx
17
17
  */
18
18
  export function spawn(file: string, args: string[] | string, options: IPtyForkOptions | IWindowsPtyForkOptions): IPty;