Skip to content

Commit 77b0098

Browse files
committed
WIP events: optimize emit()
EventEmitter#emit() can be called with many different arguments, but there are a few that are most common. Increase performance by optimizing those most common cases. It also drastically decreases the amount of output from --trace_deopt.
1 parent 8b98096 commit 77b0098

File tree

1 file changed

+54
-27
lines changed

1 file changed

+54
-27
lines changed

lib/events.js

+54-27
Original file line numberDiff line numberDiff line change
@@ -56,38 +56,14 @@ EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
5656
return $getMaxListeners(this);
5757
};
5858

59-
EventEmitter.prototype.emit = function emit(type) {
60-
var er, handler, len, args, i, listeners;
61-
62-
if (!this._events)
63-
this._events = {};
64-
65-
// If there is no 'error' event listener then throw.
66-
if (type === 'error' && !this._events.error) {
67-
er = arguments[1];
68-
if (this.domain) {
69-
if (!er)
70-
er = new Error('Uncaught, unspecified "error" event.');
71-
er.domainEmitter = this;
72-
er.domain = this.domain;
73-
er.domainThrown = false;
74-
this.domain.emit('error', er);
75-
} else if (er instanceof Error) {
76-
throw er; // Unhandled 'error' event
77-
} else {
78-
throw Error('Uncaught, unspecified "error" event.');
79-
}
80-
return false;
81-
}
59+
function $emitGeneric(type) {
60+
var handler, len, args, i, listeners;
8261

8362
handler = this._events[type];
8463

8564
if (util.isUndefined(handler))
8665
return false;
8766

88-
if (this.domain && this !== process)
89-
this.domain.enter();
90-
9167
if (util.isFunction(handler)) {
9268
switch (arguments.length) {
9369
// fast cases
@@ -120,10 +96,61 @@ EventEmitter.prototype.emit = function emit(type) {
12096
listeners[i].apply(this, args);
12197
}
12298

99+
return true;
100+
}
101+
102+
function $emitUncaughtError(type, er) {
103+
// If there is no 'error' event listener then throw.
104+
if (this.domain) {
105+
if (!er)
106+
er = new Error('Uncaught, unspecified "error" event.');
107+
er.domainEmitter = this;
108+
er.domain = this.domain;
109+
er.domainThrown = false;
110+
this.domain.emit('error', er);
111+
} else if (er instanceof Error) {
112+
throw er; // Unhandled 'error' event
113+
} else {
114+
throw new Error('Uncaught, unspecified "error" event.');
115+
}
116+
return false;
117+
}
118+
119+
function $emitNoArguments(type) {
120+
var handler = this._events[type];
121+
122+
if (typeof handler === 'function')
123+
handler.call(this);
124+
if (typeof handler !== 'object')
125+
return;
126+
127+
var listeners = handler.slice();
128+
for (var i = 0; i < listeners.length; i++)
129+
listeners[i].call(this);
130+
131+
return true;
132+
}
133+
134+
EventEmitter.prototype.emit = function emit(type) {
135+
var ret;
136+
137+
if (!this._events)
138+
this._events = {};
139+
140+
if (this.domain && this !== process)
141+
this.domain.enter();
142+
143+
if (type === 'error' && !this._events.error)
144+
ret = $emitUncaughtError.apply(this, arguments);
145+
else if (arguments.length === 1)
146+
ret = $emitNoArguments.call(this, type);
147+
else
148+
ret = $emitGeneric.apply(this, arguments);
149+
123150
if (this.domain && this !== process)
124151
this.domain.exit();
125152

126-
return true;
153+
return ret;
127154
};
128155

129156
EventEmitter.prototype.addListener = function addListener(type, listener) {

0 commit comments

Comments
 (0)