Merge branch 'master' into net2

This commit is contained in:
Ryan Dahl 2010-03-12 13:51:00 -08:00
commit c6ebfb0cc6
2 changed files with 68 additions and 27 deletions

View File

@ -170,37 +170,63 @@ var eventsModule = createInternalModule('events', function (exports) {
// process.EventEmitter is defined in src/events.cc // process.EventEmitter is defined in src/events.cc
// process.EventEmitter.prototype.emit() is also defined there. // process.EventEmitter.prototype.emit() is also defined there.
process.EventEmitter.prototype.addListener = function (type, listener) { process.EventEmitter.prototype.addListener = function (type, listener) {
if (listener instanceof Function) { if (!(listener instanceof Function)) {
if (!this._events) this._events = {}; throw new Error('addListener only takes instances of Function');
if (!this._events.hasOwnProperty(type)) this._events[type] = [];
// To avoid recursion in the case that type == "newListeners"! Before
// adding it to the listeners, first emit "newListeners".
this.emit("newListener", type, listener);
this._events[type].push(listener);
} }
if (!this._events) this._events = {};
// To avoid recursion in the case that type == "newListeners"! Before
// adding it to the listeners, first emit "newListeners".
this.emit("newListener", type, listener);
if (!this._events[type]) {
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
} else if (this._events[type] instanceof Array) {
// If we've already got an array, just append.
this._events[type].push(listener);
} else {
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
}
return this; return this;
}; };
process.EventEmitter.prototype.removeListener = function (type, listener) { process.EventEmitter.prototype.removeListener = function (type, listener) {
if (listener instanceof Function) { if (!(listener instanceof Function)) {
// does not use listeners(), so no side effect of creating _events[type] throw new Error('removeListener only takes instances of Function');
if (!this._events || !this._events.hasOwnProperty(type)) return;
var list = this._events[type];
if (list.indexOf(listener) < 0) return;
list.splice(list.indexOf(listener), 1);
} }
// does not use listeners(), so no side effect of creating _events[type]
if (!this._events || !this._events[type]) return this;
var list = this._events[type];
if (list instanceof Array) {
var i = list.indexOf(listener);
if (i < 0) return this;
list.splice(i, 1);
} else {
this._events[type] = null;
}
return this; return this;
}; };
process.EventEmitter.prototype.removeAllListeners = function (type) { process.EventEmitter.prototype.removeAllListeners = function (type) {
// does not use listeners(), so no side effect of creating _events[type] // does not use listeners(), so no side effect of creating _events[type]
if (!type || !this._events || !this._events.hasOwnProperty(type)) return this; if (!type || !this._events || !this._events[type]) return this;
this._events[type].length = 0; this._events[type] = null;
}; };
process.EventEmitter.prototype.listeners = function (type) { process.EventEmitter.prototype.listeners = function (type) {
if (!this._events) this._events = {}; if (!this._events) this._events = {};
if (!this._events.hasOwnProperty(type)) this._events[type] = []; if (!this._events[type]) this._events[type] = [];
if (!(this._events[type] instanceof Array)) {
this._events[type] = [this._events[type]];
}
return this._events[type]; return this._events[type];
}; };

View File

@ -43,24 +43,20 @@ static bool ReallyEmit(Handle<Object> self,
Handle<String> event, Handle<String> event,
int argc, int argc,
Handle<Value> argv[]) { Handle<Value> argv[]) {
HandleScope scope; // HandleScope not needed here because only called from one of the two
// functions below
Local<Value> events_v = self->Get(events_symbol); Local<Value> events_v = self->Get(events_symbol);
if (!events_v->IsObject()) return false; if (!events_v->IsObject()) return false;
Local<Object> events = events_v->ToObject(); Local<Object> events = events_v->ToObject();
Local<Value> listeners_v = events->Get(event); Local<Value> listeners_v = events->Get(event);
if (!listeners_v->IsArray()) return false; Local<Function> listener;
Local<Array> listeners = Local<Array>::Cast(listeners_v);
for (unsigned int i = 0; i < listeners->Length(); i++) { TryCatch try_catch;
HandleScope scope;
Local<Value> listener_v = listeners->Get(Integer::New(i)); if (listeners_v->IsFunction()) {
if (!listener_v->IsFunction()) continue; // Optimized one-listener case
Local<Function> listener = Local<Function>::Cast(listener_v); Local<Function> listener = Local<Function>::Cast(listeners_v);
TryCatch try_catch;
listener->Call(self, argc, argv); listener->Call(self, argc, argv);
@ -68,6 +64,25 @@ static bool ReallyEmit(Handle<Object> self,
FatalException(try_catch); FatalException(try_catch);
return false; return false;
} }
} else if (listeners_v->IsArray()) {
Local<Array> listeners = Local<Array>::Cast(listeners_v);
for (uint32_t i = 0; i < listeners->Length(); i++) {
Local<Value> listener_v = listeners->Get(i);
if (!listener_v->IsFunction()) continue;
Local<Function> listener = Local<Function>::Cast(listener_v);
listener->Call(self, argc, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
return false;
}
}
} else {
return false;
} }
return true; return true;