refine emitter
This commit is contained in:
parent
e773b03e93
commit
22288f55b0
40
README.md
40
README.md
|
@ -587,6 +587,10 @@ emits an event with the given `name` and, optionally, some additional arguments
|
||||||
subscribes `that[method]` to receive `name` events from this emitter, basically
|
subscribes `that[method]` to receive `name` events from this emitter, basically
|
||||||
`emitter.on(name, that[method])`.
|
`emitter.on(name, that[method])`.
|
||||||
|
|
||||||
|
* `virtual void _destroy()` - destroys the object, i.e. deactivates it and frees
|
||||||
|
resources, also emitting a `'destroy'` event. This is what also called inside
|
||||||
|
`~EventEmitter()`, but only the first call is effective anyway.
|
||||||
|
|
||||||
|
|
||||||
Be sure to add the include directory in **binding.gyp**:
|
Be sure to add the include directory in **binding.gyp**:
|
||||||
|
|
||||||
|
@ -596,7 +600,8 @@ Be sure to add the include directory in **binding.gyp**:
|
||||||
],
|
],
|
||||||
```
|
```
|
||||||
|
|
||||||
Include the **event-emitter.hpp**, it also includes **addon-tools.hpp**.
|
Though it is the same directory for all the **addon-tools**.
|
||||||
|
Then include the **event-emitter.hpp**, it also includes **addon-tools.hpp**.
|
||||||
Inherit from `EventEmitter`, it already inherits from `Nan::ObjectWrap`:
|
Inherit from `EventEmitter`, it already inherits from `Nan::ObjectWrap`:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -607,43 +612,30 @@ class Example : public EventEmitter {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
NOTE: Do not forget to call `EventEmitter::init()` once, in the module `init()`.
|
||||||
|
|
||||||
First add EventEmitter dynamic methods to the prototype via
|
|
||||||
`static void extendPrototype(v8::Local<v8::FunctionTemplate> &proto)` and then,
|
Now that everything is in place, consider providing **V8** with JS inheritance info:
|
||||||
after constructor function instance is created,
|
|
||||||
`static void extendConstructor(v8::Local<v8::Function> &ctorFn)`:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
void Example::init(Handle<Object> target) {
|
void Example::init(Handle<Object> target) {
|
||||||
|
|
||||||
Local<FunctionTemplate> proto = Nan::New<FunctionTemplate>(newCtor);
|
Local<FunctionTemplate> proto = Nan::New<FunctionTemplate>(newCtor);
|
||||||
|
|
||||||
|
// -------------------------- HERE!
|
||||||
|
// class Example extends EventEmitter
|
||||||
|
Local<FunctionTemplate> parent = Nan::New(EventEmitter::_prototype);
|
||||||
|
proto->Inherit(parent);
|
||||||
|
// --------------------------
|
||||||
|
|
||||||
proto->InstanceTemplate()->SetInternalFieldCount(1);
|
proto->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
proto->SetClassName(JS_STR("Example"));
|
proto->SetClassName(JS_STR("Example"));
|
||||||
|
|
||||||
|
|
||||||
// -------- dynamic
|
|
||||||
|
|
||||||
// Add EventEmitter methods
|
|
||||||
extendPrototype(proto);
|
|
||||||
|
|
||||||
Nan::SetPrototypeMethod(proto, "destroy", destroy);
|
|
||||||
|
|
||||||
|
|
||||||
// -------- static
|
|
||||||
|
|
||||||
Local<Function> ctor = Nan::GetFunction(proto).ToLocalChecked();
|
Local<Function> ctor = Nan::GetFunction(proto).ToLocalChecked();
|
||||||
|
|
||||||
extendConstructor(ctor);
|
_prototype.Reset(proto);
|
||||||
|
|
||||||
|
|
||||||
_constructor.Reset(ctor);
|
|
||||||
Nan::Set(target, JS_STR("Example"), ctor);
|
Nan::Set(target, JS_STR("Example"), ctor);
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: after a `v8::Function` is created from the `v8::FunctionTemplate`, no
|
|
||||||
additional methods can be added to the prototype. Also static members can only
|
|
||||||
be added to the created `v8::Function` representing the constructor. This is why
|
|
||||||
there are 2 extend methods: `extendPrototype` and `extendConstructor`.
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
#ifndef _COMMON_HPP_
|
|
||||||
#define _COMMON_HPP_
|
|
||||||
|
|
||||||
|
|
||||||
#include <addon-tools.hpp>
|
|
||||||
|
|
||||||
#define DES_CHECK \
|
|
||||||
if (_isDestroyed) return;
|
|
||||||
|
|
||||||
#endif /* _COMMON_HPP_ */
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <event-emitter.hpp>
|
|
||||||
|
|
||||||
#include "example.hpp"
|
#include "example.hpp"
|
||||||
|
|
||||||
|
|
||||||
using namespace v8;
|
using namespace v8;
|
||||||
using namespace node;
|
using namespace node;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -12,14 +11,10 @@ using namespace std;
|
||||||
#define THIS_EXAMPLE \
|
#define THIS_EXAMPLE \
|
||||||
Example *example = ObjectWrap::Unwrap<Example>(info.This());
|
Example *example = ObjectWrap::Unwrap<Example>(info.This());
|
||||||
|
|
||||||
#define THIS_EVENT_EMITTER \
|
|
||||||
EventEmitter *eventEmitter = ObjectWrap::Unwrap<EventEmitter>(info.This());
|
|
||||||
|
|
||||||
#define THIS_CHECK \
|
#define THIS_CHECK \
|
||||||
if (example->_isDestroyed) return;
|
if (example->_isDestroyed) return;
|
||||||
|
|
||||||
|
|
||||||
Nan::Persistent<v8::FunctionTemplate> Example::_prototype;
|
|
||||||
Nan::Persistent<v8::Function> Example::_constructor;
|
Nan::Persistent<v8::Function> Example::_constructor;
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,22 +26,15 @@ void Example::init(Handle<Object> target) {
|
||||||
Local<FunctionTemplate> parent = Nan::New(EventEmitter::_prototype);
|
Local<FunctionTemplate> parent = Nan::New(EventEmitter::_prototype);
|
||||||
proto->Inherit(parent);
|
proto->Inherit(parent);
|
||||||
|
|
||||||
|
|
||||||
proto->InstanceTemplate()->SetInternalFieldCount(1);
|
proto->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
proto->SetClassName(JS_STR("Example"));
|
proto->SetClassName(JS_STR("Example"));
|
||||||
|
|
||||||
|
|
||||||
// -------- dynamic
|
// -------- dynamic
|
||||||
|
|
||||||
Nan::SetPrototypeMethod(proto, "destroy", destroy);
|
Nan::SetPrototypeMethod(proto, "destroy", destroy);
|
||||||
|
|
||||||
|
|
||||||
// -------- static
|
// -------- static
|
||||||
|
|
||||||
Local<Function> ctor = Nan::GetFunction(proto).ToLocalChecked();
|
Local<Function> ctor = Nan::GetFunction(proto).ToLocalChecked();
|
||||||
|
|
||||||
|
|
||||||
_prototype.Reset(proto);
|
|
||||||
_constructor.Reset(ctor);
|
_constructor.Reset(ctor);
|
||||||
|
|
||||||
Nan::Set(target, JS_STR("Example"), ctor);
|
Nan::Set(target, JS_STR("Example"), ctor);
|
||||||
|
@ -56,19 +44,17 @@ void Example::init(Handle<Object> target) {
|
||||||
|
|
||||||
NAN_METHOD(Example::newCtor) {
|
NAN_METHOD(Example::newCtor) {
|
||||||
|
|
||||||
std::cout << "Example() 1" << std::endl;
|
CTOR_CHECK("EventEmitter");
|
||||||
v8::Local<v8::Function> superCtor = Nan::New(EventEmitter::_constructor);
|
|
||||||
superCtor->Call(info.This(), 0, nullptr);
|
|
||||||
std::cout << "Example() 2" << std::endl;
|
|
||||||
Example *example = new Example();
|
Example *example = new Example();
|
||||||
example->Wrap(info.This());
|
example->Wrap(info.This());
|
||||||
std::cout << "Example() 3 @" << example << std::endl;
|
|
||||||
RET_VALUE(info.This());
|
RET_VALUE(info.This());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Example::Example() {
|
Example::Example() : EventEmitter() {
|
||||||
|
|
||||||
_isDestroyed = false;
|
_isDestroyed = false;
|
||||||
|
|
||||||
|
@ -86,12 +72,13 @@ void Example::_destroy() { DES_CHECK;
|
||||||
|
|
||||||
_isDestroyed = true;
|
_isDestroyed = true;
|
||||||
|
|
||||||
|
EventEmitter::_destroy();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NAN_METHOD(Example::destroy) { THIS_EXAMPLE; THIS_CHECK; THIS_EVENT_EMITTER;
|
NAN_METHOD(Example::destroy) { THIS_EXAMPLE; THIS_CHECK;
|
||||||
|
|
||||||
eventEmitter->_destroy();
|
|
||||||
example->_destroy();
|
example->_destroy();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,33 +2,31 @@
|
||||||
#define _EXAMPLE_HPP_
|
#define _EXAMPLE_HPP_
|
||||||
|
|
||||||
|
|
||||||
#include <addon-tools.hpp>
|
#include <event-emitter.hpp>
|
||||||
|
|
||||||
#include "common.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
class Example : public Nan::ObjectWrap {
|
class Example : public EventEmitter {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void init(v8::Handle<v8::Object> target);
|
static void init(v8::Handle<v8::Object> target);
|
||||||
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
Example();
|
Example();
|
||||||
virtual ~Example();
|
~Example();
|
||||||
|
|
||||||
static NAN_METHOD(newCtor);
|
|
||||||
|
|
||||||
static NAN_METHOD(destroy);
|
|
||||||
|
|
||||||
void _destroy();
|
void _destroy();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
static NAN_METHOD(newCtor);
|
||||||
|
|
||||||
|
static NAN_METHOD(destroy);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static Nan::Persistent<v8::FunctionTemplate> _prototype;
|
|
||||||
static Nan::Persistent<v8::Function> _constructor;
|
static Nan::Persistent<v8::Function> _constructor;
|
||||||
|
|
||||||
bool _isDestroyed;
|
bool _isDestroyed;
|
||||||
|
|
|
@ -7,7 +7,7 @@ console.log('Example', Example);
|
||||||
|
|
||||||
const example = new Example();
|
const example = new Example();
|
||||||
|
|
||||||
console.log('example 0', example);
|
console.log('example 0', example, 'instanceof EventEmitter', example instanceof EventEmitter);
|
||||||
|
|
||||||
console.log('static listenerCount', EventEmitter.listenerCount);
|
console.log('static listenerCount', EventEmitter.listenerCount);
|
||||||
|
|
||||||
|
@ -27,11 +27,11 @@ console.log('setMaxListeners', example.setMaxListeners);
|
||||||
console.log('rawListeners', example.rawListeners);
|
console.log('rawListeners', example.rawListeners);
|
||||||
console.log('destroy', example.destroy);
|
console.log('destroy', example.destroy);
|
||||||
|
|
||||||
console.log('index.js', 'ON1');
|
|
||||||
example.on('evt1', (arg1, arg2) => {
|
example.on('evt1', (arg1, arg2) => {
|
||||||
console.log('EVT1', arg1, arg2, example.eventNames());
|
console.log('EVT1', arg1, arg2, example.eventNames());
|
||||||
});
|
});
|
||||||
console.log('index.js', 'ON2');
|
|
||||||
example.once('evt2', (arg1, arg2) => {
|
example.once('evt2', (arg1, arg2) => {
|
||||||
console.log('EVT2', arg1, arg2, example.eventNames());
|
console.log('EVT2', arg1, arg2, example.eventNames());
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
#define EVENT_EMITTER_THIS_CHECK \
|
#define EVENT_EMITTER_THIS_CHECK \
|
||||||
if (eventEmitter->_isDestroyed) return;
|
if (eventEmitter->_isDestroyed) return;
|
||||||
|
|
||||||
#define EVENT_EMITTER_DES_CHECK \
|
|
||||||
if (_isDestroyed) return;
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct StaticHolder {
|
struct StaticHolder {
|
||||||
|
@ -136,13 +133,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _destroy() { EVENT_EMITTER_DES_CHECK;
|
virtual void _destroy() { DES_CHECK;
|
||||||
_isDestroyed = true;
|
_isDestroyed = true;
|
||||||
emit("destroy");
|
emit("destroy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
EventEmitter () {
|
EventEmitter () {
|
||||||
_isDestroyed = false;
|
_isDestroyed = false;
|
||||||
|
@ -153,11 +150,15 @@ private:
|
||||||
virtual ~EventEmitter () { _destroy(); }
|
virtual ~EventEmitter () { _destroy(); }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
static NAN_METHOD(newCtor) {
|
static NAN_METHOD(newCtor) {
|
||||||
std::cout << "EventEmitter() 1" << std::endl;
|
|
||||||
|
CTOR_CHECK("EventEmitter");
|
||||||
|
|
||||||
EventEmitter *eventEmitter = new EventEmitter();
|
EventEmitter *eventEmitter = new EventEmitter();
|
||||||
eventEmitter->Wrap(info.This());
|
eventEmitter->Wrap(info.This());
|
||||||
std::cout << "EventEmitter() 2 : @" << eventEmitter << std::endl;
|
|
||||||
RET_VALUE(info.This());
|
RET_VALUE(info.This());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -213,10 +214,8 @@ private:
|
||||||
|
|
||||||
static NAN_METHOD(jsEventNames) { THIS_EVENT_EMITTER;
|
static NAN_METHOD(jsEventNames) { THIS_EVENT_EMITTER;
|
||||||
|
|
||||||
std::cout << "jsEventNames() 1: @" << eventEmitter << " x " << eventEmitter->_raw.size() << std::endl;
|
|
||||||
|
|
||||||
v8::Local<v8::Array> jsNames = Nan::New<v8::Array>(eventEmitter->_raw.size());
|
v8::Local<v8::Array> jsNames = Nan::New<v8::Array>(eventEmitter->_raw.size());
|
||||||
std::cout << "jsEventNames() 2" << std::endl;
|
|
||||||
if (eventEmitter->_raw.empty()) {
|
if (eventEmitter->_raw.empty()) {
|
||||||
RET_VALUE(jsNames);
|
RET_VALUE(jsNames);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue