-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
events: fix unwrapping of ee.once() listeners #5564
Conversation
I'm going to look to see if anything can be done about the perf hit. |
Not using |
@mscdex I'm thinking the changes to That would revert any performance regression on that side of it. Don't see how to avoid |
4ebeab8
to
9bbeca8
Compare
Updated as mentioned, so ee-add-remove is unaffected now. Relevant numbers for
(master:)
|
Change from this.removeListener(type, g); You can add listener many times. |
@omsmith Yeah I think that's probably going to be the best that can be done from what I can tell. |
LGTM |
As @simonkcleung points out, the current diff changes the following behaviour: function listener() {}
new EventEmitter()
.on('foo', listener)
.once('foo', listener)
.emit('foo'); With the change in place, the Don't have a strong opinion either way. EDIT: Original first commit, for reference: omsmith@840a772 |
9bbeca8
to
ae7db76
Compare
@jasnell @mscdex I've reverted to the original change, minus the "helper function" I've tried to run the benchmarking tools now that I know how to use them (thanks to @mscdex explaining it to someone else :)), but getting pretty inconsistent results on my machine. My best guess is that ee-listeners(-many) has about a 5% drop, and ee-add-remove is approximately unaffected. |
@nodejs/ctc ... thoughts? |
@@ -306,7 +306,8 @@ EventEmitter.prototype.removeListener = | |||
else { | |||
delete events[type]; | |||
if (events.removeListener) | |||
this.emit('removeListener', type, listener); | |||
this.emit('removeListener', type, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a suggestion. Let's do let currentListener = list.listener ? list.listener : listener
and check against it everywhere in this function. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@omsmith ... ping
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Jeeze, has it been 6 days? Apologies.
Had a few long days at work and needed the weekend to unwind. This is in my inbox to get to - probably tomorrow night.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-) no worries! just going through backlog!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@indutny Thanks for having a look. That would probably do fine for the "there is a single listener right now" case, but I'm not sure it would work out for when list
is actually a list, given:
- passed in
listener
could be either the wrapped listener, or the unwrapped one (internal call vs user call) - the unwrapped listener could be used multiple times, either for
once
andon
or multipleonce
s or whatever, and so we should prefer to match the wrapped fn
So we could remove repetition by doing const listenerToEmit = listener.listener ? listener.listener : listener;
at the top, but you aren't necessarily (or as I understand it, likely) going to even need that (not the common case to have removeListener
events).
When a user listens for an event using #once, their listener is wrapped in a function which will remove it after being called. While this was accounted for with the 'newListener' event, 'removeListener' would receive the wrapped function. Fixes nodejs#5551
ae7db76
to
3465da2
Compare
@indutny any followup to that? |
Line 401 |
7da4fd4
to
c7066fb
Compare
#6394 provides an alternative to this that is a bit simpler. Recommend closing this in favor of that one. |
@jasnell Hmm, apparently I pushed an older variation here by accident when I can fix mine up to be just the fix for #listeners() (or you could suggest
|
#6394 landed. Closing this! Thanks! |
@omsmith I think it might be a good idea if you PRed again with a fix for |
Pull Request check-list
Please make sure to review and check all of these items:
make -j8 test
(UNIX) orvcbuild test nosign
(Windows) pass withthis change (including linting)?
test (or a benchmark) included?
existing APIs, or introduces new ones)?
NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open.
Affected core subsystem(s)
Description of change
The wrapped listeners from
once()
weren't handled consistently. This PR fixes up the two additional places that they are exposed publicly ('removeListener'
andlisteners()
). There is a slowdown in doing so, but not too bad.Unsure if a documentation update would be necessary (to say "it used to behave like so").
make bench-events:
(master):