• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "env-inl.h"
2 #include "node_errors.h"
3 #include "node_external_reference.h"
4 #include "node_internals.h"
5 #include "node_metadata.h"
6 #include "node_options-inl.h"
7 #include "node_process-inl.h"
8 #include "node_realm-inl.h"
9 #include "node_revert.h"
10 #include "util-inl.h"
11 
12 #include <climits>  // PATH_MAX
13 
14 namespace node {
15 using v8::Context;
16 using v8::DEFAULT;
17 using v8::EscapableHandleScope;
18 using v8::Function;
19 using v8::FunctionCallbackInfo;
20 using v8::FunctionTemplate;
21 using v8::Integer;
22 using v8::Isolate;
23 using v8::Local;
24 using v8::MaybeLocal;
25 using v8::Name;
26 using v8::NewStringType;
27 using v8::None;
28 using v8::Object;
29 using v8::PropertyCallbackInfo;
30 using v8::SideEffectType;
31 using v8::String;
32 using v8::Value;
33 
ProcessTitleGetter(Local<Name> property,const PropertyCallbackInfo<Value> & info)34 static void ProcessTitleGetter(Local<Name> property,
35                                const PropertyCallbackInfo<Value>& info) {
36   std::string title = GetProcessTitle("node");
37   info.GetReturnValue().Set(
38       String::NewFromUtf8(info.GetIsolate(), title.data(),
39                           NewStringType::kNormal, title.size())
40       .ToLocalChecked());
41 }
42 
ProcessTitleSetter(Local<Name> property,Local<Value> value,const PropertyCallbackInfo<void> & info)43 static void ProcessTitleSetter(Local<Name> property,
44                                Local<Value> value,
45                                const PropertyCallbackInfo<void>& info) {
46   node::Utf8Value title(info.GetIsolate(), value);
47   TRACE_EVENT_METADATA1(
48       "__metadata", "process_name", "name", TRACE_STR_COPY(*title));
49   uv_set_process_title(*title);
50 }
51 
DebugPortGetter(Local<Name> property,const PropertyCallbackInfo<Value> & info)52 static void DebugPortGetter(Local<Name> property,
53                             const PropertyCallbackInfo<Value>& info) {
54   Environment* env = Environment::GetCurrent(info);
55   ExclusiveAccess<HostPort>::Scoped host_port(env->inspector_host_port());
56   int port = host_port->port();
57   info.GetReturnValue().Set(port);
58 }
59 
DebugPortSetter(Local<Name> property,Local<Value> value,const PropertyCallbackInfo<void> & info)60 static void DebugPortSetter(Local<Name> property,
61                             Local<Value> value,
62                             const PropertyCallbackInfo<void>& info) {
63   Environment* env = Environment::GetCurrent(info);
64   int32_t port = value->Int32Value(env->context()).FromMaybe(0);
65 
66   if ((port != 0 && port < 1024) || port > 65535) {
67     return THROW_ERR_OUT_OF_RANGE(
68       env,
69       "process.debugPort must be 0 or in range 1024 to 65535");
70   }
71 
72   ExclusiveAccess<HostPort>::Scoped host_port(env->inspector_host_port());
73   host_port->set_port(static_cast<int>(port));
74 }
75 
GetParentProcessId(Local<Name> property,const PropertyCallbackInfo<Value> & info)76 static void GetParentProcessId(Local<Name> property,
77                                const PropertyCallbackInfo<Value>& info) {
78   info.GetReturnValue().Set(uv_os_getppid());
79 }
80 
CreateProcessObject(Realm * realm)81 MaybeLocal<Object> CreateProcessObject(Realm* realm) {
82   Isolate* isolate = realm->isolate();
83   EscapableHandleScope scope(isolate);
84   Local<Context> context = realm->context();
85 
86   Local<FunctionTemplate> process_template = FunctionTemplate::New(isolate);
87   process_template->SetClassName(realm->env()->process_string());
88   Local<Function> process_ctor;
89   Local<Object> process;
90   if (!process_template->GetFunction(context).ToLocal(&process_ctor) ||
91       !process_ctor->NewInstance(context).ToLocal(&process)) {
92     return MaybeLocal<Object>();
93   }
94 
95   // process[exiting_aliased_Uint32Array]
96   if (process
97           ->SetPrivate(context,
98                        realm->env()->exiting_aliased_Uint32Array(),
99                        realm->env()->exiting().GetJSArray())
100           .IsNothing()) {
101     return {};
102   }
103 
104   // process.version
105   READONLY_PROPERTY(
106       process, "version", FIXED_ONE_BYTE_STRING(isolate, NODE_VERSION));
107 
108   Local<Object> versions = Object::New(isolate);
109   // Node.js version is always on the top
110   READONLY_STRING_PROPERTY(
111       versions, "node", per_process::metadata.versions.node);
112 
113 #define V(key) +1
114   std::pair<std::string_view, std::string_view>
115       versions_array[NODE_VERSIONS_KEYS(V)];
116 #undef V
117   auto* slot = &versions_array[0];
118 
119 #define V(key)                                                                 \
120   do {                                                                         \
121     *slot++ = std::pair<std::string_view, std::string_view>(                   \
122         #key, per_process::metadata.versions.key);                             \
123   } while (0);
124   NODE_VERSIONS_KEYS(V)
125 #undef V
126 
127   std::sort(&versions_array[0],
128             &versions_array[arraysize(versions_array)],
129             [](auto& a, auto& b) { return a.first < b.first; });
130 
131   for (const auto& version : versions_array) {
132     versions
133         ->DefineOwnProperty(
134             context,
135             OneByteString(isolate, version.first.data(), version.first.size()),
136             OneByteString(
137                 isolate, version.second.data(), version.second.size()),
138             v8::ReadOnly)
139         .Check();
140   }
141 
142   // process.versions
143   READONLY_PROPERTY(process, "versions", versions);
144 
145   // process.arch
146   READONLY_STRING_PROPERTY(process, "arch", per_process::metadata.arch);
147 
148   // process.platform
149   READONLY_STRING_PROPERTY(process, "platform", per_process::metadata.platform);
150 
151   // process.release
152   Local<Object> release = Object::New(isolate);
153   READONLY_PROPERTY(process, "release", release);
154   READONLY_STRING_PROPERTY(release, "name", per_process::metadata.release.name);
155 #if NODE_VERSION_IS_LTS
156   READONLY_STRING_PROPERTY(release, "lts", per_process::metadata.release.lts);
157 #endif  // NODE_VERSION_IS_LTS
158 
159 #ifdef NODE_HAS_RELEASE_URLS
160   READONLY_STRING_PROPERTY(
161       release, "sourceUrl", per_process::metadata.release.source_url);
162   READONLY_STRING_PROPERTY(
163       release, "headersUrl", per_process::metadata.release.headers_url);
164 #ifdef _WIN32
165   READONLY_STRING_PROPERTY(
166       release, "libUrl", per_process::metadata.release.lib_url);
167 #endif  // _WIN32
168 #endif  // NODE_HAS_RELEASE_URLS
169 
170   // process._rawDebug: may be overwritten later in JS land, but should be
171   // available from the beginning for debugging purposes
172   SetMethod(context, process, "_rawDebug", RawDebug);
173 
174   return scope.Escape(process);
175 }
176 
PatchProcessObject(const FunctionCallbackInfo<Value> & args)177 void PatchProcessObject(const FunctionCallbackInfo<Value>& args) {
178   Isolate* isolate = args.GetIsolate();
179   Local<Context> context = isolate->GetCurrentContext();
180   Environment* env = Environment::GetCurrent(context);
181   CHECK(args[0]->IsObject());
182   Local<Object> process = args[0].As<Object>();
183 
184   // process.title
185   CHECK(process
186             ->SetAccessor(
187                 context,
188                 FIXED_ONE_BYTE_STRING(isolate, "title"),
189                 ProcessTitleGetter,
190                 env->owns_process_state() ? ProcessTitleSetter : nullptr,
191                 Local<Value>(),
192                 DEFAULT,
193                 None,
194                 SideEffectType::kHasNoSideEffect)
195             .FromJust());
196 
197   // process.argv
198   process->Set(context,
199                FIXED_ONE_BYTE_STRING(isolate, "argv"),
200                ToV8Value(context, env->argv()).ToLocalChecked()).Check();
201 
202   // process.execArgv
203   process->Set(context,
204                FIXED_ONE_BYTE_STRING(isolate, "execArgv"),
205                ToV8Value(context, env->exec_argv())
206                    .ToLocalChecked()).Check();
207 
208   READONLY_PROPERTY(process, "pid",
209                     Integer::New(isolate, uv_os_getpid()));
210 
211   CHECK(process->SetAccessor(context,
212                              FIXED_ONE_BYTE_STRING(isolate, "ppid"),
213                              GetParentProcessId).FromJust());
214 
215   // --security-revert flags
216 #define V(code, _, __)                                                        \
217   do {                                                                        \
218     if (IsReverted(SECURITY_REVERT_ ## code)) {                               \
219       READONLY_PROPERTY(process, "REVERT_" #code, True(isolate));             \
220     }                                                                         \
221   } while (0);
222   SECURITY_REVERSIONS(V)
223 #undef V
224 
225   // process.execPath
226   process
227       ->Set(context,
228             FIXED_ONE_BYTE_STRING(isolate, "execPath"),
229             String::NewFromUtf8(isolate,
230                                 env->exec_path().c_str(),
231                                 NewStringType::kInternalized,
232                                 env->exec_path().size())
233                 .ToLocalChecked())
234       .Check();
235 
236   // process.debugPort
237   CHECK(process
238             ->SetAccessor(context,
239                           FIXED_ONE_BYTE_STRING(isolate, "debugPort"),
240                           DebugPortGetter,
241                           env->owns_process_state() ? DebugPortSetter : nullptr,
242                           Local<Value>())
243             .FromJust());
244 }
245 
RegisterProcessExternalReferences(ExternalReferenceRegistry * registry)246 void RegisterProcessExternalReferences(ExternalReferenceRegistry* registry) {
247   registry->Register(RawDebug);
248   registry->Register(GetParentProcessId);
249   registry->Register(DebugPortSetter);
250   registry->Register(DebugPortGetter);
251   registry->Register(ProcessTitleSetter);
252   registry->Register(ProcessTitleGetter);
253 }
254 
255 }  // namespace node
256 
257 NODE_BINDING_EXTERNAL_REFERENCE(process_object,
258                                 node::RegisterProcessExternalReferences)
259