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