• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "util-inl.h"
32 #include "uv.h"
33 #include "v8.h"
34 #include "node_perf_common.h"
35 #include "node_context_data.h"
36 
37 #include <cstddef>
38 #include <cstdint>
39 
40 #include <utility>
41 
42 namespace node {
43 
isolate()44 inline v8::Isolate* IsolateData::isolate() const {
45   return isolate_;
46 }
47 
event_loop()48 inline uv_loop_t* IsolateData::event_loop() const {
49   return event_loop_;
50 }
51 
uses_node_allocator()52 inline bool IsolateData::uses_node_allocator() const {
53   return uses_node_allocator_;
54 }
55 
allocator()56 inline v8::ArrayBuffer::Allocator* IsolateData::allocator() const {
57   return allocator_;
58 }
59 
node_allocator()60 inline NodeArrayBufferAllocator* IsolateData::node_allocator() const {
61   return node_allocator_;
62 }
63 
platform()64 inline MultiIsolatePlatform* IsolateData::platform() const {
65   return platform_;
66 }
67 
async_wrap_provider(int index)68 inline v8::Local<v8::String> IsolateData::async_wrap_provider(int index) const {
69   return async_wrap_providers_[index].Get(isolate_);
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 
AsyncHooks()81 inline AsyncHooks::AsyncHooks()
82     : async_ids_stack_(env()->isolate(), 16 * 2),
83       fields_(env()->isolate(), kFieldsCount),
84       async_id_fields_(env()->isolate(), kUidFieldsCount) {
85   clear_async_id_stack();
86 
87   // Always perform async_hooks checks, not just when async_hooks is enabled.
88   // TODO(AndreasMadsen): Consider removing this for LTS releases.
89   // See discussion in https://github.com/nodejs/node/pull/15454
90   // When removing this, do it by reverting the commit. Otherwise the test
91   // and flag changes won't be included.
92   fields_[kCheck] = 1;
93 
94   // kDefaultTriggerAsyncId should be -1, this indicates that there is no
95   // specified default value and it should fallback to the executionAsyncId.
96   // 0 is not used as the magic value, because that indicates a missing context
97   // which is different from a default context.
98   async_id_fields_[AsyncHooks::kDefaultTriggerAsyncId] = -1;
99 
100   // kAsyncIdCounter should start at 1 because that'll be the id the execution
101   // context during bootstrap (code that runs before entering uv_run()).
102   async_id_fields_[AsyncHooks::kAsyncIdCounter] = 1;
103 }
fields()104 inline AliasedUint32Array& AsyncHooks::fields() {
105   return fields_;
106 }
107 
async_id_fields()108 inline AliasedFloat64Array& AsyncHooks::async_id_fields() {
109   return async_id_fields_;
110 }
111 
async_ids_stack()112 inline AliasedFloat64Array& AsyncHooks::async_ids_stack() {
113   return async_ids_stack_;
114 }
115 
js_execution_async_resources()116 v8::Local<v8::Array> AsyncHooks::js_execution_async_resources() {
117   if (UNLIKELY(js_execution_async_resources_.IsEmpty())) {
118     js_execution_async_resources_.Reset(
119         env()->isolate(), v8::Array::New(env()->isolate()));
120   }
121   return PersistentToLocal::Strong(js_execution_async_resources_);
122 }
123 
native_execution_async_resource(size_t i)124 v8::Local<v8::Object> AsyncHooks::native_execution_async_resource(size_t i) {
125   if (i >= native_execution_async_resources_.size()) return {};
126   return PersistentToLocal::Strong(native_execution_async_resources_[i]);
127 }
128 
provider_string(int idx)129 inline v8::Local<v8::String> AsyncHooks::provider_string(int idx) {
130   return env()->isolate_data()->async_wrap_provider(idx);
131 }
132 
no_force_checks()133 inline void AsyncHooks::no_force_checks() {
134   fields_[kCheck] -= 1;
135 }
136 
env()137 inline Environment* AsyncHooks::env() {
138   return Environment::ForAsyncHooks(this);
139 }
140 
141 // Remember to keep this code aligned with pushAsyncContext() in JS.
push_async_context(double async_id,double trigger_async_id,v8::Local<v8::Object> resource)142 inline void AsyncHooks::push_async_context(double async_id,
143                                            double trigger_async_id,
144                                            v8::Local<v8::Object> resource) {
145   // Since async_hooks is experimental, do only perform the check
146   // when async_hooks is enabled.
147   if (fields_[kCheck] > 0) {
148     CHECK_GE(async_id, -1);
149     CHECK_GE(trigger_async_id, -1);
150   }
151 
152   uint32_t offset = fields_[kStackLength];
153   if (offset * 2 >= async_ids_stack_.Length())
154     grow_async_ids_stack();
155   async_ids_stack_[2 * offset] = async_id_fields_[kExecutionAsyncId];
156   async_ids_stack_[2 * offset + 1] = async_id_fields_[kTriggerAsyncId];
157   fields_[kStackLength] += 1;
158   async_id_fields_[kExecutionAsyncId] = async_id;
159   async_id_fields_[kTriggerAsyncId] = trigger_async_id;
160 
161 #ifdef DEBUG
162   for (uint32_t i = offset; i < native_execution_async_resources_.size(); i++)
163     CHECK(native_execution_async_resources_[i].IsEmpty());
164 #endif
165 
166   // When this call comes from JS (as a way of increasing the stack size),
167   // `resource` will be empty, because JS caches these values anyway, and
168   // we should avoid creating strong global references that might keep
169   // these JS resource objects alive longer than necessary.
170   if (!resource.IsEmpty()) {
171     native_execution_async_resources_.resize(offset + 1);
172     native_execution_async_resources_[offset].Reset(env()->isolate(), resource);
173   }
174 }
175 
176 // Remember to keep this code aligned with popAsyncContext() in JS.
pop_async_context(double async_id)177 inline bool AsyncHooks::pop_async_context(double async_id) {
178   // In case of an exception then this may have already been reset, if the
179   // stack was multiple MakeCallback()'s deep.
180   if (fields_[kStackLength] == 0) return false;
181 
182   // Ask for the async_id to be restored as a check that the stack
183   // hasn't been corrupted.
184   // Since async_hooks is experimental, do only perform the check
185   // when async_hooks is enabled.
186   if (fields_[kCheck] > 0 && async_id_fields_[kExecutionAsyncId] != async_id) {
187     fprintf(stderr,
188             "Error: async hook stack has become corrupted ("
189             "actual: %.f, expected: %.f)\n",
190             async_id_fields_.GetValue(kExecutionAsyncId),
191             async_id);
192     DumpBacktrace(stderr);
193     fflush(stderr);
194     if (!env()->abort_on_uncaught_exception())
195       exit(1);
196     fprintf(stderr, "\n");
197     fflush(stderr);
198     ABORT_NO_BACKTRACE();
199   }
200 
201   uint32_t offset = fields_[kStackLength] - 1;
202   async_id_fields_[kExecutionAsyncId] = async_ids_stack_[2 * offset];
203   async_id_fields_[kTriggerAsyncId] = async_ids_stack_[2 * offset + 1];
204   fields_[kStackLength] = offset;
205 
206   if (LIKELY(offset < native_execution_async_resources_.size() &&
207              !native_execution_async_resources_[offset].IsEmpty())) {
208 #ifdef DEBUG
209     for (uint32_t i = offset + 1;
210          i < native_execution_async_resources_.size();
211          i++) {
212       CHECK(native_execution_async_resources_[i].IsEmpty());
213     }
214 #endif
215     native_execution_async_resources_.resize(offset);
216     if (native_execution_async_resources_.size() <
217             native_execution_async_resources_.capacity() / 2 &&
218         native_execution_async_resources_.size() > 16) {
219       native_execution_async_resources_.shrink_to_fit();
220     }
221   }
222 
223   if (UNLIKELY(js_execution_async_resources()->Length() > offset)) {
224     v8::HandleScope handle_scope(env()->isolate());
225     USE(js_execution_async_resources()->Set(
226         env()->context(),
227         env()->length_string(),
228         v8::Integer::NewFromUnsigned(env()->isolate(), offset)));
229   }
230 
231   return fields_[kStackLength] > 0;
232 }
233 
clear_async_id_stack()234 void AsyncHooks::clear_async_id_stack() {
235   v8::Isolate* isolate = env()->isolate();
236   v8::HandleScope handle_scope(isolate);
237   if (!js_execution_async_resources_.IsEmpty()) {
238     USE(PersistentToLocal::Strong(js_execution_async_resources_)->Set(
239         env()->context(),
240         env()->length_string(),
241         v8::Integer::NewFromUnsigned(isolate, 0)));
242   }
243   native_execution_async_resources_.clear();
244   native_execution_async_resources_.shrink_to_fit();
245 
246   async_id_fields_[kExecutionAsyncId] = 0;
247   async_id_fields_[kTriggerAsyncId] = 0;
248   fields_[kStackLength] = 0;
249 }
250 
251 // The DefaultTriggerAsyncIdScope(AsyncWrap*) constructor is defined in
252 // async_wrap-inl.h to avoid a circular dependency.
253 
DefaultTriggerAsyncIdScope(Environment * env,double default_trigger_async_id)254 inline AsyncHooks::DefaultTriggerAsyncIdScope ::DefaultTriggerAsyncIdScope(
255     Environment* env, double default_trigger_async_id)
256     : async_hooks_(env->async_hooks()) {
257   if (env->async_hooks()->fields()[AsyncHooks::kCheck] > 0) {
258     CHECK_GE(default_trigger_async_id, 0);
259   }
260 
261   old_default_trigger_async_id_ =
262     async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId];
263   async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] =
264     default_trigger_async_id;
265 }
266 
~DefaultTriggerAsyncIdScope()267 inline AsyncHooks::DefaultTriggerAsyncIdScope ::~DefaultTriggerAsyncIdScope() {
268   async_hooks_->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] =
269     old_default_trigger_async_id_;
270 }
271 
ForAsyncHooks(AsyncHooks * hooks)272 Environment* Environment::ForAsyncHooks(AsyncHooks* hooks) {
273   return ContainerOf(&Environment::async_hooks_, hooks);
274 }
275 
async_callback_scope_depth()276 inline size_t Environment::async_callback_scope_depth() const {
277   return async_callback_scope_depth_;
278 }
279 
PushAsyncCallbackScope()280 inline void Environment::PushAsyncCallbackScope() {
281   async_callback_scope_depth_++;
282 }
283 
PopAsyncCallbackScope()284 inline void Environment::PopAsyncCallbackScope() {
285   async_callback_scope_depth_--;
286 }
287 
ImmediateInfo(v8::Isolate * isolate)288 inline ImmediateInfo::ImmediateInfo(v8::Isolate* isolate)
289     : fields_(isolate, kFieldsCount) {}
290 
fields()291 inline AliasedUint32Array& ImmediateInfo::fields() {
292   return fields_;
293 }
294 
count()295 inline uint32_t ImmediateInfo::count() const {
296   return fields_[kCount];
297 }
298 
ref_count()299 inline uint32_t ImmediateInfo::ref_count() const {
300   return fields_[kRefCount];
301 }
302 
has_outstanding()303 inline bool ImmediateInfo::has_outstanding() const {
304   return fields_[kHasOutstanding] == 1;
305 }
306 
ref_count_inc(uint32_t increment)307 inline void ImmediateInfo::ref_count_inc(uint32_t increment) {
308   fields_[kRefCount] += increment;
309 }
310 
ref_count_dec(uint32_t decrement)311 inline void ImmediateInfo::ref_count_dec(uint32_t decrement) {
312   fields_[kRefCount] -= decrement;
313 }
314 
TickInfo(v8::Isolate * isolate)315 inline TickInfo::TickInfo(v8::Isolate* isolate)
316     : fields_(isolate, kFieldsCount) {}
317 
fields()318 inline AliasedUint8Array& TickInfo::fields() {
319   return fields_;
320 }
321 
has_tick_scheduled()322 inline bool TickInfo::has_tick_scheduled() const {
323   return fields_[kHasTickScheduled] == 1;
324 }
325 
has_rejection_to_warn()326 inline bool TickInfo::has_rejection_to_warn() const {
327   return fields_[kHasRejectionToWarn] == 1;
328 }
329 
AssignToContext(v8::Local<v8::Context> context,const ContextInfo & info)330 inline void Environment::AssignToContext(v8::Local<v8::Context> context,
331                                          const ContextInfo& info) {
332   context->SetAlignedPointerInEmbedderData(
333       ContextEmbedderIndex::kEnvironment, this);
334   // Used by Environment::GetCurrent to know that we are on a node context.
335   context->SetAlignedPointerInEmbedderData(
336     ContextEmbedderIndex::kContextTag, Environment::kNodeContextTagPtr);
337 #if HAVE_INSPECTOR
338   inspector_agent()->ContextCreated(context, info);
339 #endif  // HAVE_INSPECTOR
340 }
341 
GetCurrent(v8::Isolate * isolate)342 inline Environment* Environment::GetCurrent(v8::Isolate* isolate) {
343   if (UNLIKELY(!isolate->InContext())) return nullptr;
344   v8::HandleScope handle_scope(isolate);
345   return GetCurrent(isolate->GetCurrentContext());
346 }
347 
GetCurrent(v8::Local<v8::Context> context)348 inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
349   if (UNLIKELY(context.IsEmpty())) {
350     return nullptr;
351   }
352   if (UNLIKELY(context->GetNumberOfEmbedderDataFields() <=
353                ContextEmbedderIndex::kContextTag)) {
354     return nullptr;
355   }
356   if (UNLIKELY(context->GetAlignedPointerFromEmbedderData(
357                    ContextEmbedderIndex::kContextTag) !=
358                Environment::kNodeContextTagPtr)) {
359     return nullptr;
360   }
361   return static_cast<Environment*>(
362       context->GetAlignedPointerFromEmbedderData(
363           ContextEmbedderIndex::kEnvironment));
364 }
365 
GetCurrent(const v8::FunctionCallbackInfo<v8::Value> & info)366 inline Environment* Environment::GetCurrent(
367     const v8::FunctionCallbackInfo<v8::Value>& info) {
368   return GetFromCallbackData(info.Data());
369 }
370 
371 template <typename T>
GetCurrent(const v8::PropertyCallbackInfo<T> & info)372 inline Environment* Environment::GetCurrent(
373     const v8::PropertyCallbackInfo<T>& info) {
374   return GetFromCallbackData(info.Data());
375 }
376 
GetFromCallbackData(v8::Local<v8::Value> val)377 inline Environment* Environment::GetFromCallbackData(v8::Local<v8::Value> val) {
378   DCHECK(val->IsObject());
379   v8::Local<v8::Object> obj = val.As<v8::Object>();
380   DCHECK_GE(obj->InternalFieldCount(), 1);
381   Environment* env =
382       static_cast<Environment*>(obj->GetAlignedPointerFromInternalField(0));
383   DCHECK(env->as_callback_data_template()->HasInstance(obj));
384   return env;
385 }
386 
GetThreadLocalEnv()387 inline Environment* Environment::GetThreadLocalEnv() {
388   return static_cast<Environment*>(uv_key_get(&thread_local_env));
389 }
390 
profiler_idle_notifier_started()391 inline bool Environment::profiler_idle_notifier_started() const {
392   return profiler_idle_notifier_started_;
393 }
394 
isolate()395 inline v8::Isolate* Environment::isolate() const {
396   return isolate_;
397 }
398 
from_timer_handle(uv_timer_t * handle)399 inline Environment* Environment::from_timer_handle(uv_timer_t* handle) {
400   return ContainerOf(&Environment::timer_handle_, handle);
401 }
402 
timer_handle()403 inline uv_timer_t* Environment::timer_handle() {
404   return &timer_handle_;
405 }
406 
from_immediate_check_handle(uv_check_t * handle)407 inline Environment* Environment::from_immediate_check_handle(
408     uv_check_t* handle) {
409   return ContainerOf(&Environment::immediate_check_handle_, handle);
410 }
411 
immediate_check_handle()412 inline uv_check_t* Environment::immediate_check_handle() {
413   return &immediate_check_handle_;
414 }
415 
immediate_idle_handle()416 inline uv_idle_t* Environment::immediate_idle_handle() {
417   return &immediate_idle_handle_;
418 }
419 
RegisterHandleCleanup(uv_handle_t * handle,HandleCleanupCb cb,void * arg)420 inline void Environment::RegisterHandleCleanup(uv_handle_t* handle,
421                                                HandleCleanupCb cb,
422                                                void* arg) {
423   handle_cleanup_queue_.push_back(HandleCleanup{handle, cb, arg});
424 }
425 
426 template <typename T, typename OnCloseCallback>
CloseHandle(T * handle,OnCloseCallback callback)427 inline void Environment::CloseHandle(T* handle, OnCloseCallback callback) {
428   handle_cleanup_waiting_++;
429   static_assert(sizeof(T) >= sizeof(uv_handle_t), "T is a libuv handle");
430   static_assert(offsetof(T, data) == offsetof(uv_handle_t, data),
431                 "T is a libuv handle");
432   static_assert(offsetof(T, close_cb) == offsetof(uv_handle_t, close_cb),
433                 "T is a libuv handle");
434   struct CloseData {
435     Environment* env;
436     OnCloseCallback callback;
437     void* original_data;
438   };
439   handle->data = new CloseData { this, callback, handle->data };
440   uv_close(reinterpret_cast<uv_handle_t*>(handle), [](uv_handle_t* handle) {
441     std::unique_ptr<CloseData> data { static_cast<CloseData*>(handle->data) };
442     data->env->handle_cleanup_waiting_--;
443     handle->data = data->original_data;
444     data->callback(reinterpret_cast<T*>(handle));
445   });
446 }
447 
IncreaseWaitingRequestCounter()448 void Environment::IncreaseWaitingRequestCounter() {
449   request_waiting_++;
450 }
451 
DecreaseWaitingRequestCounter()452 void Environment::DecreaseWaitingRequestCounter() {
453   request_waiting_--;
454   CHECK_GE(request_waiting_, 0);
455 }
456 
event_loop()457 inline uv_loop_t* Environment::event_loop() const {
458   return isolate_data()->event_loop();
459 }
460 
TryLoadAddon(const char * filename,int flags,const std::function<bool (binding::DLib *)> & was_loaded)461 inline void Environment::TryLoadAddon(
462     const char* filename,
463     int flags,
464     const std::function<bool(binding::DLib*)>& was_loaded) {
465   loaded_addons_.emplace_back(filename, flags);
466   if (!was_loaded(&loaded_addons_.back())) {
467     loaded_addons_.pop_back();
468   }
469 }
470 
471 #if HAVE_INSPECTOR
is_in_inspector_console_call()472 inline bool Environment::is_in_inspector_console_call() const {
473   return is_in_inspector_console_call_;
474 }
475 
set_is_in_inspector_console_call(bool value)476 inline void Environment::set_is_in_inspector_console_call(bool value) {
477   is_in_inspector_console_call_ = value;
478 }
479 #endif
480 
async_hooks()481 inline AsyncHooks* Environment::async_hooks() {
482   return &async_hooks_;
483 }
484 
immediate_info()485 inline ImmediateInfo* Environment::immediate_info() {
486   return &immediate_info_;
487 }
488 
tick_info()489 inline TickInfo* Environment::tick_info() {
490   return &tick_info_;
491 }
492 
timer_base()493 inline uint64_t Environment::timer_base() const {
494   return timer_base_;
495 }
496 
env_vars()497 inline std::shared_ptr<KVStore> Environment::env_vars() {
498   return env_vars_;
499 }
500 
set_env_vars(std::shared_ptr<KVStore> env_vars)501 inline void Environment::set_env_vars(std::shared_ptr<KVStore> env_vars) {
502   env_vars_ = env_vars;
503 }
504 
printed_error()505 inline bool Environment::printed_error() const {
506   return printed_error_;
507 }
508 
set_printed_error(bool value)509 inline void Environment::set_printed_error(bool value) {
510   printed_error_ = value;
511 }
512 
set_trace_sync_io(bool value)513 inline void Environment::set_trace_sync_io(bool value) {
514   trace_sync_io_ = value;
515 }
516 
abort_on_uncaught_exception()517 inline bool Environment::abort_on_uncaught_exception() const {
518   return options_->abort_on_uncaught_exception;
519 }
520 
set_force_context_aware(bool value)521 inline void Environment::set_force_context_aware(bool value) {
522   options_->force_context_aware = value;
523 }
524 
force_context_aware()525 inline bool Environment::force_context_aware() const {
526   return options_->force_context_aware;
527 }
528 
set_abort_on_uncaught_exception(bool value)529 inline void Environment::set_abort_on_uncaught_exception(bool value) {
530   options_->abort_on_uncaught_exception = value;
531 }
532 
should_abort_on_uncaught_toggle()533 inline AliasedUint32Array& Environment::should_abort_on_uncaught_toggle() {
534   return should_abort_on_uncaught_toggle_;
535 }
536 
stream_base_state()537 inline AliasedInt32Array& Environment::stream_base_state() {
538   return stream_base_state_;
539 }
540 
get_next_module_id()541 inline uint32_t Environment::get_next_module_id() {
542   return module_id_counter_++;
543 }
get_next_script_id()544 inline uint32_t Environment::get_next_script_id() {
545   return script_id_counter_++;
546 }
get_next_function_id()547 inline uint32_t Environment::get_next_function_id() {
548   return function_id_counter_++;
549 }
550 
ShouldNotAbortOnUncaughtScope(Environment * env)551 ShouldNotAbortOnUncaughtScope::ShouldNotAbortOnUncaughtScope(
552     Environment* env)
553     : env_(env) {
554   env_->PushShouldNotAbortOnUncaughtScope();
555 }
556 
~ShouldNotAbortOnUncaughtScope()557 ShouldNotAbortOnUncaughtScope::~ShouldNotAbortOnUncaughtScope() {
558   Close();
559 }
560 
Close()561 void ShouldNotAbortOnUncaughtScope::Close() {
562   if (env_ != nullptr) {
563     env_->PopShouldNotAbortOnUncaughtScope();
564     env_ = nullptr;
565   }
566 }
567 
PushShouldNotAbortOnUncaughtScope()568 inline void Environment::PushShouldNotAbortOnUncaughtScope() {
569   should_not_abort_scope_counter_++;
570 }
571 
PopShouldNotAbortOnUncaughtScope()572 inline void Environment::PopShouldNotAbortOnUncaughtScope() {
573   should_not_abort_scope_counter_--;
574 }
575 
inside_should_not_abort_on_uncaught_scope()576 inline bool Environment::inside_should_not_abort_on_uncaught_scope() const {
577   return should_not_abort_scope_counter_ > 0;
578 }
579 
destroy_async_id_list()580 inline std::vector<double>* Environment::destroy_async_id_list() {
581   return &destroy_async_id_list_;
582 }
583 
new_async_id()584 inline double Environment::new_async_id() {
585   async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] += 1;
586   return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter];
587 }
588 
execution_async_id()589 inline double Environment::execution_async_id() {
590   return async_hooks()->async_id_fields()[AsyncHooks::kExecutionAsyncId];
591 }
592 
trigger_async_id()593 inline double Environment::trigger_async_id() {
594   return async_hooks()->async_id_fields()[AsyncHooks::kTriggerAsyncId];
595 }
596 
get_default_trigger_async_id()597 inline double Environment::get_default_trigger_async_id() {
598   double default_trigger_async_id =
599     async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId];
600   // If defaultTriggerAsyncId isn't set, use the executionAsyncId
601   if (default_trigger_async_id < 0)
602     default_trigger_async_id = execution_async_id();
603   return default_trigger_async_id;
604 }
605 
heap_statistics_buffer()606 inline double* Environment::heap_statistics_buffer() const {
607   CHECK_NOT_NULL(heap_statistics_buffer_);
608   return heap_statistics_buffer_;
609 }
610 
set_heap_statistics_buffer(double * pointer)611 inline void Environment::set_heap_statistics_buffer(double* pointer) {
612   CHECK_NULL(heap_statistics_buffer_);  // Should be set only once.
613   heap_statistics_buffer_ = pointer;
614 }
615 
heap_space_statistics_buffer()616 inline double* Environment::heap_space_statistics_buffer() const {
617   CHECK_NOT_NULL(heap_space_statistics_buffer_);
618   return heap_space_statistics_buffer_;
619 }
620 
set_heap_space_statistics_buffer(double * pointer)621 inline void Environment::set_heap_space_statistics_buffer(double* pointer) {
622   CHECK_NULL(heap_space_statistics_buffer_);  // Should be set only once.
623   heap_space_statistics_buffer_ = pointer;
624 }
625 
heap_code_statistics_buffer()626 inline double* Environment::heap_code_statistics_buffer() const {
627   CHECK_NOT_NULL(heap_code_statistics_buffer_);
628   return heap_code_statistics_buffer_;
629 }
630 
set_heap_code_statistics_buffer(double * pointer)631 inline void Environment::set_heap_code_statistics_buffer(double* pointer) {
632   CHECK_NULL(heap_code_statistics_buffer_);  // Should be set only once.
633   heap_code_statistics_buffer_ = pointer;
634 }
635 
http_parser_buffer()636 inline char* Environment::http_parser_buffer() const {
637   return http_parser_buffer_;
638 }
639 
set_http_parser_buffer(char * buffer)640 inline void Environment::set_http_parser_buffer(char* buffer) {
641   CHECK_NULL(http_parser_buffer_);  // Should be set only once.
642   http_parser_buffer_ = buffer;
643 }
644 
http_parser_buffer_in_use()645 inline bool Environment::http_parser_buffer_in_use() const {
646   return http_parser_buffer_in_use_;
647 }
648 
set_http_parser_buffer_in_use(bool in_use)649 inline void Environment::set_http_parser_buffer_in_use(bool in_use) {
650   http_parser_buffer_in_use_ = in_use;
651 }
652 
http2_state()653 inline http2::Http2State* Environment::http2_state() const {
654   return http2_state_.get();
655 }
656 
set_http2_state(std::unique_ptr<http2::Http2State> buffer)657 inline void Environment::set_http2_state(
658     std::unique_ptr<http2::Http2State> buffer) {
659   CHECK(!http2_state_);  // Should be set only once.
660   http2_state_ = std::move(buffer);
661 }
662 
fs_stats_field_array()663 inline AliasedFloat64Array* Environment::fs_stats_field_array() {
664   return &fs_stats_field_array_;
665 }
666 
fs_stats_field_bigint_array()667 inline AliasedBigUint64Array* Environment::fs_stats_field_bigint_array() {
668   return &fs_stats_field_bigint_array_;
669 }
670 
671 inline std::vector<std::unique_ptr<fs::FileHandleReadWrap>>&
file_handle_read_wrap_freelist()672 Environment::file_handle_read_wrap_freelist() {
673   return file_handle_read_wrap_freelist_;
674 }
675 
options()676 inline std::shared_ptr<EnvironmentOptions> Environment::options() {
677   return options_;
678 }
679 
argv()680 inline const std::vector<std::string>& Environment::argv() {
681   return argv_;
682 }
683 
exec_argv()684 inline const std::vector<std::string>& Environment::exec_argv() {
685   return exec_argv_;
686 }
687 
exec_path()688 inline const std::string& Environment::exec_path() const {
689   return exec_path_;
690 }
691 
692 #if HAVE_INSPECTOR
set_coverage_directory(const char * dir)693 inline void Environment::set_coverage_directory(const char* dir) {
694   coverage_directory_ = std::string(dir);
695 }
696 
set_coverage_connection(std::unique_ptr<profiler::V8CoverageConnection> connection)697 inline void Environment::set_coverage_connection(
698     std::unique_ptr<profiler::V8CoverageConnection> connection) {
699   CHECK_NULL(coverage_connection_);
700   std::swap(coverage_connection_, connection);
701 }
702 
coverage_connection()703 inline profiler::V8CoverageConnection* Environment::coverage_connection() {
704   return coverage_connection_.get();
705 }
706 
coverage_directory()707 inline const std::string& Environment::coverage_directory() const {
708   return coverage_directory_;
709 }
710 
set_cpu_profiler_connection(std::unique_ptr<profiler::V8CpuProfilerConnection> connection)711 inline void Environment::set_cpu_profiler_connection(
712     std::unique_ptr<profiler::V8CpuProfilerConnection> connection) {
713   CHECK_NULL(cpu_profiler_connection_);
714   std::swap(cpu_profiler_connection_, connection);
715 }
716 
717 inline profiler::V8CpuProfilerConnection*
cpu_profiler_connection()718 Environment::cpu_profiler_connection() {
719   return cpu_profiler_connection_.get();
720 }
721 
set_cpu_prof_interval(uint64_t interval)722 inline void Environment::set_cpu_prof_interval(uint64_t interval) {
723   cpu_prof_interval_ = interval;
724 }
725 
cpu_prof_interval()726 inline uint64_t Environment::cpu_prof_interval() const {
727   return cpu_prof_interval_;
728 }
729 
set_cpu_prof_name(const std::string & name)730 inline void Environment::set_cpu_prof_name(const std::string& name) {
731   cpu_prof_name_ = name;
732 }
733 
cpu_prof_name()734 inline const std::string& Environment::cpu_prof_name() const {
735   return cpu_prof_name_;
736 }
737 
set_cpu_prof_dir(const std::string & dir)738 inline void Environment::set_cpu_prof_dir(const std::string& dir) {
739   cpu_prof_dir_ = dir;
740 }
741 
cpu_prof_dir()742 inline const std::string& Environment::cpu_prof_dir() const {
743   return cpu_prof_dir_;
744 }
745 
set_heap_profiler_connection(std::unique_ptr<profiler::V8HeapProfilerConnection> connection)746 inline void Environment::set_heap_profiler_connection(
747     std::unique_ptr<profiler::V8HeapProfilerConnection> connection) {
748   CHECK_NULL(heap_profiler_connection_);
749   std::swap(heap_profiler_connection_, connection);
750 }
751 
752 inline profiler::V8HeapProfilerConnection*
heap_profiler_connection()753 Environment::heap_profiler_connection() {
754   return heap_profiler_connection_.get();
755 }
756 
set_heap_prof_name(const std::string & name)757 inline void Environment::set_heap_prof_name(const std::string& name) {
758   heap_prof_name_ = name;
759 }
760 
heap_prof_name()761 inline const std::string& Environment::heap_prof_name() const {
762   return heap_prof_name_;
763 }
764 
set_heap_prof_dir(const std::string & dir)765 inline void Environment::set_heap_prof_dir(const std::string& dir) {
766   heap_prof_dir_ = dir;
767 }
768 
heap_prof_dir()769 inline const std::string& Environment::heap_prof_dir() const {
770   return heap_prof_dir_;
771 }
772 
set_heap_prof_interval(uint64_t interval)773 inline void Environment::set_heap_prof_interval(uint64_t interval) {
774   heap_prof_interval_ = interval;
775 }
776 
heap_prof_interval()777 inline uint64_t Environment::heap_prof_interval() const {
778   return heap_prof_interval_;
779 }
780 
781 #endif  // HAVE_INSPECTOR
782 
783 inline
inspector_host_port()784 std::shared_ptr<ExclusiveAccess<HostPort>> Environment::inspector_host_port() {
785   return inspector_host_port_;
786 }
787 
options()788 inline std::shared_ptr<PerIsolateOptions> IsolateData::options() {
789   return options_;
790 }
791 
set_options(std::shared_ptr<PerIsolateOptions> options)792 inline void IsolateData::set_options(
793     std::shared_ptr<PerIsolateOptions> options) {
794   options_ = std::move(options);
795 }
796 
797 template <typename Fn>
SetImmediate(Fn && cb,CallbackFlags::Flags flags)798 void Environment::SetImmediate(Fn&& cb, CallbackFlags::Flags flags) {
799   auto callback = native_immediates_.CreateCallback(std::move(cb), flags);
800   native_immediates_.Push(std::move(callback));
801 
802   if (flags & CallbackFlags::kRefed) {
803     if (immediate_info()->ref_count() == 0)
804       ToggleImmediateRef(true);
805     immediate_info()->ref_count_inc(1);
806   }
807 }
808 
809 template <typename Fn>
SetImmediateThreadsafe(Fn && cb,CallbackFlags::Flags flags)810 void Environment::SetImmediateThreadsafe(Fn&& cb, CallbackFlags::Flags flags) {
811   auto callback = native_immediates_threadsafe_.CreateCallback(
812       std::move(cb), flags);
813   {
814     Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
815     native_immediates_threadsafe_.Push(std::move(callback));
816     if (task_queues_async_initialized_)
817       uv_async_send(&task_queues_async_);
818   }
819 }
820 
821 template <typename Fn>
RequestInterrupt(Fn && cb)822 void Environment::RequestInterrupt(Fn&& cb) {
823   auto callback = native_immediates_interrupts_.CreateCallback(
824       std::move(cb), CallbackFlags::kRefed);
825   {
826     Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
827     native_immediates_interrupts_.Push(std::move(callback));
828     if (task_queues_async_initialized_)
829       uv_async_send(&task_queues_async_);
830   }
831   RequestInterruptFromV8();
832 }
833 
can_call_into_js()834 inline bool Environment::can_call_into_js() const {
835   return can_call_into_js_ && !is_stopping();
836 }
837 
set_can_call_into_js(bool can_call_into_js)838 inline void Environment::set_can_call_into_js(bool can_call_into_js) {
839   can_call_into_js_ = can_call_into_js;
840 }
841 
has_run_bootstrapping_code()842 inline bool Environment::has_run_bootstrapping_code() const {
843   return has_run_bootstrapping_code_;
844 }
845 
set_has_run_bootstrapping_code(bool value)846 inline void Environment::set_has_run_bootstrapping_code(bool value) {
847   has_run_bootstrapping_code_ = value;
848 }
849 
has_serialized_options()850 inline bool Environment::has_serialized_options() const {
851   return has_serialized_options_;
852 }
853 
set_has_serialized_options(bool value)854 inline void Environment::set_has_serialized_options(bool value) {
855   has_serialized_options_ = value;
856 }
857 
is_main_thread()858 inline bool Environment::is_main_thread() const {
859   return worker_context() == nullptr;
860 }
861 
should_not_register_esm_loader()862 inline bool Environment::should_not_register_esm_loader() const {
863   return flags_ & EnvironmentFlags::kNoRegisterESMLoader;
864 }
865 
owns_process_state()866 inline bool Environment::owns_process_state() const {
867   return flags_ & EnvironmentFlags::kOwnsProcessState;
868 }
869 
owns_inspector()870 inline bool Environment::owns_inspector() const {
871   return flags_ & EnvironmentFlags::kOwnsInspector;
872 }
873 
tracks_unmanaged_fds()874 inline bool Environment::tracks_unmanaged_fds() const {
875   return flags_ & EnvironmentFlags::kTrackUnmanagedFds;
876 }
877 
thread_id()878 inline uint64_t Environment::thread_id() const {
879   return thread_id_;
880 }
881 
worker_context()882 inline worker::Worker* Environment::worker_context() const {
883   return isolate_data()->worker_context();
884 }
885 
add_sub_worker_context(worker::Worker * context)886 inline void Environment::add_sub_worker_context(worker::Worker* context) {
887   sub_worker_contexts_.insert(context);
888 }
889 
remove_sub_worker_context(worker::Worker * context)890 inline void Environment::remove_sub_worker_context(worker::Worker* context) {
891   sub_worker_contexts_.erase(context);
892 }
893 
894 template <typename Fn>
ForEachWorker(Fn && iterator)895 inline void Environment::ForEachWorker(Fn&& iterator) {
896   for (worker::Worker* w : sub_worker_contexts_) iterator(w);
897 }
898 
add_refs(int64_t diff)899 inline void Environment::add_refs(int64_t diff) {
900   task_queues_async_refs_ += diff;
901   CHECK_GE(task_queues_async_refs_, 0);
902   if (task_queues_async_refs_ == 0)
903     uv_unref(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
904   else
905     uv_ref(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
906 }
907 
is_stopping()908 inline bool Environment::is_stopping() const {
909   return is_stopping_.load();
910 }
911 
set_stopping(bool value)912 inline void Environment::set_stopping(bool value) {
913   is_stopping_.store(value);
914 }
915 
extra_linked_bindings()916 inline std::list<node_module>* Environment::extra_linked_bindings() {
917   return &extra_linked_bindings_;
918 }
919 
extra_linked_bindings_head()920 inline node_module* Environment::extra_linked_bindings_head() {
921   return extra_linked_bindings_.size() > 0 ?
922       &extra_linked_bindings_.front() : nullptr;
923 }
924 
extra_linked_bindings_mutex()925 inline const Mutex& Environment::extra_linked_bindings_mutex() const {
926   return extra_linked_bindings_mutex_;
927 }
928 
performance_state()929 inline performance::PerformanceState* Environment::performance_state() {
930   return performance_state_.get();
931 }
932 
933 inline std::unordered_map<std::string, uint64_t>*
performance_marks()934     Environment::performance_marks() {
935   return &performance_marks_;
936 }
937 
isolate_data()938 inline IsolateData* Environment::isolate_data() const {
939   return isolate_data_;
940 }
941 
AllocateUnchecked(size_t size)942 inline char* Environment::AllocateUnchecked(size_t size) {
943   return static_cast<char*>(
944       isolate_data()->allocator()->AllocateUninitialized(size));
945 }
946 
Allocate(size_t size)947 inline char* Environment::Allocate(size_t size) {
948   char* ret = AllocateUnchecked(size);
949   CHECK_NE(ret, nullptr);
950   return ret;
951 }
952 
Free(char * data,size_t size)953 inline void Environment::Free(char* data, size_t size) {
954   if (data != nullptr)
955     isolate_data()->allocator()->Free(data, size);
956 }
957 
AllocateManaged(size_t size,bool checked)958 inline AllocatedBuffer Environment::AllocateManaged(size_t size, bool checked) {
959   char* data = checked ? Allocate(size) : AllocateUnchecked(size);
960   if (data == nullptr) size = 0;
961   return AllocatedBuffer(this, uv_buf_init(data, size));
962 }
963 
AllocatedBuffer(Environment * env,uv_buf_t buf)964 inline AllocatedBuffer::AllocatedBuffer(Environment* env, uv_buf_t buf)
965     : env_(env), buffer_(buf) {}
966 
Resize(size_t len)967 inline void AllocatedBuffer::Resize(size_t len) {
968   // The `len` check is to make sure we don't end up with `nullptr` as our base.
969   char* new_data = env_->Reallocate(buffer_.base, buffer_.len,
970                                     len > 0 ? len : 1);
971   CHECK_NOT_NULL(new_data);
972   buffer_ = uv_buf_init(new_data, len);
973 }
974 
release()975 inline uv_buf_t AllocatedBuffer::release() {
976   uv_buf_t ret = buffer_;
977   buffer_ = uv_buf_init(nullptr, 0);
978   return ret;
979 }
980 
data()981 inline char* AllocatedBuffer::data() {
982   return buffer_.base;
983 }
984 
data()985 inline const char* AllocatedBuffer::data() const {
986   return buffer_.base;
987 }
988 
size()989 inline size_t AllocatedBuffer::size() const {
990   return buffer_.len;
991 }
992 
AllocatedBuffer(Environment * env)993 inline AllocatedBuffer::AllocatedBuffer(Environment* env)
994     : env_(env), buffer_(uv_buf_init(nullptr, 0)) {}
995 
AllocatedBuffer(AllocatedBuffer && other)996 inline AllocatedBuffer::AllocatedBuffer(AllocatedBuffer&& other)
997     : AllocatedBuffer() {
998   *this = std::move(other);
999 }
1000 
1001 inline AllocatedBuffer& AllocatedBuffer::operator=(AllocatedBuffer&& other) {
1002   clear();
1003   env_ = other.env_;
1004   buffer_ = other.release();
1005   return *this;
1006 }
1007 
~AllocatedBuffer()1008 inline AllocatedBuffer::~AllocatedBuffer() {
1009   clear();
1010 }
1011 
clear()1012 inline void AllocatedBuffer::clear() {
1013   uv_buf_t buf = release();
1014   if (buf.base != nullptr) {
1015     CHECK_NOT_NULL(env_);
1016     env_->Free(buf.base, buf.len);
1017   }
1018 }
1019 
1020 // It's a bit awkward to define this Buffer::New() overload here, but it
1021 // avoids a circular dependency with node_internals.h.
1022 namespace Buffer {
1023 v8::MaybeLocal<v8::Object> New(Environment* env,
1024                                char* data,
1025                                size_t length,
1026                                bool uses_malloc);
1027 }
1028 
ToBuffer()1029 inline v8::MaybeLocal<v8::Object> AllocatedBuffer::ToBuffer() {
1030   CHECK_NOT_NULL(env_);
1031   v8::MaybeLocal<v8::Object> obj = Buffer::New(env_, data(), size(), false);
1032   if (!obj.IsEmpty()) release();
1033   return obj;
1034 }
1035 
ToArrayBuffer()1036 inline v8::Local<v8::ArrayBuffer> AllocatedBuffer::ToArrayBuffer() {
1037   CHECK_NOT_NULL(env_);
1038   uv_buf_t buf = release();
1039   return v8::ArrayBuffer::New(env_->isolate(),
1040                               buf.base,
1041                               buf.len,
1042                               v8::ArrayBufferCreationMode::kInternalized);
1043 }
1044 
ThrowError(const char * errmsg)1045 inline void Environment::ThrowError(const char* errmsg) {
1046   ThrowError(v8::Exception::Error, errmsg);
1047 }
1048 
ThrowTypeError(const char * errmsg)1049 inline void Environment::ThrowTypeError(const char* errmsg) {
1050   ThrowError(v8::Exception::TypeError, errmsg);
1051 }
1052 
ThrowRangeError(const char * errmsg)1053 inline void Environment::ThrowRangeError(const char* errmsg) {
1054   ThrowError(v8::Exception::RangeError, errmsg);
1055 }
1056 
ThrowError(v8::Local<v8::Value> (* fun)(v8::Local<v8::String>),const char * errmsg)1057 inline void Environment::ThrowError(
1058     v8::Local<v8::Value> (*fun)(v8::Local<v8::String>),
1059     const char* errmsg) {
1060   v8::HandleScope handle_scope(isolate());
1061   isolate()->ThrowException(fun(OneByteString(isolate(), errmsg)));
1062 }
1063 
ThrowErrnoException(int errorno,const char * syscall,const char * message,const char * path)1064 inline void Environment::ThrowErrnoException(int errorno,
1065                                              const char* syscall,
1066                                              const char* message,
1067                                              const char* path) {
1068   isolate()->ThrowException(
1069       ErrnoException(isolate(), errorno, syscall, message, path));
1070 }
1071 
ThrowUVException(int errorno,const char * syscall,const char * message,const char * path,const char * dest)1072 inline void Environment::ThrowUVException(int errorno,
1073                                           const char* syscall,
1074                                           const char* message,
1075                                           const char* path,
1076                                           const char* dest) {
1077   isolate()->ThrowException(
1078       UVException(isolate(), errorno, syscall, message, path, dest));
1079 }
1080 
1081 inline v8::Local<v8::FunctionTemplate>
NewFunctionTemplate(v8::FunctionCallback callback,v8::Local<v8::Signature> signature,v8::ConstructorBehavior behavior,v8::SideEffectType side_effect_type)1082     Environment::NewFunctionTemplate(v8::FunctionCallback callback,
1083                                      v8::Local<v8::Signature> signature,
1084                                      v8::ConstructorBehavior behavior,
1085                                      v8::SideEffectType side_effect_type) {
1086   v8::Local<v8::Object> external = as_callback_data();
1087   return v8::FunctionTemplate::New(isolate(), callback, external,
1088                                    signature, 0, behavior, side_effect_type);
1089 }
1090 
SetMethod(v8::Local<v8::Object> that,const char * name,v8::FunctionCallback callback)1091 inline void Environment::SetMethod(v8::Local<v8::Object> that,
1092                                    const char* name,
1093                                    v8::FunctionCallback callback) {
1094   v8::Local<v8::Context> context = isolate()->GetCurrentContext();
1095   v8::Local<v8::Function> function =
1096       NewFunctionTemplate(callback, v8::Local<v8::Signature>(),
1097                           v8::ConstructorBehavior::kThrow,
1098                           v8::SideEffectType::kHasSideEffect)
1099           ->GetFunction(context)
1100           .ToLocalChecked();
1101   // kInternalized strings are created in the old space.
1102   const v8::NewStringType type = v8::NewStringType::kInternalized;
1103   v8::Local<v8::String> name_string =
1104       v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1105   that->Set(context, name_string, function).Check();
1106   function->SetName(name_string);  // NODE_SET_METHOD() compatibility.
1107 }
1108 
SetMethodNoSideEffect(v8::Local<v8::Object> that,const char * name,v8::FunctionCallback callback)1109 inline void Environment::SetMethodNoSideEffect(v8::Local<v8::Object> that,
1110                                                const char* name,
1111                                                v8::FunctionCallback callback) {
1112   v8::Local<v8::Context> context = isolate()->GetCurrentContext();
1113   v8::Local<v8::Function> function =
1114       NewFunctionTemplate(callback, v8::Local<v8::Signature>(),
1115                           v8::ConstructorBehavior::kThrow,
1116                           v8::SideEffectType::kHasNoSideEffect)
1117           ->GetFunction(context)
1118           .ToLocalChecked();
1119   // kInternalized strings are created in the old space.
1120   const v8::NewStringType type = v8::NewStringType::kInternalized;
1121   v8::Local<v8::String> name_string =
1122       v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1123   that->Set(context, name_string, function).Check();
1124   function->SetName(name_string);  // NODE_SET_METHOD() compatibility.
1125 }
1126 
SetProtoMethod(v8::Local<v8::FunctionTemplate> that,const char * name,v8::FunctionCallback callback)1127 inline void Environment::SetProtoMethod(v8::Local<v8::FunctionTemplate> that,
1128                                         const char* name,
1129                                         v8::FunctionCallback callback) {
1130   v8::Local<v8::Signature> signature = v8::Signature::New(isolate(), that);
1131   v8::Local<v8::FunctionTemplate> t =
1132       NewFunctionTemplate(callback, signature, v8::ConstructorBehavior::kThrow,
1133                           v8::SideEffectType::kHasSideEffect);
1134   // kInternalized strings are created in the old space.
1135   const v8::NewStringType type = v8::NewStringType::kInternalized;
1136   v8::Local<v8::String> name_string =
1137       v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1138   that->PrototypeTemplate()->Set(name_string, t);
1139   t->SetClassName(name_string);  // NODE_SET_PROTOTYPE_METHOD() compatibility.
1140 }
1141 
SetProtoMethodNoSideEffect(v8::Local<v8::FunctionTemplate> that,const char * name,v8::FunctionCallback callback)1142 inline void Environment::SetProtoMethodNoSideEffect(
1143     v8::Local<v8::FunctionTemplate> that,
1144     const char* name,
1145     v8::FunctionCallback callback) {
1146   v8::Local<v8::Signature> signature = v8::Signature::New(isolate(), that);
1147   v8::Local<v8::FunctionTemplate> t =
1148       NewFunctionTemplate(callback, signature, v8::ConstructorBehavior::kThrow,
1149                           v8::SideEffectType::kHasNoSideEffect);
1150   // kInternalized strings are created in the old space.
1151   const v8::NewStringType type = v8::NewStringType::kInternalized;
1152   v8::Local<v8::String> name_string =
1153       v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1154   that->PrototypeTemplate()->Set(name_string, t);
1155   t->SetClassName(name_string);  // NODE_SET_PROTOTYPE_METHOD() compatibility.
1156 }
1157 
SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,const char * name,v8::FunctionCallback callback)1158 inline void Environment::SetInstanceMethod(v8::Local<v8::FunctionTemplate> that,
1159                                            const char* name,
1160                                            v8::FunctionCallback callback) {
1161   v8::Local<v8::Signature> signature = v8::Signature::New(isolate(), that);
1162   v8::Local<v8::FunctionTemplate> t =
1163       NewFunctionTemplate(callback, signature, v8::ConstructorBehavior::kThrow,
1164                           v8::SideEffectType::kHasSideEffect);
1165   // kInternalized strings are created in the old space.
1166   const v8::NewStringType type = v8::NewStringType::kInternalized;
1167   v8::Local<v8::String> name_string =
1168       v8::String::NewFromUtf8(isolate(), name, type).ToLocalChecked();
1169   that->InstanceTemplate()->Set(name_string, t);
1170   t->SetClassName(name_string);
1171 }
1172 
AddCleanupHook(void (* fn)(void *),void * arg)1173 void Environment::AddCleanupHook(void (*fn)(void*), void* arg) {
1174   auto insertion_info = cleanup_hooks_.emplace(CleanupHookCallback {
1175     fn, arg, cleanup_hook_counter_++
1176   });
1177   // Make sure there was no existing element with these values.
1178   CHECK_EQ(insertion_info.second, true);
1179 }
1180 
RemoveCleanupHook(void (* fn)(void *),void * arg)1181 void Environment::RemoveCleanupHook(void (*fn)(void*), void* arg) {
1182   CleanupHookCallback search { fn, arg, 0 };
1183   cleanup_hooks_.erase(search);
1184 }
1185 
RegisterFinalizationGroupForCleanup(v8::Local<v8::FinalizationGroup> group)1186 inline void Environment::RegisterFinalizationGroupForCleanup(
1187     v8::Local<v8::FinalizationGroup> group) {
1188   cleanup_finalization_groups_.emplace_back(isolate(), group);
1189   DCHECK(task_queues_async_initialized_);
1190   uv_async_send(&task_queues_async_);
1191 }
1192 
operator()1193 size_t CleanupHookCallback::Hash::operator()(
1194     const CleanupHookCallback& cb) const {
1195   return std::hash<void*>()(cb.arg_);
1196 }
1197 
operator()1198 bool CleanupHookCallback::Equal::operator()(
1199     const CleanupHookCallback& a, const CleanupHookCallback& b) const {
1200   return a.fn_ == b.fn_ && a.arg_ == b.arg_;
1201 }
1202 
GetBaseObject()1203 BaseObject* CleanupHookCallback::GetBaseObject() const {
1204   if (fn_ == BaseObject::DeleteMe)
1205     return static_cast<BaseObject*>(arg_);
1206   else
1207     return nullptr;
1208 }
1209 
1210 template <typename T>
ForEachBaseObject(T && iterator)1211 void Environment::ForEachBaseObject(T&& iterator) {
1212   for (const auto& hook : cleanup_hooks_) {
1213     BaseObject* obj = hook.GetBaseObject();
1214     if (obj != nullptr)
1215       iterator(obj);
1216   }
1217 }
1218 
modify_base_object_count(int64_t delta)1219 void Environment::modify_base_object_count(int64_t delta) {
1220   base_object_count_ += delta;
1221 }
1222 
base_object_count()1223 int64_t Environment::base_object_count() const {
1224   return base_object_count_;
1225 }
1226 
set_main_utf16(std::unique_ptr<v8::String::Value> str)1227 void Environment::set_main_utf16(std::unique_ptr<v8::String::Value> str) {
1228   CHECK(!main_utf16_);
1229   main_utf16_ = std::move(str);
1230 }
1231 
set_process_exit_handler(std::function<void (Environment *,int)> && handler)1232 void Environment::set_process_exit_handler(
1233     std::function<void(Environment*, int)>&& handler) {
1234   process_exit_handler_ = std::move(handler);
1235 }
1236 
1237 #define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
1238 #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
1239 #define VS(PropertyName, StringValue) V(v8::String, PropertyName)
1240 #define V(TypeName, PropertyName)                                             \
1241   inline                                                                      \
1242   v8::Local<TypeName> IsolateData::PropertyName() const {                     \
1243     return PropertyName ## _ .Get(isolate_);                                  \
1244   }
1245   PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
PER_ISOLATE_SYMBOL_PROPERTIES(VY)1246   PER_ISOLATE_SYMBOL_PROPERTIES(VY)
1247   PER_ISOLATE_STRING_PROPERTIES(VS)
1248 #undef V
1249 #undef VS
1250 #undef VY
1251 #undef VP
1252 
1253 #define VP(PropertyName, StringValue) V(v8::Private, PropertyName)
1254 #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName)
1255 #define VS(PropertyName, StringValue) V(v8::String, PropertyName)
1256 #define V(TypeName, PropertyName)                                             \
1257   inline v8::Local<TypeName> Environment::PropertyName() const {              \
1258     return isolate_data()->PropertyName();                                    \
1259   }
1260   PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP)
1261   PER_ISOLATE_SYMBOL_PROPERTIES(VY)
1262   PER_ISOLATE_STRING_PROPERTIES(VS)
1263 #undef V
1264 #undef VS
1265 #undef VY
1266 #undef VP
1267 
1268 #define V(PropertyName, TypeName)                                             \
1269   inline v8::Local<TypeName> Environment::PropertyName() const {              \
1270     return PersistentToLocal::Strong(PropertyName ## _);                      \
1271   }                                                                           \
1272   inline void Environment::set_ ## PropertyName(v8::Local<TypeName> value) {  \
1273     PropertyName ## _.Reset(isolate(), value);                                \
1274   }
1275   ENVIRONMENT_STRONG_PERSISTENT_TEMPLATES(V)
1276   ENVIRONMENT_STRONG_PERSISTENT_VALUES(V)
1277 #undef V
1278 
1279   inline v8::Local<v8::Context> Environment::context() const {
1280     return PersistentToLocal::Strong(context_);
1281   }
1282 }  // namespace node
1283 
1284 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
1285 
1286 #endif  // SRC_ENV_INL_H_
1287