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