GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: env.h Lines: 39 39 100.0 %
Date: 2022-12-07 04:23:16 Branches: 0 0 - %

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