Check that `listeners` is actually an array before trying to manipulate it
because it won't be if no regular event listeners have been registered yet
but there are 'removeListener' event listeners.
Emitting an event within a `EventEmitter#once` callback of the same
event name will cause subsequent `EventEmitter#once` listeners of the
same name to be called multiple times.
var emitter = new EventEmitter();
emitter.once('e', function() {
emitter.emit('e');
console.log(1);
});
emitter.once('e', function() {
console.log(2);
});
emitter.emit('e');
// Output
// 2
// 1
// 2
Fix the issue, by calling the listener method only if it was not
already called.
The domain module has been switched over to use the domain module API as
much as currently possible. There are still some hooks in the
EventEmitter, but hopefully we can remove those in the future.
This change is 100% backwards compatible.
This change will make using `EventEmitter` slightly simpler / nicer and
adheres to the best practice set forth by substack.
```js
var EventEmitter = require("events")
var emitter = new EventEmitter()
```
The only difference is that we now have to set `EventEmitter` as a
property of `EventEmitter` for backwards compatibility like we do with
[`Stream`][1]
We have also set the `usingDomains` property on the `EventEmitter`
constructor itself because that aligns with it's current usage of
`require("events").usingDomains = true`
There are other internals that would benefit from this change as well
like `StringDecoder`
Before this commit, events were set to undefined rather than deleted
from the EventEmitter's backing dictionary for performance reasons:
`delete obj.key` causes a transition of the dictionary's hidden class
and that can be costly.
Unfortunately, that introduces a memory leak when many events are added
and then removed again. The strings containing the event names are never
reclaimed by the garbage collector because they remain part of the
dictionary.
That's why this commit makes EventEmitter delete events again. This
effectively reverts commit 0397223.
Fixes#5970.
so `ee.emit('error')` doesn't throw when domains are active
create an empty error only when handled by a domain
test for when no error is provided to an error event
Strict checking for typeof types broke backwards compatibility for other
libraries. This reverts those checks.
The subclass test has been changed to ensure all operations can be
performed on the inherited EE before instantiation. Including the
ability to set event names with numbers.
By making sure the _events is always an object there is one less check
that needs to be performed by emit.
Use undefined instead of null. typeof checks are a lot faster than
isArray.
There are a few places where the this._events check cannot be removed
because it is possible for the user to call those methods after using
utils.extend to create their own EventEmitter, but before it has
actually been instantiated.
Unnecessary checks were being performed on if the event existed before
being removed.
_events starts out as null, so reset to null when emptied.
Checking typeof is a lot cheaper than isArray().
Ability to return just the length of listeners for a given type, using
EventEmitter.listenerCount(emitter, event). This will be a lot cheaper
than creating a copy of the listeners array just to check its length.
Unfortunately, it's just too slow to do this in events.js. Users will
just have to live with not having events named __proto__ or toString.
This reverts commit b48e303af0.
While it's true that error objects have a history of getting snake_case
properties attached by the host system, it's a point of confusion to
Node users that comes up a lot. It's still 'experimental', so best to
change this sooner rather than later.
Always add domain, _events, and _maxListeners properties, set to the
default values at first.
Leads to a very very slight perf improvement when using setMaxListeners,
or dealing with a lot of EE objects that don't have any listeners.
This addresses #4034. There are two problems happening:
1. The domain is not exited automatically when calling dispose() on it.
Then, since the domain is disposed, attempting to exit it again will do
nothing.
2. The active domain is stored on process.domain. Since thrown errors
call `process.emit('uncaughtException', er)`, and the process is an
event emitter with a `.domain` member, it re-enters the domain a second
time before calling the error handler, pushing it onto the stack again.
Thus, if the handler calls `domain.dispose()`, then the domain is now on
the stack twice, and cannot be exited properly. Since the domain is
disposed, any subsequent IO will be no-op'ed, since we've declared that
this context is done and best forgotten.
The solution here is twofold:
1. In EventEmitter.emit, do not enter the domain if `this===process`.
2. Automatically exit the domain when calling `domain.dispose()`.
This reverts commit 928ea564d1.
Keeping the original Array instance in-place essentially causes a memory leak
on EventEmitters that use an infinite number of event names (an incrementing
counter, for example), which isn't an unreasonable thing to want to do.
Fixes#3702.
When removeAllListeners is called, the listeners array
is deleted to maintain compatibility with v0.6.
Reverts "events: don't delete the listeners array"
This reverts commit 78dc13fbf9.
Conflicts:
test/simple/test-event-emitter-remove-all-listeners.js
This is a squashed commit of the main work done on the domains-wip branch.
The original commit messages are preserved for posterity:
* Implicitly add EventEmitters to active domain
* Implicitly add timers to active domain
* domain: add members, remove ctor cb
* Don't hijack bound callbacks for Domain error events
* Add dispose method
* Add domain.remove(ee) method
* A test of multiple domains in process at once
* Put the active domain on the process object
* Only intercept error arg if explicitly requested
* Typo
* Don't auto-add new domains to the current domain
While an automatic parent/child relationship is sort of neat,
and leads to some nice error-bubbling characteristics, it also
results in keeping a reference to every EE and timer created,
unless domains are explicitly disposed of.
* Explicitly adding one domain to another is still fine, of course.
* Don't allow circular domain->domain memberships
* Disposing of a domain removes it from its parent
* Domain disposal turns functions into no-ops
* More documentation of domains
* More thorough dispose() semantics
* An example using domains in an HTTP server
* Don't handle errors on a disposed domain
* Need to push, even if the same domain is entered multiple times
* Array.push is too slow for the EE Ctor
* lint domain
* domain: docs
* Also call abort and destroySoon to clean up event emitters
* domain: Wrap destroy methods in a try/catch
* Attach tick callbacks to active domain
* domain: Only implicitly bind timers, not explicitly
* domain: Don't fire timers when disposed.
* domain: Simplify naming so that MakeCallback works on Timers
* Add setInterval and nextTick to domain test
* domain: Make stack private