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