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_H_ 23 #define SRC_ENV_H_ 24 25 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 26 27 #include "aliased_buffer.h" 28 #if HAVE_INSPECTOR 29 #include "inspector_agent.h" 30 #include "inspector_profiler.h" 31 #endif 32 #include "callback_queue.h" 33 #include "cleanup_queue-inl.h" 34 #include "debug_utils.h" 35 #include "env_properties.h" 36 #include "handle_wrap.h" 37 #include "node.h" 38 #include "node_binding.h" 39 #include "node_builtins.h" 40 #include "node_main_instance.h" 41 #include "node_options.h" 42 #include "node_perf_common.h" 43 #include "node_realm.h" 44 #include "node_snapshotable.h" 45 #include "req_wrap.h" 46 #include "util.h" 47 #include "uv.h" 48 #include "v8.h" 49 50 #include <array> 51 #include <atomic> 52 #include <cstdint> 53 #include <functional> 54 #include <list> 55 #include <memory> 56 #include <ostream> 57 #include <set> 58 #include <string> 59 #include <unordered_map> 60 #include <unordered_set> 61 #include <vector> 62 63 namespace node { 64 65 namespace contextify { 66 class ContextifyScript; 67 class CompiledFnEntry; 68 } 69 70 namespace performance { 71 class PerformanceState; 72 } 73 74 namespace tracing { 75 class AgentWriterHandle; 76 } 77 78 #if HAVE_INSPECTOR 79 namespace profiler { 80 class V8CoverageConnection; 81 class V8CpuProfilerConnection; 82 class V8HeapProfilerConnection; 83 } // namespace profiler 84 85 namespace inspector { 86 class ParentInspectorHandle; 87 } 88 #endif // HAVE_INSPECTOR 89 90 namespace worker { 91 class Worker; 92 } 93 94 namespace loader { 95 class ModuleWrap; 96 } // namespace loader 97 98 class Environment; 99 class Realm; 100 101 // Disables zero-filling for ArrayBuffer allocations in this scope. This is 102 // similar to how we implement Buffer.allocUnsafe() in JS land. 103 class NoArrayBufferZeroFillScope { 104 public: 105 inline explicit NoArrayBufferZeroFillScope(IsolateData* isolate_data); 106 inline ~NoArrayBufferZeroFillScope(); 107 108 private: 109 NodeArrayBufferAllocator* node_allocator_; 110 111 friend class Environment; 112 }; 113 114 struct IsolateDataSerializeInfo { 115 std::vector<SnapshotIndex> primitive_values; 116 std::vector<PropInfo> template_values; 117 118 friend std::ostream& operator<<(std::ostream& o, 119 const IsolateDataSerializeInfo& i); 120 }; 121 122 class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer { 123 public: 124 IsolateData(v8::Isolate* isolate, 125 uv_loop_t* event_loop, 126 MultiIsolatePlatform* platform = nullptr, 127 ArrayBufferAllocator* node_allocator = nullptr, 128 const IsolateDataSerializeInfo* isolate_data_info = nullptr); 129 SET_MEMORY_INFO_NAME(IsolateData) 130 SET_SELF_SIZE(IsolateData) 131 void MemoryInfo(MemoryTracker* tracker) const override; 132 IsolateDataSerializeInfo Serialize(v8::SnapshotCreator* creator); 133 134 inline uv_loop_t* event_loop() const; 135 inline MultiIsolatePlatform* platform() const; 136 inline std::shared_ptr<PerIsolateOptions> options(); 137 inline void set_options(std::shared_ptr<PerIsolateOptions> options); 138 139 inline NodeArrayBufferAllocator* node_allocator() const; 140 141 inline worker::Worker* worker_context() const; 142 inline void set_worker_context(worker::Worker* context); 143 144 #define VP(PropertyName, StringValue) V(v8::Private, PropertyName) 145 #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName) 146 #define VS(PropertyName, StringValue) V(v8::String, PropertyName) 147 #define V(TypeName, PropertyName) \ 148 inline v8::Local<TypeName> PropertyName() const; 149 PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) 150 PER_ISOLATE_SYMBOL_PROPERTIES(VY) 151 PER_ISOLATE_STRING_PROPERTIES(VS) 152 #undef V 153 #undef VY 154 #undef VS 155 #undef VP 156 157 #define VM(PropertyName) V(PropertyName##_binding, v8::FunctionTemplate) 158 #define V(PropertyName, TypeName) \ 159 inline v8::Local<TypeName> PropertyName() const; \ 160 inline void set_##PropertyName(v8::Local<TypeName> value); 161 PER_ISOLATE_TEMPLATE_PROPERTIES(V) 162 NODE_BINDINGS_WITH_PER_ISOLATE_INIT(VM) 163 #undef V 164 #undef VM 165 166 inline v8::Local<v8::String> async_wrap_provider(int index) const; 167 168 size_t max_young_gen_size = 1; 169 std::unordered_map<const char*, v8::Eternal<v8::String>> static_str_map; 170 171 inline v8::Isolate* isolate() const; 172 IsolateData(const IsolateData&) = delete; 173 IsolateData& operator=(const IsolateData&) = delete; 174 IsolateData(IsolateData&&) = delete; 175 IsolateData& operator=(IsolateData&&) = delete; 176 177 private: 178 void DeserializeProperties(const IsolateDataSerializeInfo* isolate_data_info); 179 void CreateProperties(); 180 181 #define VP(PropertyName, StringValue) V(v8::Private, PropertyName) 182 #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName) 183 #define VS(PropertyName, StringValue) V(v8::String, PropertyName) 184 #define VM(PropertyName) V(v8::FunctionTemplate, PropertyName##_binding) 185 #define VT(PropertyName, TypeName) V(TypeName, PropertyName) 186 #define V(TypeName, PropertyName) \ 187 v8::Eternal<TypeName> PropertyName ## _; 188 PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) 189 PER_ISOLATE_SYMBOL_PROPERTIES(VY) 190 PER_ISOLATE_STRING_PROPERTIES(VS) 191 PER_ISOLATE_TEMPLATE_PROPERTIES(VT) 192 NODE_BINDINGS_WITH_PER_ISOLATE_INIT(VM) 193 #undef V 194 #undef VM 195 #undef VT 196 #undef VS 197 #undef VY 198 #undef VP 199 // Keep a list of all Persistent strings used for AsyncWrap Provider types. 200 std::array<v8::Eternal<v8::String>, AsyncWrap::PROVIDERS_LENGTH> 201 async_wrap_providers_; 202 203 v8::Isolate* const isolate_; 204 uv_loop_t* const event_loop_; 205 NodeArrayBufferAllocator* const node_allocator_; 206 MultiIsolatePlatform* platform_; 207 std::shared_ptr<PerIsolateOptions> options_; 208 worker::Worker* worker_context_ = nullptr; 209 }; 210 211 struct ContextInfo { ContextInfoContextInfo212 explicit ContextInfo(const std::string& name) : name(name) {} 213 const std::string name; 214 std::string origin; 215 bool is_default = false; 216 }; 217 218 class EnabledDebugList; 219 220 namespace per_process { 221 extern std::shared_ptr<KVStore> system_environment; 222 } 223 224 struct EnvSerializeInfo; 225 226 class AsyncHooks : public MemoryRetainer { 227 public: 228 SET_MEMORY_INFO_NAME(AsyncHooks) 229 SET_SELF_SIZE(AsyncHooks) 230 void MemoryInfo(MemoryTracker* tracker) const override; 231 232 // Reason for both UidFields and Fields are that one is stored as a double* 233 // and the other as a uint32_t*. 234 enum Fields { 235 kInit, 236 kBefore, 237 kAfter, 238 kDestroy, 239 kPromiseResolve, 240 kTotals, 241 kCheck, 242 kStackLength, 243 kUsesExecutionAsyncResource, 244 kFieldsCount, 245 }; 246 247 enum UidFields { 248 kExecutionAsyncId, 249 kTriggerAsyncId, 250 kAsyncIdCounter, 251 kDefaultTriggerAsyncId, 252 kUidFieldsCount, 253 }; 254 255 inline AliasedUint32Array& fields(); 256 inline AliasedFloat64Array& async_id_fields(); 257 inline AliasedFloat64Array& async_ids_stack(); 258 inline v8::Local<v8::Array> js_execution_async_resources(); 259 // Returns the native executionAsyncResource value at stack index `index`. 260 // Resources provided on the JS side are not stored on the native stack, 261 // in which case an empty `Local<>` is returned. 262 // The `js_execution_async_resources` array contains the value in that case. 263 inline v8::Local<v8::Object> native_execution_async_resource(size_t index); 264 265 void InstallPromiseHooks(v8::Local<v8::Context> ctx); 266 void ResetPromiseHooks(v8::Local<v8::Function> init, 267 v8::Local<v8::Function> before, 268 v8::Local<v8::Function> after, 269 v8::Local<v8::Function> resolve); 270 271 inline v8::Local<v8::String> provider_string(int idx); 272 273 inline void no_force_checks(); 274 inline Environment* env(); 275 276 // NB: This call does not take (co-)ownership of `execution_async_resource`. 277 // The lifetime of the `v8::Local<>` pointee must last until 278 // `pop_async_context()` or `clear_async_id_stack()` are called. 279 void push_async_context(double async_id, 280 double trigger_async_id, 281 v8::Local<v8::Object> execution_async_resource); 282 bool pop_async_context(double async_id); 283 void clear_async_id_stack(); // Used in fatal exceptions. 284 285 AsyncHooks(const AsyncHooks&) = delete; 286 AsyncHooks& operator=(const AsyncHooks&) = delete; 287 AsyncHooks(AsyncHooks&&) = delete; 288 AsyncHooks& operator=(AsyncHooks&&) = delete; 289 ~AsyncHooks() = default; 290 291 // Used to set the kDefaultTriggerAsyncId in a scope. This is instead of 292 // passing the trigger_async_id along with other constructor arguments. 293 class DefaultTriggerAsyncIdScope { 294 public: 295 DefaultTriggerAsyncIdScope() = delete; 296 explicit DefaultTriggerAsyncIdScope(Environment* env, 297 double init_trigger_async_id); 298 explicit DefaultTriggerAsyncIdScope(AsyncWrap* async_wrap); 299 ~DefaultTriggerAsyncIdScope(); 300 301 DefaultTriggerAsyncIdScope(const DefaultTriggerAsyncIdScope&) = delete; 302 DefaultTriggerAsyncIdScope& operator=(const DefaultTriggerAsyncIdScope&) = 303 delete; 304 DefaultTriggerAsyncIdScope(DefaultTriggerAsyncIdScope&&) = delete; 305 DefaultTriggerAsyncIdScope& operator=(DefaultTriggerAsyncIdScope&&) = 306 delete; 307 308 private: 309 AsyncHooks* async_hooks_; 310 double old_default_trigger_async_id_; 311 }; 312 313 struct SerializeInfo { 314 AliasedBufferIndex async_ids_stack; 315 AliasedBufferIndex fields; 316 AliasedBufferIndex async_id_fields; 317 SnapshotIndex js_execution_async_resources; 318 std::vector<SnapshotIndex> native_execution_async_resources; 319 }; 320 321 SerializeInfo Serialize(v8::Local<v8::Context> context, 322 v8::SnapshotCreator* creator); 323 void Deserialize(v8::Local<v8::Context> context); 324 325 private: 326 friend class Environment; // So we can call the constructor. 327 explicit AsyncHooks(v8::Isolate* isolate, const SerializeInfo* info); 328 329 [[noreturn]] void FailWithCorruptedAsyncStack(double expected_async_id); 330 331 // Stores the ids of the current execution context stack. 332 AliasedFloat64Array async_ids_stack_; 333 // Attached to a Uint32Array that tracks the number of active hooks for 334 // each type. 335 AliasedUint32Array fields_; 336 // Attached to a Float64Array that tracks the state of async resources. 337 AliasedFloat64Array async_id_fields_; 338 339 void grow_async_ids_stack(); 340 341 v8::Global<v8::Array> js_execution_async_resources_; 342 std::vector<v8::Local<v8::Object>> native_execution_async_resources_; 343 344 // Non-empty during deserialization 345 const SerializeInfo* info_ = nullptr; 346 347 std::array<v8::Global<v8::Function>, 4> js_promise_hooks_; 348 }; 349 350 class ImmediateInfo : public MemoryRetainer { 351 public: 352 inline AliasedUint32Array& fields(); 353 inline uint32_t count() const; 354 inline uint32_t ref_count() const; 355 inline bool has_outstanding() const; 356 inline void ref_count_inc(uint32_t increment); 357 inline void ref_count_dec(uint32_t decrement); 358 359 ImmediateInfo(const ImmediateInfo&) = delete; 360 ImmediateInfo& operator=(const ImmediateInfo&) = delete; 361 ImmediateInfo(ImmediateInfo&&) = delete; 362 ImmediateInfo& operator=(ImmediateInfo&&) = delete; 363 ~ImmediateInfo() = default; 364 365 SET_MEMORY_INFO_NAME(ImmediateInfo) 366 SET_SELF_SIZE(ImmediateInfo) 367 void MemoryInfo(MemoryTracker* tracker) const override; 368 369 struct SerializeInfo { 370 AliasedBufferIndex fields; 371 }; 372 SerializeInfo Serialize(v8::Local<v8::Context> context, 373 v8::SnapshotCreator* creator); 374 void Deserialize(v8::Local<v8::Context> context); 375 376 private: 377 friend class Environment; // So we can call the constructor. 378 explicit ImmediateInfo(v8::Isolate* isolate, const SerializeInfo* info); 379 380 enum Fields { kCount, kRefCount, kHasOutstanding, kFieldsCount }; 381 382 AliasedUint32Array fields_; 383 }; 384 385 class TickInfo : public MemoryRetainer { 386 public: 387 inline AliasedUint8Array& fields(); 388 inline bool has_tick_scheduled() const; 389 inline bool has_rejection_to_warn() const; 390 391 SET_MEMORY_INFO_NAME(TickInfo) 392 SET_SELF_SIZE(TickInfo) 393 void MemoryInfo(MemoryTracker* tracker) const override; 394 395 TickInfo(const TickInfo&) = delete; 396 TickInfo& operator=(const TickInfo&) = delete; 397 TickInfo(TickInfo&&) = delete; 398 TickInfo& operator=(TickInfo&&) = delete; 399 ~TickInfo() = default; 400 401 struct SerializeInfo { 402 AliasedBufferIndex fields; 403 }; 404 SerializeInfo Serialize(v8::Local<v8::Context> context, 405 v8::SnapshotCreator* creator); 406 void Deserialize(v8::Local<v8::Context> context); 407 408 private: 409 friend class Environment; // So we can call the constructor. 410 explicit TickInfo(v8::Isolate* isolate, const SerializeInfo* info); 411 412 enum Fields { kHasTickScheduled = 0, kHasRejectionToWarn, kFieldsCount }; 413 414 AliasedUint8Array fields_; 415 }; 416 417 class TrackingTraceStateObserver : 418 public v8::TracingController::TraceStateObserver { 419 public: TrackingTraceStateObserver(Environment * env)420 explicit TrackingTraceStateObserver(Environment* env) : env_(env) {} 421 OnTraceEnabled()422 void OnTraceEnabled() override { 423 UpdateTraceCategoryState(); 424 } 425 OnTraceDisabled()426 void OnTraceDisabled() override { 427 UpdateTraceCategoryState(); 428 } 429 430 private: 431 void UpdateTraceCategoryState(); 432 433 Environment* env_; 434 }; 435 436 class ShouldNotAbortOnUncaughtScope { 437 public: 438 explicit inline ShouldNotAbortOnUncaughtScope(Environment* env); 439 inline void Close(); 440 inline ~ShouldNotAbortOnUncaughtScope(); 441 ShouldNotAbortOnUncaughtScope(const ShouldNotAbortOnUncaughtScope&) = delete; 442 ShouldNotAbortOnUncaughtScope& operator=( 443 const ShouldNotAbortOnUncaughtScope&) = delete; 444 ShouldNotAbortOnUncaughtScope(ShouldNotAbortOnUncaughtScope&&) = delete; 445 ShouldNotAbortOnUncaughtScope& operator=(ShouldNotAbortOnUncaughtScope&&) = 446 delete; 447 448 private: 449 Environment* env_; 450 }; 451 452 typedef void (*DeserializeRequestCallback)(v8::Local<v8::Context> context, 453 v8::Local<v8::Object> holder, 454 int index, 455 InternalFieldInfoBase* info); 456 struct DeserializeRequest { 457 DeserializeRequestCallback cb; 458 v8::Global<v8::Object> holder; 459 int index; 460 InternalFieldInfoBase* info = nullptr; // Owned by the request 461 }; 462 463 struct EnvSerializeInfo { 464 AsyncHooks::SerializeInfo async_hooks; 465 TickInfo::SerializeInfo tick_info; 466 ImmediateInfo::SerializeInfo immediate_info; 467 AliasedBufferIndex timeout_info; 468 performance::PerformanceState::SerializeInfo performance_state; 469 AliasedBufferIndex exiting; 470 AliasedBufferIndex stream_base_state; 471 AliasedBufferIndex should_abort_on_uncaught_toggle; 472 473 RealmSerializeInfo principal_realm; 474 friend std::ostream& operator<<(std::ostream& o, const EnvSerializeInfo& i); 475 }; 476 477 struct SnapshotMetadata { 478 // For now kFullyCustomized is only built with the --build-snapshot CLI flag. 479 // We might want to add more types of snapshots in the future. 480 enum class Type : uint8_t { kDefault, kFullyCustomized }; 481 482 Type type; 483 std::string node_version; 484 std::string node_arch; 485 std::string node_platform; 486 // Result of v8::ScriptCompiler::CachedDataVersionTag(). 487 uint32_t v8_cache_version_tag; 488 }; 489 490 struct SnapshotData { 491 enum class DataOwnership { kOwned, kNotOwned }; 492 493 static const uint32_t kMagic = 0x143da19; 494 static const SnapshotIndex kNodeVMContextIndex = 0; 495 static const SnapshotIndex kNodeBaseContextIndex = kNodeVMContextIndex + 1; 496 static const SnapshotIndex kNodeMainContextIndex = kNodeBaseContextIndex + 1; 497 498 DataOwnership data_ownership = DataOwnership::kOwned; 499 500 SnapshotMetadata metadata; 501 502 // The result of v8::SnapshotCreator::CreateBlob() during the snapshot 503 // building process. 504 v8::StartupData v8_snapshot_blob_data{nullptr, 0}; 505 506 IsolateDataSerializeInfo isolate_data_info; 507 // TODO(joyeecheung): there should be a vector of env_info once we snapshot 508 // the worker environments. 509 EnvSerializeInfo env_info; 510 511 // A vector of built-in ids and v8::ScriptCompiler::CachedData, this can be 512 // shared across Node.js instances because they are supposed to share the 513 // read only space. We use builtins::CodeCacheInfo because 514 // v8::ScriptCompiler::CachedData is not copyable. 515 std::vector<builtins::CodeCacheInfo> code_cache; 516 517 void ToBlob(FILE* out) const; 518 // If returns false, the metadata doesn't match the current Node.js binary, 519 // and the caller should not consume the snapshot data. 520 bool Check() const; 521 static bool FromBlob(SnapshotData* out, FILE* in); 522 523 ~SnapshotData(); 524 }; 525 526 /** 527 * Environment is a per-isolate data structure that represents an execution 528 * environment. Each environment has a principal realm. An environment can 529 * create multiple subsidiary synthetic realms. 530 */ 531 class Environment : public MemoryRetainer { 532 public: 533 Environment(const Environment&) = delete; 534 Environment& operator=(const Environment&) = delete; 535 Environment(Environment&&) = delete; 536 Environment& operator=(Environment&&) = delete; 537 538 SET_MEMORY_INFO_NAME(Environment) 539 540 inline size_t SelfSize() const override; IsRootNode()541 bool IsRootNode() const override { return true; } 542 void MemoryInfo(MemoryTracker* tracker) const override; 543 544 EnvSerializeInfo Serialize(v8::SnapshotCreator* creator); 545 void DeserializeProperties(const EnvSerializeInfo* info); 546 547 void PrintInfoForSnapshotIfDebug(); 548 void EnqueueDeserializeRequest(DeserializeRequestCallback cb, 549 v8::Local<v8::Object> holder, 550 int index, 551 InternalFieldInfoBase* info); 552 void RunDeserializeRequests(); 553 // Should be called before InitializeInspector() 554 void InitializeDiagnostics(); 555 556 std::string GetCwd(); 557 558 #if HAVE_INSPECTOR 559 // If the environment is created for a worker, pass parent_handle and 560 // the ownership if transferred into the Environment. 561 int InitializeInspector( 562 std::unique_ptr<inspector::ParentInspectorHandle> parent_handle); 563 #endif 564 565 inline size_t async_callback_scope_depth() const; 566 inline void PushAsyncCallbackScope(); 567 inline void PopAsyncCallbackScope(); 568 569 static inline Environment* GetCurrent(v8::Isolate* isolate); 570 static inline Environment* GetCurrent(v8::Local<v8::Context> context); 571 static inline Environment* GetCurrent( 572 const v8::FunctionCallbackInfo<v8::Value>& info); 573 574 template <typename T> 575 static inline Environment* GetCurrent( 576 const v8::PropertyCallbackInfo<T>& info); 577 578 // Create an Environment without initializing a main Context. Use 579 // InitializeMainContext() to initialize a main context for it. 580 Environment(IsolateData* isolate_data, 581 v8::Isolate* isolate, 582 const std::vector<std::string>& args, 583 const std::vector<std::string>& exec_args, 584 const EnvSerializeInfo* env_info, 585 EnvironmentFlags::Flags flags, 586 ThreadId thread_id); 587 void InitializeMainContext(v8::Local<v8::Context> context, 588 const EnvSerializeInfo* env_info); 589 // Create an Environment and initialize the provided principal context for it. 590 Environment(IsolateData* isolate_data, 591 v8::Local<v8::Context> context, 592 const std::vector<std::string>& args, 593 const std::vector<std::string>& exec_args, 594 const EnvSerializeInfo* env_info, 595 EnvironmentFlags::Flags flags, 596 ThreadId thread_id); 597 ~Environment() override; 598 599 void InitializeLibuv(); 600 inline const std::vector<std::string>& exec_argv(); 601 inline const std::vector<std::string>& argv(); 602 const std::string& exec_path() const; 603 604 typedef void (*HandleCleanupCb)(Environment* env, 605 uv_handle_t* handle, 606 void* arg); 607 struct HandleCleanup { 608 uv_handle_t* handle_; 609 HandleCleanupCb cb_; 610 void* arg_; 611 }; 612 613 void RegisterHandleCleanups(); 614 void CleanupHandles(); 615 void Exit(int code); 616 void ExitEnv(StopFlags::Flags flags); 617 618 // Register clean-up cb to be called on environment destruction. 619 inline void RegisterHandleCleanup(uv_handle_t* handle, 620 HandleCleanupCb cb, 621 void* arg); 622 623 template <typename T, typename OnCloseCallback> 624 inline void CloseHandle(T* handle, OnCloseCallback callback); 625 626 void ResetPromiseHooks(v8::Local<v8::Function> init, 627 v8::Local<v8::Function> before, 628 v8::Local<v8::Function> after, 629 v8::Local<v8::Function> resolve); 630 void AssignToContext(v8::Local<v8::Context> context, 631 Realm* realm, 632 const ContextInfo& info); 633 void TrackContext(v8::Local<v8::Context> context); 634 void UntrackContext(v8::Local<v8::Context> context); 635 636 void StartProfilerIdleNotifier(); 637 638 inline v8::Isolate* isolate() const; 639 inline uv_loop_t* event_loop() const; 640 void TryLoadAddon(const char* filename, 641 int flags, 642 const std::function<bool(binding::DLib*)>& was_loaded); 643 644 static inline Environment* from_timer_handle(uv_timer_t* handle); 645 inline uv_timer_t* timer_handle(); 646 647 static inline Environment* from_immediate_check_handle(uv_check_t* handle); 648 inline uv_check_t* immediate_check_handle(); 649 inline uv_idle_t* immediate_idle_handle(); 650 651 inline void IncreaseWaitingRequestCounter(); 652 inline void DecreaseWaitingRequestCounter(); 653 654 inline AsyncHooks* async_hooks(); 655 inline ImmediateInfo* immediate_info(); 656 inline AliasedInt32Array& timeout_info(); 657 inline TickInfo* tick_info(); 658 inline uint64_t timer_base() const; 659 inline std::shared_ptr<KVStore> env_vars(); 660 inline void set_env_vars(std::shared_ptr<KVStore> env_vars); 661 662 inline IsolateData* isolate_data() const; 663 664 inline bool printed_error() const; 665 inline void set_printed_error(bool value); 666 667 void PrintSyncTrace() const; 668 inline void set_trace_sync_io(bool value); 669 670 inline void set_force_context_aware(bool value); 671 inline bool force_context_aware() const; 672 673 // This is a pseudo-boolean that keeps track of whether the process is 674 // exiting. 675 inline void set_exiting(bool value); 676 inline AliasedUint32Array& exiting(); 677 678 // This stores whether the --abort-on-uncaught-exception flag was passed 679 // to Node. 680 inline bool abort_on_uncaught_exception() const; 681 inline void set_abort_on_uncaught_exception(bool value); 682 // This is a pseudo-boolean that keeps track of whether an uncaught exception 683 // should abort the process or not if --abort-on-uncaught-exception was 684 // passed to Node. If the flag was not passed, it is ignored. 685 inline AliasedUint32Array& should_abort_on_uncaught_toggle(); 686 687 inline AliasedInt32Array& stream_base_state(); 688 689 // The necessary API for async_hooks. 690 inline double new_async_id(); 691 inline double execution_async_id(); 692 inline double trigger_async_id(); 693 inline double get_default_trigger_async_id(); 694 695 // List of id's that have been destroyed and need the destroy() cb called. 696 inline std::vector<double>* destroy_async_id_list(); 697 698 builtins::BuiltinLoader* builtin_loader(); 699 700 std::unordered_multimap<int, loader::ModuleWrap*> hash_to_module_map; 701 enabled_debug_list()702 EnabledDebugList* enabled_debug_list() { return &enabled_debug_list_; } 703 704 inline performance::PerformanceState* performance_state(); 705 706 void CollectUVExceptionInfo(v8::Local<v8::Value> context, 707 int errorno, 708 const char* syscall = nullptr, 709 const char* message = nullptr, 710 const char* path = nullptr, 711 const char* dest = nullptr); 712 713 // If this flag is set, calls into JS (if they would be observable 714 // from userland) must be avoided. This flag does not indicate whether 715 // calling into JS is allowed from a VM perspective at this point. 716 inline bool can_call_into_js() const; 717 inline void set_can_call_into_js(bool can_call_into_js); 718 719 // Increase or decrease a counter that manages whether this Environment 720 // keeps the event loop alive on its own or not. The counter starts out at 0, 721 // meaning it does not, and any positive value will make it keep the event 722 // loop alive. 723 // This is used by Workers to manage their own .ref()/.unref() implementation, 724 // as Workers aren't directly associated with their own libuv handles. 725 void add_refs(int64_t diff); 726 727 // Convenient getter of the principal realm's has_run_bootstrapping_code(). 728 inline bool has_run_bootstrapping_code() const; 729 730 inline bool has_serialized_options() const; 731 inline void set_has_serialized_options(bool has_serialized_options); 732 733 inline bool is_main_thread() const; 734 inline bool no_native_addons() const; 735 inline bool should_not_register_esm_loader() const; 736 inline bool should_create_inspector() const; 737 inline bool owns_process_state() const; 738 inline bool owns_inspector() const; 739 inline bool tracks_unmanaged_fds() const; 740 inline bool hide_console_windows() const; 741 inline bool no_global_search_paths() const; 742 inline bool no_browser_globals() const; 743 inline uint64_t thread_id() const; 744 inline worker::Worker* worker_context() const; 745 Environment* worker_parent_env() const; 746 inline void add_sub_worker_context(worker::Worker* context); 747 inline void remove_sub_worker_context(worker::Worker* context); 748 void stop_sub_worker_contexts(); 749 template <typename Fn> 750 inline void ForEachWorker(Fn&& iterator); 751 // Determine if the environment is stopping. This getter is thread-safe. 752 inline bool is_stopping() const; 753 inline void set_stopping(bool value); 754 inline std::list<node_module>* extra_linked_bindings(); 755 inline node_module* extra_linked_bindings_head(); 756 inline node_module* extra_linked_bindings_tail(); 757 inline const Mutex& extra_linked_bindings_mutex() const; 758 759 inline bool filehandle_close_warning() const; 760 inline void set_filehandle_close_warning(bool on); 761 762 inline void set_source_maps_enabled(bool on); 763 inline bool source_maps_enabled() const; 764 765 inline void ThrowError(const char* errmsg); 766 inline void ThrowTypeError(const char* errmsg); 767 inline void ThrowRangeError(const char* errmsg); 768 inline void ThrowErrnoException(int errorno, 769 const char* syscall = nullptr, 770 const char* message = nullptr, 771 const char* path = nullptr); 772 inline void ThrowUVException(int errorno, 773 const char* syscall = nullptr, 774 const char* message = nullptr, 775 const char* path = nullptr, 776 const char* dest = nullptr); 777 778 void AtExit(void (*cb)(void* arg), void* arg); 779 void RunAtExitCallbacks(); 780 781 void RunWeakRefCleanup(); 782 783 v8::MaybeLocal<v8::Value> RunSnapshotSerializeCallback() const; 784 v8::MaybeLocal<v8::Value> RunSnapshotDeserializeCallback() const; 785 v8::MaybeLocal<v8::Value> RunSnapshotDeserializeMain() const; 786 787 // Primitive values are shared across realms. 788 // The getters simply proxy to the per-isolate primitive. 789 #define VP(PropertyName, StringValue) V(v8::Private, PropertyName) 790 #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName) 791 #define VS(PropertyName, StringValue) V(v8::String, PropertyName) 792 #define V(TypeName, PropertyName) \ 793 inline v8::Local<TypeName> PropertyName() const; 794 PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(VP) 795 PER_ISOLATE_SYMBOL_PROPERTIES(VY) 796 PER_ISOLATE_STRING_PROPERTIES(VS) 797 #undef V 798 #undef VS 799 #undef VY 800 #undef VP 801 802 #define V(PropertyName, TypeName) \ 803 inline v8::Local<TypeName> PropertyName() const; \ 804 inline void set_ ## PropertyName(v8::Local<TypeName> value); 805 PER_ISOLATE_TEMPLATE_PROPERTIES(V) 806 // Per-realm strong persistent values of the principal realm. 807 // Get/set the value with an explicit realm instead when possible. 808 // Deprecate soon. 809 PER_REALM_STRONG_PERSISTENT_VALUES(V) 810 #undef V 811 812 // Return the context of the principal realm. 813 // Get the context with an explicit realm instead when possible. 814 // Deprecate soon. 815 inline v8::Local<v8::Context> context() const; 816 inline Realm* principal_realm() const; 817 818 #if HAVE_INSPECTOR inspector_agent()819 inline inspector::Agent* inspector_agent() const { 820 return inspector_agent_.get(); 821 } 822 823 inline bool is_in_inspector_console_call() const; 824 inline void set_is_in_inspector_console_call(bool value); 825 #endif 826 827 typedef ListHead<HandleWrap, &HandleWrap::handle_wrap_queue_> HandleWrapQueue; 828 typedef ListHead<ReqWrapBase, &ReqWrapBase::req_wrap_queue_> ReqWrapQueue; 829 handle_wrap_queue()830 inline HandleWrapQueue* handle_wrap_queue() { return &handle_wrap_queue_; } req_wrap_queue()831 inline ReqWrapQueue* req_wrap_queue() { return &req_wrap_queue_; } 832 EmitProcessEnvWarning()833 inline bool EmitProcessEnvWarning() { 834 bool current_value = emit_env_nonstring_warning_; 835 emit_env_nonstring_warning_ = false; 836 return current_value; 837 } 838 EmitErrNameWarning()839 inline bool EmitErrNameWarning() { 840 bool current_value = emit_err_name_warning_; 841 emit_err_name_warning_ = false; 842 return current_value; 843 } 844 845 // cb will be called as cb(env) on the next event loop iteration. 846 // Unlike the JS setImmediate() function, nested SetImmediate() calls will 847 // be run without returning control to the event loop, similar to nextTick(). 848 template <typename Fn> 849 inline void SetImmediate( 850 Fn&& cb, CallbackFlags::Flags flags = CallbackFlags::kRefed); 851 template <typename Fn> 852 // This behaves like SetImmediate() but can be called from any thread. 853 inline void SetImmediateThreadsafe( 854 Fn&& cb, CallbackFlags::Flags flags = CallbackFlags::kRefed); 855 // This behaves like V8's Isolate::RequestInterrupt(), but also accounts for 856 // the event loop (i.e. combines the V8 function with SetImmediate()). 857 // The passed callback may not throw exceptions. 858 // This function can be called from any thread. 859 template <typename Fn> 860 inline void RequestInterrupt(Fn&& cb); 861 // This needs to be available for the JS-land setImmediate(). 862 void ToggleImmediateRef(bool ref); 863 864 inline void PushShouldNotAbortOnUncaughtScope(); 865 inline void PopShouldNotAbortOnUncaughtScope(); 866 inline bool inside_should_not_abort_on_uncaught_scope() const; 867 868 static inline Environment* ForAsyncHooks(AsyncHooks* hooks); 869 870 v8::Local<v8::Value> GetNow(); 871 void ScheduleTimer(int64_t duration); 872 void ToggleTimerRef(bool ref); 873 874 inline void AddCleanupHook(CleanupQueue::Callback cb, void* arg); 875 inline void RemoveCleanupHook(CleanupQueue::Callback cb, void* arg); 876 void RunCleanup(); 877 878 static size_t NearHeapLimitCallback(void* data, 879 size_t current_heap_limit, 880 size_t initial_heap_limit); 881 static void BuildEmbedderGraph(v8::Isolate* isolate, 882 v8::EmbedderGraph* graph, 883 void* data); 884 885 inline std::shared_ptr<EnvironmentOptions> options(); 886 inline std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port(); 887 stack_trace_limit()888 inline int32_t stack_trace_limit() const { return 10; } 889 890 #if HAVE_INSPECTOR 891 void set_coverage_connection( 892 std::unique_ptr<profiler::V8CoverageConnection> connection); 893 profiler::V8CoverageConnection* coverage_connection(); 894 895 inline void set_coverage_directory(const char* directory); 896 inline const std::string& coverage_directory() const; 897 898 void set_cpu_profiler_connection( 899 std::unique_ptr<profiler::V8CpuProfilerConnection> connection); 900 profiler::V8CpuProfilerConnection* cpu_profiler_connection(); 901 902 inline void set_cpu_prof_name(const std::string& name); 903 inline const std::string& cpu_prof_name() const; 904 905 inline void set_cpu_prof_interval(uint64_t interval); 906 inline uint64_t cpu_prof_interval() const; 907 908 inline void set_cpu_prof_dir(const std::string& dir); 909 inline const std::string& cpu_prof_dir() const; 910 911 void set_heap_profiler_connection( 912 std::unique_ptr<profiler::V8HeapProfilerConnection> connection); 913 profiler::V8HeapProfilerConnection* heap_profiler_connection(); 914 915 inline void set_heap_prof_name(const std::string& name); 916 inline const std::string& heap_prof_name() const; 917 918 inline void set_heap_prof_dir(const std::string& dir); 919 inline const std::string& heap_prof_dir() const; 920 921 inline void set_heap_prof_interval(uint64_t interval); 922 inline uint64_t heap_prof_interval() const; 923 924 #endif // HAVE_INSPECTOR 925 926 inline void set_process_exit_handler( 927 std::function<void(Environment*, int)>&& handler); 928 929 void RunAndClearNativeImmediates(bool only_refed = false); 930 void RunAndClearInterrupts(); 931 932 uv_buf_t allocate_managed_buffer(const size_t suggested_size); 933 std::unique_ptr<v8::BackingStore> release_managed_buffer(const uv_buf_t& buf); 934 935 void AddUnmanagedFd(int fd); 936 void RemoveUnmanagedFd(int fd); 937 938 template <typename T> 939 void ForEachRealm(T&& iterator) const; 940 941 inline void set_heap_snapshot_near_heap_limit(uint32_t limit); 942 inline bool is_in_heapsnapshot_heap_limit_callback() const; 943 944 inline void AddHeapSnapshotNearHeapLimitCallback(); 945 946 inline void RemoveHeapSnapshotNearHeapLimitCallback(size_t heap_limit); 947 948 private: 949 inline void ThrowError(v8::Local<v8::Value> (*fun)(v8::Local<v8::String>), 950 const char* errmsg); 951 952 std::list<binding::DLib> loaded_addons_; 953 v8::Isolate* const isolate_; 954 IsolateData* const isolate_data_; 955 uv_timer_t timer_handle_; 956 uv_check_t immediate_check_handle_; 957 uv_idle_t immediate_idle_handle_; 958 uv_prepare_t idle_prepare_handle_; 959 uv_check_t idle_check_handle_; 960 uv_async_t task_queues_async_; 961 int64_t task_queues_async_refs_ = 0; 962 963 // These may be read by ctors and should be listed before complex fields. 964 std::atomic_bool is_stopping_{false}; 965 std::atomic_bool can_call_into_js_{true}; 966 967 AsyncHooks async_hooks_; 968 ImmediateInfo immediate_info_; 969 AliasedInt32Array timeout_info_; 970 TickInfo tick_info_; 971 const uint64_t timer_base_; 972 std::shared_ptr<KVStore> env_vars_; 973 bool printed_error_ = false; 974 bool trace_sync_io_ = false; 975 bool emit_env_nonstring_warning_ = true; 976 bool emit_err_name_warning_ = true; 977 bool emit_filehandle_warning_ = true; 978 bool source_maps_enabled_ = false; 979 980 size_t async_callback_scope_depth_ = 0; 981 std::vector<double> destroy_async_id_list_; 982 983 #if HAVE_INSPECTOR 984 std::unique_ptr<profiler::V8CoverageConnection> coverage_connection_; 985 std::unique_ptr<profiler::V8CpuProfilerConnection> cpu_profiler_connection_; 986 std::string coverage_directory_; 987 std::string cpu_prof_dir_; 988 std::string cpu_prof_name_; 989 uint64_t cpu_prof_interval_; 990 std::unique_ptr<profiler::V8HeapProfilerConnection> heap_profiler_connection_; 991 std::string heap_prof_dir_; 992 std::string heap_prof_name_; 993 uint64_t heap_prof_interval_; 994 #endif // HAVE_INSPECTOR 995 996 std::shared_ptr<EnvironmentOptions> options_; 997 // options_ contains debug options parsed from CLI arguments, 998 // while inspector_host_port_ stores the actual inspector host 999 // and port being used. For example the port is -1 by default 1000 // and can be specified as 0 (meaning any port allocated when the 1001 // server starts listening), but when the inspector server starts 1002 // the inspector_host_port_->port() will be the actual port being 1003 // used. 1004 std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port_; 1005 std::vector<std::string> exec_argv_; 1006 std::vector<std::string> argv_; 1007 std::string exec_path_; 1008 1009 bool is_in_heapsnapshot_heap_limit_callback_ = false; 1010 uint32_t heap_limit_snapshot_taken_ = 0; 1011 uint32_t heap_snapshot_near_heap_limit_ = 0; 1012 bool heapsnapshot_near_heap_limit_callback_added_ = false; 1013 1014 uint32_t module_id_counter_ = 0; 1015 uint32_t script_id_counter_ = 0; 1016 uint32_t function_id_counter_ = 0; 1017 1018 AliasedUint32Array exiting_; 1019 1020 AliasedUint32Array should_abort_on_uncaught_toggle_; 1021 int should_not_abort_scope_counter_ = 0; 1022 1023 std::unique_ptr<TrackingTraceStateObserver> trace_state_observer_; 1024 1025 AliasedInt32Array stream_base_state_; 1026 1027 uint64_t environment_start_time_; 1028 std::unique_ptr<performance::PerformanceState> performance_state_; 1029 1030 bool has_serialized_options_ = false; 1031 1032 uint64_t flags_; 1033 uint64_t thread_id_; 1034 std::unordered_set<worker::Worker*> sub_worker_contexts_; 1035 1036 #if HAVE_INSPECTOR 1037 std::unique_ptr<inspector::Agent> inspector_agent_; 1038 bool is_in_inspector_console_call_ = false; 1039 #endif 1040 1041 std::list<DeserializeRequest> deserialize_requests_; 1042 1043 // handle_wrap_queue_ and req_wrap_queue_ needs to be at a fixed offset from 1044 // the start of the class because it is used by 1045 // src/node_postmortem_metadata.cc to calculate offsets and generate debug 1046 // symbols for Environment, which assumes that the position of members in 1047 // memory are predictable. For more information please refer to 1048 // `doc/contributing/node-postmortem-support.md` 1049 friend int GenDebugSymbols(); 1050 HandleWrapQueue handle_wrap_queue_; 1051 ReqWrapQueue req_wrap_queue_; 1052 std::list<HandleCleanup> handle_cleanup_queue_; 1053 int handle_cleanup_waiting_ = 0; 1054 int request_waiting_ = 0; 1055 1056 EnabledDebugList enabled_debug_list_; 1057 1058 std::vector<v8::Global<v8::Context>> contexts_; 1059 std::list<node_module> extra_linked_bindings_; 1060 Mutex extra_linked_bindings_mutex_; 1061 1062 static void RunTimers(uv_timer_t* handle); 1063 1064 struct ExitCallback { 1065 void (*cb_)(void* arg); 1066 void* arg_; 1067 }; 1068 1069 std::list<ExitCallback> at_exit_functions_; 1070 1071 typedef CallbackQueue<void, Environment*> NativeImmediateQueue; 1072 NativeImmediateQueue native_immediates_; 1073 Mutex native_immediates_threadsafe_mutex_; 1074 NativeImmediateQueue native_immediates_threadsafe_; 1075 NativeImmediateQueue native_immediates_interrupts_; 1076 // Also guarded by native_immediates_threadsafe_mutex_. This can be used when 1077 // trying to post tasks from other threads to an Environment, as the libuv 1078 // handle for the immediate queues (task_queues_async_) may not be initialized 1079 // yet or already have been destroyed. 1080 bool task_queues_async_initialized_ = false; 1081 1082 std::atomic<Environment**> interrupt_data_ {nullptr}; 1083 void RequestInterruptFromV8(); 1084 static void CheckImmediate(uv_check_t* handle); 1085 1086 CleanupQueue cleanup_queue_; 1087 bool started_cleanup_ = false; 1088 1089 std::unordered_set<int> unmanaged_fds_; 1090 1091 std::function<void(Environment*, int)> process_exit_handler_ { 1092 DefaultProcessExitHandler }; 1093 1094 std::unique_ptr<Realm> principal_realm_ = nullptr; 1095 1096 builtins::BuiltinLoader builtin_loader_; 1097 1098 // Used by allocate_managed_buffer() and release_managed_buffer() to keep 1099 // track of the BackingStore for a given pointer. 1100 std::unordered_map<char*, std::unique_ptr<v8::BackingStore>> 1101 released_allocated_buffers_; 1102 }; 1103 1104 } // namespace node 1105 1106 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 1107 1108 #endif // SRC_ENV_H_ 1109