GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_native_module.cc Lines: 236 266 88.7 %
Date: 2022-07-29 04:16:17 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
5355
NativeModuleLoader::NativeModuleLoader()
34
5355
    : config_(GetConfig()), has_code_cache_(false) {
35
5355
  LoadJavaScriptSource();
36
5355
}
37
38
493050
NativeModuleLoader* NativeModuleLoader::GetInstance() {
39
493050
  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
1347
Local<String> NativeModuleLoader::GetConfigString(Isolate* isolate) {
64
1347
  return GetInstance()->config_.ToStringChecked(isolate);
65
}
66
67
1350
std::vector<std::string> NativeModuleLoader::GetModuleIds() {
68
1350
  std::vector<std::string> ids;
69
1350
  ids.reserve(source_.size());
70
406505
  for (auto const& x : source_) {
71
405155
    ids.emplace_back(x.first);
72
  }
73
1350
  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
5287
NativeModuleCacheMap* NativeModuleLoader::code_cache() {
173
5287
  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
473055
MaybeLocal<Function> NativeModuleLoader::CompileAsModule(
188
    Local<Context> context,
189
    const char* id,
190
    NativeModuleLoader::Result* result) {
191
473055
  Isolate* isolate = context->GetIsolate();
192
  std::vector<Local<String>> parameters = {
193
473055
      FIXED_ONE_BYTE_STRING(isolate, "exports"),
194
473055
      FIXED_ONE_BYTE_STRING(isolate, "require"),
195
473055
      FIXED_ONE_BYTE_STRING(isolate, "module"),
196
473055
      FIXED_ONE_BYTE_STRING(isolate, "process"),
197
473055
      FIXED_ONE_BYTE_STRING(isolate, "internalBinding"),
198
946110
      FIXED_ONE_BYTE_STRING(isolate, "primordials")};
199
473055
  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
486543
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
486543
    const auto source_it = source_.find(id);
225
486543
    if (UNLIKELY(source_it == source_.end())) {
226
      fprintf(stderr, "Cannot find native builtin: \"%s\".\n", id);
227
      ABORT();
228
    }
229
973086
    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
486543
MaybeLocal<Function> NativeModuleLoader::LookupAndCompileInternal(
254
    Local<Context> context,
255
    const char* id,
256
    std::vector<Local<String>>* parameters,
257
    NativeModuleLoader::Result* result) {
258
486543
  Isolate* isolate = context->GetIsolate();
259
486543
  EscapableHandleScope scope(isolate);
260
261
  Local<String> source;
262
973086
  if (!LoadBuiltinModuleSource(isolate, id).ToLocal(&source)) {
263
    return {};
264
  }
265
266
1459629
  std::string filename_s = std::string("node:") + id;
267
  Local<String> filename =
268
486543
      OneByteString(isolate, filename_s.c_str(), filename_s.size());
269
486543
  ScriptOrigin origin(isolate, filename, 0, 0, true);
270
271
486543
  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
973086
    Mutex::ScopedLock lock(code_cache_mutex_);
278
486543
    auto cache_it = code_cache_.find(id);
279
486543
    if (cache_it != code_cache_.end()) {
280
      // Transfer ownership to ScriptCompiler::Source later.
281
469664
      cached_data = cache_it->second.release();
282
469664
      code_cache_.erase(cache_it);
283
    }
284
  }
285
286
486543
  const bool has_cache = cached_data != nullptr;
287
486543
  ScriptCompiler::CompileOptions options =
288
486543
      has_cache ? ScriptCompiler::kConsumeCodeCache
289
                : ScriptCompiler::kEagerCompile;
290
486543
  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
486543
                     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
486543
                                               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
486543
  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
469664
  *result = (has_cache && !script_source.GetCachedData()->rejected)
322
956207
                ? Result::kWithCache
323
                : Result::kWithoutCache;
324
325
486543
  if (has_cache) {
326
469664
    per_process::Debug(DebugCategory::CODE_CACHE,
327
                       "Code cache of %s (%s) %s\n",
328
                       id,
329
469664
                       script_source.GetCachedData()->buffer_policy ==
330
                               ScriptCompiler::CachedData::BufferNotOwned
331
939328
                           ? "BufferNotOwned"
332
                           : "BufferOwned",
333
469664
                       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
486543
      ScriptCompiler::CreateCodeCacheForFunction(fun));
340
486543
  CHECK_NOT_NULL(new_cached_data);
341
342
  {
343
973086
    Mutex::ScopedLock lock(code_cache_mutex_);
344
486543
    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
486543
    if (it == code_cache_.end()) {
348
484345
      code_cache_.emplace(id, std::move(new_cached_data));
349
    } else {
350
2198
      it->second.reset(new_cached_data.release());
351
    }
352
  }
353
354
486543
  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
13488
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
13488
      GetInstance()->LookupAndCompileInternal(context, id, parameters, &result);
368
13488
  if (optional_env != nullptr) {
369
13095
    RecordResult(id, result, optional_env);
370
  }
371
13488
  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
5281
void NativeModuleLoader::RefreshCodeCache(
409
    const std::vector<CodeCacheInfo>& in) {
410
5281
  NativeModuleLoader* loader = GetInstance();
411
5281
  Mutex::ScopedLock lock(loader->code_cache_mutex());
412
5281
  auto out = loader->code_cache();
413
1404746
  for (auto const& item : in) {
414
1399465
    size_t length = item.data.size();
415
1399465
    uint8_t* buffer = new uint8_t[length];
416
1399465
    memcpy(buffer, item.data.data(), length);
417
    auto new_cache = std::make_unique<v8::ScriptCompiler::CachedData>(
418
2798930
        buffer, length, v8::ScriptCompiler::CachedData::BufferOwned);
419
1399465
    auto cache_it = out->find(item.id);
420
1399465
    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
1399465
      out->emplace(item.id, new_cache.release());
425
    }
426
  }
427
5281
  loader->has_code_cache_ = true;
428
5281
}
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
1344
void NativeModuleLoader::ModuleIdsGetter(
519
    Local<Name> property, const PropertyCallbackInfo<Value>& info) {
520
1344
  Isolate* isolate = info.GetIsolate();
521
522
1344
  std::vector<std::string> ids = GetInstance()->GetModuleIds();
523
4032
  info.GetReturnValue().Set(
524
2688
      ToV8Value(isolate->GetCurrentContext(), ids).ToLocalChecked());
525
1344
}
526
527
1305
void NativeModuleLoader::ConfigStringGetter(
528
    Local<Name> property, const PropertyCallbackInfo<Value>& info) {
529
1305
  info.GetReturnValue().Set(GetConfigString(info.GetIsolate()));
530
1305
}
531
532
484608
void NativeModuleLoader::RecordResult(const char* id,
533
                                      NativeModuleLoader::Result result,
534
                                      Environment* env) {
535
484608
  if (result == NativeModuleLoader::Result::kWithCache) {
536
461413
    env->native_modules_with_cache.insert(id);
537
  } else {
538
23195
    env->native_modules_without_cache.insert(id);
539
  }
540
484608
}
541
471513
void NativeModuleLoader::CompileFunction(
542
    const FunctionCallbackInfo<Value>& args) {
543
471513
  Environment* env = Environment::GetCurrent(args);
544
943026
  CHECK(args[0]->IsString());
545
1414539
  node::Utf8Value id_v(env->isolate(), args[0].As<String>());
546
471513
  const char* id = *id_v;
547
  NativeModuleLoader::Result result;
548
  MaybeLocal<Function> maybe =
549
471513
      GetInstance()->CompileAsModule(env->context(), id, &result);
550
471513
  RecordResult(id, result, env);
551
  Local<Function> fn;
552
471513
  if (maybe.ToLocal(&fn)) {
553
943026
    args.GetReturnValue().Set(fn);
554
  }
555
471513
}
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
1305
void NativeModuleLoader::Initialize(Local<Object> target,
567
                                    Local<Value> unused,
568
                                    Local<Context> context,
569
                                    void* priv) {
570
1305
  Environment* env = Environment::GetCurrent(context);
571
572
  target
573
1305
      ->SetAccessor(env->context(),
574
                    env->config_string(),
575
                    ConfigStringGetter,
576
                    nullptr,
577
                    MaybeLocal<Value>(),
578
                    DEFAULT,
579
                    None,
580
5220
                    SideEffectType::kHasNoSideEffect)
581
      .Check();
582
  target
583
1305
      ->SetAccessor(env->context(),
584
                    FIXED_ONE_BYTE_STRING(env->isolate(), "moduleIds"),
585
                    ModuleIdsGetter,
586
                    nullptr,
587
                    MaybeLocal<Value>(),
588
                    DEFAULT,
589
                    None,
590
5220
                    SideEffectType::kHasNoSideEffect)
591
      .Check();
592
593
  target
594
1305
      ->SetAccessor(env->context(),
595
                    FIXED_ONE_BYTE_STRING(env->isolate(), "moduleCategories"),
596
                    GetModuleCategories,
597
                    nullptr,
598
                    Local<Value>(),
599
                    DEFAULT,
600
                    None,
601
2610
                    SideEffectType::kHasNoSideEffect)
602
      .Check();
603
604
1305
  env->SetMethod(target, "getCacheUsage", NativeModuleLoader::GetCacheUsage);
605
1305
  env->SetMethod(
606
      target, "compileFunction", NativeModuleLoader::CompileFunction);
607
1305
  env->SetMethod(target, "hasCachedBuiltins", HasCachedBuiltins);
608
  // internalBinding('native_module') should be frozen
609
1305
  target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust();
610
1305
}
611
612
5287
void NativeModuleLoader::RegisterExternalReferences(
613
    ExternalReferenceRegistry* registry) {
614
5287
  registry->Register(ConfigStringGetter);
615
5287
  registry->Register(ModuleIdsGetter);
616
5287
  registry->Register(GetModuleCategories);
617
5287
  registry->Register(GetCacheUsage);
618
5287
  registry->Register(CompileFunction);
619
5287
  registry->Register(HasCachedBuiltins);
620
5287
}
621
622
}  // namespace native_module
623
}  // namespace node
624
625
5355
NODE_MODULE_CONTEXT_AWARE_INTERNAL(
626
    native_module, node::native_module::NativeModuleLoader::Initialize)
627
5287
NODE_MODULE_EXTERNAL_REFERENCE(
628
    native_module,
629
    node::native_module::NativeModuleLoader::RegisterExternalReferences)