1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #ifndef SRC_ENV_INL_H_
23 #define SRC_ENV_INL_H_
24
25 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26
27 #include "aliased_buffer.h"
28 #include "callback_queue-inl.h"
29 #include "env.h"
30 #include "node.h"
31 #include "node_context_data.h"
32 #include "node_internals.h"
33 #include "node_perf_common.h"
34 #include "node_realm-inl.h"
35 #include "util-inl.h"
36 #include "uv.h"
37 #include "v8.h"
38
39 #include <cstddef>
40 #include <cstdint>
41
42 #include <utility>
43
44 namespace node {
45
NoArrayBufferZeroFillScope(IsolateData * isolate_data)46 NoArrayBufferZeroFillScope::NoArrayBufferZeroFillScope(
47 IsolateData* isolate_data)
48 : node_allocator_(isolate_data->node_allocator()) {
49 if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 0;
50 }
51
~NoArrayBufferZeroFillScope()52 NoArrayBufferZeroFillScope::~NoArrayBufferZeroFillScope() {
53 if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 1;
54 }
55
isolate()56 inline v8::Isolate* IsolateData::isolate() const {
57 return isolate_;
58 }
59
event_loop()60 inline uv_loop_t* IsolateData::event_loop() const {
61 return event_loop_;
62 }
63
node_allocator()64 inline NodeArrayBufferAllocator* IsolateData::node_allocator() const {
65 return node_allocator_;
66 }
67
platform()68 inline MultiIsolatePlatform* IsolateData::platform() const {
69 return platform_;
70 }
71
set_worker_context(worker::Worker * context)72 inline void IsolateData::set_worker_context(worker::Worker* context) {
73 CHECK_NULL(worker_context_); // Should be set only once.
74 worker_context_ = context;
75 }
76
worker_context()77 inline worker::Worker* IsolateData::worker_context() const {
78 return worker_context_;
79 }
80
async_wrap_provider(int index)81 inline v8::Local<v8::String> IsolateData::async_wrap_provider(int index) const {
82 return async_wrap_providers_[index].Get(isolate_);
83 }
84
fields()85 inline AliasedUint32Array& AsyncHooks::fields() {
86 return fields_;
87 }
88
async_id_fields()89 inline AliasedFloat64Array& AsyncHooks::async_id_fields() {
90 return async_id_fields_;
91 }
92
async_ids_stack()93 inline AliasedFloat64Array& AsyncHooks::async_ids_stack() {
94 return async_ids_stack_;
95 }
96
js_execution_async_resources()97 v8::Local<v8::Array> AsyncHooks::js_execution_async_resources() {
98 if (UNLIKELY(js_execution_async_resources_.IsEmpty())) {
99 js_execution_async_resources_.Reset(
100 env()->isolate(), v8::Array::New(env()->isolate()));
101 }
102 return PersistentToLocal::Strong(js_execution_async_resources_);
103 }
104
native_execution_async_resource(size_t i)105 v8::Local<v8::Object> AsyncHooks::native_execution_async_resource(size_t i) {
106 if (i >= native_execution_async_resources_.size()) return {};
107 return native_execution_async_resources_[i];
108 }
109
provider_string(int idx)110 inline v8::Local<v8::String> AsyncHooks::provider_string(int idx) {
111 return env()->isolate_data()->async_wrap_provider(idx);
112 }
113
no_force_checks()114 inline void AsyncHooks::no_force_checks() {
115 fields_[kCheck] -= 1;
116 }
117
env()118 inline Environment* AsyncHooks::env() {
119 return Environment::ForAsyncHooks(this);
120 }
121
ForAsyncHooks(AsyncHooks * hooks)122 Environment* Environment::ForAsyncHooks(AsyncHooks* hooks) {
123 return ContainerOf(&Environment::async_hooks_, hooks);
124 }
125
async_callback_scope_depth()126 inline size_t Environment::async_callback_scope_depth() const {
127 return async_callback_scope_depth_;
128 }
129
PushAsyncCallbackScope()130 inline void Environment::PushAsyncCallbackScope() {
131 async_callback_scope_depth_++;
132 }
133
PopAsyncCallbackScope()134 inline void Environment::PopAsyncCallbackScope() {
135 async_callback_scope_depth_--;
136 }
137
fields()138 inline AliasedUint32Array& ImmediateInfo::fields() {
139 return fields_;
140 }
141
count()142 inline uint32_t ImmediateInfo::count() const {
143 return fields_[kCount];
144 }
145
ref_count()146 inline uint32_t ImmediateInfo::ref_count() const {
147 return fields_[kRefCount];
148 }
149
has_outstanding()150 inline bool ImmediateInfo::has_outstanding() const {
151 return fields_[kHasOutstanding] == 1;
152 }
153
ref_count_inc(uint32_t increment)154 inline void ImmediateInfo::ref_count_inc(uint32_t increment) {
155 fields_[kRefCount] += increment;
156 }
157
ref_count_dec(uint32_t decrement)158 inline void ImmediateInfo::ref_count_dec(uint32_t decrement) {
159 fields_[kRefCount] -= decrement;
160 }
161
fields()162 inline AliasedUint8Array& TickInfo::fields() {
163 return fields_;
164 }
165
has_tick_scheduled()166 inline bool TickInfo::has_tick_scheduled() const {
167 return fields_[kHasTickScheduled] == 1;
168 }
169
has_rejection_to_warn()170 inline bool TickInfo::has_rejection_to_warn() const {
171 return fields_[kHasRejectionToWarn] == 1;
172 }
173
GetCurrent(v8::Isolate * isolate)174 inline Environment* Environment::GetCurrent(v8::Isolate* isolate) {
175 if (UNLIKELY(!isolate->InContext())) return nullptr;
176 v8::HandleScope handle_scope(isolate);
177 return GetCurrent(isolate->GetCurrentContext());
178 }
179
GetCurrent(v8::Local<v8::Context> context)180 inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
181 if (UNLIKELY(!ContextEmbedderTag::IsNodeContext(context))) {
182 return nullptr;
183 }
184 return static_cast<Environment*>(
185 context->GetAlignedPointerFromEmbedderData(
186 ContextEmbedderIndex::kEnvironment));
187 }
188
GetCurrent(const v8::FunctionCallbackInfo<v8::Value> & info)189 inline Environment* Environment::GetCurrent(
190 const v8::FunctionCallbackInfo<v8::Value>& info) {
191 return GetCurrent(info.GetIsolate()->GetCurrentContext());
192 }
193
194 template <typename T>
GetCurrent(const v8::PropertyCallbackInfo<T> & info)195 inline Environment* Environment::GetCurrent(
196 const v8::PropertyCallbackInfo<T>& info) {
197 return GetCurrent(info.GetIsolate()->GetCurrentContext());
198 }
199
isolate()200 inline v8::Isolate* Environment::isolate() const {
201 return isolate_;
202 }
203
from_timer_handle(uv_timer_t * handle)204 inline Environment* Environment::from_timer_handle(uv_timer_t* handle) {
205 return ContainerOf(&Environment::timer_handle_, handle);
206 }
207
timer_handle()208 inline uv_timer_t* Environment::timer_handle() {
209 return &timer_handle_;
210 }
211
from_immediate_check_handle(uv_check_t * handle)212 inline Environment* Environment::from_immediate_check_handle(
213 uv_check_t* handle) {
214 return ContainerOf(&Environment::immediate_check_handle_, handle);
215 }
216
immediate_check_handle()217 inline uv_check_t* Environment::immediate_check_handle() {
218 return &immediate_check_handle_;
219 }
220
immediate_idle_handle()221 inline uv_idle_t* Environment::immediate_idle_handle() {
222 return &immediate_idle_handle_;
223 }
224
RegisterHandleCleanup(uv_handle_t * handle,HandleCleanupCb cb,void * arg)225 inline void Environment::RegisterHandleCleanup(uv_handle_t* handle,
226 HandleCleanupCb cb,
227 void* arg) {
228 handle_cleanup_queue_.push_back(HandleCleanup{handle, cb, arg});
229 }
230
231 template <typename T, typename OnCloseCallback>
CloseHandle(T * handle,OnCloseCallback callback)232 inline void Environment::CloseHandle(T* handle, OnCloseCallback callback) {
233 handle_cleanup_waiting_++;
234 static_assert(sizeof(T) >= sizeof(uv_handle_t), "T is a libuv handle");
235 static_assert(offsetof(T, data) == offsetof(uv_handle_t, data),
236 "T is a libuv handle");
237 static_assert(offsetof(T, close_cb) == offsetof(uv_handle_t, close_cb),
238 "T is a libuv handle");
239 struct CloseData {
240 Environment* env;
241 OnCloseCallback callback;
242 void* original_data;
243 };
244 handle->data = new CloseData { this, callback, handle->data };
245 uv_close(reinterpret_cast<uv_handle_t*>(handle), [](uv_handle_t* handle) {
246 std::unique_ptr<CloseData> data { static_cast<CloseData*>(handle->data) };
247 data->env->handle_cleanup_waiting_--;
248 handle->data = data->original_data;
249 data->callback(reinterpret_cast<T*>(handle));
250 });
251 }
252
IncreaseWaitingRequestCounter()253 void Environment::IncreaseWaitingRequestCounter() {
254 request_waiting_++;
255 }
256
DecreaseWaitingRequestCounter()257 void Environment::DecreaseWaitingRequestCounter() {
258 request_waiting_--;
259 CHECK_GE(request_waiting_, 0);
260 }
261
event_loop()262 inline uv_loop_t* Environment::event_loop() const {
263 return isolate_data()->event_loop();
264 }
265
266 #if HAVE_INSPECTOR
is_in_inspector_console_call()267 inline bool Environment::is_in_inspector_console_call() const {
268 return is_in_inspector_console_call_;
269 }
270
set_is_in_inspector_console_call(bool value)271 inline void Environment::set_is_in_inspector_console_call(bool value) {
272 is_in_inspector_console_call_ = value;
273 }
274 #endif
275
async_hooks()276 inline AsyncHooks* Environment::async_hooks() {
277 return &async_hooks_;
278 }
279
immediate_info()280 inline ImmediateInfo* Environment::immediate_info() {
281 return &immediate_info_;
282 }
283
timeout_info()284 inline AliasedInt32Array& Environment::timeout_info() {
285 return timeout_info_;
286 }
287
tick_info()288 inline TickInfo* Environment::tick_info() {
289 return &tick_info_;
290 }
291
timer_base()292 inline uint64_t Environment::timer_base() const {
293 return timer_base_;
294 }
295
env_vars()296 inline std::shared_ptr<KVStore> Environment::env_vars() {
297 return env_vars_;
298 }
299
set_env_vars(std::shared_ptr<KVStore> env_vars)300 inline void Environment::set_env_vars(std::shared_ptr<KVStore> env_vars) {
301 env_vars_ = env_vars;
302 }
303
printed_error()304 inline bool Environment::printed_error() const {
305 return printed_error_;
306 }
307
set_printed_error(bool value)308 inline void Environment::set_printed_error(bool value) {
309 printed_error_ = value;
310 }
311
set_trace_sync_io(bool value)312 inline void Environment::set_trace_sync_io(bool value) {
313 trace_sync_io_ = value;
314 }
315
abort_on_uncaught_exception()316 inline bool Environment::abort_on_uncaught_exception() const {
317 return options_->abort_on_uncaught_exception;
318 }
319
set_force_context_aware(bool value)320 inline void Environment::set_force_context_aware(bool value) {
321 options_->force_context_aware = value;
322 }
323
force_context_aware()324 inline bool Environment::force_context_aware() const {
325 return options_->force_context_aware;
326 }
327
set_exiting(bool value)328 inline void Environment::set_exiting(bool value) {
329 exiting_[0] = value ? 1 : 0;
330 }
331
exiting()332 inline AliasedUint32Array& Environment::exiting() {
333 return exiting_;
334 }
335
set_abort_on_uncaught_exception(bool value)336 inline void Environment::set_abort_on_uncaught_exception(bool value) {
337 options_->abort_on_uncaught_exception = value;
338 }
339
should_abort_on_uncaught_toggle()340 inline AliasedUint32Array& Environment::should_abort_on_uncaught_toggle() {
341 return should_abort_on_uncaught_toggle_;
342 }
343
stream_base_state()344 inline AliasedInt32Array& Environment::stream_base_state() {
345 return stream_base_state_;
346 }
347
get_next_module_id()348 inline uint32_t Environment::get_next_module_id() {
349 return module_id_counter_++;
350 }
get_next_script_id()351 inline uint32_t Environment::get_next_script_id() {
352 return script_id_counter_++;
353 }
get_next_function_id()354 inline uint32_t Environment::get_next_function_id() {
355 return function_id_counter_++;
356 }
357
ShouldNotAbortOnUncaughtScope(Environment * env)358 ShouldNotAbortOnUncaughtScope::ShouldNotAbortOnUncaughtScope(
359 Environment* env)
360 : env_(env) {
361 env_->PushShouldNotAbortOnUncaughtScope();
362 }
363
~ShouldNotAbortOnUncaughtScope()364 ShouldNotAbortOnUncaughtScope::~ShouldNotAbortOnUncaughtScope() {
365 Close();
366 }
367
Close()368 void ShouldNotAbortOnUncaughtScope::Close() {
369 if (env_ != nullptr) {
370 env_->PopShouldNotAbortOnUncaughtScope();
371 env_ = nullptr;
372 }
373 }
374
PushShouldNotAbortOnUncaughtScope()375 inline void Environment::PushShouldNotAbortOnUncaughtScope() {
376 should_not_abort_scope_counter_++;
377 }
378
PopShouldNotAbortOnUncaughtScope()379 inline void Environment::PopShouldNotAbortOnUncaughtScope() {
380 should_not_abort_scope_counter_--;
381 }
382
inside_should_not_abort_on_uncaught_scope()383 inline bool Environment::inside_should_not_abort_on_uncaught_scope() const {
384 return should_not_abort_scope_counter_ > 0;
385 }
386
destroy_async_id_list()387 inline std::vector<double>* Environment::destroy_async_id_list() {
388 return &destroy_async_id_list_;
389 }
390
new_async_id()391 inline double Environment::new_async_id() {
392 async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] += 1;
393 return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter];
394 }
395
execution_async_id()396 inline double Environment::execution_async_id() {
397 return async_hooks()->async_id_fields()[AsyncHooks::kExecutionAsyncId];
398 }
399
trigger_async_id()400 inline double Environment::trigger_async_id() {
401 return async_hooks()->async_id_fields()[AsyncHooks::kTriggerAsyncId];
402 }
403
get_default_trigger_async_id()404 inline double Environment::get_default_trigger_async_id() {
405 double default_trigger_async_id =
406 async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId];
407 // If defaultTriggerAsyncId isn't set, use the executionAsyncId
408 if (default_trigger_async_id < 0)
409 default_trigger_async_id = execution_async_id();
410 return default_trigger_async_id;
411 }
412
options()413 inline std::shared_ptr<EnvironmentOptions> Environment::options() {
414 return options_;
415 }
416
argv()417 inline const std::vector<std::string>& Environment::argv() {
418 return argv_;
419 }
420
exec_argv()421 inline const std::vector<std::string>& Environment::exec_argv() {
422 return exec_argv_;
423 }
424
exec_path()425 inline const std::string& Environment::exec_path() const {
426 return exec_path_;
427 }
428
429 #if HAVE_INSPECTOR
set_coverage_directory(const char * dir)430 inline void Environment::set_coverage_directory(const char* dir) {
431 coverage_directory_ = std::string(dir);
432 }
433
set_coverage_connection(std::unique_ptr<profiler::V8CoverageConnection> connection)434 inline void Environment::set_coverage_connection(
435 std::unique_ptr<profiler::V8CoverageConnection> connection) {
436 CHECK_NULL(coverage_connection_);
437 std::swap(coverage_connection_, connection);
438 }
439
coverage_connection()440 inline profiler::V8CoverageConnection* Environment::coverage_connection() {
441 return coverage_connection_.get();
442 }
443
coverage_directory()444 inline const std::string& Environment::coverage_directory() const {
445 return coverage_directory_;
446 }
447
set_cpu_profiler_connection(std::unique_ptr<profiler::V8CpuProfilerConnection> connection)448 inline void Environment::set_cpu_profiler_connection(
449 std::unique_ptr<profiler::V8CpuProfilerConnection> connection) {
450 CHECK_NULL(cpu_profiler_connection_);
451 std::swap(cpu_profiler_connection_, connection);
452 }
453
454 inline profiler::V8CpuProfilerConnection*
cpu_profiler_connection()455 Environment::cpu_profiler_connection() {
456 return cpu_profiler_connection_.get();
457 }
458
set_cpu_prof_interval(uint64_t interval)459 inline void Environment::set_cpu_prof_interval(uint64_t interval) {
460 cpu_prof_interval_ = interval;
461 }
462
cpu_prof_interval()463 inline uint64_t Environment::cpu_prof_interval() const {
464 return cpu_prof_interval_;
465 }
466
set_cpu_prof_name(const std::string & name)467 inline void Environment::set_cpu_prof_name(const std::string& name) {
468 cpu_prof_name_ = name;
469 }
470
cpu_prof_name()471 inline const std::string& Environment::cpu_prof_name() const {
472 return cpu_prof_name_;
473 }
474
set_cpu_prof_dir(const std::string & dir)475 inline void Environment::set_cpu_prof_dir(const std::string& dir) {
476 cpu_prof_dir_ = dir;
477 }
478
cpu_prof_dir()479 inline const std::string& Environment::cpu_prof_dir() const {
480 return cpu_prof_dir_;
481 }
482
set_heap_profiler_connection(std::unique_ptr<profiler::V8HeapProfilerConnection> connection)483 inline void Environment::set_heap_profiler_connection(
484 std::unique_ptr<profiler::V8HeapProfilerConnection> connection) {
485 CHECK_NULL(heap_profiler_connection_);
486 std::swap(heap_profiler_connection_, connection);
487 }
488
489 inline profiler::V8HeapProfilerConnection*
heap_profiler_connection()490 Environment::heap_profiler_connection() {
491 return heap_profiler_connection_.get();
492 }
493
set_heap_prof_name(const std::string & name)494 inline void Environment::set_heap_prof_name(const std::string& name) {
495 heap_prof_name_ = name;
496 }
497
heap_prof_name()498 inline const std::string& Environment::heap_prof_name() const {
499 return heap_prof_name_;
500 }
501
set_heap_prof_dir(const std::string & dir)502 inline void Environment::set_heap_prof_dir(const std::string& dir) {
503 heap_prof_dir_ = dir;
504 }
505
heap_prof_dir()506 inline const std::string& Environment::heap_prof_dir() const {
507 return heap_prof_dir_;
508 }
509
set_heap_prof_interval(uint64_t interval)510 inline void Environment::set_heap_prof_interval(uint64_t interval) {
511 heap_prof_interval_ = interval;
512 }
513
heap_prof_interval()514 inline uint64_t Environment::heap_prof_interval() const {
515 return heap_prof_interval_;
516 }
517
518 #endif // HAVE_INSPECTOR
519
520 inline
inspector_host_port()521 std::shared_ptr<ExclusiveAccess<HostPort>> Environment::inspector_host_port() {
522 return inspector_host_port_;
523 }
524
options()525 inline std::shared_ptr<PerIsolateOptions> IsolateData::options() {
526 return options_;
527 }
528
set_options(std::shared_ptr<PerIsolateOptions> options)529 inline void IsolateData::set_options(
530 std::shared_ptr<PerIsolateOptions> options) {
531 options_ = std::move(options);
532 }
533
534 template <typename Fn>
SetImmediate(Fn && cb,CallbackFlags::Flags flags)535 void Environment::SetImmediate(Fn&& cb, CallbackFlags::Flags flags) {
536 auto callback = native_immediates_.CreateCallback(std::move(cb), flags);
537 native_immediates_.Push(std::move(callback));
538
539 if (flags & CallbackFlags::kRefed) {
540 if (immediate_info()->ref_count() == 0)
541 ToggleImmediateRef(true);
542 immediate_info()->ref_count_inc(1);
543 }
544 }
545
546 template <typename Fn>
SetImmediateThreadsafe(Fn && cb,CallbackFlags::Flags flags)547 void Environment::SetImmediateThreadsafe(Fn&& cb, CallbackFlags::Flags flags) {
548 auto callback = native_immediates_threadsafe_.CreateCallback(
549 std::move(cb), flags);
550 {
551 Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
552 native_immediates_threadsafe_.Push(std::move(callback));
553 if (task_queues_async_initialized_)
554 uv_async_send(&task_queues_async_);
555 }
556 }
557
558 template <typename Fn>
RequestInterrupt(Fn && cb)559 void Environment::RequestInterrupt(Fn&& cb) {
560 auto callback = native_immediates_interrupts_.CreateCallback(
561 std::move(cb), CallbackFlags::kRefed);
562 {
563 Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
564 native_immediates_interrupts_.Push(std::move(callback));
565 if (task_queues_async_initialized_)
566 uv_async_send(&task_queues_async_);
567 }
568 RequestInterruptFromV8();
569 }
570
can_call_into_js()571 inline bool Environment::can_call_into_js() const {
572 return can_call_into_js_ && !is_stopping();
573 }
574
set_can_call_into_js(bool can_call_into_js)575 inline void Environment::set_can_call_into_js(bool can_call_into_js) {
576 can_call_into_js_ = can_call_into_js;
577 }
578
has_run_bootstrapping_code()579 inline bool Environment::has_run_bootstrapping_code() const {
580 return principal_realm_->has_run_bootstrapping_code();
581 }
582
has_serialized_options()583 inline bool Environment::has_serialized_options() const {
584 return has_serialized_options_;
585 }
586
set_has_serialized_options(bool value)587 inline void Environment::set_has_serialized_options(bool value) {
588 has_serialized_options_ = value;
589 }
590
is_main_thread()591 inline bool Environment::is_main_thread() const {
592 return worker_context() == nullptr;
593 }
594
no_native_addons()595 inline bool Environment::no_native_addons() const {
596 return (flags_ & EnvironmentFlags::kNoNativeAddons) ||
597 !options_->allow_native_addons;
598 }
599
should_not_register_esm_loader()600 inline bool Environment::should_not_register_esm_loader() const {
601 return flags_ & EnvironmentFlags::kNoRegisterESMLoader;
602 }
603
owns_process_state()604 inline bool Environment::owns_process_state() const {
605 return flags_ & EnvironmentFlags::kOwnsProcessState;
606 }
607
owns_inspector()608 inline bool Environment::owns_inspector() const {
609 return flags_ & EnvironmentFlags::kOwnsInspector;
610 }
611
should_create_inspector()612 inline bool Environment::should_create_inspector() const {
613 return (flags_ & EnvironmentFlags::kNoCreateInspector) == 0 &&
614 !options_->test_runner && !options_->watch_mode;
615 }
616
tracks_unmanaged_fds()617 inline bool Environment::tracks_unmanaged_fds() const {
618 return flags_ & EnvironmentFlags::kTrackUnmanagedFds;
619 }
620
hide_console_windows()621 inline bool Environment::hide_console_windows() const {
622 return flags_ & EnvironmentFlags::kHideConsoleWindows;
623 }
624
no_global_search_paths()625 inline bool Environment::no_global_search_paths() const {
626 return (flags_ & EnvironmentFlags::kNoGlobalSearchPaths) ||
627 !options_->global_search_paths;
628 }
629
no_browser_globals()630 inline bool Environment::no_browser_globals() const {
631 // configure --no-browser-globals
632 #ifdef NODE_NO_BROWSER_GLOBALS
633 return true;
634 #else
635 return flags_ & EnvironmentFlags::kNoBrowserGlobals;
636 #endif
637 }
638
filehandle_close_warning()639 bool Environment::filehandle_close_warning() const {
640 return emit_filehandle_warning_;
641 }
642
set_filehandle_close_warning(bool on)643 void Environment::set_filehandle_close_warning(bool on) {
644 emit_filehandle_warning_ = on;
645 }
646
set_source_maps_enabled(bool on)647 void Environment::set_source_maps_enabled(bool on) {
648 source_maps_enabled_ = on;
649 }
650
source_maps_enabled()651 bool Environment::source_maps_enabled() const {
652 return source_maps_enabled_;
653 }
654
thread_id()655 inline uint64_t Environment::thread_id() const {
656 return thread_id_;
657 }
658
worker_context()659 inline worker::Worker* Environment::worker_context() const {
660 return isolate_data()->worker_context();
661 }
662
add_sub_worker_context(worker::Worker * context)663 inline void Environment::add_sub_worker_context(worker::Worker* context) {
664 sub_worker_contexts_.insert(context);
665 }
666
remove_sub_worker_context(worker::Worker * context)667 inline void Environment::remove_sub_worker_context(worker::Worker* context) {
668 sub_worker_contexts_.erase(context);
669 }
670
671 template <typename Fn>
ForEachWorker(Fn && iterator)672 inline void Environment::ForEachWorker(Fn&& iterator) {
673 for (worker::Worker* w : sub_worker_contexts_) iterator(w);
674 }
675
is_stopping()676 inline bool Environment::is_stopping() const {
677 return is_stopping_.load();
678 }
679
set_stopping(bool value)680 inline void Environment::set_stopping(bool value) {
681 is_stopping_.store(value);
682 }
683
extra_linked_bindings()684 inline std::list<node_module>* Environment::extra_linked_bindings() {
685 return &extra_linked_bindings_;
686 }
687
extra_linked_bindings_head()688 inline node_module* Environment::extra_linked_bindings_head() {
689 return extra_linked_bindings_.size() > 0 ?
690 &extra_linked_bindings_.front() : nullptr;
691 }
692
extra_linked_bindings_tail()693 inline node_module* Environment::extra_linked_bindings_tail() {
694 return extra_linked_bindings_.size() > 0 ?
695 &extra_linked_bindings_.back() : nullptr;
696 }
697
extra_linked_bindings_mutex()698 inline const Mutex& Environment::extra_linked_bindings_mutex() const {
699 return extra_linked_bindings_mutex_;
700 }
701
performance_state()702 inline performance::PerformanceState* Environment::performance_state() {
703 return performance_state_.get();
704 }
705
isolate_data()706 inline IsolateData* Environment::isolate_data() const {
707 return isolate_data_;
708 }
709
710 template <typename T>
ForEachRealm(T && iterator)711 inline void Environment::ForEachRealm(T&& iterator) const {
712 // TODO(legendecas): iterate over more realms bound to the environment.
713 iterator(principal_realm());
714 }
715
ThrowError(const char * errmsg)716 inline void Environment::ThrowError(const char* errmsg) {
717 ThrowError(v8::Exception::Error, errmsg);
718 }
719
ThrowTypeError(const char * errmsg)720 inline void Environment::ThrowTypeError(const char* errmsg) {
721 ThrowError(v8::Exception::TypeError, errmsg);
722 }
723
ThrowRangeError(const char * errmsg)724 inline void Environment::ThrowRangeError(const char* errmsg) {
725 ThrowError(v8::Exception::RangeError, errmsg);
726 }
727
ThrowError(v8::Local<v8::Value> (* fun)(v8::Local<v8::String>),const char * errmsg)728 inline void Environment::ThrowError(
729 v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
730 const char* errmsg) {
731 v8::HandleScope handle_scope(isolate());
732 isolate()->ThrowException(fun(OneByteString(isolate(), errmsg)));
733 }
734
ThrowErrnoException(int errorno,const char * syscall,const char * message,const char * path)735 inline void Environment::ThrowErrnoException(int errorno,
736 const char* syscall,
737 const char* message,
738 const char* path) {
739 isolate()->ThrowException(
740 ErrnoException(isolate(), errorno, syscall, message, path));
741 }
742
ThrowUVException(int errorno,const char * syscall,const char * message,const char * path,const char * dest)743 inline void Environment::ThrowUVException(int errorno,
744 const char* syscall,
745 const char* message,
746 const char* path,
747 const char* dest) {
748 isolate()->ThrowException(
749 UVException(isolate(), errorno, syscall, message, path, dest));
750 }
751
AddCleanupHook(CleanupQueue::Callback fn,void * arg)752 void Environment::AddCleanupHook(CleanupQueue::Callback fn, void* arg) {
753 cleanup_queue_.Add(fn, arg);
754 }
755
RemoveCleanupHook(CleanupQueue::Callback fn,void * arg)756 void Environment::RemoveCleanupHook(CleanupQueue::Callback fn, void* arg) {
757 cleanup_queue_.Remove(fn, arg);
758 }
759
set_process_exit_handler(std::function<void (Environment *,int)> && handler)760 void Environment::set_process_exit_handler(
761 std::function<void(Environment*, int)>&& handler) {
762 process_exit_handler_ = std::move(handler);
763 }
764
765 #define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
766 #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
767 #define VS(PropertyName, StringValue) V(v8::String, PropertyName)
768 #define V(TypeName, PropertyName) \
769 inline \
770 v8::Local<TypeName> IsolateData::PropertyName() const { \
771 return PropertyName ## _ .Get(isolate_); \
772 }
773 PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
PER_ISOLATE_SYMBOL_PROPERTIES(VY)774 PER_ISOLATE_SYMBOL_PROPERTIES(VY)
775 PER_ISOLATE_STRING_PROPERTIES(VS)
776 #undef V
777 #undef VS
778 #undef VY
779 #undef VP
780
781 #define V(PropertyName, TypeName) \
782 inline v8::Local<TypeName> IsolateData::PropertyName() const { \
783 return PropertyName##_.Get(isolate_); \
784 } \
785 inline void IsolateData::set_##PropertyName(v8::Local<TypeName> value) { \
786 PropertyName##_.Set(isolate_, value); \
787 }
788 PER_ISOLATE_TEMPLATE_PROPERTIES(V)
789 #undef V
790
791 #define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
792 #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
793 #define VS(PropertyName, StringValue) V(v8::String, PropertyName)
794 #define V(TypeName, PropertyName) \
795 inline v8::Local<TypeName> Environment::PropertyName() const { \
796 return isolate_data()->PropertyName(); \
797 }
798 PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
799 PER_ISOLATE_SYMBOL_PROPERTIES(VY)
800 PER_ISOLATE_STRING_PROPERTIES(VS)
801 #undef V
802 #undef VS
803 #undef VY
804 #undef VP
805
806 #define V(PropertyName, TypeName) \
807 inline v8::Local<TypeName> Environment::PropertyName() const { \
808 return isolate_data()->PropertyName(); \
809 } \
810 inline void Environment::set_##PropertyName(v8::Local<TypeName> value) { \
811 DCHECK(isolate_data()->PropertyName().IsEmpty()); \
812 isolate_data()->set_##PropertyName(value); \
813 }
814 PER_ISOLATE_TEMPLATE_PROPERTIES(V)
815 #undef V
816
817 #define V(PropertyName, TypeName) \
818 inline v8::Local<TypeName> Environment::PropertyName() const { \
819 DCHECK_NOT_NULL(principal_realm_); \
820 return principal_realm_->PropertyName(); \
821 } \
822 inline void Environment::set_##PropertyName(v8::Local<TypeName> value) { \
823 DCHECK_NOT_NULL(principal_realm_); \
824 principal_realm_->set_##PropertyName(value); \
825 }
826 PER_REALM_STRONG_PERSISTENT_VALUES(V)
827 #undef V
828
829 v8::Local<v8::Context> Environment::context() const {
830 return principal_realm()->context();
831 }
832
principal_realm()833 Realm* Environment::principal_realm() const {
834 return principal_realm_.get();
835 }
836
set_heap_snapshot_near_heap_limit(uint32_t limit)837 inline void Environment::set_heap_snapshot_near_heap_limit(uint32_t limit) {
838 heap_snapshot_near_heap_limit_ = limit;
839 }
840
is_in_heapsnapshot_heap_limit_callback()841 inline bool Environment::is_in_heapsnapshot_heap_limit_callback() const {
842 return is_in_heapsnapshot_heap_limit_callback_;
843 }
844
AddHeapSnapshotNearHeapLimitCallback()845 inline void Environment::AddHeapSnapshotNearHeapLimitCallback() {
846 DCHECK(!heapsnapshot_near_heap_limit_callback_added_);
847 heapsnapshot_near_heap_limit_callback_added_ = true;
848 isolate_->AddNearHeapLimitCallback(Environment::NearHeapLimitCallback, this);
849 }
850
RemoveHeapSnapshotNearHeapLimitCallback(size_t heap_limit)851 inline void Environment::RemoveHeapSnapshotNearHeapLimitCallback(
852 size_t heap_limit) {
853 DCHECK(heapsnapshot_near_heap_limit_callback_added_);
854 heapsnapshot_near_heap_limit_callback_added_ = false;
855 isolate_->RemoveNearHeapLimitCallback(Environment::NearHeapLimitCallback,
856 heap_limit);
857 }
858
859 } // namespace node
860
861 // These two files depend on each other. Including base_object-inl.h after this
862 // file is the easiest way to avoid issues with that circular dependency.
863 #include "base_object-inl.h"
864
865 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
866
867 #endif // SRC_ENV_INL_H_
868