1 #include "async_wrap-inl.h"
2 #include "base_object-inl.h"
3 #include "debug_utils-inl.h"
4 #include "env-inl.h"
5 #include "memory_tracker-inl.h"
6 #include "node.h"
7 #include "node_errors.h"
8 #include "node_external_reference.h"
9 #include "node_internals.h"
10 #include "node_process-inl.h"
11 #include "util-inl.h"
12 #include "uv.h"
13 #include "v8-fast-api-calls.h"
14 #include "v8.h"
15
16 #include <vector>
17
18 #if HAVE_INSPECTOR
19 #include "inspector_io.h"
20 #endif
21
22 #include <climits> // PATH_MAX
23 #include <cstdio>
24
25 #if defined(_MSC_VER)
26 #include <direct.h>
27 #include <io.h>
28 #define umask _umask
29 typedef int mode_t;
30 #else
31 #include <pthread.h>
32 #include <sys/resource.h> // getrlimit, setrlimit
33 #include <termios.h> // tcgetattr, tcsetattr
34 #endif
35
36 namespace node {
37
38 using v8::Array;
39 using v8::ArrayBuffer;
40 using v8::CFunction;
41 using v8::Context;
42 using v8::Float64Array;
43 using v8::FunctionCallbackInfo;
44 using v8::HeapStatistics;
45 using v8::Integer;
46 using v8::Isolate;
47 using v8::Local;
48 using v8::NewStringType;
49 using v8::Number;
50 using v8::Object;
51 using v8::String;
52 using v8::Uint32;
53 using v8::Value;
54
55 namespace per_process {
56 Mutex umask_mutex;
57 } // namespace per_process
58
59 // Microseconds in a second, as a float, used in CPUUsage() below
60 #define MICROS_PER_SEC 1e6
61 // used in Hrtime() and Uptime() below
62 #define NANOS_PER_SEC 1000000000
63
Abort(const FunctionCallbackInfo<Value> & args)64 static void Abort(const FunctionCallbackInfo<Value>& args) {
65 Abort();
66 }
67
68 // For internal testing only, not exposed to userland.
CauseSegfault(const FunctionCallbackInfo<Value> & args)69 static void CauseSegfault(const FunctionCallbackInfo<Value>& args) {
70 // This should crash hard all platforms.
71 volatile void** d = static_cast<volatile void**>(nullptr);
72 *d = nullptr;
73 }
74
Chdir(const FunctionCallbackInfo<Value> & args)75 static void Chdir(const FunctionCallbackInfo<Value>& args) {
76 Environment* env = Environment::GetCurrent(args);
77 CHECK(env->owns_process_state());
78
79 CHECK_EQ(args.Length(), 1);
80 CHECK(args[0]->IsString());
81 Utf8Value path(env->isolate(), args[0]);
82 int err = uv_chdir(*path);
83 if (err) {
84 // Also include the original working directory, since that will usually
85 // be helpful information when debugging a `chdir()` failure.
86 char buf[PATH_MAX_BYTES];
87 size_t cwd_len = sizeof(buf);
88 uv_cwd(buf, &cwd_len);
89 return env->ThrowUVException(err, "chdir", nullptr, buf, *path);
90 }
91 }
92
get_fields_array_buffer(const FunctionCallbackInfo<Value> & args,size_t index,size_t array_length)93 inline Local<ArrayBuffer> get_fields_array_buffer(
94 const FunctionCallbackInfo<Value>& args,
95 size_t index,
96 size_t array_length) {
97 CHECK(args[index]->IsFloat64Array());
98 Local<Float64Array> arr = args[index].As<Float64Array>();
99 CHECK_EQ(arr->Length(), array_length);
100 return arr->Buffer();
101 }
102
103 // CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
104 // to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
105 // which are uv_timeval_t structs (long tv_sec, long tv_usec).
106 // Returns those values as Float64 microseconds in the elements of the array
107 // passed to the function.
CPUUsage(const FunctionCallbackInfo<Value> & args)108 static void CPUUsage(const FunctionCallbackInfo<Value>& args) {
109 Environment* env = Environment::GetCurrent(args);
110 uv_rusage_t rusage;
111
112 // Call libuv to get the values we'll return.
113 int err = uv_getrusage(&rusage);
114 if (err)
115 return env->ThrowUVException(err, "uv_getrusage");
116
117 // Get the double array pointer from the Float64Array argument.
118 Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 2);
119 double* fields = static_cast<double*>(ab->Data());
120
121 // Set the Float64Array elements to be user / system values in microseconds.
122 fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
123 fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
124 }
125
Cwd(const FunctionCallbackInfo<Value> & args)126 static void Cwd(const FunctionCallbackInfo<Value>& args) {
127 Environment* env = Environment::GetCurrent(args);
128 CHECK(env->has_run_bootstrapping_code());
129 char buf[PATH_MAX_BYTES];
130 size_t cwd_len = sizeof(buf);
131 int err = uv_cwd(buf, &cwd_len);
132 if (err)
133 return env->ThrowUVException(err, "uv_cwd");
134
135 Local<String> cwd = String::NewFromUtf8(env->isolate(),
136 buf,
137 NewStringType::kNormal,
138 cwd_len).ToLocalChecked();
139 args.GetReturnValue().Set(cwd);
140 }
141
Kill(const FunctionCallbackInfo<Value> & args)142 static void Kill(const FunctionCallbackInfo<Value>& args) {
143 Environment* env = Environment::GetCurrent(args);
144 Local<Context> context = env->context();
145
146 if (args.Length() < 2) {
147 THROW_ERR_MISSING_ARGS(env, "Bad argument.");
148 }
149
150 int pid;
151 if (!args[0]->Int32Value(context).To(&pid)) return;
152 int sig;
153 if (!args[1]->Int32Value(context).To(&sig)) return;
154
155 uv_pid_t own_pid = uv_os_getpid();
156 if (sig > 0 &&
157 (pid == 0 || pid == -1 || pid == own_pid || pid == -own_pid) &&
158 !HasSignalJSHandler(sig)) {
159 // This is most likely going to terminate this process.
160 // It's not an exact method but it might be close enough.
161 RunAtExit(env);
162 }
163
164 int err = uv_kill(pid, sig);
165 args.GetReturnValue().Set(err);
166 }
167
Rss(const FunctionCallbackInfo<Value> & args)168 static void Rss(const FunctionCallbackInfo<Value>& args) {
169 Environment* env = Environment::GetCurrent(args);
170
171 size_t rss;
172 int err = uv_resident_set_memory(&rss);
173 if (err)
174 return env->ThrowUVException(err, "uv_resident_set_memory");
175
176 args.GetReturnValue().Set(static_cast<double>(rss));
177 }
178
MemoryUsage(const FunctionCallbackInfo<Value> & args)179 static void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
180 Environment* env = Environment::GetCurrent(args);
181
182 Isolate* isolate = env->isolate();
183 // V8 memory usage
184 HeapStatistics v8_heap_stats;
185 isolate->GetHeapStatistics(&v8_heap_stats);
186
187 NodeArrayBufferAllocator* array_buffer_allocator =
188 env->isolate_data()->node_allocator();
189
190 // Get the double array pointer from the Float64Array argument.
191 Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 5);
192 double* fields = static_cast<double*>(ab->Data());
193
194 size_t rss;
195 int err = uv_resident_set_memory(&rss);
196 if (err)
197 return env->ThrowUVException(err, "uv_resident_set_memory");
198
199 fields[0] = static_cast<double>(rss);
200 fields[1] = static_cast<double>(v8_heap_stats.total_heap_size());
201 fields[2] = static_cast<double>(v8_heap_stats.used_heap_size());
202 fields[3] = static_cast<double>(v8_heap_stats.external_memory());
203 fields[4] =
204 array_buffer_allocator == nullptr
205 ? 0
206 : static_cast<double>(array_buffer_allocator->total_mem_usage());
207 }
208
GetConstrainedMemory(const FunctionCallbackInfo<Value> & args)209 static void GetConstrainedMemory(const FunctionCallbackInfo<Value>& args) {
210 uint64_t value = uv_get_constrained_memory();
211 if (value != 0) {
212 args.GetReturnValue().Set(static_cast<double>(value));
213 }
214 }
215
RawDebug(const FunctionCallbackInfo<Value> & args)216 void RawDebug(const FunctionCallbackInfo<Value>& args) {
217 CHECK(args.Length() == 1 && args[0]->IsString() &&
218 "must be called with a single string");
219 Utf8Value message(args.GetIsolate(), args[0]);
220 FPrintF(stderr, "%s\n", message);
221 fflush(stderr);
222 }
223
Umask(const FunctionCallbackInfo<Value> & args)224 static void Umask(const FunctionCallbackInfo<Value>& args) {
225 Environment* env = Environment::GetCurrent(args);
226 CHECK(env->has_run_bootstrapping_code());
227 CHECK_EQ(args.Length(), 1);
228 CHECK(args[0]->IsUndefined() || args[0]->IsUint32());
229 Mutex::ScopedLock scoped_lock(per_process::umask_mutex);
230
231 uint32_t old;
232 if (args[0]->IsUndefined()) {
233 old = umask(0);
234 umask(static_cast<mode_t>(old));
235 } else {
236 int oct = args[0].As<Uint32>()->Value();
237 old = umask(static_cast<mode_t>(oct));
238 }
239
240 args.GetReturnValue().Set(old);
241 }
242
Uptime(const FunctionCallbackInfo<Value> & args)243 static void Uptime(const FunctionCallbackInfo<Value>& args) {
244 Environment* env = Environment::GetCurrent(args);
245
246 uv_update_time(env->event_loop());
247 double uptime =
248 static_cast<double>(uv_hrtime() - per_process::node_start_time);
249 Local<Number> result = Number::New(env->isolate(), uptime / NANOS_PER_SEC);
250 args.GetReturnValue().Set(result);
251 }
252
GetActiveRequests(const FunctionCallbackInfo<Value> & args)253 static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) {
254 Environment* env = Environment::GetCurrent(args);
255
256 std::vector<Local<Value>> request_v;
257 for (ReqWrapBase* req_wrap : *env->req_wrap_queue()) {
258 AsyncWrap* w = req_wrap->GetAsyncWrap();
259 if (w->persistent().IsEmpty())
260 continue;
261 request_v.emplace_back(w->GetOwner());
262 }
263
264 args.GetReturnValue().Set(
265 Array::New(env->isolate(), request_v.data(), request_v.size()));
266 }
267
268 // Non-static, friend of HandleWrap. Could have been a HandleWrap method but
269 // implemented here for consistency with GetActiveRequests().
GetActiveHandles(const FunctionCallbackInfo<Value> & args)270 void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
271 Environment* env = Environment::GetCurrent(args);
272
273 std::vector<Local<Value>> handle_v;
274 for (auto w : *env->handle_wrap_queue()) {
275 if (!HandleWrap::HasRef(w))
276 continue;
277 handle_v.emplace_back(w->GetOwner());
278 }
279 args.GetReturnValue().Set(
280 Array::New(env->isolate(), handle_v.data(), handle_v.size()));
281 }
282
GetActiveResourcesInfo(const FunctionCallbackInfo<Value> & args)283 static void GetActiveResourcesInfo(const FunctionCallbackInfo<Value>& args) {
284 Environment* env = Environment::GetCurrent(args);
285 std::vector<Local<Value>> resources_info;
286
287 // Active requests
288 for (ReqWrapBase* req_wrap : *env->req_wrap_queue()) {
289 AsyncWrap* w = req_wrap->GetAsyncWrap();
290 if (w->persistent().IsEmpty()) continue;
291 resources_info.emplace_back(
292 OneByteString(env->isolate(), w->MemoryInfoName()));
293 }
294
295 // Active handles
296 for (HandleWrap* w : *env->handle_wrap_queue()) {
297 if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w)) continue;
298 resources_info.emplace_back(
299 OneByteString(env->isolate(), w->MemoryInfoName()));
300 }
301
302 // Active timeouts
303 resources_info.insert(resources_info.end(),
304 env->timeout_info()[0],
305 OneByteString(env->isolate(), "Timeout"));
306
307 // Active immediates
308 resources_info.insert(resources_info.end(),
309 env->immediate_info()->ref_count(),
310 OneByteString(env->isolate(), "Immediate"));
311
312 args.GetReturnValue().Set(
313 Array::New(env->isolate(), resources_info.data(), resources_info.size()));
314 }
315
ResourceUsage(const FunctionCallbackInfo<Value> & args)316 static void ResourceUsage(const FunctionCallbackInfo<Value>& args) {
317 Environment* env = Environment::GetCurrent(args);
318
319 uv_rusage_t rusage;
320 int err = uv_getrusage(&rusage);
321 if (err)
322 return env->ThrowUVException(err, "uv_getrusage");
323
324 Local<ArrayBuffer> ab = get_fields_array_buffer(args, 0, 16);
325 double* fields = static_cast<double*>(ab->Data());
326
327 fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
328 fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
329 fields[2] = static_cast<double>(rusage.ru_maxrss);
330 fields[3] = static_cast<double>(rusage.ru_ixrss);
331 fields[4] = static_cast<double>(rusage.ru_idrss);
332 fields[5] = static_cast<double>(rusage.ru_isrss);
333 fields[6] = static_cast<double>(rusage.ru_minflt);
334 fields[7] = static_cast<double>(rusage.ru_majflt);
335 fields[8] = static_cast<double>(rusage.ru_nswap);
336 fields[9] = static_cast<double>(rusage.ru_inblock);
337 fields[10] = static_cast<double>(rusage.ru_oublock);
338 fields[11] = static_cast<double>(rusage.ru_msgsnd);
339 fields[12] = static_cast<double>(rusage.ru_msgrcv);
340 fields[13] = static_cast<double>(rusage.ru_nsignals);
341 fields[14] = static_cast<double>(rusage.ru_nvcsw);
342 fields[15] = static_cast<double>(rusage.ru_nivcsw);
343 }
344
345 #ifdef __POSIX__
DebugProcess(const FunctionCallbackInfo<Value> & args)346 static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
347 Environment* env = Environment::GetCurrent(args);
348
349 if (args.Length() < 1) {
350 return THROW_ERR_MISSING_ARGS(env, "Invalid number of arguments.");
351 }
352
353 CHECK(args[0]->IsNumber());
354 pid_t pid = args[0].As<Integer>()->Value();
355 int r = kill(pid, SIGUSR1);
356
357 if (r != 0) {
358 return env->ThrowErrnoException(errno, "kill");
359 }
360 }
361 #endif // __POSIX__
362
363 #ifdef _WIN32
GetDebugSignalHandlerMappingName(DWORD pid,wchar_t * buf,size_t buf_len)364 static int GetDebugSignalHandlerMappingName(DWORD pid,
365 wchar_t* buf,
366 size_t buf_len) {
367 return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
368 }
369
DebugProcess(const FunctionCallbackInfo<Value> & args)370 static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
371 Environment* env = Environment::GetCurrent(args);
372 Isolate* isolate = args.GetIsolate();
373
374 if (args.Length() < 1) {
375 return THROW_ERR_MISSING_ARGS(env, "Invalid number of arguments.");
376 }
377
378 HANDLE process = nullptr;
379 HANDLE thread = nullptr;
380 HANDLE mapping = nullptr;
381 wchar_t mapping_name[32];
382 LPTHREAD_START_ROUTINE* handler = nullptr;
383 DWORD pid = 0;
384
385 auto cleanup = OnScopeLeave([&]() {
386 if (process != nullptr) CloseHandle(process);
387 if (thread != nullptr) CloseHandle(thread);
388 if (handler != nullptr) UnmapViewOfFile(handler);
389 if (mapping != nullptr) CloseHandle(mapping);
390 });
391
392 CHECK(args[0]->IsNumber());
393 pid = static_cast<DWORD>(args[0].As<Integer>()->Value());
394
395 process =
396 OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
397 PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
398 FALSE,
399 pid);
400 if (process == nullptr) {
401 isolate->ThrowException(
402 WinapiErrnoException(isolate, GetLastError(), "OpenProcess"));
403 return;
404 }
405
406 if (GetDebugSignalHandlerMappingName(
407 pid, mapping_name, arraysize(mapping_name)) < 0) {
408 env->ThrowErrnoException(errno, "sprintf");
409 return;
410 }
411
412 mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
413 if (mapping == nullptr) {
414 isolate->ThrowException(
415 WinapiErrnoException(isolate, GetLastError(), "OpenFileMappingW"));
416 return;
417 }
418
419 handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
420 MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, sizeof *handler));
421 if (handler == nullptr || *handler == nullptr) {
422 isolate->ThrowException(
423 WinapiErrnoException(isolate, GetLastError(), "MapViewOfFile"));
424 return;
425 }
426
427 thread =
428 CreateRemoteThread(process, nullptr, 0, *handler, nullptr, 0, nullptr);
429 if (thread == nullptr) {
430 isolate->ThrowException(
431 WinapiErrnoException(isolate, GetLastError(), "CreateRemoteThread"));
432 return;
433 }
434
435 // Wait for the thread to terminate
436 if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0) {
437 isolate->ThrowException(
438 WinapiErrnoException(isolate, GetLastError(), "WaitForSingleObject"));
439 return;
440 }
441 }
442 #endif // _WIN32
443
DebugEnd(const FunctionCallbackInfo<Value> & args)444 static void DebugEnd(const FunctionCallbackInfo<Value>& args) {
445 #if HAVE_INSPECTOR
446 Environment* env = Environment::GetCurrent(args);
447 if (env->inspector_agent()->IsListening()) {
448 env->inspector_agent()->Stop();
449 }
450 #endif
451 }
452
ReallyExit(const FunctionCallbackInfo<Value> & args)453 static void ReallyExit(const FunctionCallbackInfo<Value>& args) {
454 Environment* env = Environment::GetCurrent(args);
455 RunAtExit(env);
456 int code = args[0]->Int32Value(env->context()).FromMaybe(0);
457 env->Exit(code);
458 }
459
460 namespace process {
461
BindingData(Realm * realm,v8::Local<v8::Object> object)462 BindingData::BindingData(Realm* realm, v8::Local<v8::Object> object)
463 : SnapshotableObject(realm, object, type_int) {
464 Isolate* isolate = realm->isolate();
465 Local<Context> context = realm->context();
466 Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, kBufferSize);
467 array_buffer_.Reset(isolate, ab);
468 object->Set(context, FIXED_ONE_BYTE_STRING(isolate, "hrtimeBuffer"), ab)
469 .ToChecked();
470 backing_store_ = ab->GetBackingStore();
471 }
472
473 v8::CFunction BindingData::fast_number_(v8::CFunction::Make(FastNumber));
474 v8::CFunction BindingData::fast_bigint_(v8::CFunction::Make(FastBigInt));
475
AddMethods()476 void BindingData::AddMethods() {
477 Local<Context> ctx = env()->context();
478 SetFastMethodNoSideEffect(ctx, object(), "hrtime", SlowNumber, &fast_number_);
479 SetFastMethodNoSideEffect(
480 ctx, object(), "hrtimeBigInt", SlowBigInt, &fast_bigint_);
481 }
482
RegisterExternalReferences(ExternalReferenceRegistry * registry)483 void BindingData::RegisterExternalReferences(
484 ExternalReferenceRegistry* registry) {
485 registry->Register(SlowNumber);
486 registry->Register(SlowBigInt);
487 registry->Register(FastNumber);
488 registry->Register(FastBigInt);
489 registry->Register(fast_number_.GetTypeInfo());
490 registry->Register(fast_bigint_.GetTypeInfo());
491 }
492
FromV8Value(Local<Value> value)493 BindingData* BindingData::FromV8Value(Local<Value> value) {
494 Local<Object> v8_object = value.As<Object>();
495 return static_cast<BindingData*>(
496 v8_object->GetAlignedPointerFromInternalField(BaseObject::kSlot));
497 }
498
MemoryInfo(MemoryTracker * tracker) const499 void BindingData::MemoryInfo(MemoryTracker* tracker) const {
500 tracker->TrackField("array_buffer", array_buffer_);
501 }
502
503 // This is the legacy version of hrtime before BigInt was introduced in
504 // JavaScript.
505 // The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
506 // so this function instead fills in an Uint32Array with 3 entries,
507 // to avoid any integer overflow possibility.
508 // The first two entries contain the second part of the value
509 // broken into the upper/lower 32 bits to be converted back in JS,
510 // because there is no Uint64Array in JS.
511 // The third entry contains the remaining nanosecond part of the value.
NumberImpl(BindingData * receiver)512 void BindingData::NumberImpl(BindingData* receiver) {
513 // Make sure we don't accidentally access buffers wiped for snapshot.
514 CHECK(!receiver->array_buffer_.IsEmpty());
515 uint64_t t = uv_hrtime();
516 uint32_t* fields = static_cast<uint32_t*>(receiver->backing_store_->Data());
517 fields[0] = (t / NANOS_PER_SEC) >> 32;
518 fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
519 fields[2] = t % NANOS_PER_SEC;
520 }
521
BigIntImpl(BindingData * receiver)522 void BindingData::BigIntImpl(BindingData* receiver) {
523 // Make sure we don't accidentally access buffers wiped for snapshot.
524 CHECK(!receiver->array_buffer_.IsEmpty());
525 uint64_t t = uv_hrtime();
526 uint64_t* fields = static_cast<uint64_t*>(receiver->backing_store_->Data());
527 fields[0] = t;
528 }
529
SlowBigInt(const FunctionCallbackInfo<Value> & args)530 void BindingData::SlowBigInt(const FunctionCallbackInfo<Value>& args) {
531 BigIntImpl(FromJSObject<BindingData>(args.Holder()));
532 }
533
SlowNumber(const v8::FunctionCallbackInfo<v8::Value> & args)534 void BindingData::SlowNumber(const v8::FunctionCallbackInfo<v8::Value>& args) {
535 NumberImpl(FromJSObject<BindingData>(args.Holder()));
536 }
537
PrepareForSerialization(Local<Context> context,v8::SnapshotCreator * creator)538 bool BindingData::PrepareForSerialization(Local<Context> context,
539 v8::SnapshotCreator* creator) {
540 // It's not worth keeping.
541 // Release it, we will recreate it when the instance is dehydrated.
542 array_buffer_.Reset();
543 // Return true because we need to maintain the reference to the binding from
544 // JS land.
545 return true;
546 }
547
Serialize(int index)548 InternalFieldInfoBase* BindingData::Serialize(int index) {
549 DCHECK_EQ(index, BaseObject::kEmbedderType);
550 InternalFieldInfo* info =
551 InternalFieldInfoBase::New<InternalFieldInfo>(type());
552 return info;
553 }
554
Deserialize(Local<Context> context,Local<Object> holder,int index,InternalFieldInfoBase * info)555 void BindingData::Deserialize(Local<Context> context,
556 Local<Object> holder,
557 int index,
558 InternalFieldInfoBase* info) {
559 DCHECK_EQ(index, BaseObject::kEmbedderType);
560 v8::HandleScope scope(context->GetIsolate());
561 Realm* realm = Realm::GetCurrent(context);
562 // Recreate the buffer in the constructor.
563 BindingData* binding = realm->AddBindingData<BindingData>(context, holder);
564 CHECK_NOT_NULL(binding);
565 }
566
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)567 static void Initialize(Local<Object> target,
568 Local<Value> unused,
569 Local<Context> context,
570 void* priv) {
571 Realm* realm = Realm::GetCurrent(context);
572 Environment* env = realm->env();
573 BindingData* const binding_data =
574 realm->AddBindingData<BindingData>(context, target);
575 if (binding_data == nullptr) return;
576 binding_data->AddMethods();
577
578 // define various internal methods
579 if (env->owns_process_state()) {
580 SetMethod(context, target, "_debugProcess", DebugProcess);
581 SetMethod(context, target, "abort", Abort);
582 SetMethod(context, target, "causeSegfault", CauseSegfault);
583 SetMethod(context, target, "chdir", Chdir);
584 }
585
586 SetMethod(context, target, "umask", Umask);
587 SetMethod(context, target, "memoryUsage", MemoryUsage);
588 SetMethod(context, target, "constrainedMemory", GetConstrainedMemory);
589 SetMethod(context, target, "rss", Rss);
590 SetMethod(context, target, "cpuUsage", CPUUsage);
591 SetMethod(context, target, "resourceUsage", ResourceUsage);
592
593 SetMethod(context, target, "_debugEnd", DebugEnd);
594 SetMethod(context, target, "_getActiveRequests", GetActiveRequests);
595 SetMethod(context, target, "_getActiveHandles", GetActiveHandles);
596 SetMethod(context, target, "getActiveResourcesInfo", GetActiveResourcesInfo);
597 SetMethod(context, target, "_kill", Kill);
598 SetMethod(context, target, "_rawDebug", RawDebug);
599
600 SetMethodNoSideEffect(context, target, "cwd", Cwd);
601 SetMethod(context, target, "dlopen", binding::DLOpen);
602 SetMethod(context, target, "reallyExit", ReallyExit);
603 SetMethodNoSideEffect(context, target, "uptime", Uptime);
604 SetMethod(context, target, "patchProcessObject", PatchProcessObject);
605 }
606
RegisterExternalReferences(ExternalReferenceRegistry * registry)607 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
608 BindingData::RegisterExternalReferences(registry);
609
610 registry->Register(DebugProcess);
611 registry->Register(DebugEnd);
612 registry->Register(Abort);
613 registry->Register(CauseSegfault);
614 registry->Register(Chdir);
615
616 registry->Register(Umask);
617 registry->Register(RawDebug);
618 registry->Register(MemoryUsage);
619 registry->Register(GetConstrainedMemory);
620 registry->Register(Rss);
621 registry->Register(CPUUsage);
622 registry->Register(ResourceUsage);
623
624 registry->Register(GetActiveRequests);
625 registry->Register(GetActiveHandles);
626 registry->Register(GetActiveResourcesInfo);
627 registry->Register(Kill);
628
629 registry->Register(Cwd);
630 registry->Register(binding::DLOpen);
631 registry->Register(ReallyExit);
632 registry->Register(Uptime);
633 registry->Register(PatchProcessObject);
634 }
635
636 } // namespace process
637 } // namespace node
638
639 NODE_BINDING_CONTEXT_AWARE_INTERNAL(process_methods, node::process::Initialize)
640 NODE_BINDING_EXTERNAL_REFERENCE(process_methods,
641 node::process::RegisterExternalReferences)
642