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-05-05 22:32:45 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
4525
NativeModuleLoader NativeModuleLoader::instance_;
23
24
4525
NativeModuleLoader::NativeModuleLoader() : config_(GetConfig()) {
25
4525
  LoadJavaScriptSource();
26
4525
}
27
28
400746
NativeModuleLoader* NativeModuleLoader::GetInstance() {
29
400746
  return &instance_;
30
}
31
32
4469
bool NativeModuleLoader::Exists(const char* id) {
33
4469
  return source_.find(id) != source_.end();
34
}
35
36
83
Local<Object> NativeModuleLoader::GetSourceObject(Local<Context> context) {
37
83
  Isolate* isolate = context->GetIsolate();
38
83
  Local<Object> out = Object::New(isolate);
39
17015
  for (auto const& x : source_) {
40
16932
    Local<String> key = OneByteString(isolate, x.first.c_str(), x.first.size());
41
50796
    out->Set(context, key, x.second.ToStringChecked(isolate)).FromJust();
42
  }
43
83
  return out;
44
}
45
46
4729
Local<String> NativeModuleLoader::GetConfigString(Isolate* isolate) {
47
4729
  return config_.ToStringChecked(isolate);
48
}
49
50
4652
std::vector<std::string> NativeModuleLoader::GetModuleIds() {
51
4652
  std::vector<std::string> ids;
52
4652
  ids.reserve(source_.size());
53
953660
  for (auto const& x : source_) {
54
949008
    ids.emplace_back(x.first);
55
  }
56
4652
  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
566
        continue;
111
      }
112
1066
      if (id.find(prefix) == 0) {
113
80
        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
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
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
4474
NativeModuleCacheMap* NativeModuleLoader::code_cache() {
147
4474
  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
353214
MaybeLocal<Function> NativeModuleLoader::CompileAsModule(
162
    Local<Context> context,
163
    const char* id,
164
    NativeModuleLoader::Result* result) {
165
353214
  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
353220
      FIXED_ONE_BYTE_STRING(isolate, "primordials")};
173
353220
  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
382499
MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
180
    Local<Context> context,
181
    const char* id,
182
    std::vector<Local<String>>* parameters,
183
    NativeModuleLoader::Result* result) {
184
382499
  Isolate* isolate = context->GetIsolate();
185
382500
  EscapableHandleScope scope(isolate);
186
187
382500
  const auto source_it = source_.find(id);
188
382500
  CHECK_NE(source_it, source_.end());
189
382500
  Local<String> source = source_it->second.ToStringChecked(isolate);
190
191
764999
  std::string filename_s = id + std::string(".js");
192
  Local<String> filename =
193
382496
      OneByteString(isolate, filename_s.c_str(), filename_s.size());
194
382501
  Local<Integer> line_offset = Integer::New(isolate, 0);
195
382497
  Local<Integer> column_offset = Integer::New(isolate, 0);
196
382499
  ScriptOrigin origin(filename, line_offset, column_offset, True(isolate));
197
198
765000
  Mutex::ScopedLock lock(code_cache_mutex_);
199
200
382501
  ScriptCompiler::CachedData* cached_data = nullptr;
201
  {
202
382501
    auto cache_it = code_cache_.find(id);
203
382501
    if (cache_it != code_cache_.end()) {
204
      // Transfer ownership to ScriptCompiler::Source later.
205
350262
      cached_data = cache_it->second.release();
206
350262
      code_cache_.erase(cache_it);
207
    }
208
  }
209
210
382501
  const bool has_cache = cached_data != nullptr;
211
  ScriptCompiler::CompileOptions options =
212
      has_cache ? ScriptCompiler::kConsumeCodeCache
213
382501
                : 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
382501
                                               options);
224
225
  // This could fail when there are early errors in the native modules,
226
  // e.g. the syntax errors
227
382501
  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
382501
  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
350262
  *result = (has_cache && !script_source.GetCachedData()->rejected)
241
                ? Result::kWithCache
242

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

13575
}  // namespace node