• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #ifndef SRC_ENV_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