Coverage Report

Created: 2025-07-04 09:33

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