@@ -36,6 +36,75 @@ using v8::String;
3636using v8::Uint8Array;
3737using v8::Value;
3838
39+ void NativeModuleLoader::InitializeModuleCategories () {
40+ if (module_categories_.is_initialized ) {
41+ DCHECK (!module_categories_.can_be_required .empty ());
42+ return ;
43+ }
44+
45+ std::vector<std::string> prefixes = {
46+ #if !HAVE_OPENSSL
47+ " internal/crypto/" ,
48+ #endif // !HAVE_OPENSSL
49+
50+ " internal/bootstrap/" ,
51+ " internal/per_context/" ,
52+ " internal/deps/" ,
53+ " internal/main/"
54+ };
55+
56+ module_categories_.cannot_be_required = std::set<std::string> {
57+ #if !HAVE_INSPECTOR
58+ " inspector" ,
59+ " internal/util/inspector" ,
60+ #endif // !HAVE_INSPECTOR
61+
62+ #if !NODE_USE_V8_PLATFORM || !defined(NODE_HAVE_I18N_SUPPORT)
63+ " trace_events" ,
64+ #endif // !NODE_USE_V8_PLATFORM
65+
66+ #if !HAVE_OPENSSL
67+ " crypto" ,
68+ " https" ,
69+ " http2" ,
70+ " tls" ,
71+ " _tls_common" ,
72+ " _tls_wrap" ,
73+ " internal/http2/core" ,
74+ " internal/http2/compat" ,
75+ " internal/policy/manifest" ,
76+ " internal/process/policy" ,
77+ " internal/streams/lazy_transform" ,
78+ #endif // !HAVE_OPENSSL
79+
80+ " sys" , // Deprecated.
81+ " internal/test/binding" ,
82+ " internal/v8_prof_polyfill" ,
83+ " internal/v8_prof_processor" ,
84+ };
85+
86+ for (auto const & x : source_) {
87+ const std::string& id = x.first ;
88+ for (auto const & prefix : prefixes) {
89+ if (prefix.length () > id.length ()) {
90+ continue ;
91+ }
92+ if (id.find (prefix) == 0 ) {
93+ module_categories_.cannot_be_required .emplace (id);
94+ }
95+ }
96+ }
97+
98+ for (auto const & x : source_) {
99+ const std::string& id = x.first ;
100+ if (0 == module_categories_.cannot_be_required .count (id)) {
101+ module_categories_.can_be_required .emplace (id);
102+ }
103+ }
104+
105+ module_categories_.is_initialized = true ;
106+ }
107+
39108// TODO(joyeecheung): make these more general and put them into util.h
40109Local<Object> MapToObject (Local<Context> context,
41110 const NativeModuleRecordMap& in) {
@@ -63,6 +132,39 @@ bool NativeModuleLoader::Exists(const char* id) {
63132 return source_.find (id) != source_.end ();
64133}
65134
135+ void NativeModuleLoader::GetModuleCategories (
136+ Local<Name> property, const PropertyCallbackInfo<Value>& info) {
137+ per_process::native_module_loader.InitializeModuleCategories ();
138+
139+ Environment* env = Environment::GetCurrent (info);
140+ Isolate* isolate = env->isolate ();
141+ Local<Context> context = env->context ();
142+ Local<Object> result = Object::New (isolate);
143+
144+ // Copy from the per-process categories
145+ std::set<std::string> cannot_be_required =
146+ per_process::native_module_loader.module_categories_ .cannot_be_required ;
147+ std::set<std::string> can_be_required =
148+ per_process::native_module_loader.module_categories_ .can_be_required ;
149+
150+ if (!env->owns_process_state ()) {
151+ can_be_required.erase (" trace_events" );
152+ cannot_be_required.insert (" trace_events" );
153+ }
154+
155+ result
156+ ->Set (context,
157+ OneByteString (isolate, " cannotBeRequired" ),
158+ ToJsSet (context, cannot_be_required))
159+ .FromJust ();
160+ result
161+ ->Set (context,
162+ OneByteString (isolate, " canBeRequired" ),
163+ ToJsSet (context, can_be_required))
164+ .FromJust ();
165+ info.GetReturnValue ().Set (result);
166+ }
167+
66168void NativeModuleLoader::GetCacheUsage (
67169 const FunctionCallbackInfo<Value>& args) {
68170 Environment* env = Environment::GetCurrent (args);
@@ -298,6 +400,18 @@ void NativeModuleLoader::Initialize(Local<Object> target,
298400 SideEffectType::kHasNoSideEffect )
299401 .FromJust ());
300402
403+ CHECK (target
404+ ->SetAccessor (
405+ env->context (),
406+ FIXED_ONE_BYTE_STRING (env->isolate (), " moduleCategories" ),
407+ GetModuleCategories,
408+ nullptr ,
409+ env->as_callback_data (),
410+ DEFAULT,
411+ None,
412+ SideEffectType::kHasNoSideEffect )
413+ .FromJust ());
414+
301415 env->SetMethod (
302416 target, " getCacheUsage" , NativeModuleLoader::GetCacheUsage);
303417 env->SetMethod (
0 commit comments