build ok
This commit is contained in:
parent
cdb498aac3
commit
4e2728c8bc
|
@ -1,3 +1,3 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('./binary/example');
|
module.exports = require('./binary/addon');
|
||||||
|
|
|
@ -28,12 +28,13 @@ void Example::init(Handle<Object> target) {
|
||||||
// prototype
|
// prototype
|
||||||
Nan::SetPrototypeMethod(ctor, "destroy", destroy);
|
Nan::SetPrototypeMethod(ctor, "destroy", destroy);
|
||||||
|
|
||||||
|
extend(ctor);
|
||||||
|
|
||||||
|
|
||||||
Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
|
Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
|
||||||
// ACCESSOR_RW(proto, prop);
|
// ACCESSOR_RW(proto, prop);
|
||||||
|
|
||||||
|
|
||||||
EventEmitter::extend(ctor, proto);
|
|
||||||
|
|
||||||
|
|
||||||
_constructor.Reset(Nan::GetFunction(ctor).ToLocalChecked());
|
_constructor.Reset(Nan::GetFunction(ctor).ToLocalChecked());
|
||||||
Nan::Set(target, JS_STR("Example"), Nan::GetFunction(ctor).ToLocalChecked());
|
Nan::Set(target, JS_STR("Example"), Nan::GetFunction(ctor).ToLocalChecked());
|
||||||
|
|
|
@ -1,10 +1,46 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Wrapped = require('./js/wrapped');
|
const Example = require('./core');
|
||||||
const Example = require('./js/example');
|
|
||||||
|
|
||||||
console.log('Example', Example);
|
console.log('Example', Example);
|
||||||
|
|
||||||
console.log('Wrapped', Wrapped);
|
|
||||||
|
const example = new Example();
|
||||||
|
|
||||||
|
|
||||||
|
console.log('static listenerCount', Example.listenerCount);
|
||||||
|
|
||||||
|
console.log('listenerCount', example.listenerCount);
|
||||||
|
console.log('addListener', example.addListener);
|
||||||
|
console.log('emit', example.emit);
|
||||||
|
console.log('eventNames', example.eventNames);
|
||||||
|
console.log('getMaxListeners', example.getMaxListeners);
|
||||||
|
console.log('listeners', example.listeners);
|
||||||
|
console.log('on', example.on);
|
||||||
|
console.log('once', example.once);
|
||||||
|
console.log('prependListener', example.prependListener);
|
||||||
|
console.log('prependOnceListener', example.prependOnceListener);
|
||||||
|
console.log('removeAllListeners', example.removeAllListeners);
|
||||||
|
console.log('removeListener', example.removeListener);
|
||||||
|
console.log('setMaxListeners', example.setMaxListeners);
|
||||||
|
console.log('rawListeners', example.rawListeners);
|
||||||
|
console.log('destroy', example.destroy);
|
||||||
|
|
||||||
|
|
||||||
|
example.on('evt1', (arg1, arg2) => {
|
||||||
|
console.log('EVT1', arg1, arg2);
|
||||||
|
});
|
||||||
|
|
||||||
|
example.once('evt2', (arg1, arg2) => {
|
||||||
|
console.log('EVT2', arg1, arg2);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
example.emit('evt1', 111, '221');
|
||||||
|
example.emit('evt1', 112, '222');
|
||||||
|
|
||||||
|
example.emit('evt2', 111, '221');
|
||||||
|
example.emit('evt2', 112, '222');
|
||||||
|
|
||||||
|
|
||||||
module.exports = { Wrapped, Example };
|
module.exports = { Wrapped, Example };
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
|
|
||||||
const { Example } = require('../core');
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = Example;
|
|
|
@ -1,12 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
|
|
||||||
const { Example } = require('../core');
|
|
||||||
|
|
||||||
|
|
||||||
class Wrapped extends Example {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = Wrapped;
|
|
|
@ -12,7 +12,19 @@
|
||||||
EventEmitter *emitter = ObjectWrap::Unwrap<EventEmitter>(info.This());
|
EventEmitter *emitter = ObjectWrap::Unwrap<EventEmitter>(info.This());
|
||||||
|
|
||||||
|
|
||||||
class EventEmitter : public Nan::ObjectWrap {
|
// Use the dummy template for static-int initialization
|
||||||
|
|
||||||
|
template< class Dummy >
|
||||||
|
class EventEmitterStatics {
|
||||||
|
protected:
|
||||||
|
static int _defaultMaxListeners;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< class Dummy >
|
||||||
|
int EventEmitterStatics<Dummy>::_defaultMaxListeners = 10;
|
||||||
|
|
||||||
|
|
||||||
|
class EventEmitter : public Nan::ObjectWrap, public EventEmitterStatics<void> {
|
||||||
|
|
||||||
typedef Nan::CopyablePersistentTraits<v8::Function>::CopyablePersistent FN_TYPE;
|
typedef Nan::CopyablePersistentTraits<v8::Function>::CopyablePersistent FN_TYPE;
|
||||||
typedef std::deque<FN_TYPE> VEC_TYPE;
|
typedef std::deque<FN_TYPE> VEC_TYPE;
|
||||||
|
@ -22,8 +34,51 @@ class EventEmitter : public Nan::ObjectWrap {
|
||||||
typedef MAP_TYPE::iterator MAP_IT_TYPE;
|
typedef MAP_TYPE::iterator MAP_IT_TYPE;
|
||||||
typedef FNMAP_TYPE::iterator FNMAP_IT_TYPE;
|
typedef FNMAP_TYPE::iterator FNMAP_IT_TYPE;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// C++ side emit() method
|
||||||
|
void emit(const std::string &name, int argc = 0, v8::Local<v8::Value> *argv = NULL) {
|
||||||
|
|
||||||
|
VEC_TYPE list = _listeners[name];
|
||||||
|
|
||||||
|
if (list.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (IT_TYPE it = list.begin(); it != list.end(); ++it) {
|
||||||
|
|
||||||
|
Nan::Callback callback(Nan::New(*it));
|
||||||
|
|
||||||
|
if ( ! callback.IsEmpty() ) {
|
||||||
|
callback.Call(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// C++ side on() method
|
||||||
|
void on(const std::string &name, v8::Local<v8::Value> that, const std::string &method) {
|
||||||
|
|
||||||
|
v8::Local<v8::String> code = JS_STR(
|
||||||
|
"((emitter, name, that, method) => emitter.on(name, that[method]))"
|
||||||
|
);
|
||||||
|
|
||||||
|
v8::Local<v8::Function> connector = v8::Local<v8::Function>::Cast(v8::Script::Compile(code)->Run());
|
||||||
|
Nan::Callback connectorCb(connector);
|
||||||
|
|
||||||
|
v8::Local<v8::Object> emitter = Nan::New<v8::Object>();
|
||||||
|
this->Wrap(emitter);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> argv[] = { emitter, JS_STR(name.c_str()), that, JS_STR(method.c_str()) };
|
||||||
|
connectorCb.Call(4, argv);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
EventEmitter () {
|
EventEmitter () {
|
||||||
_maxListeners = _defaultMaxListeners;
|
_maxListeners = _defaultMaxListeners;
|
||||||
_freeId = 0;
|
_freeId = 0;
|
||||||
|
@ -31,17 +86,7 @@ public:
|
||||||
~EventEmitter () {}
|
~EventEmitter () {}
|
||||||
|
|
||||||
|
|
||||||
static void extend(v8::Local<v8::FunctionTemplate> &ctor, v8::Local<v8::ObjectTemplate> &proto) {
|
static void extend(v8::Local<v8::FunctionTemplate> &ctor) {
|
||||||
|
|
||||||
v8::Local<v8::Function> ctorFunc = Nan::GetFunction(ctor).ToLocalChecked();
|
|
||||||
v8::Local<v8::Object> ctorObj = ctorFunc;
|
|
||||||
|
|
||||||
|
|
||||||
// -------- static
|
|
||||||
|
|
||||||
Nan::SetMethod(ctorFunc, "listenerCount", jsStaticListenerCount);
|
|
||||||
ACCESSOR_RW(ctorObj, defaultMaxListeners);
|
|
||||||
|
|
||||||
|
|
||||||
// -------- dynamic
|
// -------- dynamic
|
||||||
|
|
||||||
|
@ -60,41 +105,31 @@ public:
|
||||||
Nan::SetPrototypeMethod(ctor, "setMaxListeners", jsSetMaxListeners);
|
Nan::SetPrototypeMethod(ctor, "setMaxListeners", jsSetMaxListeners);
|
||||||
Nan::SetPrototypeMethod(ctor, "rawListeners", jsRawListeners);
|
Nan::SetPrototypeMethod(ctor, "rawListeners", jsRawListeners);
|
||||||
|
|
||||||
|
|
||||||
|
// -------- static
|
||||||
|
|
||||||
|
v8::Local<v8::Function> ctorFunc = Nan::GetFunction(ctor).ToLocalChecked();
|
||||||
|
v8::Local<v8::Object> ctorObj = ctorFunc;
|
||||||
|
|
||||||
|
Nan::SetMethod(ctorFunc, "listenerCount", jsStaticListenerCount);
|
||||||
|
ACCESSOR_RW(ctorObj, defaultMaxListeners);
|
||||||
|
|
||||||
|
//Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
|
||||||
// ACCESSOR_RW(proto, type);
|
// ACCESSOR_RW(proto, type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void emit(const std::string &name, int argc = 0, v8::Local<v8::Value> *argv = NULL) {
|
// Deprecated static method
|
||||||
|
|
||||||
VEC_TYPE &list = _listeners[name];
|
|
||||||
|
|
||||||
if (list.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (IT_TYPE it = list.begin(); it != list.end(); ++it) {
|
|
||||||
|
|
||||||
Nan::Callback callback(Nan::New(*it));
|
|
||||||
|
|
||||||
if ( ! callback.IsEmpty() ) {
|
|
||||||
callback.Call(argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Deprecated method
|
|
||||||
static NAN_METHOD(jsStaticListenerCount) {
|
static NAN_METHOD(jsStaticListenerCount) {
|
||||||
|
|
||||||
// EventEmitter *emitter = ObjectWrap::Unwrap<EventEmitter>(info[0]);
|
REQ_OBJ_ARG(0, obj);
|
||||||
// REQ_UTF8_ARG(1, name);
|
EventEmitter *emitter = ObjectWrap::Unwrap<EventEmitter>(obj);
|
||||||
|
REQ_UTF8_ARG(1, name);
|
||||||
|
|
||||||
// const VEC_TYPE &list = emitter->_listeners[*name];
|
const VEC_TYPE &list = emitter->_listeners[*name];
|
||||||
|
|
||||||
// RET_VALUE(JS_NUM(list.size()));
|
RET_VALUE(JS_INT(static_cast<int>(list.size())));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +164,15 @@ public:
|
||||||
|
|
||||||
REQ_UTF8_ARG(0, name);
|
REQ_UTF8_ARG(0, name);
|
||||||
|
|
||||||
emitter->emit(*name, info.Length() - 1, &info[1]);
|
int length = info.Length();
|
||||||
|
|
||||||
|
std::vector< v8::Local<v8::Value> > args;
|
||||||
|
|
||||||
|
for (int i = 1; i < length; i++) {
|
||||||
|
args.push_back(info[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter->emit(*name, length - 1, &args[0]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +248,9 @@ public:
|
||||||
bool isFront
|
bool isFront
|
||||||
) { THIS_EMITTER;
|
) { THIS_EMITTER;
|
||||||
|
|
||||||
|
v8::Local<v8::Value> args[] = { info[0], info[1] };
|
||||||
|
emitter->emit("newListener", 2, args);
|
||||||
|
|
||||||
if (isFront) {
|
if (isFront) {
|
||||||
emitter->_listeners[name].push_front(cb);
|
emitter->_listeners[name].push_front(cb);
|
||||||
emitter->_raw[name].push_front(cb);
|
emitter->_raw[name].push_front(cb);
|
||||||
|
@ -240,6 +286,9 @@ public:
|
||||||
bool isFront
|
bool isFront
|
||||||
) { THIS_EMITTER;
|
) { THIS_EMITTER;
|
||||||
|
|
||||||
|
v8::Local<v8::Value> args[] = { info[0], info[1] };
|
||||||
|
emitter->emit("newListener", 2, args);
|
||||||
|
|
||||||
if (isFront) {
|
if (isFront) {
|
||||||
emitter->_listeners[name].push_front(cb);
|
emitter->_listeners[name].push_front(cb);
|
||||||
emitter->_raw[name].push_front(raw);
|
emitter->_raw[name].push_front(raw);
|
||||||
|
@ -264,16 +313,16 @@ public:
|
||||||
REQ_FUN_ARG(1, raw);
|
REQ_FUN_ARG(1, raw);
|
||||||
|
|
||||||
v8::Local<v8::String> code = JS_STR(
|
v8::Local<v8::String> code = JS_STR(
|
||||||
"((emitter, cb) => (...args) => {\n\
|
"((emitter, name, cb) => (...args) => {\n\
|
||||||
cb(...args);\n\
|
cb(...args);\n\
|
||||||
emitter.removeListener(cb);\n\
|
emitter.removeListener(name, cb);\n\
|
||||||
})"
|
})"
|
||||||
);
|
);
|
||||||
|
|
||||||
v8::Local<v8::Function> decor = v8::Local<v8::Function>::Cast(v8::Script::Compile(code)->Run());
|
v8::Local<v8::Function> decor = v8::Local<v8::Function>::Cast(v8::Script::Compile(code)->Run());
|
||||||
Nan::Callback decorCb(decor);
|
Nan::Callback decorCb(decor);
|
||||||
v8::Local<v8::Value> argv[] = { info.This(), raw };
|
v8::Local<v8::Value> argv[] = { info.This(), info[0], raw };
|
||||||
v8::Local<v8::Function> wrap = v8::Local<v8::Function>::Cast(decorCb.Call(2, argv));
|
v8::Local<v8::Function> wrap = v8::Local<v8::Function>::Cast(decorCb.Call(3, argv));
|
||||||
|
|
||||||
Nan::Persistent<v8::Function> persistentWrap;
|
Nan::Persistent<v8::Function> persistentWrap;
|
||||||
persistentWrap.Reset(wrap);
|
persistentWrap.Reset(wrap);
|
||||||
|
@ -299,11 +348,27 @@ public:
|
||||||
|
|
||||||
if (info.Length() > 0 && info[0]->IsString()) {
|
if (info.Length() > 0 && info[0]->IsString()) {
|
||||||
|
|
||||||
|
MAP_TYPE tmpMap = emitter->_raw;
|
||||||
|
|
||||||
emitter->_listeners.clear();
|
emitter->_listeners.clear();
|
||||||
emitter->_raw.clear();
|
emitter->_raw.clear();
|
||||||
emitter->_wrappedIds.clear();
|
emitter->_wrappedIds.clear();
|
||||||
emitter->_rawIds.clear();
|
emitter->_rawIds.clear();
|
||||||
|
|
||||||
|
for (MAP_IT_TYPE itMap = tmpMap.begin(); itMap != tmpMap.end(); ++itMap) {
|
||||||
|
|
||||||
|
const std::string ¤t = itMap->first;
|
||||||
|
VEC_TYPE &list = itMap->second;
|
||||||
|
|
||||||
|
for (IT_TYPE it = list.begin(); it != list.end(); ++it) {
|
||||||
|
|
||||||
|
v8::Local<v8::Value> args[] = { JS_STR(current.c_str()), Nan::New(*it) };
|
||||||
|
emitter->emit("removeListener", 2, args);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -326,7 +391,6 @@ public:
|
||||||
FN_TYPE fn = *it;
|
FN_TYPE fn = *it;
|
||||||
|
|
||||||
for (FNMAP_IT_TYPE itRaw = emitter->_rawIds.begin(); itRaw != emitter->_rawIds.end(); ++itRaw) {
|
for (FNMAP_IT_TYPE itRaw = emitter->_rawIds.begin(); itRaw != emitter->_rawIds.end(); ++itRaw) {
|
||||||
// emitter->_wrappedIds.erase(*it);
|
|
||||||
if (fn == itRaw->second) {
|
if (fn == itRaw->second) {
|
||||||
removes.push_back(itRaw->first);
|
removes.push_back(itRaw->first);
|
||||||
}
|
}
|
||||||
|
@ -346,9 +410,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VEC_TYPE tmpVec = emitter->_raw[name];
|
||||||
|
|
||||||
emitter->_listeners[name].clear();
|
emitter->_listeners[name].clear();
|
||||||
emitter->_raw[name].clear();
|
emitter->_raw[name].clear();
|
||||||
|
|
||||||
|
for (IT_TYPE it = tmpVec.begin(); it != tmpVec.end(); ++it) {
|
||||||
|
|
||||||
|
v8::Local<v8::Value> args[] = { JS_STR(name.c_str()), Nan::New(*it) };
|
||||||
|
emitter->emit("removeListener", 2, args);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -362,13 +435,14 @@ public:
|
||||||
|
|
||||||
std::string name = std::string(*n);
|
std::string name = std::string(*n);
|
||||||
|
|
||||||
|
|
||||||
VEC_TYPE &rawList = emitter->_raw[name];
|
VEC_TYPE &rawList = emitter->_raw[name];
|
||||||
|
|
||||||
if (rawList.empty()) {
|
if (rawList.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> args[] = { info[0], info[1] };
|
||||||
|
|
||||||
for (IT_TYPE it = rawList.begin(); it != rawList.end(); ++it) {
|
for (IT_TYPE it = rawList.begin(); it != rawList.end(); ++it) {
|
||||||
|
|
||||||
if (*it == persistentRaw) {
|
if (*it == persistentRaw) {
|
||||||
|
@ -392,6 +466,7 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emitter->emit("removeListener", 2, args);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -421,6 +496,8 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emitter->emit("removeListener", 2, args);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -458,11 +535,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static int _defaultMaxListeners;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int _maxListeners;
|
int _maxListeners;
|
||||||
|
|
Loading…
Reference in New Issue