Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34.4k
events: add ability to prepend event listeners#6032
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
mscdex commented Apr 4, 2016
I'm not sure something like this should be documented since the whole point of Readable's use of Yes, it's still possible for people to do this even if left undocumented, but it's less likely to happen and if it does, the end user should know they could end up shooting themselves in the foot. |
jasnell commented Apr 4, 2016
Another option: Readable can implement an override for on/once/addListener that emits a process warning if the flag is used to prepend error handlers. |
jasnell commented Apr 4, 2016
Or... a similar on/once/addListener override on listener could remove it's listener and prepend it again whenever the flag is used to prepend a new error listener. |
ChALkeR commented Apr 4, 2016
@mscdex Could this be solved by throwing an exception if a listener with |
mscdex commented Apr 4, 2016
@ChALkeR That would mean storing more state somehow and AFAIK the way that would have to be implemented (storing flags for existing events in a separate object) would cause noticeable performance regressions. |
jasnell commented Apr 4, 2016
I'd considered something along those lines also but I'd prefer not to have
|
vkurchatkin commented Apr 4, 2016
-1, it makes no sense to make it public.:
A couple of ideas:
|
Fishrock123 commented Apr 4, 2016
Refs: #5833 (comment) -- I think it should be an options object over a flag. |
jasnell commented Apr 4, 2016
@vkurchatkin ... I'm fine if this doesn't make it in but the motivation for making this public is to discourage module developers from hacking against internal fields like |
jasnell commented Apr 4, 2016
@Fishrock123 ... I'm good with the options object. |
Fishrock123 commented Apr 4, 2016
Note: if this ends up internal, we can just use a true/false parameter |
ChALkeR commented Apr 4, 2016
@vkurchatkin We have an external module inside the org atm that misuses the internal API: nodejs/readable-stream. |
vkurchatkin commented Apr 4, 2016
@ChALkeR true, not sure what to do with this. Maybe we can just add listener normally? Is there an explanation, why it's really necessary to prepend the listener? |
ChALkeR commented Apr 4, 2016
/cc @nodejs/streams |
calvinmetcalf commented Apr 4, 2016
so what streams is really trying to do (and other modules might need to do as well) is set an error listener that doesn't prevent the default throwing behavior from also happening (in the case of streams it's to do resource cleanup), some other way we could handle it include
|
jasnell commented Apr 4, 2016
Looking at the readable streams case in more detail, the error handler that is being prepended is getting set on the destination object that is being passed to the pipe method. In other words, Readable is modifying the internal private state of an object that it does not own. The only way to do this correctly would be via a public API. I suppose that we could introduce a new |
mscdex commented Apr 4, 2016
What about just monkey-patching |
jasnell commented Apr 4, 2016
@mscdex ... that seems a bit too hackish also, and given that we've made the decision not to support modules that monkey patch node internals we likely shouldn't be relying on that kind of behavior either. Again, just continuing the brainstorming here: Another thought came to mind: an undocumented constmyEE=newEventEmitter();myEE.on('pre-error',(er)=>{/* ... */});myEE.on('pre-foo',(a,b,c)=>{/* ... */});Essentially, prefix any event name with |
ChALkeR commented Apr 4, 2016
@jasnell Seems good to me, but why keep it undocumented? If those events would be added, at some point someone would want to document them. Why not document those from the beginning? |
jasnell commented Apr 4, 2016
Personally I'm good with documenting it. I suggested that given the feedback here questioning whether it should be documented. |
mscdex commented Apr 4, 2016
For a solution like that I'd be very careful about reserving such a prefix since I could easily see someone already implementing similarly-named events. |
calvinmetcalf commented Apr 4, 2016
if we were to add a before method to the event object that would also help with versioning, if it was a pre event or an options object there would be no way to know if the event emitter supported that api. |
ChALkeR commented Apr 4, 2016
@mscdex I couldn't find |
jasnell commented Apr 4, 2016
@calvinmetcalf makes a very good point. Having something like a |
jasnell commented Apr 4, 2016
If we went with e.g. what should happen in the following case: constmyEE=newEventEmitter();myEE.before('foo',()=>console.log('a'));myEE.before('foo',()=>console.log('b'));myEE.on('foo',()=>console.log('c'));myEE.emit('foo'); |
mafintosh commented Apr 4, 2016
Should we name it something more explicit than |
calvinmetcalf commented Apr 4, 2016
the other option would be just have an |
mafintosh commented Apr 4, 2016
@calvinmetcalf i like that. error listeners are already special anyway |
jasnell commented Apr 19, 2016
Done! PTAL |
jasnell commented Apr 19, 2016
jasnell commented Apr 19, 2016
CI is green |
ChALkeR commented Apr 19, 2016
Yes, those sound better to me, thanks! |
ChALkeR commented Apr 19, 2016
LGTM |
doc/api/events.markdown Outdated
| *`listener`{Function} The callback function | ||
| Adds a **one time**`listener` function for the event named `eventName` to the | ||
| beginning of the listeners array. This listener is invoked only the next time |
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.
Should "beginning" be emphasized too for consistency?
Fishrock123 commented Apr 19, 2016
I'd like to still take a look at this if possible. May be a day or so. |
| myEE.emit('foo'); | ||
| // Test fail-back if prependListener is undefined |
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.
s/fail-back/fallback ?
jasnell commented Apr 19, 2016
@mscdex ... updated to address nits |
mscdex commented Apr 19, 2016
LGTM. Hopefully once this change has been around for a long while I will finally be able to land my |
jasnell commented Apr 19, 2016
Yeah I was going to ping you about that. Would definitely like to get those in soon. |
mscdex commented Apr 19, 2016
@jasnell The problem with modules using old |
| emitter._events[event].unshift(fn); | ||
| else | ||
| emitter._events[event]=[fn,emitter._events[event]]; | ||
| } |
mcollinaApr 19, 2016 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
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.
Thanks for including the monkeypatch here.
Maybe we can even avoid that, and just move it to readable-stream.
I don't see any case these lines will be executed in core.
cc @nodejs/streams
mcollina commented Apr 19, 2016
Anyway, we should land this asap and include it in a release asap, so we can start integrating the change into readable-stream. |
jasnell commented Apr 20, 2016
@mcollina ... yep, @Fishrock123 asked for another day or two to review. My plan is to get this landed on Thursday if there are no objections between now and then |
A handful of modules (including readable-streams) make inappropriate use of the internal _events property. One such use is to prepend an event listener to the front of the array of listeners. This adds EE.prototype.prependListener() and EE.prototype.prependOnceListener() methods to add handlers to the *front* of the listener array. Doc update and test case is included. Fixes: nodejs#1817
jasnell commented Apr 21, 2016
Commits squashed and rebased. Planning to get this landed later on today. |
jasnell commented Apr 22, 2016
One final CI run: https://ci.nodejs.org/job/node-test-pull-request/2367/ |
A handful of modules (including readable-streams) make inappropriate use of the internal _events property. One such use is to prepend an event listener to the front of the array of listeners. This adds EE.prototype.prependListener() and EE.prototype.prependOnceListener() methods to add handlers to the *front* of the listener array. Doc update and test case is included. Fixes: #1817 PR-URL: #6032 Reviewed-By: Сковорода Никита Андреевич <[email protected]> Reviewed-By: Brian White <[email protected]>
jasnell commented Apr 22, 2016
Landed in 0e7d57a |
A handful of modules (including readable-streams) make inappropriate use of the internal _events property. One such use is to prepend an event listener to the front of the array of listeners. This adds EE.prototype.prependListener() and EE.prototype.prependOnceListener() methods to add handlers to the *front* of the listener array. Doc update and test case is included. Fixes: nodejs#1817 PR-URL: nodejs#6032 Reviewed-By: Сковорода Никита Андреевич <[email protected]> Reviewed-By: Brian White <[email protected]>
A handful of modules (including readable-streams) make inappropriate use of the internal _events property. One such use is to prepend an event listener to the front of the array of listeners. This adds EE.prototype.prependListener() and EE.prototype.prependOnceListener() methods to add handlers to the *front* of the listener array. Doc update and test case is included. Fixes: #1817 PR-URL: #6032 Reviewed-By: Сковорода Никита Андреевич <[email protected]> Reviewed-By: Brian White <[email protected]>
Pull Request check-list
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)
events
Description of change
A handful of modules (including readable-streams) make inappropriate use of the internal _events property. One such use is to prepend an event listener to the front of the array of listeners.
To address part of the issue, this adds a new optional bitwise flag to the addListener/on/once methods that, when set, causes the listener to be prepended.
Doc update and test case is included.
Fixes: #1817
/cc @ChALkeR