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
6 changes: 2 additions & 4 deletions src/async-wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,7 @@ static void SetupHooks(const FunctionCallbackInfo<Value>& args) {
}


static void Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
static void Initialize(Local<Object> target, Local<Context> context) {
Environment* env = Environment::GetCurrent(context);
Isolate* isolate = env->isolate();
HandleScope scope(isolate);
Expand Down Expand Up @@ -270,4 +268,4 @@ Handle<Value> AsyncWrap::MakeCallback(const Handle<Function> cb,

} // namespace node

NODE_MODULE_CONTEXT_AWARE_BUILTIN(async_wrap, node::Initialize)
NODE_MODULE_BUILTIN(async_wrap, node::Initialize)
6 changes: 2 additions & 4 deletions src/cares_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1240,9 +1240,7 @@ static void CaresTimerClose(Environment* env,
}


static void Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
static void Initialize(Local<Object> target, Local<Context> context) {
Environment* env = Environment::GetCurrent(context);

int r = ares_library_init(ARES_LIB_INIT_ALL);
Expand Down Expand Up @@ -1318,4 +1316,4 @@ static void Initialize(Handle<Object> target,
} // namespace cares_wrap
} // namespace node

NODE_MODULE_CONTEXT_AWARE_BUILTIN(cares_wrap, node::cares_wrap::Initialize)
NODE_MODULE_BUILTIN(cares_wrap, node::cares_wrap::Initialize)
10 changes: 3 additions & 7 deletions src/fs_event_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ using v8::Value;

class FSEventWrap: public HandleWrap {
public:
static void Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context);
static void Initialize(Local<Object> target, Local<Context> context);
static void New(const FunctionCallbackInfo<Value>& args);
static void Start(const FunctionCallbackInfo<Value>& args);
static void Close(const FunctionCallbackInfo<Value>& args);
Expand Down Expand Up @@ -59,9 +57,7 @@ FSEventWrap::~FSEventWrap() {
}


void FSEventWrap::Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
void FSEventWrap::Initialize(Local<Object> target, Local<Context> context) {
Environment* env = Environment::GetCurrent(context);

Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
Expand Down Expand Up @@ -176,4 +172,4 @@ void FSEventWrap::Close(const FunctionCallbackInfo<Value>& args) {

} // namespace node

NODE_MODULE_CONTEXT_AWARE_BUILTIN(fs_event_wrap, node::FSEventWrap::Initialize)
NODE_MODULE_BUILTIN(fs_event_wrap, node::FSEventWrap::Initialize)
6 changes: 2 additions & 4 deletions src/js_stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,7 @@ void JSStream::EmitEOF(const FunctionCallbackInfo<Value>& args) {
}


void JSStream::Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
void JSStream::Initialize(Local<Object> target, Local<Context> context) {
Environment* env = Environment::GetCurrent(context);

Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
Expand All @@ -226,4 +224,4 @@ void JSStream::Initialize(Handle<Object> target,

} // namespace node

NODE_MODULE_CONTEXT_AWARE_BUILTIN(js_stream, node::JSStream::Initialize)
NODE_MODULE_BUILTIN(js_stream, node::JSStream::Initialize)
5 changes: 2 additions & 3 deletions src/js_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ namespace node {

class JSStream : public StreamBase, public AsyncWrap {
public:
static void Initialize(v8::Handle<v8::Object> target,
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);
static void Initialize(v8::Local<v8::Object> target,
v8::Local<v8::Context> context);

~JSStream();

Expand Down
38 changes: 22 additions & 16 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2149,6 +2149,10 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
env->ThrowError("Built-in module self-registered.");
return;
}
if (mp->nm_flags & NM_F_NODE_MODULE_CONTEXT_AWARE_IS_DEPRECATED) {
fprintf(stderr, "NODE_MODULE_CONTEXT_AWARE(...) used by module %s is "
"deprecated. Use NODE_MODULE(...) instead\n", mp->nm_modname);
}

mp->nm_dso_handle = lib.handle;
mp->nm_link = modlist_addon;
Expand All @@ -2157,10 +2161,12 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
Local<String> exports_string = env->exports_string();
Local<Object> exports = module->Get(exports_string)->ToObject(env->isolate());

if (mp->nm_context_register_func != nullptr) {
mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
} else if (mp->nm_register_func != nullptr) {
mp->nm_register_func(exports, module, mp->nm_priv);
if (mp->nm_register_func != nullptr) {
mp->nm_register_func(mp->nm_init,
exports,
module,
env->context(),
mp->nm_priv);
} else {
env->ThrowError("Module has no declared entry point.");
return;
Expand Down Expand Up @@ -2271,11 +2277,12 @@ static void Binding(const FunctionCallbackInfo<Value>& args) {
if (mod != nullptr) {
exports = Object::New(env->isolate());
// Internal bindings don't have a "module" object, only exports.
CHECK_EQ(mod->nm_register_func, nullptr);
CHECK_NE(mod->nm_context_register_func, nullptr);
Local<Value> unused = Undefined(env->isolate());
mod->nm_context_register_func(exports, unused,
env->context(), mod->nm_priv);
CHECK_NE(mod->nm_register_func, nullptr);
mod->nm_register_func(mod->nm_init,
exports,
Undefined(env->isolate()).As<Object>(),
env->context(),
mod->nm_priv);
cache->Set(module, exports);
} else if (!strcmp(*module_v, "constants")) {
exports = Object::New(env->isolate());
Expand Down Expand Up @@ -2322,13 +2329,12 @@ static void LinkedBinding(const FunctionCallbackInfo<Value>& args) {

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

if (mod->nm_context_register_func != nullptr) {
mod->nm_context_register_func(exports,
module,
env->context(),
mod->nm_priv);
} else if (mod->nm_register_func != nullptr) {
mod->nm_register_func(exports, module, mod->nm_priv);
if (mod->nm_register_func != nullptr) {
mod->nm_register_func(mod->nm_init,
exports,
Undefined(env->isolate()).As<Object>(),
env->context(),
mod->nm_priv);
} else {
return env->ThrowError("Linked module has no declared entry point.");
}
Expand Down
175 changes: 126 additions & 49 deletions src/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,28 +357,122 @@ NODE_DEPRECATED("Use WinapiErrnoException(isolate, ...)",

const char *signo_string(int errorno);

//==============================================================================
// Init Function Argument Discomvobulator
//==============================================================================
namespace detail {

typedef void (*addon_register_func)(
v8::Handle<v8::Object> exports,
v8::Handle<v8::Value> module,
void* init_function,
v8::Local<v8::Object> exports,
v8::Local<v8::Object> module,
v8::Local<v8::Context> context,
void* priv);

typedef void (*addon_context_register_func)(
v8::Handle<v8::Object> exports,
v8::Handle<v8::Value> module,
v8::Handle<v8::Context> context,
void* priv);
// This template is used to select the optional arguments of the (addon) init
// function. Each specialization returns the corresponding argument.
template <typename T> struct OptionalInitArg;

template <>
struct OptionalInitArg<v8::Local<v8::Object> > {
static inline
v8::Local<v8::Object>
pick(v8::Local<v8::Object> module, v8::Local<v8::Context>, void*) {
return module;
}
};

template <>
struct OptionalInitArg<v8::Local<v8::Context> > {
static inline
v8::Local<v8::Context>
pick(v8::Local<v8::Object>, v8::Local<v8::Context> context, void*) {
return context;
}
};

template <>
struct OptionalInitArg<void*> {
static inline
void*
pick(v8::Local<v8::Object>, v8::Local<v8::Context>, void* private_) {
return private_;
}
};

#define NM_F_BUILTIN 0x01
#define NM_F_LINKED 0x02
// Template that takes the type of the init function as an argument. It is used
// to inspect the arguments of the init function at compile time and provide a
// suitable adapter registerAddon(...). This adapter is always of type
// addon_register_func. It calls the actual init function with the "requested"
// arguments. To put it differently, the implementation of registerAddon(...)
// is selected (or generated, if you like) based on the functions signature.
template <typename F> struct AddonInitAdapter;

// Partial specialization: Allow only function pointers with the following
// properties:
// - returns void
// - takes a Local<Object> as first argument (exports)
// - takes zero or more additional arguments of arbitrary type
//
// To further narrow it down it uses a little bit of SFINAE. It only matches
// if there is a suitable specialization of OptionalInitArg<> for each
// additional argument. See registerAddon(...) below. This limits the argument
// types to:
// - Local<Object> (the module)
// - Local<Context> (the context, duh)
// - void* (the private pointer)
//
// The interesting thing about this application of SFINAE is that we use it
// to trigger a compile-time error. Since the generic version of
// AddonInitAdapter<> is only declared but never defined, the compiler bails
// after the substitution failure.
template <typename... Args>
struct AddonInitAdapter<void (*)(v8::Local<v8::Object>, Args...)> {
typedef void (*init_function)(v8::Local<v8::Object>, Args...);

static
void
registerAddon(void* f,
v8::Local<v8::Object> exports,
v8::Local<v8::Object> module,
v8::Local<v8::Context> context,
void* priv) {
// restore function pointer type
init_function init(reinterpret_cast<init_function>(f));
// call it
init(exports, OptionalInitArg<Args>::pick(module, context, priv)...);
}
};

// Main entry point into the init-fuction-argument-discomvobulator. It is
// called with an init function as argument and returns a suitable
// addon_register_func. Note how a template function is used to capture
// the type F. A user of this function (our NODE_MODULE_X(...) macro, below)
// does not have to provide a type. No function pointer types, not even angular
// brackets at the call site. (Remember this pattern. It's pretty powerful)
template <typename F>
addon_register_func
selectAddonRegisterFunction(F f) {
return AddonInitAdapter<F>::registerAddon;
}

} // end of namespace detail

enum node_module_flags {
NM_F_BUILTIN = (1<<0),
NM_F_LINKED = (1<<1),
// Used to emit a deprecation warning. Remove once
// NODE_MODULE_CONTEXT_AWARE is phased out.
NM_F_NODE_MODULE_CONTEXT_AWARE_IS_DEPRECATED = (1<<31)
};

struct node_module {
int nm_version;
unsigned int nm_flags;
void* nm_dso_handle;
const char* nm_filename;
node::addon_register_func nm_register_func;
node::addon_context_register_func nm_context_register_func;
node::detail::addon_register_func nm_register_func;
void* nm_init;
const char* nm_modname;
void* nm_priv;
struct node_module* nm_link;
Expand Down Expand Up @@ -408,52 +502,35 @@ extern "C" NODE_EXTERN void node_module_register(void* mod);
static void fn(void)
#endif

#define NODE_MODULE_X(modname, regfunc, priv, flags) \
extern "C" { \
static node::node_module _module = \
{ \
NODE_MODULE_VERSION, \
flags, \
NULL, \
__FILE__, \
(node::addon_register_func) (regfunc), \
NULL, \
NODE_STRINGIFY(modname), \
priv, \
NULL \
}; \
NODE_C_CTOR(_register_ ## modname) { \
node_module_register(&_module); \
} \
}

#define NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, priv, flags) \
#define NODE_MODULE_X(modname, initfunc, priv, flags) \
extern "C" { \
static node::node_module _module = \
{ \
NODE_MODULE_VERSION, \
flags, \
NULL, \
__FILE__, \
NULL, \
(node::addon_context_register_func) (regfunc), \
NODE_STRINGIFY(modname), \
priv, \
NULL \
}; \
NODE_C_CTOR(_register_ ## modname) { \
static node::node_module _module = \
{ \
NODE_MODULE_VERSION, \
flags, \
NULL, \
__FILE__, \
node::detail::selectAddonRegisterFunction(initfunc), \
reinterpret_cast<void*>(initfunc), \
NODE_STRINGIFY(modname), \
priv, \
NULL \
}; \
node_module_register(&_module); \
} \
}

#define NODE_MODULE(modname, regfunc) \
NODE_MODULE_X(modname, regfunc, NULL, 0)
#define NODE_MODULE(modname, initfunc) \
NODE_MODULE_X(modname, initfunc, NULL, 0)

#define NODE_MODULE_CONTEXT_AWARE(modname, regfunc) \
NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, 0)
// NOTE(agnat): Deprecated. Just use NODE_MODULE(...)
#define NODE_MODULE_CONTEXT_AWARE(modname, initfunc) \
NODE_MODULE_X(modname, initfunc, NULL, \
NM_F_NODE_MODULE_CONTEXT_AWARE_IS_DEPRECATED)

#define NODE_MODULE_CONTEXT_AWARE_BUILTIN(modname, regfunc) \
NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, NM_F_BUILTIN) \
#define NODE_MODULE_BUILTIN(modname, initfunc) \
NODE_MODULE_X(modname, initfunc, NULL, node::NM_F_BUILTIN)

/*
* For backward compatibility in add-on modules.
Expand Down
6 changes: 2 additions & 4 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -991,9 +991,7 @@ void SetupBufferJS(const FunctionCallbackInfo<Value>& args) {
}


void Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
void Initialize(Local<Object> target, Local<Context> context) {
Environment* env = Environment::GetCurrent(context);

env->SetMethod(target, "setupBufferJS", SetupBufferJS);
Expand Down Expand Up @@ -1028,4 +1026,4 @@ void Initialize(Handle<Object> target,
} // namespace Buffer
} // namespace node

NODE_MODULE_CONTEXT_AWARE_BUILTIN(buffer, node::Buffer::Initialize)
NODE_MODULE_BUILTIN(buffer, node::Buffer::Initialize)
6 changes: 2 additions & 4 deletions src/node_contextify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -704,14 +704,12 @@ class ContextifyScript : public BaseObject {
};


void InitContextify(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
void InitContextify(Local<Object> target, Local<Context> context) {
Environment* env = Environment::GetCurrent(context);
ContextifyContext::Init(env, target);
ContextifyScript::Init(env, target);
}

} // namespace node

NODE_MODULE_CONTEXT_AWARE_BUILTIN(contextify, node::InitContextify);
NODE_MODULE_BUILTIN(contextify, node::InitContextify);
Loading