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 24namespace node { 25 26using v8::Context; 27using v8::HandleScope; 28using v8::Isolate; 29using v8::Local; 30using v8::Locker; 31 32NodeMainInstance::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 50std::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 60NodeMainInstance::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 95void 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 102NodeMainInstance::~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 111int 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 126void 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 138DeleteFnPtr<Environment, FreeEnvironment> 139NodeMainInstance::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