From 15508589a163b0c9f09ac608281f9ebb015d4deb Mon Sep 17 00:00:00 2001 From: isaacs Date: Thu, 24 Jan 2013 15:40:58 -0800 Subject: [PATCH] addon: Pass module object to NODE_MODULE init function mainly to allow native addons to export single functions on rather than being restricted to operating on an existing object. Init functions now receive exports as the first argument, like before, but also the module object as the second argument, if they support it. Related to #4634 cc: @rvagg --- lib/module.js | 4 +--- src/node.cc | 23 +++++++++++++------ src/node.h | 11 ++++++--- .../hello-world-function-export/binding.cc | 15 ++++++++++++ .../hello-world-function-export/binding.gyp | 8 +++++++ .../hello-world-function-export/test.js | 4 ++++ 6 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 test/addons/hello-world-function-export/binding.cc create mode 100644 test/addons/hello-world-function-export/binding.gyp create mode 100644 test/addons/hello-world-function-export/test.js 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());