Skip to content

Commit

Permalink
modules: adding load linked modules feature
Browse files Browse the repository at this point in the history
- introduced NM_F_LINKED flag to identify linked modules
- setting node_is_initialized after calling V8::Initialize in order to
  make the right decision during initial module registration
- introduced modlist_linked in order to track modules that were
  pre-registered in order to complete it once node is initialized
- completing registration of linked module similarly to the way it's
  done inside DLOpen

PR-URL: #8
Reviewed-by: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
  • Loading branch information
thlorenz authored and rvagg committed Dec 4, 2014
1 parent 766d063 commit 0fe7a0d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
64 changes: 64 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,10 @@ static bool use_debug_agent = false;
static bool debug_wait_connect = false;
static int debug_port = 5858;
static bool v8_is_profiling = false;
static bool node_is_initialized = false;
static node_module* modpending;
static node_module* modlist_builtin;
static node_module* modlist_linked;
static node_module* modlist_addon;

#if defined(NODE_HAVE_I18N_SUPPORT)
Expand Down Expand Up @@ -2040,7 +2042,15 @@ extern "C" void node_module_register(void* m) {
if (mp->nm_flags & NM_F_BUILTIN) {
mp->nm_link = modlist_builtin;
modlist_builtin = mp;
} else if (!node_is_initialized) {
// "Linked" modules are included as part of the node project.
// Like builtins they are registered *before* node::Init runs.
mp->nm_flags = NM_F_LINKED;
mp->nm_link = modlist_linked;
modlist_linked = mp;
} else {
// Once node::Init was called we can only register dynamic modules.
// See DLOpen.
CHECK_EQ(modpending, nullptr);
modpending = mp;
}
Expand All @@ -2058,6 +2068,18 @@ struct node_module* get_builtin_module(const char* name) {
return (mp);
}

struct node_module* get_linked_module(const char* name) {
struct node_module* mp;

for (mp = modlist_linked; mp != NULL; mp = mp->nm_link) {
if (strcmp(mp->nm_modname, name) == 0)
break;
}

CHECK(mp == NULL || (mp->nm_flags & NM_F_LINKED) != 0);
return mp;
}

typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);

// DLOpen is process.dlopen(module, filename).
Expand Down Expand Up @@ -2262,6 +2284,46 @@ static void Binding(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(exports);
}

static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args.GetIsolate());

Local<String> module = args[0]->ToString();

Local<Object> cache = env->binding_cache_object();
Local<Value> exports_v = cache->Get(module);

if (exports_v->IsObject())
return args.GetReturnValue().Set(exports_v.As<Object>());

node::Utf8Value module_v(module);
node_module* mod = get_linked_module(*module_v);

if (mod == NULL) {
char errmsg[1024];
snprintf(errmsg,
sizeof(errmsg),
"No such module was linked: %s",
*module_v);
return env->ThrowError(errmsg);
}

Local<Object> exports = Object::New(env->isolate());

if (mod->nm_context_register_func != NULL) {
mod->nm_context_register_func(exports,
module,
env->context(),
mod->nm_priv);
} else if (mod->nm_register_func != NULL) {
mod->nm_register_func(exports, module, mod->nm_priv);
} else {
return env->ThrowError("Linked module has no declared entry point.");
}

cache->Set(module, exports);

args.GetReturnValue().Set(exports);
}

static void ProcessTitleGetter(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
Expand Down Expand Up @@ -2801,6 +2863,7 @@ void SetupProcessObject(Environment* env,
env->SetMethod(process, "memoryUsage", MemoryUsage);

env->SetMethod(process, "binding", Binding);
env->SetMethod(process, "_linkedBinding", LinkedBinding);

env->SetMethod(process, "_setupAsyncListener", SetupAsyncListener);
env->SetMethod(process, "_setupNextTick", SetupNextTick);
Expand Down Expand Up @@ -3700,6 +3763,7 @@ int Start(int argc, char** argv) {

int code;
V8::Initialize();
node_is_initialized = true;

// Fetch a reference to the main isolate, so we have a reference to it
// even when we need it to access it from another (debugger) thread.
Expand Down
2 changes: 2 additions & 0 deletions src/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ typedef void (*addon_context_register_func)(
void* priv);

#define NM_F_BUILTIN 0x01
#define NM_F_LINKED 0x02

struct node_module {
int nm_version;
Expand All @@ -353,6 +354,7 @@ struct node_module {
};

node_module* get_builtin_module(const char *name);
node_module* get_linked_module(const char *name);

extern "C" NODE_EXTERN void node_module_register(void* mod);

Expand Down

0 comments on commit 0fe7a0d

Please sign in to comment.