GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_native_module.cc Lines: 89 93 95.7 %
Date: 2019-10-08 22:34:21 Branches: 36 42 85.7 %

Line Branch Exec Source
1
#include "node_native_module.h"
2
#include "util-inl.h"
3
4
namespace node {
5
namespace native_module {
6
7
using v8::Context;
8
using v8::EscapableHandleScope;
9
using v8::Function;
10
using v8::HandleScope;
11
using v8::Integer;
12
using v8::Isolate;
13
using v8::Local;
14
using v8::Maybe;
15
using v8::MaybeLocal;
16
using v8::Object;
17
using v8::Script;
18
using v8::ScriptCompiler;
19
using v8::ScriptOrigin;
20
using v8::String;
21
22
4982
NativeModuleLoader NativeModuleLoader::instance_;
23
24
4982
NativeModuleLoader::NativeModuleLoader() : config_(GetConfig()) {
25
4982
  LoadJavaScriptSource();
26
4982
}
27
28
437686
NativeModuleLoader* NativeModuleLoader::GetInstance() {
29
437686
  return &instance_;
30
}
31
32
4923
bool NativeModuleLoader::Exists(const char* id) {
33
4923
  return source_.find(id) != source_.end();
34
}
35
36
279
Local<Object> NativeModuleLoader::GetSourceObject(Local<Context> context) {
37
279
  Isolate* isolate = context->GetIsolate();
38
279
  Local<Object> out = Object::New(isolate);
39
57474
  for (auto const& x : source_) {
40
57195
    Local<String> key = OneByteString(isolate, x.first.c_str(), x.first.size());
41
171585
    out->Set(context, key, x.second.ToStringChecked(isolate)).FromJust();
42
  }
43
279
  return out;
44
}
45
46
5410
Local<String> NativeModuleLoader::GetConfigString(Isolate* isolate) {
47
5410
  return config_.ToStringChecked(isolate);
48
}
49
50
5134
std::vector<std::string> NativeModuleLoader::GetModuleIds() {
51
5134
  std::vector<std::string> ids;
52
5134
  ids.reserve(source_.size());
53
1057604
  for (auto const& x : source_) {
54
1052470
    ids.emplace_back(x.first);
55
  }
56
5134
  return ids;
57
}
58
59
207
void NativeModuleLoader::InitializeModuleCategories() {
60
207
  if (module_categories_.is_initialized) {
61
    DCHECK(!module_categories_.can_be_required.empty());
62
412
    return;
63
  }
64
65
  std::vector<std::string> prefixes = {
66
#if !HAVE_OPENSSL
67
    "internal/crypto/",
68
#endif  // !HAVE_OPENSSL
69
70
    "internal/bootstrap/",
71
    "internal/per_context/",
72
    "internal/deps/",
73
    "internal/main/"
74
2
  };
75
76
12
  module_categories_.cannot_be_required = std::set<std::string> {
77
#if !HAVE_INSPECTOR
78
      "inspector",
79
      "internal/util/inspector",
80
#endif  // !HAVE_INSPECTOR
81
82
#if !NODE_USE_V8_PLATFORM || !defined(NODE_HAVE_I18N_SUPPORT)
83
      "trace_events",
84
#endif  // !NODE_USE_V8_PLATFORM
85
86
#if !HAVE_OPENSSL
87
      "crypto",
88
      "https",
89
      "http2",
90
      "tls",
91
      "_tls_common",
92
      "_tls_wrap",
93
      "internal/http2/core",
94
      "internal/http2/compat",
95
      "internal/policy/manifest",
96
      "internal/process/policy",
97
      "internal/streams/lazy_transform",
98
#endif  // !HAVE_OPENSSL
99
100
      "sys",  // Deprecated.
101
      "internal/test/binding",
102
      "internal/v8_prof_polyfill",
103
      "internal/v8_prof_processor",
104
10
  };
105
106
412
  for (auto const& x : source_) {
107
410
    const std::string& id = x.first;
108
2050
    for (auto const& prefix : prefixes) {
109
1640
      if (prefix.length() > id.length()) {
110
568
        continue;
111
      }
112
1072
      if (id.find(prefix) == 0) {
113
76
        module_categories_.cannot_be_required.emplace(id);
114
      }
115
    }
116
  }
117
118
412
  for (auto const& x : source_) {
119
410
    const std::string& id = x.first;
120
410
    if (0 == module_categories_.cannot_be_required.count(id)) {
121
326
      module_categories_.can_be_required.emplace(id);
122
    }
123
  }
124
125
2
  module_categories_.is_initialized = true;
126
}
127
128
1
const std::set<std::string>& NativeModuleLoader::GetCannotBeRequired() {
129
1
  InitializeModuleCategories();
130
1
  return module_categories_.cannot_be_required;
131
}
132
133
206
const std::set<std::string>& NativeModuleLoader::GetCanBeRequired() {
134
206
  InitializeModuleCategories();
135
206
  return module_categories_.can_be_required;
136
}
137
138
205
bool NativeModuleLoader::CanBeRequired(const char* id) {
139
205
  return GetCanBeRequired().count(id) == 1;
140
}
141
142
bool NativeModuleLoader::CannotBeRequired(const char* id) {
143
  return GetCannotBeRequired().count(id) == 1;
144
}
145
146
4928
NativeModuleCacheMap* NativeModuleLoader::code_cache() {
147
4928
  return &code_cache_;
148
}
149
150
163
ScriptCompiler::CachedData* NativeModuleLoader::GetCodeCache(
151
    const char* id) const {
152
163
  Mutex::ScopedLock lock(code_cache_mutex_);
153
163
  const auto it = code_cache_.find(id);
154
163
  if (it == code_cache_.end()) {
155
    // The module has not been compiled before.
156
    return nullptr;
157
  }
158
163
  return it->second.get();
159
}
160
161
400346
MaybeLocal<Function> NativeModuleLoader::CompileAsModule(
162
    Local<Context> context,
163
    const char* id,
164
    NativeModuleLoader::Result* result) {
165
400346
  Isolate* isolate = context->GetIsolate();
166
  std::vector<Local<String>> parameters = {
167
      FIXED_ONE_BYTE_STRING(isolate, "exports"),
168
      FIXED_ONE_BYTE_STRING(isolate, "require"),
169
      FIXED_ONE_BYTE_STRING(isolate, "module"),
170
      FIXED_ONE_BYTE_STRING(isolate, "process"),
171
      FIXED_ONE_BYTE_STRING(isolate, "internalBinding"),
172
400348
      FIXED_ONE_BYTE_STRING(isolate, "primordials")};
173
400350
  return LookupAndCompile(context, id, &parameters, result);
174
}
175
176
// Returns Local<Function> of the compiled module if return_code_cache
177
// is false (we are only compiling the function).
178
// Otherwise return a Local<Object> containing the cache.
179
417176
MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
180
    Local<Context> context,
181
    const char* id,
182
    std::vector<Local<String>>* parameters,
183
    NativeModuleLoader::Result* result) {
184
417176
  Isolate* isolate = context->GetIsolate();
185
417178
  EscapableHandleScope scope(isolate);
186
187
417178
  const auto source_it = source_.find(id);
188
417176
  CHECK_NE(source_it, source_.end());
189
417176
  Local<String> source = source_it->second.ToStringChecked(isolate);
190
191
834353
  std::string filename_s = id + std::string(".js");
192
  Local<String> filename =
193
417176
      OneByteString(isolate, filename_s.c_str(), filename_s.size());
194
417177
  Local<Integer> line_offset = Integer::New(isolate, 0);
195
417173
  Local<Integer> column_offset = Integer::New(isolate, 0);
196
417175
  ScriptOrigin origin(filename, line_offset, column_offset, True(isolate));
197
198
834353
  Mutex::ScopedLock lock(code_cache_mutex_);
199
200
417178
  ScriptCompiler::CachedData* cached_data = nullptr;
201
  {
202
417178
    auto cache_it = code_cache_.find(id);
203
417178
    if (cache_it != code_cache_.end()) {
204
      // Transfer ownership to ScriptCompiler::Source later.
205
395841
      cached_data = cache_it->second.release();
206
395841
      code_cache_.erase(cache_it);
207
    }
208
  }
209
210
417178
  const bool has_cache = cached_data != nullptr;
211
  ScriptCompiler::CompileOptions options =
212
      has_cache ? ScriptCompiler::kConsumeCodeCache
213
417178
                : ScriptCompiler::kEagerCompile;
214
  ScriptCompiler::Source script_source(source, origin, cached_data);
215
216
  MaybeLocal<Function> maybe_fun =
217
      ScriptCompiler::CompileFunctionInContext(context,
218
                                               &script_source,
219
                                               parameters->size(),
220
                                               parameters->data(),
221
                                               0,
222
                                               nullptr,
223
417178
                                               options);
224
225
  // This could fail when there are early errors in the native modules,
226
  // e.g. the syntax errors
227
417178
  if (maybe_fun.IsEmpty()) {
228
    // In the case of early errors, v8 is already capable of
229
    // decorating the stack for us - note that we use CompileFunctionInContext
230
    // so there is no need to worry about wrappers.
231
    return MaybeLocal<Function>();
232
  }
233
234
417178
  Local<Function> fun = maybe_fun.ToLocalChecked();
235
  // XXX(joyeecheung): this bookkeeping is not exactly accurate because
236
  // it only starts after the Environment is created, so the per_context.js
237
  // will never be in any of these two sets, but the two sets are only for
238
  // testing anyway.
239
240
395841
  *result = (has_cache && !script_source.GetCachedData()->rejected)
241
                ? Result::kWithCache
242

813019
                : Result::kWithoutCache;
243
  // Generate new cache for next compilation
244
  std::unique_ptr<ScriptCompiler::CachedData> new_cached_data(
245
834356
      ScriptCompiler::CreateCodeCacheForFunction(fun));
246
417178
  CHECK_NOT_NULL(new_cached_data);
247
248
  // The old entry should've been erased by now so we can just emplace
249
417178
  code_cache_.emplace(id, std::move(new_cached_data));
250
251
417178
  return scope.Escape(fun);
252
}
253
254
}  // namespace native_module
255

14946
}  // namespace node