Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Commit 76b9846

Browse files
Keith M Wesolowskitjfontaine
authored andcommitted
node: register modules from DSO constructors
Built-in modules should be automatically registered, replacing the static module list. Add-on modules should also be automatically registered via DSO constructors. This improves flexibility in adding built-in modules and is also a prerequisite to pure-C addon modules.
1 parent f4c8020 commit 76b9846

25 files changed

+159
-236
lines changed

node.gyp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@
9191
'src/node_buffer.cc',
9292
'src/node_constants.cc',
9393
'src/node_contextify.cc',
94-
'src/node_extensions.cc',
9594
'src/node_file.cc',
9695
'src/node_http_parser.cc',
9796
'src/node_javascript.cc',
@@ -123,7 +122,6 @@
123122
'src/node_buffer.h',
124123
'src/node_constants.h',
125124
'src/node_contextify.h',
126-
'src/node_extensions.h',
127125
'src/node_file.h',
128126
'src/node_http_parser.h',
129127
'src/node_internals.h',

src/cares_wrap.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1177,4 +1177,4 @@ static void Initialize(Handle<Object> target,
11771177
} // namespace cares_wrap
11781178
} // namespace node
11791179

1180-
NODE_MODULE_CONTEXT_AWARE(node_cares_wrap, node::cares_wrap::Initialize)
1180+
NODE_MODULE_CONTEXT_AWARE_BUILTIN(cares_wrap, node::cares_wrap::Initialize)

src/fs_event_wrap.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,4 @@ void FSEventWrap::Close(const FunctionCallbackInfo<Value>& args) {
193193

194194
} // namespace node
195195

196-
NODE_MODULE_CONTEXT_AWARE(node_fs_event_wrap, node::FSEventWrap::Initialize)
196+
NODE_MODULE_CONTEXT_AWARE_BUILTIN(fs_event_wrap, node::FSEventWrap::Initialize)

src/node.cc

Lines changed: 61 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ static bool use_debug_agent = false;
130130
static bool debug_wait_connect = false;
131131
static int debug_port = 5858;
132132
static bool v8_is_profiling = false;
133+
static node_module* modpending;
134+
static node_module* modlist_builtin;
135+
static node_module* modlist_addon;
133136

134137
// used by C++ modules as well
135138
bool no_deprecation = false;
@@ -1882,6 +1885,29 @@ void Hrtime(const FunctionCallbackInfo<Value>& args) {
18821885
args.GetReturnValue().Set(tuple);
18831886
}
18841887

1888+
extern "C" void node_module_register(void* m) {
1889+
struct node_module* mp = reinterpret_cast<struct node_module*>(m);
1890+
1891+
if (mp->nm_flags & NM_F_BUILTIN) {
1892+
mp->nm_link = modlist_builtin;
1893+
modlist_builtin = mp;
1894+
} else {
1895+
assert(modpending == NULL);
1896+
modpending = mp;
1897+
}
1898+
}
1899+
1900+
struct node_module* get_builtin_module(const char* name) {
1901+
struct node_module* mp;
1902+
1903+
for (mp = modlist_builtin; mp != NULL; mp = mp->nm_link) {
1904+
if (strcmp(mp->nm_modname, name) == 0)
1905+
break;
1906+
}
1907+
1908+
assert(mp == NULL || (mp->nm_flags & NM_F_BUILTIN) != 0);
1909+
return (mp);
1910+
}
18851911

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

@@ -1894,12 +1920,12 @@ typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
18941920
void DLOpen(const FunctionCallbackInfo<Value>& args) {
18951921
HandleScope handle_scope(args.GetIsolate());
18961922
Environment* env = Environment::GetCurrent(args.GetIsolate());
1897-
char symbol[1024], *base, *pos;
1923+
struct node_module* mp;
18981924
uv_lib_t lib;
1899-
int r;
19001925

19011926
if (args.Length() < 2) {
1902-
return ThrowError("process.dlopen takes exactly 2 arguments.");
1927+
ThrowError("process.dlopen takes exactly 2 arguments.");
1928+
return;
19031929
}
19041930

19051931
Local<Object> module = args[0]->ToObject(); // Cast
@@ -1918,68 +1944,43 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
19181944
return;
19191945
}
19201946

