@@ -131,8 +131,10 @@ static bool use_debug_agent = false;
131131static bool debug_wait_connect = false ;
132132static int debug_port = 5858 ;
133133static bool v8_is_profiling = false ;
134+ static bool node_is_initialized = false ;
134135static node_module* modpending;
135136static node_module* modlist_builtin;
137+ static node_module* modlist_linked;
136138static node_module* modlist_addon;
137139
138140#if defined(NODE_HAVE_I18N_SUPPORT)
@@ -2040,7 +2042,15 @@ extern "C" void node_module_register(void* m) {
20402042 if (mp->nm_flags & NM_F_BUILTIN) {
20412043 mp->nm_link = modlist_builtin;
20422044 modlist_builtin = mp;
2045+ } else if (!node_is_initialized) {
2046+ // "Linked" modules are included as part of the node project.
2047+ // Like builtins they are registered *before* node::Init runs.
2048+ mp->nm_flags = NM_F_LINKED;
2049+ mp->nm_link = modlist_linked;
2050+ modlist_linked = mp;
20432051 } else {
2052+ // Once node::Init was called we can only register dynamic modules.
2053+ // See DLOpen.
20442054 CHECK_EQ (modpending, nullptr );
20452055 modpending = mp;
20462056 }
@@ -2058,6 +2068,18 @@ struct node_module* get_builtin_module(const char* name) {
20582068 return (mp);
20592069}
20602070
2071+ struct node_module * get_linked_module (const char * name) {
2072+ struct node_module * mp;
2073+
2074+ for (mp = modlist_linked; mp != NULL ; mp = mp->nm_link ) {
2075+ if (strcmp (mp->nm_modname , name) == 0 )
2076+ break ;
2077+ }
2078+
2079+ CHECK (mp == NULL || (mp->nm_flags & NM_F_LINKED) != 0 );
2080+ return mp;
2081+ }
2082+
20612083typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
20622084
20632085// DLOpen is process.dlopen(module, filename).
@@ -2262,6 +2284,46 @@ static void Binding(const FunctionCallbackInfo<Value>& args) {
22622284 args.GetReturnValue ().Set (exports);
22632285}
22642286
2287+ static void LinkedBinding (const FunctionCallbackInfo<Value>& args) {
2288+ Environment* env = Environment::GetCurrent (args.GetIsolate ());
2289+
2290+ Local<String> module = args[0 ]->ToString ();
2291+
2292+ Local<Object> cache = env->binding_cache_object ();
2293+ Local<Value> exports_v = cache->Get (module );
2294+
2295+ if (exports_v->IsObject ())
2296+ return args.GetReturnValue ().Set (exports_v.As <Object>());
2297+
2298+ node::Utf8Value module_v (module );
2299+ node_module* mod = get_linked_module (*module_v);
2300+
2301+ if (mod == NULL ) {
2302+ char errmsg[1024 ];
2303+ snprintf (errmsg,
2304+ sizeof (errmsg),
2305+ " No such module was linked: %s" ,
2306+ *module_v);
2307+ return env->ThrowError (errmsg);
2308+ }
2309+
2310+ Local<Object> exports = Object::New (env->isolate ());
2311+
2312+ if (mod->nm_context_register_func != NULL ) {
2313+ mod->nm_context_register_func (exports,
2314+ module ,
2315+ env->context (),
2316+ mod->nm_priv );
2317+ } else if (mod->nm_register_func != NULL ) {
2318+ mod->nm_register_func (exports, module , mod->nm_priv );
2319+ } else {
2320+ return env->ThrowError (" Linked module has no declared entry point." );
2321+ }
2322+
2323+ cache->Set (module , exports);
2324+
2325+ args.GetReturnValue ().Set (exports);
2326+ }
22652327
22662328static void ProcessTitleGetter (Local<String> property,
22672329 const PropertyCallbackInfo<Value>& info) {
@@ -2801,6 +2863,7 @@ void SetupProcessObject(Environment* env,
28012863 env->SetMethod (process, " memoryUsage" , MemoryUsage);
28022864
28032865 env->SetMethod (process, " binding" , Binding);
2866+ env->SetMethod (process, " _linkedBinding" , LinkedBinding);
28042867
28052868 env->SetMethod (process, " _setupAsyncListener" , SetupAsyncListener);
28062869 env->SetMethod (process, " _setupNextTick" , SetupNextTick);
@@ -3700,6 +3763,7 @@ int Start(int argc, char** argv) {
37003763
37013764 int code;
37023765 V8::Initialize ();
3766+ node_is_initialized = true ;
37033767
37043768 // Fetch a reference to the main isolate, so we have a reference to it
37053769 // even when we need it to access it from another (debugger) thread.
0 commit comments