@@ -131,8 +131,10 @@ static bool use_debug_agent = false;
131
131
static bool debug_wait_connect = false ;
132
132
static int debug_port = 5858 ;
133
133
static bool v8_is_profiling = false ;
134
+ static bool node_is_initialized = false ;
134
135
static node_module* modpending;
135
136
static node_module* modlist_builtin;
137
+ static node_module* modlist_linked;
136
138
static node_module* modlist_addon;
137
139
138
140
#if defined(NODE_HAVE_I18N_SUPPORT)
@@ -2051,8 +2053,16 @@ extern "C" void node_module_register(void* m) {
2051
2053
if (mp->nm_flags & NM_F_BUILTIN) {
2052
2054
mp->nm_link = modlist_builtin;
2053
2055
modlist_builtin = mp;
2056
+ } else if (!node_is_initialized) {
2057
+ // "Linked" modules are included as part of the node project.
2058
+ // Like builtins they are registered *before* node::Init runs.
2059
+ mp->nm_flags = NM_F_LINKED;
2060
+ mp->nm_link = modlist_linked;
2061
+ modlist_linked = mp;
2054
2062
} else {
2055
- assert (modpending == NULL );
2063
+ // Once node::Init was called we can only register dynamic modules.
2064
+ // See DLOpen.
2065
+ CHECK_NE (modpending, NULL );
2056
2066
modpending = mp;
2057
2067
}
2058
2068
}
@@ -2069,6 +2079,18 @@ struct node_module* get_builtin_module(const char* name) {
2069
2079
return (mp);
2070
2080
}
2071
2081
2082
+ struct node_module * get_linked_module (const char * name) {
2083
+ struct node_module * mp;
2084
+
2085
+ for (mp = modlist_linked; mp != NULL ; mp = mp->nm_link ) {
2086
+ if (strcmp (mp->nm_modname , name) == 0 )
2087
+ break ;
2088
+ }
2089
+
2090
+ CHECK (mp == NULL || (mp->nm_flags & NM_F_LINKED) != 0 );
2091
+ return mp;
2092
+ }
2093
+
2072
2094
typedef void (UV_DYNAMIC* extInit)(Handle <Object> exports);
2073
2095
2074
2096
// DLOpen is process.dlopen(module, filename).
@@ -2275,6 +2297,46 @@ static void Binding(const FunctionCallbackInfo<Value>& args) {
2275
2297
args.GetReturnValue ().Set (exports);
2276
2298
}
2277
2299
2300
+ static void LinkedBinding (const FunctionCallbackInfo<Value>& args) {
2301
+ Environment* env = Environment::GetCurrent (args.GetIsolate ());
2302
+
2303
+ Local<String> module = args[0 ]->ToString ();
2304
+
2305
+ Local<Object> cache = env->binding_cache_object ();
2306
+ Local<Value> exports_v = cache->Get (module);
2307
+
2308
+ if (exports_v->IsObject ())
2309
+ return args.GetReturnValue ().Set (exports_v.As <Object>());
2310
+
2311
+ node::Utf8Value module_v (module);
2312
+ node_module* mod = get_linked_module (*module_v);
2313
+
2314
+ if (mod == NULL ) {
2315
+ char errmsg[1024 ];
2316
+ snprintf (errmsg,
2317
+ sizeof (errmsg),
2318
+ " No such module was linked: %s" ,
2319
+ *module_v);
2320
+ return env->ThrowError (errmsg);
2321
+ }
2322
+
2323
+ Local<Object> exports = Object::New (env->isolate ());
2324
+
2325
+ if (mod->nm_context_register_func != NULL ) {
2326
+ mod->nm_context_register_func (exports,
2327
+ module,
2328
+ env->context (),
2329
+ mod->nm_priv );
2330
+ } else if (mod->nm_register_func != NULL ) {
2331
+ mod->nm_register_func (exports, module, mod->nm_priv );
2332
+ } else {
2333
+ return env->ThrowError (" Linked module has no declared entry point." );
2334
+ }
2335
+
2336
+ cache->Set (module, exports);
2337
+
2338
+ args.GetReturnValue ().Set (exports);
2339
+ }
2278
2340
2279
2341
static void ProcessTitleGetter (Local<String> property,
2280
2342
const PropertyCallbackInfo<Value>& info) {
@@ -2816,6 +2878,7 @@ void SetupProcessObject(Environment* env,
2816
2878
NODE_SET_METHOD (process, " memoryUsage" , MemoryUsage);
2817
2879
2818
2880
NODE_SET_METHOD (process, " binding" , Binding);
2881
+ NODE_SET_METHOD (process, " _linkedBinding" , LinkedBinding);
2819
2882
2820
2883
NODE_SET_METHOD (process, " _setupAsyncListener" , SetupAsyncListener);
2821
2884
NODE_SET_METHOD (process, " _setupNextTick" , SetupNextTick);
@@ -3724,6 +3787,7 @@ int Start(int argc, char** argv) {
3724
3787
3725
3788
int code;
3726
3789
V8::Initialize ();
3790
+ node_is_initialized = true ;
3727
3791
{
3728
3792
Locker locker (node_isolate);
3729
3793
Isolate::Scope isolate_scope (node_isolate);
0 commit comments