1921-
String::Utf8Value path(args[1]);
1922-
base = *path;
1923-
1924-
/* Find the shared library filename within the full path. */
1925-
#ifdef __POSIX__
1926-
pos = strrchr(base, '/');
1927-
if (pos != NULL) {
1928-
base = pos + 1;
1929-
}
1930-
#else // Windows
1931-
for (;;) {
1932-
pos = strpbrk(base, "\\/:");
1933-
if (pos == NULL) {
1934-
break;
1935-
}
1936-
base = pos + 1;
1937-
}
1938-
#endif // __POSIX__
1939-
1940-
/* Strip the .node extension. */
1941-
pos = strrchr(base, '.');
1942-
if (pos != NULL) {
1943-
*pos = '\0';
1944-
}
1945-
1946-
/* Add the `_module` suffix to the extension name. */
1947-
r = snprintf(symbol, sizeof symbol, "%s_module", base);
1948-
if (r <= 0 || static_cast<size_t>(r) >= sizeof symbol) {
1949-
return ThrowError("Out of memory.");
1950-
}
1951-
1952-
/* Replace dashes with underscores. When loading foo-bar.node,
1953-
* look for foo_bar_module, not foo-bar_module.
1947+
/*
1948+
* Objects containing v14 or later modules will have registered themselves
1949+
* on the pending list. Activate all of them now. At present, only one
1950+
* module per object is supported.
19541951
*/
1955-
for (pos = symbol; *pos != '\0'; ++pos) {
1956-
if (*pos == '-')
1957-
*pos = '_';
1958-
}
1952+
mp = modpending;
1953+
modpending = NULL;
19591954

