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-07 22:40:39 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
4949
NativeModuleLoader NativeModuleLoader::instance_;
23
24
4949
NativeModuleLoader::NativeModuleLoader() : config_(GetConfig()) {
25
4949
  LoadJavaScriptSource();
26
4949
}
27
28
430413
NativeModuleLoader* NativeModuleLoader::GetInstance() {
29
430413
  return &instance_;
30
}
31
32
4894
bool NativeModuleLoader::Exists(const char* id) {
33
4894
  return source_.find(id) != source_.end();
34
}
35
36
282
Local<Object> NativeModuleLoader::GetSourceObject(Local<Context> context) {
37
282
  Isolate* isolate = context->GetIsolate();
38
282
  Local<Object> out = Object::New(isolate);
39
57810
  for (auto const& x : source_) {
40
57528
    Local<String> key = OneByteString(isolate, x.first.c_str(), x.first.size());
41
172584
    out->Set(context, key, x.second.ToStringChecked(isolate)).FromJust();
42
  }
43
282
  return out;
44
}
45
46
5379
Local<String> NativeModuleLoader::GetConfigString(Isolate* isolate) {
47
5379
  return config_.ToStringChecked(isolate);
48
}
49
50
5102
std::vector<std::string> NativeModuleLoader::GetModuleIds() {
51
5102
  std::vector<std::string> ids;
52
5102
  ids.reserve(source_.size());
53
1045910
  for (auto const& x : source_) {
54
1040808
    ids.emplace_back(x.first);
55
  }
56
5102
  return ids;
57
}
58
59
206
void NativeModuleLoader::InitializeModuleCategories() {
60
206
  if (module_categories_.is_initialized) {
61
    DCHECK(!module_categories_.can_be_required.empty());
62
410
    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
410
  for (auto const& x : source_) {
107
408
    const std::string& id = x.first;
108
2040
    for (auto const& prefix : prefixes) {
109
1632
      if (prefix.length() > id.length()) {
110
564
        continue;
111
      }
112
1068
      if (id.find(prefix) == 0) {
113
76
        module_categories_.cannot_be_required.emplace(id);
114
      }
115
    }
116
  }
117
118
410
  for (auto const& x : source_) {
119
408
    const std::string& id = x.first;
120
408
    if (0 == module_categories_.cannot_be_required.count(id)) {
121
324
      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
205
const std::set<std::string>& NativeModuleLoader::GetCanBeRequired() {
134
205
  InitializeModuleCategories();
135
205
  return module_categories_.can_be_required;
136
}
137
138
204
bool NativeModuleLoader::CanBeRequired(const char* id) {
139
204
  return GetCanBeRequired().count(id) == 1;
140
}
141
142
bool NativeModuleLoader::CannotBeRequired(const char* id) {
143
  return GetCannotBeRequired().count(id) == 1;
144
}
145
146
4899
NativeModuleCacheMap* NativeModuleLoader::code_cache() {
147
4899
  return &code_cache_;
148
}
149
150
162
ScriptCompiler::CachedData* NativeModuleLoader::GetCodeCache(
151
    const char* id) const {
152
162
  Mutex::ScopedLock lock(code_cache_mutex_);
153
162
  const auto it = code_cache_.find(id);
154
162
  if (it == code_cache_.end()) {
155
    // The module has not been compiled before.
156
    return nullptr;
157
  }
158
162
  return it->second.get();
159
}
160
161
393285
MaybeLocal<Function> NativeModuleLoader::CompileAsModule(
162
    Local<Context> context,
163
    const char* id,
164
    NativeModuleLoader::Result* result) {
165
393285
  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
393290
      FIXED_ONE_BYTE_STRING(isolate, "primordials")};
173
393290
  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
410017
MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
180
    Local<Context> context,
181
    const char* id,
182
    std::vector<Local<String>>* parameters,
183
    NativeModuleLoader::Result* result) {
184
410017
  Isolate* isolate = context->GetIsolate();
185
410017
  EscapableHandleScope scope(isolate);
186
187
410018
  const auto source_it = source_.find(id);
188
410019
  CHECK_NE(source_it, source_.end());
189
410019
  Local<String> source = source_it->second.ToStringChecked(isolate);
190
191
820034
  std::string filename_s = id + std::string(".js");
192
  Local<String> filename =
193
410017
      OneByteString(isolate, filename_s.c_str(), filename_s.size());
194
410019
  Local<Integer> line_offset = Integer::New(isolate, 0);
195
410018
  Local<Integer> column_offset = Integer::New(isolate, 0);
196
410013
  ScriptOrigin origin(filename, line_offset, column_offset, True(isolate));
197
198
820032
  Mutex::ScopedLock lock(code_cache_mutex_);
199
200
410019
  ScriptCompiler::CachedData* cached_data = nullptr;
201
  {
202
410019
    auto cache_it = code_cache_.find(id);
203
410019
    if (cache_it != code_cache_.end()) {
204
      // Transfer ownership to ScriptCompiler::Source later.
205
388801
      cached_data = cache_it->second.release();
206
388801
      code_cache_.erase(cache_it);
207
    }
208
  }
209
210
410019
  const bool has_cache = cached_data != nullptr;
211
  ScriptCompiler::CompileOptions options =
212
      has_cache ? ScriptCompiler::kConsumeCodeCache
213
410019
                : 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
410019
                                               options);
224
225
  // This could fail when there are early errors in the native modules,
226
  // e.g. the syntax errors
227
410019
  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
410019
  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
388801
  *result = (has_cache && !script_source.GetCachedData()->rejected)
241
                ? Result::kWithCache
242

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

14847
}  // namespace node