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