GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_native_module.cc Lines: 236 266 88.7 %
Date: 2022-07-31 04:16:25 Branches: 74 98 75.5 %

Line Branch Exec Source
1
#include "node_native_module.h"
2
#include "debug_utils-inl.h"
3
#include "env-inl.h"
4
#include "node_external_reference.h"
5
#include "node_internals.h"
6
#include "util-inl.h"
7
8
namespace node {
9
namespace native_module {
10
11
using v8::Context;
12
using v8::DEFAULT;
13
using v8::EscapableHandleScope;
14
using v8::Function;
15
using v8::FunctionCallbackInfo;
16
using v8::IntegrityLevel;
17
using v8::Isolate;
18
using v8::Local;
19
using v8::MaybeLocal;
20
using v8::Name;
21
using v8::None;
22
using v8::Object;
23
using v8::PropertyCallbackInfo;
24
using v8::ScriptCompiler;
25
using v8::ScriptOrigin;
26
using v8::Set;
27
using v8::SideEffectType;
28
using v8::String;
29
using v8::Value;
30
31
NativeModuleLoader NativeModuleLoader::instance_;
32
33
5356
NativeModuleLoader::NativeModuleLoader()
34
5356
    : config_(GetConfig()), has_code_cache_(false) {
35
5356
  LoadJavaScriptSource();
36
5356
}
37
38
498571
NativeModuleLoader* NativeModuleLoader::GetInstance() {
39
498571
  return &instance_;
40
}
41
42
bool NativeModuleLoader::Exists(const char* id) {
43
  auto& source = GetInstance()->source_;
44
  return source.find(id) != source.end();
45
}
46
47
17
bool NativeModuleLoader::Add(const char* id, const UnionBytes& source) {
48
17
  auto result = GetInstance()->source_.emplace(id, source);
49
17
  return result.second;
50
}
51
52
42
Local<Object> NativeModuleLoader::GetSourceObject(Local<Context> context) {
53
42
  Isolate* isolate = context->GetIsolate();
54
42
  Local<Object> out = Object::New(isolate);
55
42
  auto& source = GetInstance()->source_;
56
12642
  for (auto const& x : source) {
57
12600
    Local<String> key = OneByteString(isolate, x.first.c_str(), x.first.size());
58
37800
    out->Set(context, key, x.second.ToStringChecked(isolate)).FromJust();
59
  }
60
42
  return out;
61
}
62
63
1345
Local<String> NativeModuleLoader::GetConfigString(Isolate* isolate) {
64
1345
  return GetInstance()->config_.ToStringChecked(isolate);
65
}
66
67
1348
std::vector<std::string> NativeModuleLoader::GetModuleIds() {
68
1348
  std::vector<std::string> ids;
69
1348
  ids.reserve(source_.size());
70
405903
  for (auto const& x : source_) {
71
404555
    ids.emplace_back(x.first);
72
  }
73
1348
  return ids;
74
}
75
76
1802
void NativeModuleLoader::InitializeModuleCategories() {
77
1802
  if (module_categories_.is_initialized) {
78
    DCHECK(!module_categories_.can_be_required.empty());
79
1795
    return;
80
  }
81
82
  std::vector<std::string> prefixes = {
83
#if !HAVE_OPENSSL
84
    "internal/crypto/",
85
    "internal/debugger/",
86
#endif  // !HAVE_OPENSSL
87
88
    "internal/bootstrap/",
89
    "internal/per_context/",
90
    "internal/deps/",
91
    "internal/main/"
92
49
  };
93
94
  module_categories_.can_be_required.emplace(
95
7
      "internal/deps/cjs-module-lexer/lexer");
96
97
49
  module_categories_.cannot_be_required = std::set<std::string> {
98
#if !HAVE_INSPECTOR
99
      "inspector",
100
      "internal/util/inspector",
101
#endif  // !HAVE_INSPECTOR
102
103
#if !NODE_USE_V8_PLATFORM || !defined(NODE_HAVE_I18N_SUPPORT)
104
      "trace_events",
105
#endif  // !NODE_USE_V8_PLATFORM || !defined(NODE_HAVE_I18N_SUPPORT)
106
107
#if !HAVE_OPENSSL
108
      "crypto",
109
      "crypto/promises",
110
      "https",
111
      "http2",
112
      "tls",
113
      "_tls_common",
114
      "_tls_wrap",
115
      "internal/tls/secure-pair",
116
      "internal/tls/parse-cert-string",
117
      "internal/tls/secure-context",
118
      "internal/http2/core",
119
      "internal/http2/compat",
120
      "internal/policy/manifest",
121
      "internal/process/policy",
122
      "internal/streams/lazy_transform",
123
#endif  // !HAVE_OPENSSL
124
      "sys",  // Deprecated.
125
      "wasi",  // Experimental.
126
      "internal/test/binding",
127
      "internal/v8_prof_polyfill",
128
      "internal/v8_prof_processor",
129
42
  };
130
131
2107
  for (auto const& x : source_) {
132
2100
    const std::string& id = x.first;
133
10500
    for (auto const& prefix : prefixes) {
134
8400
      if (prefix.length() > id.length()) {
135
2429
        continue;
136
      }
137

6244
      if (id.find(prefix) == 0 &&
138
273
          module_categories_.can_be_required.count(id) == 0) {
139
266
        module_categories_.cannot_be_required.emplace(id);
140
      }
141
    }
142
  }
143
144
2107
  for (auto const& x : source_) {
145
2100
    const std::string& id = x.first;
146
2100
    if (0 == module_categories_.cannot_be_required.count(id)) {
147
1799
      module_categories_.can_be_required.emplace(id);
148
    }
149
  }
150
151
7
  module_categories_.is_initialized = true;
152
}
153
154
1
const std::set<std::string>& NativeModuleLoader::GetCannotBeRequired() {
155
1
  InitializeModuleCategories();
156
1
  return module_categories_.cannot_be_required;
157
}
158
159
1801
const std::set<std::string>& NativeModuleLoader::GetCanBeRequired() {
160
1801
  InitializeModuleCategories();
161
1801
  return module_categories_.can_be_required;
162
}
163
164
1800
bool NativeModuleLoader::CanBeRequired(const char* id) {
165
1800
  return GetCanBeRequired().count(id) == 1;
166
}
167
168
bool NativeModuleLoader::CannotBeRequired(const char* id) {
169
  return GetCannotBeRequired().count(id) == 1;
170
}
171
172
5288
NativeModuleCacheMap* NativeModuleLoader::code_cache() {
173
5288
  return &code_cache_;
174
}
175
176
ScriptCompiler::CachedData* NativeModuleLoader::GetCodeCache(
177
    const char* id) const {
178
  Mutex::ScopedLock lock(code_cache_mutex_);
179
  const auto it = code_cache_.find(id);
180
  if (it == code_cache_.end()) {
181
    // The module has not been compiled before.
182
    return nullptr;
183
  }
184
  return it->second.get();
185
}
186
187
478590
MaybeLocal<Function> NativeModuleLoader::CompileAsModule(
188
    Local<Context> context,
189
    const char* id,
190
    NativeModuleLoader::Result* result) {
191
478590
  Isolate* isolate = context->GetIsolate();
192
  std::vector<Local<String>> parameters = {
193
478590
      FIXED_ONE_BYTE_STRING(isolate, "exports"),
194
478590
      FIXED_ONE_BYTE_STRING(isolate, "require"),
195
478590
      FIXED_ONE_BYTE_STRING(isolate, "module"),
196
478590
      FIXED_ONE_BYTE_STRING(isolate, "process"),
197
478590
      FIXED_ONE_BYTE_STRING(isolate, "internalBinding"),
198
957180
      FIXED_ONE_BYTE_STRING(isolate, "primordials")};
199
478590
  return LookupAndCompileInternal(context, id, &parameters, result);
200
}
201
202
#ifdef NODE_BUILTIN_MODULES_PATH
203
static std::string OnDiskFileName(const char* id) {
204
  std::string filename = NODE_BUILTIN_MODULES_PATH;
205
  filename += "/";
206
207
  if (strncmp(id, "internal/deps", strlen("internal/deps")) == 0) {
208
    id += strlen("internal/");
209
  } else {
210
    filename += "lib/";
211
  }
212
  filename += id;
213
  filename += ".js";
214
215
  return filename;
216
}
217
#endif  // NODE_BUILTIN_MODULES_PATH
218
219
492067
MaybeLocal<String> NativeModuleLoader::LoadBuiltinModuleSource(Isolate* isolate,
220
                                                               const char* id) {
221
#ifdef NODE_BUILTIN_MODULES_PATH
222
  if (strncmp(id, "embedder_main_", strlen("embedder_main_")) == 0) {
223
#endif  // NODE_BUILTIN_MODULES_PATH
224
492067
    const auto source_it = source_.find(id);
225
492067
    if (UNLIKELY(source_it == source_.end())) {
226
      fprintf(stderr, "Cannot find native builtin: \"%s\".\n", id);
227
      ABORT();
228
    }
229
984134
    return source_it->second.ToStringChecked(isolate);
230
#ifdef NODE_BUILTIN_MODULES_PATH
231
  }
232
  std::string filename = OnDiskFileName(id);
233
234
  std::string contents;
235
  int r = ReadFileSync(&contents, filename.c_str());
236
  if (r != 0) {
237
    const std::string buf = SPrintF("Cannot read local builtin. %s: %s \"%s\"",
238
                                    uv_err_name(r),
239
                                    uv_strerror(r),
240
                                    filename);
241
    Local<String> message = OneByteString(isolate, buf.c_str());
242
    isolate->ThrowException(v8::Exception::Error(message));
243
    return MaybeLocal<String>();
244
  }
245
  return String::NewFromUtf8(
246
      isolate, contents.c_str(), v8::NewStringType::kNormal, contents.length());
247
#endif  // NODE_BUILTIN_MODULES_PATH
248
}
249
250
// Returns Local<Function> of the compiled module if return_code_cache
251
// is false (we are only compiling the function).
252
// Otherwise return a Local<Object> containing the cache.
253
492067
MaybeLocal<Function> NativeModuleLoader::LookupAndCompileInternal(
254
    Local<Context> context,
255
    const char* id,
256
    std::vector<Local<String>>* parameters,
257
    NativeModuleLoader::Result* result) {
258
492067
  Isolate* isolate = context->GetIsolate();
259
492067
  EscapableHandleScope scope(isolate);
260
261
  Local<String> source;
262
984134
  if (!LoadBuiltinModuleSource(isolate, id).ToLocal(&source)) {
263
    return {};
264
  }
265
266
1476201
  std::string filename_s = std::string("node:") + id;
267
  Local<String> filename =
268
492067
      OneByteString(isolate, filename_s.c_str(), filename_s.size());
269
492067
  ScriptOrigin origin(isolate, filename, 0, 0, true);
270
271
492067
  ScriptCompiler::CachedData* cached_data = nullptr;
272
  {
273
    // Note: The lock here should not extend into the
274
    // `CompileFunctionInContext()` call below, because this function may
275
    // recurse if there is a syntax error during bootstrap (because the fatal
276
    // exception handler is invoked, which may load built-in modules).
277
984134
    Mutex::ScopedLock lock(code_cache_mutex_);
278
492067
    auto cache_it = code_cache_.find(id);
279
492067
    if (cache_it != code_cache_.end()) {
280
      // Transfer ownership to ScriptCompiler::Source later.
281
475296
      cached_data = cache_it->second.release();
282
475296
      code_cache_.erase(cache_it);
283
    }
284
  }
285
286
492067
  const bool has_cache = cached_data != nullptr;
287
492067
  ScriptCompiler::CompileOptions options =
288
492067
      has_cache ? ScriptCompiler::kConsumeCodeCache
289
                : ScriptCompiler::kEagerCompile;
290
492067
  ScriptCompiler::Source script_source(source, origin, cached_data);
291
292
  per_process::Debug(DebugCategory::CODE_CACHE,
293
                     "Compiling %s %s code cache\n",
294
                     id,
295
492067
                     has_cache ? "with" : "without");
296
297
  MaybeLocal<Function> maybe_fun =
298
      ScriptCompiler::CompileFunctionInContext(context,
299
                                               &script_source,
300
                                               parameters->size(),
301
                                               parameters->data(),
302
                                               0,
303
                                               nullptr,
304
492067
                                               options);
305
306
  // This could fail when there are early errors in the native modules,
307
  // e.g. the syntax errors
308
  Local<Function> fun;
309
492067
  if (!maybe_fun.ToLocal(&fun)) {
310
    // In the case of early errors, v8 is already capable of
311
    // decorating the stack for us - note that we use CompileFunctionInContext
312
    // so there is no need to worry about wrappers.
313
    return MaybeLocal<Function>();
314
  }
315
316
  // XXX(joyeecheung): this bookkeeping is not exactly accurate because
317
  // it only starts after the Environment is created, so the per_context.js
318
  // will never be in any of these two sets, but the two sets are only for
319
  // testing anyway.
320
321
475296
  *result = (has_cache && !script_source.GetCachedData()->rejected)
322
967363
                ? Result::kWithCache
323
                : Result::kWithoutCache;
324
325
492067
  if (has_cache) {
326
475296
    per_process::Debug(DebugCategory::CODE_CACHE,
327
                       "Code cache of %s (%s) %s\n",
328
                       id,
329
475296
                       script_source.GetCachedData()->buffer_policy ==
330
                               ScriptCompiler::CachedData::BufferNotOwned
331
950592
                           ? "BufferNotOwned"
332
                           : "BufferOwned",
333
475296
                       script_source.GetCachedData()->rejected ? "is rejected"
334
                                                               : "is accepted");
335
  }
336
337
  // Generate new cache for next compilation
338
  std::unique_ptr<ScriptCompiler::CachedData> new_cached_data(
339
492067
      ScriptCompiler::CreateCodeCacheForFunction(fun));
340
492067
  CHECK_NOT_NULL(new_cached_data);
341
342
  {
343
984134
    Mutex::ScopedLock lock(code_cache_mutex_);
344
492067
    const auto it = code_cache_.find(id);
345
    // TODO(joyeecheung): it's safer for each thread to have its own
346
    // copy of the code cache map.
347
492067
    if (it == code_cache_.end()) {
348
489985
      code_cache_.emplace(id, std::move(new_cached_data));
349
    } else {
350
2082
      it->second.reset(new_cached_data.release());
351
    }
352
  }
353
354
492067
  return scope.Escape(fun);
355
}
356
357
// Returns Local<Function> of the compiled module if return_code_cache
358
// is false (we are only compiling the function).
359
// Otherwise return a Local<Object> containing the cache.
360
13477
MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
361
    Local<Context> context,
362
    const char* id,
363
    std::vector<Local<String>>* parameters,
364
    Environment* optional_env) {
365
  Result result;
366
  MaybeLocal<Function> maybe =
367
13477
      GetInstance()->LookupAndCompileInternal(context, id, parameters, &result);
368
13477
  if (optional_env != nullptr) {
369
13084
    RecordResult(id, result, optional_env);
370
  }
371
13477
  return maybe;
372
}
373
374
6
bool NativeModuleLoader::CompileAllModules(Local<Context> context) {
375
6
  NativeModuleLoader* loader = GetInstance();
376
6
  std::vector<std::string> ids = loader->GetModuleIds();
377
6
  bool all_succeeded = true;
378
1806
  for (const auto& id : ids) {
379
    // TODO(joyeecheung): compile non-module scripts here too.
380
1800
    if (!loader->CanBeRequired(id.c_str())) {
381
258
      continue;
382
    }
383
3084
    v8::TryCatch bootstrapCatch(context->GetIsolate());
384
    Result result;
385
1542
    USE(loader->CompileAsModule(context, id.c_str(), &result));
386
1542
    if (bootstrapCatch.HasCaught()) {
387
      per_process::Debug(DebugCategory::CODE_CACHE,
388
                         "Failed to compile code cache for %s\n",
389
                         id.c_str());
390
      all_succeeded = false;
391
      PrintCaughtException(context->GetIsolate(), context, bootstrapCatch);
392
    }
393
  }
394
6
  return all_succeeded;
395
}
396
397
6
void NativeModuleLoader::CopyCodeCache(std::vector<CodeCacheInfo>* out) {
398
6
  NativeModuleLoader* loader = GetInstance();
399
12
  Mutex::ScopedLock lock(loader->code_cache_mutex());
400
6
  auto in = loader->code_cache();
401
1596
  for (auto const& item : *in) {
402
1590
    out->push_back(
403
1590
        {item.first,
404
1590
         {item.second->data, item.second->data + item.second->length}});
405
  }
406
6
}
407
408
5282
void NativeModuleLoader::RefreshCodeCache(
409
    const std::vector<CodeCacheInfo>& in) {
410
5282
  NativeModuleLoader* loader = GetInstance();
411
5282
  Mutex::ScopedLock lock(loader->code_cache_mutex());
412
5282
  auto out = loader->code_cache();
413
1405012
  for (auto const& item : in) {
414
1399730
    size_t length = item.data.size();
415
1399730
    uint8_t* buffer = new uint8_t[length];
416
1399730
    memcpy(buffer, item.data.data(), length);
417
    auto new_cache = std::make_unique<v8::ScriptCompiler::CachedData>(
418
2799460
        buffer, length, v8::ScriptCompiler::CachedData::BufferOwned);
419
1399730
    auto cache_it = out->find(item.id);
420
1399730
    if (cache_it != out->end()) {
421
      // Release the old cache and replace it with the new copy.
422
      cache_it->second.reset(new_cache.release());
423
    } else {
424
1399730
      out->emplace(item.id, new_cache.release());
425
    }
426
  }
427
5282
  loader->has_code_cache_ = true;
428
5282
}
429
430
1
void NativeModuleLoader::GetModuleCategories(
431
    Local<Name> property, const PropertyCallbackInfo<Value>& info) {
432
1
  Environment* env = Environment::GetCurrent(info);
433
1
  Isolate* isolate = env->isolate();
434
1
  Local<Context> context = env->context();
435
1
  Local<Object> result = Object::New(isolate);
436
437
  // Copy from the per-process categories
438
  std::set<std::string> cannot_be_required =
439
1
      GetInstance()->GetCannotBeRequired();
440
1
  std::set<std::string> can_be_required = GetInstance()->GetCanBeRequired();
441
442
1
  if (!env->owns_process_state()) {
443
    can_be_required.erase("trace_events");
444
    cannot_be_required.insert("trace_events");
445
  }
446
447
  Local<Value> cannot_be_required_js;
448
  Local<Value> can_be_required_js;
449
450
2
  if (!ToV8Value(context, cannot_be_required).ToLocal(&cannot_be_required_js))
451
    return;
452
1
  if (result
453
1
          ->Set(context,
454
                OneByteString(isolate, "cannotBeRequired"),
455
2
                cannot_be_required_js)
456
1
          .IsNothing())
457
    return;
458
2
  if (!ToV8Value(context, can_be_required).ToLocal(&can_be_required_js)) return;
459
1
  if (result
460
1
          ->Set(context,
461
                OneByteString(isolate, "canBeRequired"),
462
2
                can_be_required_js)
463
1
          .IsNothing()) {
464
    return;
465
  }
466
2
  info.GetReturnValue().Set(result);
467
}
468
469
1
void NativeModuleLoader::GetCacheUsage(
470
    const FunctionCallbackInfo<Value>& args) {
471
1
  Environment* env = Environment::GetCurrent(args);
472
1
  Isolate* isolate = env->isolate();
473
1
  Local<Context> context = env->context();
474
1
  Local<Object> result = Object::New(isolate);
475
476
  Local<Value> native_modules_with_cache_js;
477
  Local<Value> native_modules_without_cache_js;
478
  Local<Value> native_modules_in_snapshot_js;
479
1
  if (!ToV8Value(context, env->native_modules_with_cache)
480
1
           .ToLocal(&native_modules_with_cache_js)) {
481
    return;
482
  }
483
1
  if (result
484
1
          ->Set(env->context(),
485
                OneByteString(isolate, "compiledWithCache"),
486
2
                native_modules_with_cache_js)
487
1
          .IsNothing()) {
488
    return;
489
  }
490
491
1
  if (!ToV8Value(context, env->native_modules_without_cache)
492
1
           .ToLocal(&native_modules_without_cache_js)) {
493
    return;
494
  }
495
1
  if (result
496
1
          ->Set(env->context(),
497
                OneByteString(isolate, "compiledWithoutCache"),
498
2
                native_modules_without_cache_js)
499
1
          .IsNothing()) {
500
    return;
501
  }
502
503
1
  if (!ToV8Value(context, env->native_modules_in_snapshot)
504
1
           .ToLocal(&native_modules_without_cache_js)) {
505
    return;
506
  }
507
1
  if (result
508
1
          ->Set(env->context(),
509
                OneByteString(isolate, "compiledInSnapshot"),
510
2
                native_modules_without_cache_js)
511
1
          .IsNothing()) {
512
    return;
513
  }
514
515
2
  args.GetReturnValue().Set(result);
516
}
517
518
1342
void NativeModuleLoader::ModuleIdsGetter(
519
    Local<Name> property, const PropertyCallbackInfo<Value>& info) {
520
1342
  Isolate* isolate = info.GetIsolate();
521
522
1342
  std::vector<std::string> ids = GetInstance()->GetModuleIds();
523
4026
  info.GetReturnValue().Set(
524
2684
      ToV8Value(isolate->GetCurrentContext(), ids).ToLocalChecked());
525
1342
}
526
527
1303
void NativeModuleLoader::ConfigStringGetter(
528
    Local<Name> property, const PropertyCallbackInfo<Value>& info) {
529
1303
  info.GetReturnValue().Set(GetConfigString(info.GetIsolate()));
530
1303
}
531
532
490132
void NativeModuleLoader::RecordResult(const char* id,
533
                                      NativeModuleLoader::Result result,
534
                                      Environment* env) {
535
490132
  if (result == NativeModuleLoader::Result::kWithCache) {
536
466925
    env->native_modules_with_cache.insert(id);
537
  } else {
538
23207
    env->native_modules_without_cache.insert(id);
539
  }
540
490132
}
541
477048
void NativeModuleLoader::CompileFunction(
542
    const FunctionCallbackInfo<Value>& args) {
543
477048
  Environment* env = Environment::GetCurrent(args);
544
954096
  CHECK(args[0]->IsString());
545
1431144
  node::Utf8Value id_v(env->isolate(), args[0].As<String>());
546
477048
  const char* id = *id_v;
547
  NativeModuleLoader::Result result;
548
  MaybeLocal<Function> maybe =
549
477048
      GetInstance()->CompileAsModule(env->context(), id, &result);
550
477048
  RecordResult(id, result, env);
551
  Local<Function> fn;
552
477048
  if (maybe.ToLocal(&fn)) {
553
954096
    args.GetReturnValue().Set(fn);
554
  }
555
477048
}
556
557
4
void NativeModuleLoader::HasCachedBuiltins(
558
    const FunctionCallbackInfo<Value>& args) {
559
4
  args.GetReturnValue().Set(
560
4
      v8::Boolean::New(args.GetIsolate(), GetInstance()->has_code_cache_));
561
4
}
562
563
// TODO(joyeecheung): It is somewhat confusing that Class::Initialize
564
// is used to initialize to the binding, but it is the current convention.
565
// Rename this across the code base to something that makes more sense.
566
1303
void NativeModuleLoader::Initialize(Local<Object> target,
567
                                    Local<Value> unused,
568
                                    Local<Context> context,
569
                                    void* priv) {
570
1303
  Environment* env = Environment::GetCurrent(context);
571
572
  target
573
1303
      ->SetAccessor(env->context(),
574
                    env->config_string(),
575
                    ConfigStringGetter,
576
                    nullptr,
577
                    MaybeLocal<Value>(),
578
                    DEFAULT,
579
                    None,
580
5212
                    SideEffectType::kHasNoSideEffect)
581
      .Check();
582
  target
583
1303
      ->SetAccessor(env->context(),
584
                    FIXED_ONE_BYTE_STRING(env->isolate(), "moduleIds"),
585
                    ModuleIdsGetter,
586
                    nullptr,
587
                    MaybeLocal<Value>(),
588
                    DEFAULT,
589
                    None,
590
5212
                    SideEffectType::kHasNoSideEffect)
591
      .Check();
592
593
  target
594
1303
      ->SetAccessor(env->context(),
595
                    FIXED_ONE_BYTE_STRING(env->isolate(), "moduleCategories"),
596
                    GetModuleCategories,
597
                    nullptr,
598
                    Local<Value>(),
599
                    DEFAULT,
600
                    None,
601
2606
                    SideEffectType::kHasNoSideEffect)
602
      .Check();
603
604
1303
  env->SetMethod(target, "getCacheUsage", NativeModuleLoader::GetCacheUsage);
605
1303
  env->SetMethod(
606
      target, "compileFunction", NativeModuleLoader::CompileFunction);
607
1303
  env->SetMethod(target, "hasCachedBuiltins", HasCachedBuiltins);
608
  // internalBinding('native_module') should be frozen
609
1303
  target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust();
610
1303
}
611
612
5288
void NativeModuleLoader::RegisterExternalReferences(
613
    ExternalReferenceRegistry* registry) {
614
5288
  registry->Register(ConfigStringGetter);
615
5288
  registry->Register(ModuleIdsGetter);
616
5288
  registry->Register(GetModuleCategories);
617
5288
  registry->Register(GetCacheUsage);
618
5288
  registry->Register(CompileFunction);
619
5288
  registry->Register(HasCachedBuiltins);
620
5288
}
621
622
}  // namespace native_module
623
}  // namespace node
624
625
5356
NODE_MODULE_CONTEXT_AWARE_INTERNAL(
626
    native_module, node::native_module::NativeModuleLoader::Initialize)
627
5288
NODE_MODULE_EXTERNAL_REFERENCE(
628
    native_module,
629
    node::native_module::NativeModuleLoader::RegisterExternalReferences)