diff --git a/lib/module.js b/lib/module.js index 67a95f0757..a7c7115566 100644 --- a/lib/module.js +++ b/lib/module.js @@ -488,9 +488,7 @@ Module._extensions['.json'] = function(module, filename) { //Native extension for .node -Module._extensions['.node'] = function(module, filename) { - process.dlopen(filename, module.exports); -}; +Module._extensions['.node'] = process.dlopen; // bootstrap main module. diff --git a/src/node.cc b/src/node.cc index 32cff1203b..fe7d4bcd32 100644 --- a/src/node.cc +++ b/src/node.cc @@ -101,6 +101,8 @@ Persistent domain_symbol; static Persistent process; +static Persistent exports_symbol; + static Persistent errno_symbol; static Persistent syscall_symbol; static Persistent errpath_symbol; @@ -1786,8 +1788,8 @@ Handle Hrtime(const v8::Arguments& args) { typedef void (UV_DYNAMIC* extInit)(Handle exports); -// DLOpen is node.dlopen(). Used to load 'module.node' dynamically shared -// objects. +// DLOpen is process.dlopen(module, filename). +// Used to load 'module.node' dynamically shared objects. Handle DLOpen(const v8::Arguments& args) { HandleScope scope; char symbol[1024], *base, *pos; @@ -1800,8 +1802,13 @@ Handle DLOpen(const v8::Arguments& args) { return ThrowException(exception); } - String::Utf8Value filename(args[0]); // Cast - Local target = args[1]->ToObject(); // Cast + Local module = args[0]->ToObject(); // Cast + String::Utf8Value filename(args[1]); // Cast + + if (exports_symbol.IsEmpty()) { + exports_symbol = NODE_PSYMBOL("exports"); + } + Local exports = module->Get(exports_symbol)->ToObject(); if (uv_dlopen(*filename, &lib)) { Local errmsg = String::New(uv_dlerror(&lib)); @@ -1812,7 +1819,7 @@ Handle DLOpen(const v8::Arguments& args) { return ThrowException(Exception::Error(errmsg)); } - String::Utf8Value path(args[0]); + String::Utf8Value path(args[1]); base = *path; /* Find the shared library filename within the full path. */ @@ -1869,7 +1876,7 @@ Handle DLOpen(const v8::Arguments& args) { } // Execute the C++ module - mod->register_func(target); + mod->register_func(exports, module); // Tell coverity that 'handle' should not be freed when we return. // coverity[leaked_storage] @@ -1953,7 +1960,9 @@ static Handle Binding(const Arguments& args) { if ((modp = get_builtin_module(*module_v)) != NULL) { exports = Object::New(); - modp->register_func(exports); + // Internal bindings don't have a "module" object, + // only exports. + modp->register_func(exports, Undefined()); binding_cache->Set(module, exports); } else if (!strcmp(*module_v, "constants")) { diff --git a/src/node.h b/src/node.h index 51da0d9474..682b505832 100644 --- a/src/node.h +++ b/src/node.h @@ -83,6 +83,7 @@ # endif #endif + namespace node { NODE_EXTERN extern bool no_deprecation; @@ -198,11 +199,15 @@ NODE_EXTERN v8::Local WinapiErrnoException(int errorno, const char *signo_string(int errorno); + +NODE_EXTERN typedef void (* addon_register_func)( + v8::Handle exports, v8::Handle module); + struct node_module_struct { int version; void *dso_handle; const char *filename; - void (*register_func) (v8::Handle target); + node::addon_register_func register_func; const char *modname; }; @@ -214,7 +219,7 @@ node_module_struct* get_builtin_module(const char *name); * an API is broken in the C++ side, including in v8 or * other dependencies. */ -#define NODE_MODULE_VERSION 0x000A /* v0.10 */ +#define NODE_MODULE_VERSION 0x000B /* v0.11 */ #define NODE_STANDARD_MODULE_STUFF \ NODE_MODULE_VERSION, \ @@ -232,7 +237,7 @@ node_module_struct* get_builtin_module(const char *name); NODE_MODULE_EXPORT node::node_module_struct modname ## _module = \ { \ NODE_STANDARD_MODULE_STUFF, \ - regfunc, \ + (node::addon_register_func)regfunc, \ NODE_STRINGIFY(modname) \ }; \ } diff --git a/test/addons/hello-world-function-export/binding.cc b/test/addons/hello-world-function-export/binding.cc new file mode 100644 index 0000000000..dcdb6b8ce8 --- /dev/null +++ b/test/addons/hello-world-function-export/binding.cc @@ -0,0 +1,15 @@ +#include +#include + +using namespace v8; + +Handle Method(const Arguments& args) { + HandleScope scope; + return scope.Close(String::New("world")); +} + +void init(Handle exports, Handle module) { + NODE_SET_METHOD(module, "exports", Method); +} + +NODE_MODULE(binding, init); diff --git a/test/addons/hello-world-function-export/binding.gyp b/test/addons/hello-world-function-export/binding.gyp new file mode 100644 index 0000000000..3bfb84493f --- /dev/null +++ b/test/addons/hello-world-function-export/binding.gyp @@ -0,0 +1,8 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'sources': [ 'binding.cc' ] + } + ] +} diff --git a/test/addons/hello-world-function-export/test.js b/test/addons/hello-world-function-export/test.js new file mode 100644 index 0000000000..238e105381 --- /dev/null +++ b/test/addons/hello-world-function-export/test.js @@ -0,0 +1,4 @@ +var assert = require('assert'); +var binding = require('./build/Release/binding'); +assert.equal('world', binding()); +console.log('binding.hello() =', binding());