This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
Fix EventEmitter.once issue and add EventEmitter removeAllListeners patch. #500
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I found several issues of patching EventEmitter's listener related methods.
with zone.js 0.6.22 release, addListener, prependListener, removeListener are patched in this commit.
100b82b
the issue can be described as the following test case.
emitter.once('test', shouldNotRun); emitter.removeListener('test', shouldNotRun);
in 0.6.22, the once listener was not removed.
the reason is when removeListener call util.ts, findExistingRegisteredTask method, it will look for the correct event task by check the eventTask.data.handler === handler, but if the handler is attached by EventEmitter.once method, the handler will not attached directly, instead it will be attached through a _onceWrap (https://github.com/nodejs/node/blob/master/lib/events.js#L286), and keep the original handler to the onceWrap.listener property, so we should not only check the data.handler but also the data.handler.listener(2ee4711#diff-2e7dc744ee86a31cde46d41cda5e42c0R714)
the issue can be described as the following test case.
emitter.on('test', expectZoneA); emitter.on('test', expectZoneA); emitter.removeAllListeners('test');
in 0.6.22, the listener was not removed.
the reason is based on the issue #491, in the zone.js 0.6.22 release, to fix #430, addListener, removeListener, prependListener, and listeners have been patched, but removeAllListeners is not, In issue #491, socket-io will call removeAllListeners to cache and remove the listeners on request event when attach server, but because the removeAllListeners is not patched and handled correctly by zone(the response listener was added to event tasks because the addListener is patched but not removed because removeAllListeners are not patched), the request event will be handled multiple times and cause express response throw "can't set header after response sent " error.
I add a patch of removeAllListeners based on the #430 release.
the issue can be described as the following test case.
emitter.on('test', listenerA); emitter.prependListener('test', listenerB); expect(emitter.listeners('test')).toEqual([listenerB, listenerA]);
in 0.6.22, the order is still listenerA, listenerB
The reason is in 0.6.22 prependListener do the same logic with addListener.
please review the source code of those 2 issues, Thank you.