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
|
||||
`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**:
|
||||
|
||||
|
@ -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`:
|
||||
|
||||
```
|
||||
|
@ -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,
|
||||
after constructor function instance is created,
|
||||
`static void extendConstructor(v8::Local<v8::Function> &ctorFn)`:
|
||||
|
||||
Now that everything is in place, consider providing **V8** with JS inheritance info:
|
||||
|
||||
```
|
||||
void Example::init(Handle<Object> target) {
|
||||
|
||||
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->SetClassName(JS_STR("Example"));
|
||||
|
||||
|
||||
// -------- dynamic
|
||||
|
||||
// Add EventEmitter methods
|
||||
extendPrototype(proto);
|
||||
|
||||
Nan::SetPrototypeMethod(proto, "destroy", destroy);
|
||||
|
||||
|
||||
// -------- static
|
||||
|
||||
Local<Function> ctor = Nan::GetFunction(proto).ToLocalChecked();
|
||||
|
||||
extendConstructor(ctor);
|
||||
_prototype.Reset(proto);
|
||||
|
||||
|
||||
_constructor.Reset(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 <iostream>
|
||||
|
||||
#include <event-emitter.hpp>
|
||||
|
||||
#include "example.hpp"
|
||||
|
||||
|
||||
using namespace v8;
|
||||
using namespace node;
|
||||
using namespace std;
|
||||
|
@ -12,14 +11,10 @@ using namespace std;
|
|||
#define THIS_EXAMPLE \
|
||||
Example *example = ObjectWrap::Unwrap<Example>(info.This());
|
||||
|
||||
#define THIS_EVENT_EMITTER \
|
||||
EventEmitter *eventEmitter = ObjectWrap::Unwrap<EventEmitter>(info.This());
|
||||
|
||||
#define THIS_CHECK \
|
||||
if (example->_isDestroyed) return;
|
||||
|
||||
|
||||
Nan::Persistent<v8::FunctionTemplate> Example::_prototype;
|
||||
Nan::Persistent<v8::Function> Example::_constructor;
|
||||
|
||||
|
||||
|
@ -31,22 +26,15 @@ void Example::init(Handle<Object> target) {
|
|||
Local<FunctionTemplate> parent = Nan::New(EventEmitter::_prototype);
|
||||
proto->Inherit(parent);
|
||||
|
||||
|
||||
proto->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
proto->SetClassName(JS_STR("Example"));
|
||||
|
||||
|
||||
// -------- dynamic
|
||||
|
||||
Nan::SetPrototypeMethod(proto, "destroy", destroy);
|
||||
|
||||
|
||||
// -------- static
|
||||
|
||||
Local<Function> ctor = Nan::GetFunction(proto).ToLocalChecked();
|
||||
|
||||
|
||||
_prototype.Reset(proto);
|
||||
_constructor.Reset(ctor);
|
||||
|
||||
Nan::Set(target, JS_STR("Example"), ctor);
|
||||
|
@ -56,19 +44,17 @@ void Example::init(Handle<Object> target) {
|
|||
|
||||
NAN_METHOD(Example::newCtor) {
|
||||
|
||||
std::cout << "Example() 1" << std::endl;
|
||||
v8::Local<v8::Function> superCtor = Nan::New(EventEmitter::_constructor);
|
||||
superCtor->Call(info.This(), 0, nullptr);
|
||||
std::cout << "Example() 2" << std::endl;
|
||||
CTOR_CHECK("EventEmitter");
|
||||
|
||||
Example *example = new Example();
|
||||
example->Wrap(info.This());
|
||||
std::cout << "Example() 3 @" << example << std::endl;
|
||||
|
||||
RET_VALUE(info.This());
|
||||
|
||||
}
|
||||
|
||||
|
||||
Example::Example() {
|
||||
Example::Example() : EventEmitter() {
|
||||
|
||||
_isDestroyed = false;
|
||||
|
||||
|
@ -86,12 +72,13 @@ void Example::_destroy() { DES_CHECK;
|
|||
|
||||
_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();
|
||||
|
||||
}
|
||||
|
|
|
@ -2,33 +2,31 @@
|
|||
#define _EXAMPLE_HPP_
|
||||
|
||||
|
||||
#include <addon-tools.hpp>
|
||||
|
||||
#include "common.hpp"
|
||||
#include <event-emitter.hpp>
|
||||
|
||||
|
||||
class Example : public Nan::ObjectWrap {
|
||||
class Example : public EventEmitter {
|
||||
|
||||
public:
|
||||
|
||||
static void init(v8::Handle<v8::Object> target);
|
||||
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
Example();
|
||||
virtual ~Example();
|
||||
|
||||
static NAN_METHOD(newCtor);
|
||||
|
||||
static NAN_METHOD(destroy);
|
||||
|
||||
~Example();
|
||||
void _destroy();
|
||||
|
||||
|
||||
private:
|
||||
static NAN_METHOD(newCtor);
|
||||
|
||||
static NAN_METHOD(destroy);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
static Nan::Persistent<v8::FunctionTemplate> _prototype;
|
||||
static Nan::Persistent<v8::Function> _constructor;
|
||||
|
||||
bool _isDestroyed;
|
||||
|
|
|
@ -7,7 +7,7 @@ console.log('Example', 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);
|
||||
|
||||
|
@ -27,11 +27,11 @@ console.log('setMaxListeners', example.setMaxListeners);
|
|||
console.log('rawListeners', example.rawListeners);
|
||||
console.log('destroy', example.destroy);
|
||||
|
||||
console.log('index.js', 'ON1');
|
||||
|
||||
example.on('evt1', (arg1, arg2) => {
|
||||
console.log('EVT1', arg1, arg2, example.eventNames());
|
||||
});
|
||||
console.log('index.js', 'ON2');
|
||||
|
||||
example.once('evt2', (arg1, arg2) => {
|
||||
console.log('EVT2', arg1, arg2, example.eventNames());
|
||||
});
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
#define EVENT_EMITTER_THIS_CHECK \
|
||||
if (eventEmitter->_isDestroyed) return;
|
||||
|
||||
#define EVENT_EMITTER_DES_CHECK \
|
||||
if (_isDestroyed) return;
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct StaticHolder {
|
||||
|
@ -136,13 +133,13 @@ public:
|
|||
}
|
||||
|
||||
|
||||
void _destroy() { EVENT_EMITTER_DES_CHECK;
|
||||
virtual void _destroy() { DES_CHECK;
|
||||
_isDestroyed = true;
|
||||
emit("destroy");
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
EventEmitter () {
|
||||
_isDestroyed = false;
|
||||
|
@ -153,11 +150,15 @@ private:
|
|||
virtual ~EventEmitter () { _destroy(); }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
static NAN_METHOD(newCtor) {
|
||||
std::cout << "EventEmitter() 1" << std::endl;
|
||||
|
||||
CTOR_CHECK("EventEmitter");
|
||||
|
||||
EventEmitter *eventEmitter = new EventEmitter();
|
||||
eventEmitter->Wrap(info.This());
|
||||
std::cout << "EventEmitter() 2 : @" << eventEmitter << std::endl;
|
||||
|
||||
RET_VALUE(info.This());
|
||||
|
||||
}
|
||||
|
@ -213,10 +214,8 @@ private:
|
|||
|
||||
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());
|
||||
std::cout << "jsEventNames() 2" << std::endl;
|
||||
|
||||
if (eventEmitter->_raw.empty()) {
|
||||
RET_VALUE(jsNames);
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue