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

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

15093
}  // namespace node