Created
September 27, 2019 13:47
-
-
Save fridgerator/789283ae01f55e9ae9b771357450e471 to your computer and use it in GitHub Desktop.
Native node module event emitter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <nan.h> | |
#include "Foo.h" | |
void InitAll(v8::Local<v8::Object> exports) { | |
Foo::Init(exports); | |
} | |
NODE_MODULE(bindings, InitAll) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"targets": [ | |
{ | |
"target_name": "hello", | |
"sources": [ | |
"src/addon.cc", "src/Foo.cc" | |
], | |
"include_dirs": [ | |
"<!(node -e \"require('nan')\")" | |
] | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/gerhardberger/addon-emitter | |
#ifndef EMITTER_H | |
#define EMITTER_H | |
#include <nan.h> | |
#include <map> | |
#include <vector> | |
#include <iostream> | |
namespace internal { | |
using CP = Nan::CopyablePersistentTraits<v8::Function>::CopyablePersistent; | |
} // namespace internal | |
class Emitter : public Nan::ObjectWrap { | |
public: | |
Emitter () {} | |
~Emitter () {} | |
template<typename... Args> | |
void Emit (v8::Local<v8::Value> info, const Args&... args) { | |
v8::String::Utf8Value name(info->ToString()); | |
if (m[std::string(*name)].empty()) return; | |
std::vector<v8::Local<v8::Value>> converted_args = { args... }; | |
for (std::vector<internal::CP>::iterator it = m[std::string(*name)].begin(); | |
it != m[std::string(*name)].end(); ++it) { | |
Nan::MakeCallback(Nan::GetCurrentContext()->Global() | |
, Nan::New(*it) | |
, converted_args.size(), &converted_args.front()); | |
} | |
} | |
static void On (const Nan::FunctionCallbackInfo<v8::Value>& info) { | |
if (!info[0]->IsString() || !info[1]->IsFunction()) return; | |
Emitter *emitter = ObjectWrap::Unwrap<Emitter>(info.Holder()); | |
v8::String::Utf8Value name(info[0]->ToString()); | |
v8::Local<v8::Function> cb = info[1].As<v8::Function>(); | |
Nan::Persistent<v8::Function> persistent_cb; | |
persistent_cb.Reset(cb); | |
emitter->m[std::string(*name)].push_back(persistent_cb); | |
} | |
private: | |
std::map<std::string, std::vector<internal::CP> > m; | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Foo.h" | |
Nan::Persistent<v8::Function> Foo::constructor; | |
Foo::Foo () { } | |
Foo::~Foo () { } | |
void Foo::Init(v8::Local<v8::Object> exports) { | |
Nan::HandleScope scope; | |
// Prepare constructor template | |
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New); | |
tpl->SetClassName(Nan::New("Foo").ToLocalChecked()); | |
tpl->InstanceTemplate()->SetInternalFieldCount(1); | |
// Prototype | |
Nan::SetPrototypeMethod(tpl, "bar", Bar); | |
Nan::SetPrototypeMethod(tpl, "on", Emitter::On); // Emitter's prototype method | |
constructor.Reset(tpl->GetFunction()); | |
exports->Set(Nan::New("Foo").ToLocalChecked(), tpl->GetFunction()); | |
} | |
void Foo::New(const Nan::FunctionCallbackInfo<v8::Value>& info) { | |
if (info.IsConstructCall()) { | |
Foo *foo = new Foo(); | |
foo->Wrap(info.This()); | |
info.GetReturnValue().Set(info.This()); | |
} else { | |
Nan::ThrowError("nope"); | |
} | |
} | |
void Foo::Bar(const Nan::FunctionCallbackInfo<v8::Value>& info) { | |
Foo *foo = ObjectWrap::Unwrap<Foo>(info.Holder()); | |
foo->Emit(Nan::New("sus").ToLocalChecked(), Nan::New("hi").ToLocalChecked(), Nan::New(6)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FOO_H | |
#define FOO_H | |
#include <nan.h> | |
#include "emitter.h" | |
class Foo : public Emitter { | |
public: | |
static void Init(v8::Local<v8::Object> exports); | |
private: | |
explicit Foo (); | |
~Foo (); | |
static void New (const Nan::FunctionCallbackInfo<v8::Value>& info); | |
static void Bar (const Nan::FunctionCallbackInfo<v8::Value>& info); | |
static Nan::Persistent<v8::Function> constructor; | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Foo = require('./build/Release/hello').Foo | |
var foo = new Foo() | |
// subscribing to an event | |
foo.on('sus', function () { | |
console.log('Received:', arguments); | |
}) | |
setInterval(function () { | |
// this method fires the `sus` event on the native side | |
foo.bar() | |
}, 1000) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment