mirror of
https://github.com/nodejs/node-v0.x-archive.git
synced 2026-04-28 03:01:10 -04:00
Move EventEmitter.prototype.emit() completely into C++.
This shows a healthy speed up.
This commit is contained in:
@@ -11,6 +11,10 @@
|
||||
#include <arpa/inet.h> /* inet_ntop */
|
||||
#include <netinet/in.h> /* sockaddr_in, sockaddr_in6 */
|
||||
|
||||
#ifndef RAMP
|
||||
# define RAMP(x) ((x) > 0 ? (x) : 0)
|
||||
#endif
|
||||
|
||||
using namespace v8;
|
||||
using namespace node;
|
||||
|
||||
@@ -22,39 +26,41 @@ EventEmitter::Initialize (v8::Handle<v8::Object> target)
|
||||
HandleScope scope;
|
||||
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New();
|
||||
|
||||
constructor_template = Persistent<FunctionTemplate>::New(t);
|
||||
|
||||
// All prototype methods are defined in events.js
|
||||
Local<FunctionTemplate> __emit = FunctionTemplate::New(Emit);
|
||||
constructor_template->PrototypeTemplate()->Set(String::NewSymbol("emit"), __emit);
|
||||
|
||||
// All other prototype methods are defined in events.js
|
||||
|
||||
target->Set(String::NewSymbol("EventEmitter"),
|
||||
constructor_template->GetFunction());
|
||||
}
|
||||
|
||||
bool
|
||||
EventEmitter::Emit (const char *type, int argc, Handle<Value> argv[])
|
||||
static bool
|
||||
ReallyEmit (Handle<Object> self, Handle<String> event, int argc, Handle<Value> argv[])
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<Value> emit_v = handle_->Get(String::NewSymbol("emit"));
|
||||
assert(emit_v->IsFunction());
|
||||
Local<Function> emit = Local<Function>::Cast(emit_v);
|
||||
|
||||
Local<Value> events_v = handle_->Get(String::NewSymbol("_events"));
|
||||
Local<Value> events_v = self->Get(String::NewSymbol("_events"));
|
||||
if (!events_v->IsObject()) return false;
|
||||
Local<Object> events = events_v->ToObject();
|
||||
|
||||
Local<Value> listeners_v = events->Get(String::NewSymbol(type));
|
||||
Local<Value> listeners_v = events->Get(event);
|
||||
if (!listeners_v->IsArray()) return false;
|
||||
Local<Array> listeners = Local<Array>::Cast(listeners_v);
|
||||
|
||||
TryCatch try_catch;
|
||||
for (unsigned int i = 0; i < listeners->Length(); i++) {
|
||||
HandleScope scope;
|
||||
|
||||
for (int i = 0; i < listeners->Length(); i++) {
|
||||
Local<Value> listener_v = listeners->Get(Integer::New(i));
|
||||
if (!listener_v->IsFunction()) continue;
|
||||
Local<Function> listener = Local<Function>::Cast(listener_v);
|
||||
|
||||
listener->Call(handle_, argc, argv);
|
||||
TryCatch try_catch;
|
||||
|
||||
listener->Call(self, argc, argv);
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
FatalException(try_catch);
|
||||
@@ -65,6 +71,36 @@ EventEmitter::Emit (const char *type, int argc, Handle<Value> argv[])
|
||||
return true;
|
||||
}
|
||||
|
||||
Handle<Value>
|
||||
EventEmitter::Emit (const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
Local<String> event = args[0]->ToString();
|
||||
int argc = 0;
|
||||
Local<Array> emit_args;
|
||||
if (args[1]->IsArray()) {
|
||||
emit_args = Local<Array>::Cast(args[1]);
|
||||
argc = emit_args->Length();
|
||||
}
|
||||
Local<Value> argv[argc];
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
argv[i] = emit_args->Get(Integer::New(i));
|
||||
}
|
||||
|
||||
bool r = ReallyEmit(args.Holder(), event, argc, argv);
|
||||
|
||||
return scope.Close(r ? True() : False());
|
||||
}
|
||||
|
||||
bool
|
||||
EventEmitter::Emit (const char *event_s, int argc, Handle<Value> argv[])
|
||||
{
|
||||
HandleScope scope;
|
||||
Local<String> event = String::NewSymbol(event_s);
|
||||
return ReallyEmit(handle_, event, argc, argv);
|
||||
}
|
||||
|
||||
Persistent<FunctionTemplate> Promise::constructor_template;
|
||||
|
||||
void
|
||||
|
||||
@@ -11,10 +11,12 @@ class EventEmitter : public ObjectWrap {
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
|
||||
bool Emit (const char *type, int argc, v8::Handle<v8::Value> argv[]);
|
||||
bool Emit (const char *event, int argc, v8::Handle<v8::Value> argv[]);
|
||||
|
||||
protected:
|
||||
EventEmitter () : ObjectWrap() { }
|
||||
static v8::Handle<v8::Value> Emit (const v8::Arguments& args);
|
||||
|
||||
EventEmitter () : ObjectWrap () { }
|
||||
};
|
||||
|
||||
class Promise : public EventEmitter {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
(function () {
|
||||
|
||||
// node.EventEmitter is defined in src/events.cc
|
||||
var emitter = node.EventEmitter.prototype;
|
||||
|
||||
emitter.addListener = function (type, listener) {
|
||||
// node.EventEmitter.prototype.emit() is also defined there.
|
||||
node.EventEmitter.prototype.addListener = function (type, listener) {
|
||||
if (listener instanceof Function) {
|
||||
if (!this._events) this._events = {};
|
||||
if (!this._events.hasOwnProperty(type)) this._events[type] = [];
|
||||
@@ -11,27 +10,12 @@ emitter.addListener = function (type, listener) {
|
||||
}
|
||||
};
|
||||
|
||||
emitter.listeners = function (type) {
|
||||
node.EventEmitter.prototype.listeners = function (type) {
|
||||
if (!this._events) this._events = {};
|
||||
if (!this._events.hasOwnProperty(type)) this._events[type] = [];
|
||||
return this._events[type];
|
||||
};
|
||||
|
||||
// This function is called often from C++.
|
||||
// FIXME there is a counterpart for this function in C++
|
||||
// both must have the same behavior.
|
||||
// See events.cc
|
||||
emitter.emit = function (type, args) {
|
||||
if (!this._events) return;
|
||||
if (!this._events.hasOwnProperty(type)) return;
|
||||
|
||||
var listeners = this._events[type];
|
||||
|
||||
for (var i = 0; i < listeners.length; i++) {
|
||||
listeners[i].apply(this, args);
|
||||
}
|
||||
};
|
||||
|
||||
// node.Promise is defined in src/events.cc
|
||||
var promise = node.Promise.prototype;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user