GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: api/embed_helpers.cc Lines: 86 97 88.7 %
Date: 2022-11-05 03:21:31 Branches: 32 50 64.0 %

Line Branch Exec Source
1
#include "node.h"
2
#include "env-inl.h"
3
#include "debug_utils-inl.h"
4
5
using v8::Context;
6
using v8::Function;
7
using v8::Global;
8
using v8::HandleScope;
9
using v8::Isolate;
10
using v8::Just;
11
using v8::Local;
12
using v8::Locker;
13
using v8::Maybe;
14
using v8::Nothing;
15
using v8::SealHandleScope;
16
17
namespace node {
18
19
5964
Maybe<ExitCode> SpinEventLoopInternal(Environment* env) {
20
5964
  CHECK_NOT_NULL(env);
21
5964
  MultiIsolatePlatform* platform = GetMultiIsolatePlatform(env);
22
5964
  CHECK_NOT_NULL(platform);
23
24
5964
  Isolate* isolate = env->isolate();
25
11676
  HandleScope handle_scope(isolate);
26
5964
  Context::Scope context_scope(env->context());
27
11676
  SealHandleScope seal(isolate);
28
29
5964
  if (env->is_stopping()) return Nothing<ExitCode>();
30
31
5964
  env->set_trace_sync_io(env->options()->trace_sync_io);
32
  {
33
    bool more;
34
5964
    env->performance_state()->Mark(
35
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
36
62
    do {
37
6026
      if (env->is_stopping()) break;
38
6026
      uv_run(env->event_loop(), UV_RUN_DEFAULT);
39
5794
      if (env->is_stopping()) break;
40
41
5492
      platform->DrainTasks(isolate);
42
43
5484
      more = uv_loop_alive(env->event_loop());
44

5484
      if (more && !env->is_stopping()) continue;
45
46
10872
      if (EmitProcessBeforeExit(env).IsNothing())
47
24
        break;
48
49
      {
50
5411
        HandleScope handle_scope(isolate);
51
10822
        if (env->RunSnapshotSerializeCallback().IsEmpty()) {
52
          break;
53
        }
54
      }
55
56
      // Emit `beforeExit` if the loop became alive either after emitting
57
      // event, or after running some callbacks.
58
5411
      more = uv_loop_alive(env->event_loop());
59

5458
    } while (more == true && !env->is_stopping());
60
5722
    env->performance_state()->Mark(
61
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
62
  }
63
5722
  if (env->is_stopping()) return Nothing<ExitCode>();
64
65
5374
  env->set_trace_sync_io(false);
66
  // Clear the serialize callback even though the JS-land queue should
67
  // be empty this point so that the deserialized instance won't
68
  // attempt to call into JS again.
69
10748
  env->set_snapshot_serialize_callback(Local<Function>());
70
71
5374
  env->PrintInfoForSnapshotIfDebug();
72
10748
  env->ForEachRealm([](Realm* realm) { realm->VerifyNoStrongBaseObjects(); });
73
5374
  return EmitProcessExitInternal(env);
74
}
75
76
struct CommonEnvironmentSetup::Impl {
77
  MultiIsolatePlatform* platform = nullptr;
78
  uv_loop_t loop;
79
  std::shared_ptr<ArrayBufferAllocator> allocator;
80
  Isolate* isolate = nullptr;
81
  DeleteFnPtr<IsolateData, FreeIsolateData> isolate_data;
82
  DeleteFnPtr<Environment, FreeEnvironment> env;
83
  Global<Context> context;
84
};
85
86
7
CommonEnvironmentSetup::CommonEnvironmentSetup(
87
    MultiIsolatePlatform* platform,
88
    std::vector<std::string>* errors,
89
7
    std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
90
7
  : impl_(new Impl()) {
91
7
  CHECK_NOT_NULL(platform);
92
7
  CHECK_NOT_NULL(errors);
93
94
7
  impl_->platform = platform;
95
7
  uv_loop_t* loop = &impl_->loop;
96
  // Use `data` to tell the destructor whether the loop was initialized or not.
97
7
  loop->data = nullptr;
98
7
  int ret = uv_loop_init(loop);
99
7
  if (ret != 0) {
100
    errors->push_back(
101
        SPrintF("Failed to initialize loop: %s", uv_err_name(ret)));
102
    return;
103
  }
104
7
  loop->data = this;
105
106
7
  impl_->allocator = ArrayBufferAllocator::Create();
107
7
  impl_->isolate = NewIsolate(impl_->allocator, &impl_->loop, platform);
108
7
  Isolate* isolate = impl_->isolate;
109
110
  {
111
    Locker locker(isolate);
112
7
    Isolate::Scope isolate_scope(isolate);
113
7
    impl_->isolate_data.reset(CreateIsolateData(
114
7
        isolate, loop, platform, impl_->allocator.get()));
115
116
7
    HandleScope handle_scope(isolate);
117
7
    Local<Context> context = NewContext(isolate);
118
7
    impl_->context.Reset(isolate, context);
119
7
    if (context.IsEmpty()) {
120
      errors->push_back("Failed to initialize V8 Context");
121
      return;
122
    }
123
124
7
    Context::Scope context_scope(context);
125
7
    impl_->env.reset(make_env(this));
126
  }
127
}
128
129
10
CommonEnvironmentSetup::~CommonEnvironmentSetup() {
130
5
  if (impl_->isolate != nullptr) {
131
5
    Isolate* isolate = impl_->isolate;
132
    {
133
5
      Locker locker(isolate);
134
10
      Isolate::Scope isolate_scope(isolate);
135
136
5
      impl_->context.Reset();
137
5
      impl_->env.reset();
138
5
      impl_->isolate_data.reset();
139
    }
140
141
5
    bool platform_finished = false;
142
5
    impl_->platform->AddIsolateFinishedCallback(isolate, [](void* data) {
143
5
      *static_cast<bool*>(data) = true;
144
5
    }, &platform_finished);
145
5
    impl_->platform->UnregisterIsolate(isolate);
146
5
    isolate->Dispose();
147
148
    // Wait until the platform has cleaned up all relevant resources.
149
10
    while (!platform_finished)
150
5
      uv_run(&impl_->loop, UV_RUN_ONCE);
151
  }
152
153

5
  if (impl_->isolate || impl_->loop.data != nullptr)
154
5
    CheckedUvLoopClose(&impl_->loop);
155
156
5
  delete impl_;
157
5
}
158
159
6
Maybe<int> SpinEventLoop(Environment* env) {
160
6
  Maybe<ExitCode> result = SpinEventLoopInternal(env);
161
6
  if (result.IsNothing()) {
162
    return Nothing<int>();
163
  }
164
6
  return Just(static_cast<int>(result.FromJust()));
165
}
166
167
uv_loop_t* CommonEnvironmentSetup::event_loop() const {
168
  return &impl_->loop;
169
}
170
171
std::shared_ptr<ArrayBufferAllocator>
172
CommonEnvironmentSetup::array_buffer_allocator() const {
173
  return impl_->allocator;
174
}
175
176
7
Isolate* CommonEnvironmentSetup::isolate() const {
177
7
  return impl_->isolate;
178
}
179
180
7
IsolateData* CommonEnvironmentSetup::isolate_data() const {
181
7
  return impl_->isolate_data.get();
182
}
183
184
7
Environment* CommonEnvironmentSetup::env() const {
185
7
  return impl_->env.get();
186
}
187
188
14
v8::Local<v8::Context> CommonEnvironmentSetup::context() const {
189
28
  return impl_->context.Get(impl_->isolate);
190
}
191
192
}  // namespace node