Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
modules: adding load linked modules feature
- 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
  • Loading branch information
thlorenz committed Nov 28, 2014
commit 4ca42aca6e7249c4e245a0b5805124b7179c5ab0
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