GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_native_module_env.cc Lines: 104 118 88.1 %
Date: 2022-04-26 04:15:06 Branches: 18 32 56.2 %

Line Branch Exec Source
1
#include "node_native_module_env.h"
2
#include "env-inl.h"
3
#include "node_external_reference.h"
4
5
namespace node {
6
namespace native_module {
7
8
using v8::Context;
9
using v8::DEFAULT;
10
using v8::Function;
11
using v8::FunctionCallbackInfo;
12
using v8::IntegrityLevel;
13
using v8::Isolate;
14
using v8::Local;
15
using v8::MaybeLocal;
16
using v8::Name;
17
using v8::None;
18
using v8::Object;
19
using v8::PropertyCallbackInfo;
20
using v8::Set;
21
using v8::SideEffectType;
22
using v8::String;
23
using v8::Value;
24
25
17
bool NativeModuleEnv::Add(const char* id, const UnionBytes& source) {
26
17
  return NativeModuleLoader::GetInstance()->Add(id, source);
27
}
28
29
bool NativeModuleEnv::Exists(const char* id) {
30
  return NativeModuleLoader::GetInstance()->Exists(id);
31
}
32
33
38
Local<Object> NativeModuleEnv::GetSourceObject(Local<Context> context) {
34
38
  return NativeModuleLoader::GetInstance()->GetSourceObject(context);
35
}
36
37
675
Local<String> NativeModuleEnv::GetConfigString(Isolate* isolate) {
38
675
  return NativeModuleLoader::GetInstance()->GetConfigString(isolate);
39
}
40
41
1
void NativeModuleEnv::GetModuleCategories(
42
    Local<Name> property, const PropertyCallbackInfo<Value>& info) {
43
1
  Environment* env = Environment::GetCurrent(info);
44
1
  Isolate* isolate = env->isolate();
45
1
  Local<Context> context = env->context();
46
1
  Local<Object> result = Object::New(isolate);
47
48
  // Copy from the per-process categories
49
  std::set<std::string> cannot_be_required =
50
1
      NativeModuleLoader::GetInstance()->GetCannotBeRequired();
51
  std::set<std::string> can_be_required =
52
1
      NativeModuleLoader::GetInstance()->GetCanBeRequired();
53
54
1
  if (!env->owns_process_state()) {
55
    can_be_required.erase("trace_events");
56
    cannot_be_required.insert("trace_events");
57
  }
58
59
  Local<Value> cannot_be_required_js;
60
  Local<Value> can_be_required_js;
61
62
2
  if (!ToV8Value(context, cannot_be_required).ToLocal(&cannot_be_required_js))
63
    return;
64
1
  if (result
65
1
      ->Set(context,
66
            OneByteString(isolate, "cannotBeRequired"),
67
2
            cannot_be_required_js)
68
1
      .IsNothing())
69
    return;
70
2
  if (!ToV8Value(context, can_be_required).ToLocal(&can_be_required_js))
71
    return;
72
1
  if (result
73
1
      ->Set(context,
74
            OneByteString(isolate, "canBeRequired"),
75
2
            can_be_required_js)
76
1
      .IsNothing()) {
77
    return;
78
  }
79
2
  info.GetReturnValue().Set(result);
80
}
81
82
1
void NativeModuleEnv::GetCacheUsage(const FunctionCallbackInfo<Value>& args) {
83
1
  Environment* env = Environment::GetCurrent(args);
84
1
  Isolate* isolate = env->isolate();
85
1
  Local<Context> context = env->context();
86
1
  Local<Object> result = Object::New(isolate);
87
88
  Local<Value> native_modules_with_cache_js;
89
  Local<Value> native_modules_without_cache_js;
90
  Local<Value> native_modules_in_snapshot_js;
91
1
  if (!ToV8Value(context, env->native_modules_with_cache)
92
1
      .ToLocal(&native_modules_with_cache_js)) {
93
    return;
94
  }
95
1
  if (result
96
1
      ->Set(env->context(),
97
            OneByteString(isolate, "compiledWithCache"),
98
2
            native_modules_with_cache_js)
99
1
      .IsNothing()) {
100
    return;
101
  }
102
103
1
  if (!ToV8Value(context, env->native_modules_without_cache)
104
1
      .ToLocal(&native_modules_without_cache_js)) {
105
    return;
106
  }
107
1
  if (result
108
1
      ->Set(env->context(),
109
            OneByteString(isolate, "compiledWithoutCache"),
110
2
            native_modules_without_cache_js)
111
1
      .IsNothing()) {
112
    return;
113
  }
114
115
1
  if (!ToV8Value(context, env->native_modules_in_snapshot)
116
1
      .ToLocal(&native_modules_without_cache_js)) {
117
    return;
118
  }
119
1
  if (result
120
1
      ->Set(env->context(),
121
            OneByteString(isolate, "compiledInSnapshot"),
122
2
            native_modules_without_cache_js)
123
1
      .IsNothing()) {
124
    return;
125
  }
126
127
2
  args.GetReturnValue().Set(result);
128
}
129
130
672
void NativeModuleEnv::ModuleIdsGetter(Local<Name> property,
131
                                      const PropertyCallbackInfo<Value>& info) {
132
672
  Isolate* isolate = info.GetIsolate();
133
134
  std::vector<std::string> ids =
135
672
      NativeModuleLoader::GetInstance()->GetModuleIds();
136
2016
  info.GetReturnValue().Set(
137
1344
      ToV8Value(isolate->GetCurrentContext(), ids).ToLocalChecked());
138
672
}
139
140
637
void NativeModuleEnv::ConfigStringGetter(
141
    Local<Name> property, const PropertyCallbackInfo<Value>& info) {
142
637
  info.GetReturnValue().Set(GetConfigString(info.GetIsolate()));
143
637
}
144
145
357106
void NativeModuleEnv::RecordResult(const char* id,
146
                                   NativeModuleLoader::Result result,
147
                                   Environment* env) {
148
357106
  if (result == NativeModuleLoader::Result::kWithCache) {
149
335264
    env->native_modules_with_cache.insert(id);
150
  } else {
151
21842
    env->native_modules_without_cache.insert(id);
152
  }
153
357106
}
154
348295
void NativeModuleEnv::CompileFunction(const FunctionCallbackInfo<Value>& args) {
155
348295
  Environment* env = Environment::GetCurrent(args);
156
696590
  CHECK(args[0]->IsString());
157
1044885
  node::Utf8Value id_v(env->isolate(), args[0].As<String>());
158
348295
  const char* id = *id_v;
159
  NativeModuleLoader::Result result;
160
  MaybeLocal<Function> maybe =
161
      NativeModuleLoader::GetInstance()->CompileAsModule(
162
348295
          env->context(), id, &result);
163
348295
  RecordResult(id, result, env);
164
  Local<Function> fn;
165
348295
  if (maybe.ToLocal(&fn)) {
166
696590
    args.GetReturnValue().Set(fn);
167
  }
168
348295
}
169
170
// Returns Local<Function> of the compiled module if return_code_cache
171
// is false (we are only compiling the function).
172
// Otherwise return a Local<Object> containing the cache.
173
12652
MaybeLocal<Function> NativeModuleEnv::LookupAndCompile(
174
    Local<Context> context,
175
    const char* id,
176
    std::vector<Local<String>>* parameters,
177
    Environment* optional_env) {
178
  NativeModuleLoader::Result result;
179
  MaybeLocal<Function> maybe =
180
      NativeModuleLoader::GetInstance()->LookupAndCompile(
181
12652
          context, id, parameters, &result);
182
12652
  if (optional_env != nullptr) {
183
8811
    RecordResult(id, result, optional_env);
184
  }
185
12652
  return maybe;
186
}
187
188
4
void HasCachedBuiltins(const FunctionCallbackInfo<Value>& args) {
189
4
  args.GetReturnValue().Set(
190
      v8::Boolean::New(args.GetIsolate(), has_code_cache));
191
4
}
192
193
// TODO(joyeecheung): It is somewhat confusing that Class::Initialize
194
// is used to initialize to the binding, but it is the current convention.
195
// Rename this across the code base to something that makes more sense.
196
637
void NativeModuleEnv::Initialize(Local<Object> target,
197
                                 Local<Value> unused,
198
                                 Local<Context> context,
199
                                 void* priv) {
200
637
  Environment* env = Environment::GetCurrent(context);
201
202
  target
203
637
      ->SetAccessor(env->context(),
204
                    env->config_string(),
205
                    ConfigStringGetter,
206
                    nullptr,
207
                    MaybeLocal<Value>(),
208
                    DEFAULT,
209
                    None,
210
2548
                    SideEffectType::kHasNoSideEffect)
211
      .Check();
212
  target
213
637
      ->SetAccessor(env->context(),
214
                    FIXED_ONE_BYTE_STRING(env->isolate(), "moduleIds"),
215
                    ModuleIdsGetter,
216
                    nullptr,
217
                    MaybeLocal<Value>(),
218
                    DEFAULT,
219
                    None,
220
2548
                    SideEffectType::kHasNoSideEffect)
221
      .Check();
222
223
  target
224
637
      ->SetAccessor(env->context(),
225
                    FIXED_ONE_BYTE_STRING(env->isolate(), "moduleCategories"),
226
                    GetModuleCategories,
227
                    nullptr,
228
                    Local<Value>(),
229
                    DEFAULT,
230
                    None,
231
1274
                    SideEffectType::kHasNoSideEffect)
232
      .Check();
233
234
637
  env->SetMethod(target, "getCacheUsage", NativeModuleEnv::GetCacheUsage);
235
637
  env->SetMethod(target, "compileFunction", NativeModuleEnv::CompileFunction);
236
637
  env->SetMethod(target, "hasCachedBuiltins", HasCachedBuiltins);
237
  // internalBinding('native_module') should be frozen
238
637
  target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust();
239
637
}
240
241
5014
void NativeModuleEnv::RegisterExternalReferences(
242
    ExternalReferenceRegistry* registry) {
243
5014
  registry->Register(ConfigStringGetter);
244
5014
  registry->Register(ModuleIdsGetter);
245
5014
  registry->Register(GetModuleCategories);
246
5014
  registry->Register(GetCacheUsage);
247
5014
  registry->Register(CompileFunction);
248
5014
  registry->Register(HasCachedBuiltins);
249
5014
}
250
251
}  // namespace native_module
252
}  // namespace node
253
254
5082
NODE_MODULE_CONTEXT_AWARE_INTERNAL(
255
    native_module, node::native_module::NativeModuleEnv::Initialize)
256
5014
NODE_MODULE_EXTERNAL_REFERENCE(
257
    native_module,
258
    node::native_module::NativeModuleEnv::RegisterExternalReferences)