GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_main_instance.cc Lines: 77 77 100.0 %
Date: 2022-12-31 04:22:30 Branches: 28 36 77.8 %

Line Branch Exec Source
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
32
8
NodeMainInstance::NodeMainInstance(Isolate* isolate,
33
                                   uv_loop_t* event_loop,
34
                                   MultiIsolatePlatform* platform,
35
                                   const std::vector<std::string>& args,
36
8
                                   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
8
      snapshot_data_(nullptr) {
44
  isolate_data_ =
45
8
      std::make_unique<IsolateData>(isolate_, event_loop, platform, nullptr);
46
47
8
  SetIsolateMiscHandlers(isolate_, {});
48
8
}
49
50
8
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
8
      new NodeMainInstance(isolate, event_loop, platform, args, exec_args));
58
}
59
60
5712
NodeMainInstance::NodeMainInstance(const SnapshotData* snapshot_data,
61
                                   uv_loop_t* event_loop,
62
                                   MultiIsolatePlatform* platform,
63
                                   const std::vector<std::string>& args,
64
5712
                                   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
5712
      snapshot_data_(snapshot_data) {
73
5712
  isolate_params_->array_buffer_allocator = array_buffer_allocator_.get();
74
5712
  if (snapshot_data != nullptr) {
75
5709
    SnapshotBuilder::InitializeIsolateParams(snapshot_data,
76
                                             isolate_params_.get());
77
  }
78
79
5712
  isolate_ = NewIsolate(
80
      isolate_params_.get(), event_loop, platform, snapshot_data != nullptr);
81
5712
  CHECK_NOT_NULL(isolate_);
82
83
  // If the indexes are not nullptr, we are not deserializing
84
5712
  isolate_data_ = std::make_unique<IsolateData>(
85
5712
      isolate_,
86
      event_loop,
87
      platform,
88
5712
      array_buffer_allocator_.get(),
89
11424
      snapshot_data == nullptr ? nullptr : &(snapshot_data->isolate_data_info));
90
91
5712
  isolate_data_->max_young_gen_size =
92
5712
      isolate_params_->constraints.max_young_generation_size_in_bytes();
93
5712
}
94
95
8
void NodeMainInstance::Dispose() {
96
  // This should only be called on a main instance that does not own its
97
  // isolate.
98
8
  CHECK_NULL(isolate_params_);
99
8
  platform_->DrainTasks(isolate_);
100
8
}
101
102


5141
NodeMainInstance::~NodeMainInstance() {
103
5109
  if (isolate_params_ == nullptr) {
104
8
    return;
105
  }
106
  // This should only be done on a main instance that owns its isolate.
107
5101
  platform_->UnregisterIsolate(isolate_);
108
5101
  isolate_->Dispose();
109
5109
}
110
111
5712
ExitCode NodeMainInstance::Run() {
112
10813
  Locker locker(isolate_);
113
10813
  Isolate::Scope isolate_scope(isolate_);
114
10813
  HandleScope handle_scope(isolate_);
115
116
5712
  ExitCode exit_code = ExitCode::kNoFailure;
117
  DeleteFnPtr<Environment, FreeEnvironment> env =
118
10813
      CreateMainEnvironment(&exit_code);
119
5712
  CHECK_NOT_NULL(env);
120
121
5712
  Context::Scope context_scope(env->context());
122
5712
  Run(&exit_code, env.get());
123
5101
  return exit_code;
124
}
125
126
5712
void NodeMainInstance::Run(ExitCode* exit_code, Environment* env) {
127
5712
  if (*exit_code == ExitCode::kNoFailure) {
128
5712
    LoadEnvironment(env, StartExecutionCallback{});
129
130
5101
    *exit_code =
131
10460
        SpinEventLoopInternal(env).FromMaybe(ExitCode::kGenericUserError);
132
  }
133
134
#if defined(LEAK_SANITIZER)
135
  __lsan_do_leak_check();
136
#endif
137
5101
}
138
139
DeleteFnPtr<Environment, FreeEnvironment>
140
5712
NodeMainInstance::CreateMainEnvironment(ExitCode* exit_code) {
141
5712
  *exit_code = ExitCode::kNoFailure;  // Reset the exit code to 0
142
143
11424
  HandleScope handle_scope(isolate_);
144
145
  // TODO(addaleax): This should load a real per-Isolate option, currently
146
  // this is still effectively per-process.
147
5712
  if (isolate_data_->options()->track_heap_objects) {
148
1
    isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
149
  }
150
151
  Local<Context> context;
152
5712
  DeleteFnPtr<Environment, FreeEnvironment> env;
153
154
5712
  if (snapshot_data_ != nullptr) {
155
11418
    env.reset(new Environment(isolate_data_.get(),
156
                              isolate_,
157
5709
                              args_,
158
5709
                              exec_args_,
159
5709
                              &(snapshot_data_->env_info),
160
                              EnvironmentFlags::kDefaultFlags,
161
5709
                              {}));
162
5709
    context = Context::FromSnapshot(isolate_,
163
                                    SnapshotData::kNodeMainContextIndex,
164
5709
                                    {DeserializeNodeInternalFields, env.get()})
165
5709
                  .ToLocalChecked();
166
167
5709
    CHECK(!context.IsEmpty());
168
5709
    Context::Scope context_scope(context);
169
170
11418
    CHECK(InitializeContextRuntime(context).IsJust());
171
5709
    SetIsolateErrorHandlers(isolate_, {});
172
5709
    env->InitializeMainContext(context, &(snapshot_data_->env_info));
173
#if HAVE_INSPECTOR
174
5709
    env->InitializeInspector({});
175
#endif
176
177
#if HAVE_OPENSSL
178
5709
    crypto::InitCryptoOnce(isolate_);
179
#endif  // HAVE_OPENSSL
180
  } else {
181
3
    context = NewContext(isolate_);
182
3
    CHECK(!context.IsEmpty());
183
3
    Context::Scope context_scope(context);
184
6
    env.reset(
185
3
        CreateEnvironment(isolate_data_.get(), context, args_, exec_args_));
186
  }
187
188
5712
  return env;
189
}
190
191
}  // namespace node