• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "node_main_instance.h"
2 #include <memory>
3 #if HAVE_OPENSSL
4 #include "crypto/crypto_util.h"
5 #endif  // HAVE_OPENSSL
6 #include "debug_utils-inl.h"
7 #include "node_builtins.h"
8 #include "node_external_reference.h"
9 #include "node_internals.h"
10 #include "node_options-inl.h"
11 #include "node_realm.h"
12 #include "node_snapshot_builder.h"
13 #include "node_snapshotable.h"
14 #include "node_v8_platform-inl.h"
15 #include "util-inl.h"
16 #if defined(LEAK_SANITIZER)
17 #include <sanitizer/lsan_interface.h>
18 #endif
19 
20 #if HAVE_INSPECTOR
21 #include "inspector/worker_inspector.h"  // ParentInspectorHandle
22 #endif
23 
24 namespace node {
25 
26 using v8::Context;
27 using v8::HandleScope;
28 using v8::Isolate;
29 using v8::Local;
30 using v8::Locker;
31 
NodeMainInstance(Isolate * isolate,uv_loop_t * event_loop,MultiIsolatePlatform * platform,const std::vector<std::string> & args,const std::vector<std::string> & exec_args)32 NodeMainInstance::NodeMainInstance(Isolate* isolate,
33                                    uv_loop_t* event_loop,
34                                    MultiIsolatePlatform* platform,
35                                    const std::vector<std::string>& args,
36                                    const std::vector<std::string>& exec_args)
37     : args_(args),
38       exec_args_(exec_args),
39       array_buffer_allocator_(nullptr),
40       isolate_(isolate),
41       platform_(platform),
42       isolate_data_(nullptr),
43       snapshot_data_(nullptr) {
44   isolate_data_ =
45       std::make_unique<IsolateData>(isolate_, event_loop, platform, nullptr);
46 
47   SetIsolateMiscHandlers(isolate_, {});
48 }
49 
Create(Isolate * isolate,uv_loop_t * event_loop,MultiIsolatePlatform * platform,const std::vector<std::string> & args,const std::vector<std::string> & exec_args)50 std::unique_ptr<NodeMainInstance> NodeMainInstance::Create(
51     Isolate* isolate,
52     uv_loop_t* event_loop,
53     MultiIsolatePlatform* platform,
54     const std::vector<std::string>& args,
55     const std::vector<std::string>& exec_args) {
56   return std::unique_ptr<NodeMainInstance>(
57       new NodeMainInstance(isolate, event_loop, platform, args, exec_args));
58 }
59 
NodeMainInstance(const SnapshotData * snapshot_data,uv_loop_t * event_loop,MultiIsolatePlatform * platform,const std::vector<std::string> & args,const std::vector<std::string> & exec_args)60 NodeMainInstance::NodeMainInstance(const SnapshotData* snapshot_data,
61                                    uv_loop_t* event_loop,
62                                    MultiIsolatePlatform* platform,
63                                    const std::vector<std::string>& args,
64                                    const std::vector<std::string>& exec_args)
65     : args_(args),
66       exec_args_(exec_args),
67       array_buffer_allocator_(ArrayBufferAllocator::Create()),
68       isolate_(nullptr),
69       platform_(platform),
70       isolate_data_(),
71       isolate_params_(std::make_unique<Isolate::CreateParams>()),
72       snapshot_data_(snapshot_data) {
73   isolate_params_->array_buffer_allocator = array_buffer_allocator_.get();
74   if (snapshot_data != nullptr) {
75     SnapshotBuilder::InitializeIsolateParams(snapshot_data,
76                                              isolate_params_.get());
77   }
78 
79   isolate_ = NewIsolate(
80       isolate_params_.get(), event_loop, platform, snapshot_data != nullptr);
81   CHECK_NOT_NULL(isolate_);
82 
83   // If the indexes are not nullptr, we are not deserializing
84   isolate_data_ = std::make_unique<IsolateData>(
85       isolate_,
86       event_loop,
87       platform,
88       array_buffer_allocator_.get(),
89       snapshot_data == nullptr ? nullptr : &(snapshot_data->isolate_data_info));
90 
91   isolate_data_->max_young_gen_size =
92       isolate_params_->constraints.max_young_generation_size_in_bytes();
93 }
94 
Dispose()95 void NodeMainInstance::Dispose() {
96   // This should only be called on a main instance that does not own its
97   // isolate.
98   CHECK_NULL(isolate_params_);
99   platform_->DrainTasks(isolate_);
100 }
101 
~NodeMainInstance()102 NodeMainInstance::~NodeMainInstance() {
103   if (isolate_params_ == nullptr) {
104     return;
105   }
106   // This should only be done on a main instance that owns its isolate.
107   platform_->UnregisterIsolate(isolate_);
108   isolate_->Dispose();
109 }
110 
Run()111 int NodeMainInstance::Run() {
112   Locker locker(isolate_);
113   Isolate::Scope isolate_scope(isolate_);
114   HandleScope handle_scope(isolate_);
115 
116   int exit_code = 0;
117   DeleteFnPtr<Environment, FreeEnvironment> env =
118       CreateMainEnvironment(&exit_code);
119   CHECK_NOT_NULL(env);
120 
121   Context::Scope context_scope(env->context());
122   Run(&exit_code, env.get());
123   return exit_code;
124 }
125 
Run(int * exit_code,Environment * env)126 void NodeMainInstance::Run(int* exit_code, Environment* env) {
127   if (*exit_code == 0) {
128     LoadEnvironment(env, StartExecutionCallback{});
129 
130     *exit_code = SpinEventLoop(env).FromMaybe(1);
131   }
132 
133 #if defined(LEAK_SANITIZER)
134   __lsan_do_leak_check();
135 #endif
136 }
137 
138 DeleteFnPtr<Environment, FreeEnvironment>
CreateMainEnvironment(int * exit_code)139 NodeMainInstance::CreateMainEnvironment(int* exit_code) {
140   *exit_code = 0;  // Reset the exit code to 0
141 
142   HandleScope handle_scope(isolate_);
143 
144   // TODO(addaleax): This should load a real per-Isolate option, currently
145   // this is still effectively per-process.
146   if (isolate_data_->options()->track_heap_objects) {
147     isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
148   }
149 
150   Local<Context> context;
151   DeleteFnPtr<Environment, FreeEnvironment> env;
152 
153   if (snapshot_data_ != nullptr) {
154     env.reset(new Environment(isolate_data_.get(),
155                               isolate_,
156                               args_,
157                               exec_args_,
158                               &(snapshot_data_->env_info),
159                               EnvironmentFlags::kDefaultFlags,
160                               {}));
161 #ifdef NODE_V8_SHARED_RO_HEAP
162     // TODO(addaleax): Do this as part of creating the Environment
163     // once we store the SnapshotData* itself on IsolateData.
164     env->builtin_loader()->RefreshCodeCache(snapshot_data_->code_cache);
165 #endif
166     context = Context::FromSnapshot(isolate_,
167                                     SnapshotData::kNodeMainContextIndex,
168                                     {DeserializeNodeInternalFields, env.get()})
169                   .ToLocalChecked();
170 
171     CHECK(!context.IsEmpty());
172     Context::Scope context_scope(context);
173 
174     CHECK(InitializeContextRuntime(context).IsJust());
175     SetIsolateErrorHandlers(isolate_, {});
176     env->InitializeMainContext(context, &(snapshot_data_->env_info));
177 #if HAVE_INSPECTOR
178     env->InitializeInspector({});
179 #endif
180 
181 #if HAVE_OPENSSL
182     crypto::InitCryptoOnce(isolate_);
183 #endif  // HAVE_OPENSSL
184   } else {
185     context = NewContext(isolate_);
186     CHECK(!context.IsEmpty());
187     Context::Scope context_scope(context);
188     env.reset(
189         CreateEnvironment(isolate_data_.get(), context, args_, exec_args_));
190   }
191 
192   return env;
193 }
194 
195 }  // namespace node
196