node-pty 1.1.0-beta5 → 1.1.0-beta6

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/src/win/winpty.cc CHANGED
@@ -8,9 +8,11 @@
8
8
  * with pseudo-terminal file descriptors.
9
9
  */
10
10
 
11
+ #define NODE_ADDON_API_DISABLE_DEPRECATED
12
+ #include <napi.h>
11
13
  #include <iostream>
14
+ #include <assert.h>
12
15
  #include <map>
13
- #include <nan.h>
14
16
  #include <Shlwapi.h> // PathCombine, PathIsRelative
15
17
  #include <sstream>
16
18
  #include <stdlib.h>
@@ -24,8 +26,6 @@
24
26
  /**
25
27
  * Misc
26
28
  */
27
- extern "C" void init(v8::Local<v8::Object>);
28
-
29
29
  #define WINPTY_DBG_VARIABLE TEXT("WINPTYDBG")
30
30
 
31
31
  /**
@@ -66,28 +66,28 @@ static bool remove_pipe_handle(DWORD pid) {
66
66
  return false;
67
67
  }
68
68
 
69
- void throw_winpty_error(const char *generalMsg, winpty_error_ptr_t error_ptr) {
70
- std::wstringstream why;
71
- std::wstring msg(winpty_error_msg(error_ptr));
72
- why << generalMsg << ": " << msg;
73
- Nan::ThrowError(path_util::from_wstring(why.str().c_str()));
69
+ Napi::Error error_with_winpty_msg(const char *generalMsg, winpty_error_ptr_t error_ptr, Napi::Env env) {
70
+ std::string why;
71
+ why += generalMsg;
72
+ why += ": ";
73
+ why += path_util::wstring_to_string(winpty_error_msg(error_ptr));
74
74
  winpty_error_free(error_ptr);
75
+ return Napi::Error::New(env, why);
75
76
  }
76
77
 
77
- static NAN_METHOD(PtyGetExitCode) {
78
- Nan::HandleScope scope;
78
+ static Napi::Value PtyGetExitCode(const Napi::CallbackInfo& info) {
79
+ Napi::Env env(info.Env());
80
+ Napi::HandleScope scope(env);
79
81
 
80
82
  if (info.Length() != 1 ||
81
- !info[0]->IsNumber()) {
82
- Nan::ThrowError("Usage: pty.getExitCode(pid)");
83
- return;
83
+ !info[0].IsNumber()) {
84
+ throw Napi::Error::New(env, "Usage: pty.getExitCode(pid)");
84
85
  }
85
86
 
86
- DWORD pid = info[0]->Uint32Value(Nan::GetCurrentContext()).FromJust();
87
+ DWORD pid = info[0].As<Napi::Number>().Uint32Value();
87
88
  HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
88
89
  if (handle == NULL) {
89
- info.GetReturnValue().Set(Nan::New<v8::Number>(-1));
90
- return;
90
+ return Napi::Number::New(env, -1);
91
91
  }
92
92
 
93
93
  DWORD exitCode = 0;
@@ -97,95 +97,86 @@ static NAN_METHOD(PtyGetExitCode) {
97
97
  }
98
98
 
99
99
  CloseHandle(handle);
100
- info.GetReturnValue().Set(Nan::New<v8::Number>(exitCode));
100
+ return Napi::Number::New(env, exitCode);
101
101
  }
102
102
 
103
- static NAN_METHOD(PtyGetProcessList) {
104
- Nan::HandleScope scope;
103
+ static Napi::Value PtyGetProcessList(const Napi::CallbackInfo& info) {
104
+ Napi::Env env(info.Env());
105
+ Napi::HandleScope scope(env);
105
106
 
106
107
  if (info.Length() != 1 ||
107
- !info[0]->IsNumber()) {
108
- Nan::ThrowError("Usage: pty.getProcessList(pid)");
109
- return;
108
+ !info[0].IsNumber()) {
109
+ throw Napi::Error::New(env, "Usage: pty.getProcessList(pid)");
110
110
  }
111
111
 
112
- DWORD pid = info[0]->Uint32Value(Nan::GetCurrentContext()).FromJust();
112
+ DWORD pid = info[0].As<Napi::Number>().Uint32Value();
113
113
  winpty_t *pc = get_pipe_handle(pid);
114
114
  if (pc == nullptr) {
115
- info.GetReturnValue().Set(Nan::New<v8::Array>(0));
116
- return;
115
+ return Napi::Number::New(env, 0);
117
116
  }
118
117
  int processList[64];
119
118
  const int processCount = 64;
120
119
  int actualCount = winpty_get_console_process_list(pc, processList, processCount, nullptr);
121
120
  if (actualCount <= 0) {
122
- info.GetReturnValue().Set(Nan::New<v8::Array>(0));
123
- return;
121
+ return Napi::Number::New(env, 0);
124
122
  }
125
- uint32_t actualCountSize = static_cast<uint32_t>(actualCount);
126
- v8::Local<v8::Array> result = Nan::New<v8::Array>(actualCountSize);
127
- for (uint32_t i = 0; i < actualCountSize; i++) {
128
- Nan::Set(result, i, Nan::New<v8::Number>(processList[i]));
123
+ Napi::Array result = Napi::Array::New(env, actualCount);
124
+ for (int i = 0; i < actualCount; i++) {
125
+ result.Set(i, Napi::Number::New(env, processList[i]));
129
126
  }
130
- info.GetReturnValue().Set(result);
127
+ return result;
131
128
  }
132
129
 
133
- static NAN_METHOD(PtyStartProcess) {
134
- Nan::HandleScope scope;
130
+ static Napi::Value PtyStartProcess(const Napi::CallbackInfo& info) {
131
+ Napi::Env env(info.Env());
132
+ Napi::HandleScope scope(env);
135
133
 
136
134
  if (info.Length() != 7 ||
137
- !info[0]->IsString() ||
138
- !info[1]->IsString() ||
139
- !info[2]->IsArray() ||
140
- !info[3]->IsString() ||
141
- !info[4]->IsNumber() ||
142
- !info[5]->IsNumber() ||
143
- !info[6]->IsBoolean()) {
144
- Nan::ThrowError("Usage: pty.startProcess(file, cmdline, env, cwd, cols, rows, debug)");
145
- return;
135
+ !info[0].IsString() ||
136
+ !info[1].IsString() ||
137
+ !info[2].IsArray() ||
138
+ !info[3].IsString() ||
139
+ !info[4].IsNumber() ||
140
+ !info[5].IsNumber() ||
141
+ !info[6].IsBoolean()) {
142
+ throw Napi::Error::New(env, "Usage: pty.startProcess(file, cmdline, env, cwd, cols, rows, debug)");
146
143
  }
147
144
 
148
- const wchar_t *filename = path_util::to_wstring(Nan::Utf8String(info[0]));
149
- const wchar_t *cmdline = path_util::to_wstring(Nan::Utf8String(info[1]));
150
- const wchar_t *cwd = path_util::to_wstring(Nan::Utf8String(info[3]));
145
+ std::wstring filename(path_util::to_wstring(info[0].As<Napi::String>()));
146
+ std::wstring cmdline(path_util::to_wstring(info[1].As<Napi::String>()));
147
+ std::wstring cwd(path_util::to_wstring(info[3].As<Napi::String>()));
151
148
 
152
149
  // create environment block
153
- std::wstring env;
154
- const v8::Local<v8::Array> envValues = v8::Local<v8::Array>::Cast(info[2]);
150
+ std::wstring envStr;
151
+ const Napi::Array envValues = info[2].As<Napi::Array>();
155
152
  if (!envValues.IsEmpty()) {
156
-
157
- std::wstringstream envBlock;
158
-
159
- for(uint32_t i = 0; i < envValues->Length(); i++) {
160
- std::wstring envValue(path_util::to_wstring(Nan::Utf8String(Nan::Get(envValues, i).ToLocalChecked())));
161
- envBlock << envValue << L'\0';
153
+ std::wstring envBlock;
154
+ for(uint32_t i = 0; i < envValues.Length(); i++) {
155
+ envBlock += path_util::to_wstring(envValues.Get(i).As<Napi::String>());
156
+ envBlock += L'\0';
162
157
  }
163
-
164
- env = envBlock.str();
158
+ envStr = std::move(envBlock);
165
159
  }
166
160
 
167
161
  // use environment 'Path' variable to determine location of
168
162
  // the relative path that we have recieved (e.g cmd.exe)
169
163
  std::wstring shellpath;
170
- if (::PathIsRelativeW(filename)) {
164
+ if (::PathIsRelativeW(filename.c_str())) {
171
165
  shellpath = path_util::get_shell_path(filename);
172
166
  } else {
173
167
  shellpath = filename;
174
168
  }
175
169
 
176
170
  if (shellpath.empty() || !path_util::file_exists(shellpath)) {
177
- std::wstringstream why;
178
- why << "File not found: " << shellpath;
179
- Nan::ThrowError(path_util::from_wstring(why.str().c_str()));
180
- delete filename;
181
- delete cmdline;
182
- delete cwd;
183
- return;
171
+ std::string why;
172
+ why += "File not found: ";
173
+ why += path_util::wstring_to_string(shellpath);
174
+ throw Napi::Error::New(env, why);
184
175
  }
185
176
 
186
- int cols = info[4]->Int32Value(Nan::GetCurrentContext()).FromJust();
187
- int rows = info[5]->Int32Value(Nan::GetCurrentContext()).FromJust();
188
- bool debug = Nan::To<bool>(info[6]).FromJust();
177
+ int cols = info[4].As<Napi::Number>().Int32Value();
178
+ int rows = info[5].As<Napi::Number>().Int32Value();
179
+ bool debug = info[6].As<Napi::Boolean>().Value();
189
180
 
190
181
  // Enable/disable debugging
191
182
  SetEnvironmentVariable(WINPTY_DBG_VARIABLE, debug ? "1" : NULL); // NULL = deletes variable
@@ -194,11 +185,7 @@ static NAN_METHOD(PtyStartProcess) {
194
185
  winpty_error_ptr_t error_ptr = nullptr;
195
186
  winpty_config_t* winpty_config = winpty_config_new(0, &error_ptr);
196
187
  if (winpty_config == nullptr) {
197
- throw_winpty_error("Error creating WinPTY config", error_ptr);
198
- delete filename;
199
- delete cmdline;
200
- delete cwd;
201
- return;
188
+ throw error_with_winpty_msg("Error creating WinPTY config", error_ptr, env);
202
189
  }
203
190
  winpty_error_free(error_ptr);
204
191
 
@@ -209,23 +196,15 @@ static NAN_METHOD(PtyStartProcess) {
209
196
  winpty_t *pc = winpty_open(winpty_config, &error_ptr);
210
197
  winpty_config_free(winpty_config);
211
198
  if (pc == nullptr) {
212
- throw_winpty_error("Error launching WinPTY agent", error_ptr);
213
- delete filename;
214
- delete cmdline;
215
- delete cwd;
216
- return;
199
+ throw error_with_winpty_msg("Error launching WinPTY agent", error_ptr, env);
217
200
  }
218
201
  winpty_error_free(error_ptr);
219
202
 
220
203
  // Create winpty spawn config
221
- winpty_spawn_config_t* config = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, shellpath.c_str(), cmdline, cwd, env.c_str(), &error_ptr);
204
+ winpty_spawn_config_t* config = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, shellpath.c_str(), cmdline.c_str(), cwd.c_str(), envStr.c_str(), &error_ptr);
222
205
  if (config == nullptr) {
223
- throw_winpty_error("Error creating WinPTY spawn config", error_ptr);
224
206
  winpty_free(pc);
225
- delete filename;
226
- delete cmdline;
227
- delete cwd;
228
- return;
207
+ throw error_with_winpty_msg("Error creating WinPTY spawn config", error_ptr, env);
229
208
  }
230
209
  winpty_error_free(error_ptr);
231
210
 
@@ -234,121 +213,99 @@ static NAN_METHOD(PtyStartProcess) {
234
213
  BOOL spawnSuccess = winpty_spawn(pc, config, &handle, nullptr, nullptr, &error_ptr);
235
214
  winpty_spawn_config_free(config);
236
215
  if (!spawnSuccess) {
237
- throw_winpty_error("Unable to start terminal process", error_ptr);
238
216
  if (handle) {
239
217
  CloseHandle(handle);
240
218
  }
241
219
  winpty_free(pc);
242
- delete filename;
243
- delete cmdline;
244
- delete cwd;
245
- return;
220
+ throw error_with_winpty_msg("Unable to start terminal process", error_ptr, env);
246
221
  }
247
222
  winpty_error_free(error_ptr);
248
223
 
249
224
  LPCWSTR coninPipeName = winpty_conin_name(pc);
250
225
  std::string coninPipeNameStr(path_util::from_wstring(coninPipeName));
251
226
  if (coninPipeNameStr.empty()) {
252
- Nan::ThrowError("Failed to initialize winpty conin");
253
227
  CloseHandle(handle);
254
228
  winpty_free(pc);
255
- delete filename;
256
- delete cmdline;
257
- delete cwd;
258
- return;
229
+ throw Napi::Error::New(env, "Failed to initialize winpty conin");
259
230
  }
260
231
 
261
232
  LPCWSTR conoutPipeName = winpty_conout_name(pc);
262
233
  std::string conoutPipeNameStr(path_util::from_wstring(conoutPipeName));
263
234
  if (conoutPipeNameStr.empty()) {
264
- Nan::ThrowError("Failed to initialize winpty conout");
265
235
  CloseHandle(handle);
266
236
  winpty_free(pc);
267
- delete filename;
268
- delete cmdline;
269
- delete cwd;
270
- return;
237
+ throw Napi::Error::New(env, "Failed to initialize winpty conout");
271
238
  }
272
239
 
273
240
  DWORD innerPid = GetProcessId(handle);
274
241
  if (createdHandles[innerPid]) {
275
- std::stringstream why;
276
- why << "There is already a process with innerPid " << innerPid;
277
- Nan::ThrowError(why.str().c_str());
278
242
  CloseHandle(handle);
279
243
  winpty_free(pc);
280
- delete filename;
281
- delete cmdline;
282
- delete cwd;
283
- return;
244
+ std::stringstream why;
245
+ why << "There is already a process with innerPid " << innerPid;
246
+ throw Napi::Error::New(env, why.str());
284
247
  }
285
248
  createdHandles[innerPid] = handle;
286
249
 
287
250
  // Save pty struct for later use
288
251
  ptyHandles.push_back(pc);
289
252
 
290
- v8::Local<v8::Object> marshal = Nan::New<v8::Object>();
291
253
  DWORD pid = GetProcessId(winpty_agent_process(pc));
292
- Nan::Set(marshal, Nan::New<v8::String>("innerPid").ToLocalChecked(), Nan::New<v8::Number>(static_cast<double>(innerPid)));
293
- Nan::Set(marshal, Nan::New<v8::String>("pid").ToLocalChecked(), Nan::New<v8::Number>(static_cast<double>(pid)));
294
- Nan::Set(marshal, Nan::New<v8::String>("pty").ToLocalChecked(), Nan::New<v8::Number>(InterlockedIncrement(&ptyCounter)));
295
- Nan::Set(marshal, Nan::New<v8::String>("fd").ToLocalChecked(), Nan::New<v8::Number>(-1));
296
- Nan::Set(marshal, Nan::New<v8::String>("conin").ToLocalChecked(), Nan::New<v8::String>(coninPipeNameStr).ToLocalChecked());
297
- Nan::Set(marshal, Nan::New<v8::String>("conout").ToLocalChecked(), Nan::New<v8::String>(conoutPipeNameStr).ToLocalChecked());
298
- info.GetReturnValue().Set(marshal);
299
-
300
- delete filename;
301
- delete cmdline;
302
- delete cwd;
254
+ Napi::Object marshal = Napi::Object::New(env);
255
+ marshal.Set("innerPid", Napi::Number::New(env, (int)innerPid));
256
+ marshal.Set("pid", Napi::Number::New(env, (int)pid));
257
+ marshal.Set("pty", Napi::Number::New(env, InterlockedIncrement(&ptyCounter)));
258
+ marshal.Set("fd", Napi::Number::New(env, -1));
259
+ marshal.Set("conin", Napi::String::New(env, coninPipeNameStr));
260
+ marshal.Set("conout", Napi::String::New(env, conoutPipeNameStr));
261
+
262
+ return marshal;
303
263
  }
304
264
 
305
- static NAN_METHOD(PtyResize) {
306
- Nan::HandleScope scope;
265
+ static Napi::Value PtyResize(const Napi::CallbackInfo& info) {
266
+ Napi::Env env(info.Env());
267
+ Napi::HandleScope scope(env);
307
268
 
308
269
  if (info.Length() != 3 ||
309
- !info[0]->IsNumber() ||
310
- !info[1]->IsNumber() ||
311
- !info[2]->IsNumber()) {
312
- Nan::ThrowError("Usage: pty.resize(pid, cols, rows)");
313
- return;
270
+ !info[0].IsNumber() ||
271
+ !info[1].IsNumber() ||
272
+ !info[2].IsNumber()) {
273
+ throw Napi::Error::New(env, "Usage: pty.resize(pid, cols, rows)");
314
274
  }
315
275
 
316
- DWORD pid = info[0]->Uint32Value(Nan::GetCurrentContext()).FromJust();
317
- int cols = info[1]->Int32Value(Nan::GetCurrentContext()).FromJust();
318
- int rows = info[2]->Int32Value(Nan::GetCurrentContext()).FromJust();
276
+ DWORD pid = info[0].As<Napi::Number>().Uint32Value();
277
+ int cols = info[1].As<Napi::Number>().Int32Value();
278
+ int rows = info[2].As<Napi::Number>().Int32Value();
319
279
 
320
280
  winpty_t *pc = get_pipe_handle(pid);
321
281
 
322
282
  if (pc == nullptr) {
323
- Nan::ThrowError("The pty doesn't appear to exist");
324
- return;
283
+ throw Napi::Error::New(env, "The pty doesn't appear to exist");
325
284
  }
326
285
  BOOL success = winpty_set_size(pc, cols, rows, nullptr);
327
286
  if (!success) {
328
- Nan::ThrowError("The pty could not be resized");
329
- return;
287
+ throw Napi::Error::New(env, "The pty could not be resized");
330
288
  }
331
289
 
332
- return info.GetReturnValue().SetUndefined();
290
+ return env.Undefined();
333
291
  }
334
292
 
335
- static NAN_METHOD(PtyKill) {
336
- Nan::HandleScope scope;
293
+ static Napi::Value PtyKill(const Napi::CallbackInfo& info) {
294
+ Napi::Env env(info.Env());
295
+ Napi::HandleScope scope(env);
337
296
 
338
297
  if (info.Length() != 2 ||
339
- !info[0]->IsNumber() ||
340
- !info[1]->IsNumber()) {
341
- Nan::ThrowError("Usage: pty.kill(pid, innerPid)");
342
- return;
298
+ !info[0].IsNumber() ||
299
+ !info[1].IsNumber()) {
300
+ throw Napi::Error::New(env, "Usage: pty.kill(pid, innerPid)");
343
301
  }
344
302
 
345
- DWORD pid = info[0]->Uint32Value(Nan::GetCurrentContext()).FromJust();
346
- DWORD innerPid = info[1]->Uint32Value(Nan::GetCurrentContext()).FromJust();
303
+ DWORD pid = info[0].As<Napi::Number>().Uint32Value();
304
+ DWORD innerPid = info[1].As<Napi::Number>().Uint32Value();
347
305
 
348
306
  winpty_t *pc = get_pipe_handle(pid);
349
307
  if (pc == nullptr) {
350
- Nan::ThrowError("Pty seems to have been killed already");
351
- return;
308
+ throw Napi::Error::New(env, "Pty seems to have been killed already");
352
309
  }
353
310
 
354
311
  assert(remove_pipe_handle(pid));
@@ -357,20 +314,20 @@ static NAN_METHOD(PtyKill) {
357
314
  createdHandles.erase(innerPid);
358
315
  CloseHandle(innerPidHandle);
359
316
 
360
- return info.GetReturnValue().SetUndefined();
317
+ return env.Undefined();
361
318
  }
362
319
 
363
320
  /**
364
321
  * Init
365
322
  */
366
323
 
367
- extern "C" void init(v8::Local<v8::Object> target) {
368
- Nan::HandleScope scope;
369
- Nan::SetMethod(target, "startProcess", PtyStartProcess);
370
- Nan::SetMethod(target, "resize", PtyResize);
371
- Nan::SetMethod(target, "kill", PtyKill);
372
- Nan::SetMethod(target, "getExitCode", PtyGetExitCode);
373
- Nan::SetMethod(target, "getProcessList", PtyGetProcessList);
324
+ Napi::Object init(Napi::Env env, Napi::Object exports) {
325
+ exports.Set("startProcess", Napi::Function::New(env, PtyStartProcess));
326
+ exports.Set("resize", Napi::Function::New(env, PtyResize));
327
+ exports.Set("kill", Napi::Function::New(env, PtyKill));
328
+ exports.Set("getExitCode", Napi::Function::New(env, PtyGetExitCode));
329
+ exports.Set("getProcessList", Napi::Function::New(env, PtyGetProcessList));
330
+ return exports;
374
331
  };
375
332
 
376
- NODE_MODULE(pty, init);
333
+ NODE_API_MODULE(NODE_GYP_MODULE_NAME, init);