GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: api/embed_helpers.cc Lines: 79 88 89.8 %
Date: 2022-05-23 04:15:47 Branches: 30 46 65.2 %

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::Global;
7
using v8::HandleScope;
8
using v8::Isolate;
9
using v8::Local;
10
using v8::Locker;
11
using v8::Maybe;
12
using v8::Nothing;
13
using v8::SealHandleScope;
14
15
namespace node {
16
17
5688
Maybe<int> SpinEventLoop(Environment* env) {
18
5688
  CHECK_NOT_NULL(env);
19
5688
  MultiIsolatePlatform* platform = GetMultiIsolatePlatform(env);
20
5688
  CHECK_NOT_NULL(platform);
21
22
5688
  Isolate* isolate = env->isolate();
23
11159
  HandleScope handle_scope(isolate);
24
5688
  Context::Scope context_scope(env->context());
25
11159
  SealHandleScope seal(isolate);
26
27
5688
  if (env->is_stopping()) return Nothing<int>();
28
29
5688
  env->set_trace_sync_io(env->options()->trace_sync_io);
30
  {
31
    bool more;
32
5688
    env->performance_state()->Mark(
33
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
34
32
    do {
35
5720
      if (env->is_stopping()) break;
36
5720
      uv_run(env->event_loop(), UV_RUN_DEFAULT);
37
5522
      if (env->is_stopping()) break;
38
39
5150
      platform->DrainTasks(isolate);
40
41
5143
      more = uv_loop_alive(env->event_loop());
42

5143
      if (more && !env->is_stopping()) continue;
43
44
10248
      if (EmitProcessBeforeExit(env).IsNothing())
45
11
        break;
46
47
      // Emit `beforeExit` if the loop became alive either after emitting
48
      // event, or after running some callbacks.
49
5112
      more = uv_loop_alive(env->event_loop());
50

5130
    } while (more == true && !env->is_stopping());
51
5481
    env->performance_state()->Mark(
52
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
53
  }
54
5481
  if (env->is_stopping()) return Nothing<int>();
55
56
5093
  env->set_trace_sync_io(false);
57
5093
  env->PrintInfoForSnapshotIfDebug();
58
5093
  env->VerifyNoStrongBaseObjects();
59
5093
  return EmitProcessExit(env);
60
}
61
62
struct CommonEnvironmentSetup::Impl {
63
  MultiIsolatePlatform* platform = nullptr;
64
  uv_loop_t loop;
65
  std::shared_ptr<ArrayBufferAllocator> allocator;
66
  Isolate* isolate = nullptr;
67
  DeleteFnPtr<IsolateData, FreeIsolateData> isolate_data;
68
  DeleteFnPtr<Environment, FreeEnvironment> env;
69
  Global<Context> context;
70
};
71
72
7
CommonEnvironmentSetup::CommonEnvironmentSetup(
73
    MultiIsolatePlatform* platform,
74
    std::vector<std::string>* errors,
75
7
    std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
76
7
  : impl_(new Impl()) {
77
7
  CHECK_NOT_NULL(platform);
78
7
  CHECK_NOT_NULL(errors);
79
80
7
  impl_->platform = platform;
81
7
  uv_loop_t* loop = &impl_->loop;
82
  // Use `data` to tell the destructor whether the loop was initialized or not.
83
7
  loop->data = nullptr;
84
7
  int ret = uv_loop_init(loop);
85
7
  if (ret != 0) {
86
    errors->push_back(
87
        SPrintF("Failed to initialize loop: %s", uv_err_name(ret)));
88
    return;
89
  }
90
7
  loop->data = this;
91
92
7
  impl_->allocator = ArrayBufferAllocator::Create();
93
7
  impl_->isolate = NewIsolate(impl_->allocator, &impl_->loop, platform);
94
7
  Isolate* isolate = impl_->isolate;
95
96
  {
97
    Locker locker(isolate);
98
7
    Isolate::Scope isolate_scope(isolate);
99
7
    impl_->isolate_data.reset(CreateIsolateData(
100
7
        isolate, loop, platform, impl_->allocator.get()));
101
102
7
    HandleScope handle_scope(isolate);
103
7
    Local<Context> context = NewContext(isolate);
104
7
    impl_->context.Reset(isolate, context);
105
7
    if (context.IsEmpty()) {
106
      errors->push_back("Failed to initialize V8 Context");
107
      return;
108
    }
109
110
7
    Context::Scope context_scope(context);
111
7
    impl_->env.reset(make_env(this));
112
  }
113
}
114
115
10
CommonEnvironmentSetup::~CommonEnvironmentSetup() {
116
5
  if (impl_->isolate != nullptr) {
117
5
    Isolate* isolate = impl_->isolate;
118
    {
119
5
      Locker locker(isolate);
120
10
      Isolate::Scope isolate_scope(isolate);
121
122
5
      impl_->context.Reset();
123
5
      impl_->env.reset();
124
5
      impl_->isolate_data.reset();
125
    }
126
127
5
    bool platform_finished = false;
128
5
    impl_->platform->AddIsolateFinishedCallback(isolate, [](void* data) {
129
5
      *static_cast<bool*>(data) = true;
130
5
    }, &platform_finished);
131
5
    impl_->platform->UnregisterIsolate(isolate);
132
5
    isolate->Dispose();
133
134
    // Wait until the platform has cleaned up all relevant resources.
135
10
    while (!platform_finished)
136
5
      uv_run(&impl_->loop, UV_RUN_ONCE);
137
  }
138
139

5
  if (impl_->isolate || impl_->loop.data != nullptr)
140
5
    CheckedUvLoopClose(&impl_->loop);
141
142
5
  delete impl_;
143
5
}
144
145
146
uv_loop_t* CommonEnvironmentSetup::event_loop() const {
147
  return &impl_->loop;
148
}
149
150
std::shared_ptr<ArrayBufferAllocator>
151
CommonEnvironmentSetup::array_buffer_allocator() const {
152
  return impl_->allocator;
153
}
154
155
7
Isolate* CommonEnvironmentSetup::isolate() const {
156
7
  return impl_->isolate;
157
}
158
159
7
IsolateData* CommonEnvironmentSetup::isolate_data() const {
160
7
  return impl_->isolate_data.get();
161
}
162
163
7
Environment* CommonEnvironmentSetup::env() const {
164
7
  return impl_->env.get();
165
}
166
167
14
v8::Local<v8::Context> CommonEnvironmentSetup::context() const {
168
28
  return impl_->context.Get(impl_->isolate);
169
}
170
171
}  // namespace node