Browse Source

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
v0.9.9-release
isaacs 12 years ago
parent
commit
15508589a1
  1. 4
      lib/module.js
  2. 23
      src/node.cc
  3. 11
      src/node.h
  4. 15
      test/addons/hello-world-function-export/binding.cc
  5. 8
      test/addons/hello-world-function-export/binding.gyp
  6. 4
      test/addons/hello-world-function-export/test.js

4
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.

23
src/node.cc

@ -101,6 +101,8 @@ Persistent<String> domain_symbol;
static Persistent<Object> process;
static Persistent<String> exports_symbol;
static Persistent<String> errno_symbol;
static Persistent<String> syscall_symbol;
static Persistent<String> errpath_symbol;
@ -1786,8 +1788,8 @@ Handle<Value> Hrtime(const v8::Arguments& args) {
typedef void (UV_DYNAMIC* extInit)(Handle<Object> 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<Value> DLOpen(const v8::Arguments& args) {
HandleScope scope;
char symbol[1024], *base, *pos;
@ -1800,8 +1802,13 @@ Handle<Value> DLOpen(const v8::Arguments& args) {
return ThrowException(exception);
}
String::Utf8Value filename(args[0]); // Cast
Local<Object> target = args[1]->ToObject(); // Cast
Local<Object> module = args[0]->ToObject(); // Cast
String::Utf8Value filename(args[1]); // Cast
if (exports_symbol.IsEmpty()) {
exports_symbol = NODE_PSYMBOL("exports");
}
Local<Object> exports = module->Get(exports_symbol)->ToObject();
if (uv_dlopen(*filename, &lib)) {
Local<String> errmsg = String::New(uv_dlerror(&lib));
@ -1812,7 +1819,7 @@ Handle<Value> 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<Value> 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<Value> 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")) {

11
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<v8::Value> WinapiErrnoException(int errorno,
const char *signo_string(int errorno);
NODE_EXTERN typedef void (* addon_register_func)(
v8::Handle<v8::Object> exports, v8::Handle<v8::Value> module);
struct node_module_struct {
int version;
void *dso_handle;
const char *filename;
void (*register_func) (v8::Handle<v8::Object> 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) \
}; \
}

15
test/addons/hello-world-function-export/binding.cc

@ -0,0 +1,15 @@
#include <node.h>
#include <v8.h>
using namespace v8;
Handle<Value> Method(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New("world"));
}
void init(Handle<Object> exports, Handle<Object> module) {
NODE_SET_METHOD(module, "exports", Method);
}
NODE_MODULE(binding, init);

8
test/addons/hello-world-function-export/binding.gyp

@ -0,0 +1,8 @@
{
'targets': [
{
'target_name': 'binding',
'sources': [ 'binding.cc' ]
}
]
}

4
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());
Loading…
Cancel
Save