1960-
node_module_struct *mod;
1961-
if (uv_dlsym(&lib, symbol, reinterpret_cast<void**>(&mod))) {
1962-
char errmsg[1024];
1963-
snprintf(errmsg, sizeof(errmsg), "Symbol %s not found.", symbol);
1964-
return ThrowError(errmsg);
1955+
if (mp == NULL) {
1956+
ThrowError("Module did not self-register.");
1957+
return;
19651958
}
1966-
1967-
if (mod->version != NODE_MODULE_VERSION) {
1959+
if (mp->nm_version != NODE_MODULE_VERSION) {
19681960
char errmsg[1024];
19691961
snprintf(errmsg,
19701962
sizeof(errmsg),
19711963
"Module version mismatch. Expected %d, got %d.",
1972-
NODE_MODULE_VERSION, mod->version);
1973-
return ThrowError(errmsg);
1964+
NODE_MODULE_VERSION, mp->nm_version);
1965+
ThrowError(errmsg);
1966+
return;
1967+
}
1968+
if (mp->nm_flags & NM_F_BUILTIN) {
1969+
ThrowError("Built-in module self-registered.");
1970+
return;
19741971
}
19751972

1976-
// Execute the C++ module
1977-
if (mod->register_context_func != NULL) {
1978-
mod->register_context_func(exports, module, env->context());
1979-
} else if (mod->register_func != NULL) {
1980-
mod->register_func(exports, module);
1973+
mp->nm_dso_handle = lib.handle;
1974+
mp->nm_link = modlist_addon;
1975+
modlist_addon = mp;
1976+
1977+
if (mp->nm_context_register_func != NULL) {
1978+
mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
1979+
} else if (mp->nm_register_func != NULL) {
1980+
mp->nm_register_func(exports, module, mp->nm_priv);
19811981
} else {
1982-
return ThrowError("Module has no declared entry point.");
1982+
ThrowError("Module has no declared entry point.");
1983+
return;
19831984
}
19841985

19851986
// Tell coverity that 'handle' should not be freed when we return.
@@ -2082,14 +2083,15 @@ static void Binding(const FunctionCallbackInfo<Value>& args) {
20822083
uint32_t l = modules->Length();
20832084
modules->Set(l, OneByteString(node_isolate, buf));
20842085

2085-
node_module_struct* mod = get_builtin_module(*module_v);
2086+
node_module* mod = get_builtin_module(*module_v);
20862087
if (mod != NULL) {
20872088
exports = Object::New();
20882089
// Internal bindings don't have a "module" object, only exports.
2089-
assert(mod->register_func == NULL);
2090-
assert(mod->register_context_func != NULL);
2090+
assert(mod->nm_register_func == NULL);
2091+
assert(mod->nm_context_register_func != NULL);
20912092
Local<Value> unused = Undefined(env->isolate());
2092-
mod->register_context_func(exports, unused, env->context());
2093+
mod->nm_context_register_func(exports, unused,
2094+
env->context(), mod->nm_priv);
20932095
cache->Set(module, exports);
20942096
} else if (!strcmp(*module_v, "constants")) {
20952097
exports = Object::New();

src/node.h

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -205,59 +205,103 @@ const char *signo_string(int errorno);
205205

206206
typedef void (*addon_register_func)(
207207
v8::Handle<v8::Object> exports,
208-
v8::Handle<v8::Value> module);
208+
v8::Handle<v8::Value> module,
209+
void* priv);
209210

210211
typedef void (*addon_context_register_func)(
211212
v8::Handle<v8::Object> exports,
212213
v8::Handle<v8::Value> module,
213-
v8::Handle<v8::Context> context);
214-
215-
struct node_module_struct {
216-
int version;
217-
void *dso_handle;
218-
const char *filename;
219-
node::addon_register_func register_func;
220-
node::addon_context_register_func register_context_func;
221-
const char *modname;
214+
v8::Handle<v8::Context> context,
215+
void* priv);
216+
217+
#define NM_F_BUILTIN 0x01
218+
219+
struct node_module {
220+
int nm_version;
221+
unsigned int nm_flags;
222+
void* nm_dso_handle;
223+
const char* nm_filename;
224+
node::addon_register_func nm_register_func;
225+
node::addon_context_register_func nm_context_register_func;
226+
const char* nm_modname;
227+
void* nm_priv;
228+
struct node_module* nm_link;
222229
};
223230

224-
node_module_struct* get_builtin_module(const char *name);
231+
node_module* get_builtin_module(const char *name);
225232

226-
#define NODE_STANDARD_MODULE_STUFF \
227-
NODE_MODULE_VERSION, \
228-
NULL, \
229-
__FILE__
233+
extern "C" NODE_EXTERN void node_module_register(void* mod);
230234

231235
#ifdef _WIN32
232236
# define NODE_MODULE_EXPORT __declspec(dllexport)
233237
#else
234238
# define NODE_MODULE_EXPORT /* empty */
235239
#endif
236240

237-
#define NODE_MODULE(modname, regfunc) \
241+
#if defined(_MSC_VER)
242+
#pragma section(".CRT$XCU", read)
243+
#define NODE_C_CTOR(fn) \
244+
static void __cdecl fn(void); \
245+
__declspec(allocate(".CRT$XCU")) static void (__cdecl*fn ## _)(void) = fn; \
246+
static void __cdecl fn(void)
247+
#else
248+
#define NODE_C_CTOR(fn) \
249+
static void fn(void) __attribute__((constructor)); \
250+
static void fn(void)
251+
#endif
252+
253+
#define NODE_MODULE_X(modstr, regfunc, priv, flags) \
238254
extern "C" { \
239-
NODE_MODULE_EXPORT node::node_module_struct modname ## _module = \
255+
static node::node_module _module = \
240256
{ \
241-
NODE_STANDARD_MODULE_STUFF, \
257+
NODE_MODULE_VERSION, \
258+
flags, \
259+
NULL, \
260+
__FILE__, \
242261
(node::addon_register_func) (regfunc), \
243262
NULL, \
244-
NODE_STRINGIFY(modname) \
263+
modstr, \
264+
priv, \
265+
NULL \
245266
}; \
267+
NODE_C_CTOR(_register) { \
268+
node_module_register(&_module); \
269+
} \
246270
}
247271

248-
#define NODE_MODULE_CONTEXT_AWARE(modname, regfunc) \
272+
#define NODE_MODULE_CONTEXT_AWARE_X(modstr, regfunc, priv, flags) \
249273
extern "C" { \
250-
NODE_MODULE_EXPORT node::node_module_struct modname ## _module = \
274+
static node::node_module _module = \
251275
{ \
252-
NODE_STANDARD_MODULE_STUFF, \
276+
NODE_MODULE_VERSION, \
277+
flags, \
253278
NULL, \
254-
(regfunc), \
255-
NODE_STRINGIFY(modname) \
279+
__FILE__, \
280+
NULL, \
281+
(node::addon_context_register_func) (regfunc), \
282+
modstr, \
283+
priv, \
284+
NULL \
256285
}; \
286+
NODE_C_CTOR(_register) { \
287+
node_module_register(&_module); \
288+
} \
257289
}
258290

259-
#define NODE_MODULE_DECL(modname) \
260-
extern "C" node::node_module_struct modname ## _module;
291+
#define NODE_MODULE(modname, regfunc) \
292+
NODE_MODULE_X(NODE_STRINGIFY(modname), regfunc, NULL, 0)
293+
294+
#define NODE_MODULE_CONTEXT_AWARE(modname, regfunc) \
295+
NODE_MODULE_CONTEXT_AWARE_X(NODE_STRINGIFY(modname), regfunc, NULL, 0)
296+
297+
#define NODE_MODULE_CONTEXT_AWARE_BUILTIN(modname, regfunc) \
298+
NODE_MODULE_CONTEXT_AWARE_X(NODE_STRINGIFY(modname), \
299+
regfunc, NULL, NM_F_BUILTIN)
300+
301+
/*
302+
* For backward compatibility in add-on modules.
303+
*/
304+
#define NODE_MODULE_DECL /* nothing */
261305

262306
/* Called after the event loop exits but before the VM is disposed.
263307
* Callbacks are run in reverse order of registration, i.e. newest first.

src/node_buffer.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,4 +665,4 @@ void Initialize(Handle<Object> target,
665665
} // namespace Buffer
666666
} // namespace node
667667

668-
NODE_MODULE_CONTEXT_AWARE(node_buffer, node::Buffer::Initialize)
668+
NODE_MODULE_CONTEXT_AWARE_BUILTIN(buffer, node::Buffer::Initialize)

src/node_contextify.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,4 +628,4 @@ void InitContextify(Handle<Object> target,
628628

629629
} // namespace node
630630

631-
NODE_MODULE_CONTEXT_AWARE(node_contextify, node::InitContextify);
631+
NODE_MODULE_CONTEXT_AWARE_BUILTIN(contextify, node::InitContextify);

src/node_crypto.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4210,7 +4210,8 @@ void SetEngine(const FunctionCallbackInfo<Value>& args) {
42104210
// FIXME(bnoordhuis) Handle global init correctly.
42114211
void InitCrypto(Handle<Object> target,
42124212
Handle<Value> unused,
4213-
Handle<Context> context) {
4213+
Handle<Context> context,
4214+
void* priv) {
42144215
static uv_once_t init_once = UV_ONCE_INIT;
42154216
uv_once(&init_once, InitCryptoOnce);
42164217

@@ -4239,4 +4240,4 @@ void InitCrypto(Handle<Object> target,
42394240
} // namespace crypto
42404241
} // namespace node
42414242

4242-
NODE_MODULE_CONTEXT_AWARE(node_crypto, node::crypto::InitCrypto)
4243+
NODE_MODULE_CONTEXT_AWARE_BUILTIN(crypto, node::crypto::InitCrypto)

0 commit comments

Comments
 (0)