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