From: Ryan Date: Fri, 24 Jul 2009 20:23:50 +0000 (+0200) Subject: Move EventEmitter.prototype.emit() completely into C++. X-Git-Tag: v0.1.1~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=842eaf446d2fdcb33b296c67c911c32a0dabc747;p=platform%2Fupstream%2Fnodejs.git Move EventEmitter.prototype.emit() completely into C++. This shows a healthy speed up. --- diff --git a/src/events.cc b/src/events.cc index 0116087..47bbba4 100644 --- a/src/events.cc +++ b/src/events.cc @@ -11,6 +11,10 @@ #include /* inet_ntop */ #include /* 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 target) HandleScope scope; Local t = FunctionTemplate::New(); + constructor_template = Persistent::New(t); - // All prototype methods are defined in events.js + Local __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 argv[]) +static bool +ReallyEmit (Handle self, Handle event, int argc, Handle argv[]) { HandleScope scope; - Local emit_v = handle_->Get(String::NewSymbol("emit")); - assert(emit_v->IsFunction()); - Local emit = Local::Cast(emit_v); - - Local events_v = handle_->Get(String::NewSymbol("_events")); + Local events_v = self->Get(String::NewSymbol("_events")); if (!events_v->IsObject()) return false; Local events = events_v->ToObject(); - Local listeners_v = events->Get(String::NewSymbol(type)); + Local listeners_v = events->Get(event); if (!listeners_v->IsArray()) return false; Local listeners = Local::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 listener_v = listeners->Get(Integer::New(i)); if (!listener_v->IsFunction()) continue; Local listener = Local::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 argv[]) return true; } +Handle +EventEmitter::Emit (const Arguments& args) +{ + HandleScope scope; + Local event = args[0]->ToString(); + int argc = 0; + Local emit_args; + if (args[1]->IsArray()) { + emit_args = Local::Cast(args[1]); + argc = emit_args->Length(); + } + Local 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 argv[]) +{ + HandleScope scope; + Local event = String::NewSymbol(event_s); + return ReallyEmit(handle_, event, argc, argv); +} + Persistent Promise::constructor_template; void diff --git a/src/events.h b/src/events.h index ca3d5fd..ded7c00 100644 --- a/src/events.h +++ b/src/events.h @@ -11,10 +11,12 @@ class EventEmitter : public ObjectWrap { static void Initialize (v8::Handle target); static v8::Persistent constructor_template; - bool Emit (const char *type, int argc, v8::Handle argv[]); + bool Emit (const char *event, int argc, v8::Handle argv[]); protected: - EventEmitter () : ObjectWrap() { } + static v8::Handle Emit (const v8::Arguments& args); + + EventEmitter () : ObjectWrap () { } }; class Promise : public EventEmitter { diff --git a/src/events.js b/src/events.js index 0430533..86cf74c 100644 --- a/src/events.js +++ b/src/events.js @@ -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;