-
Notifications
You must be signed in to change notification settings - Fork 47.2k
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
fix[react-devtools]: remove all listeners when Agent is shutdown #31151
fix[react-devtools]: remove all listeners when Agent is shutdown #31151
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
e869d7d
to
e813513
Compare
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 the original discussion and credit! Good to see this identified and fixed with a reliable repro
@@ -754,6 +754,9 @@ export default class Agent extends EventEmitter<{ | |||
shutdown: () => void = () => { | |||
// Clean up the overlay if visible, and associated events. | |||
this.emit('shutdown'); | |||
|
|||
this._bridge.removeAllListeners(); |
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.
Is this safe? What happens if other objects are listening to the shutdown
event too?
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.
It is safe, because Agent
is actually notified by Bridge
here:
bridge.addListener('shutdown', this.shutdown); |
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.
Talked irl. What I was asking was
- ProfilerStore subscribes to bridge
- Agent subscribes to bridge
- Bridge emits shutdown event
- Agent remove all listeners here
- Would ProfileStore get the shutdown event?
We found that the current impl does account for this (removing all listeners won't prevent existing listeners from getting the currently-processed event):
const clonedListeners = Array.from(listeners); |
We should prob still be a good neighbour and only unsubscribe our own listeners tho
Changes in this release: * Fix React Compiler badging ([poteto](https://github.com/poteto) in [#31196](#31196)) * fix[react-devtools]: fixed timeline profiler tests ([hoxyq](https://github.com/hoxyq) in [#31261](#31261)) * fix[react-devtools]: record timeline data only when supported ([hoxyq](https://github.com/hoxyq) in [#31154](#31154)) * refactor[react-devtools]: flatten reload and profile config ([hoxyq](https://github.com/hoxyq) in [#31132](#31132)) * fix[react-devtools]: remove all listeners when Agent is shutdown ([hoxyq](https://github.com/hoxyq) in [#31151](#31151)) * fix[react-devtools]: removed redundant startProfiling call ([hoxyq](https://github.com/hoxyq) in [#31131](#31131)) * refactor[react-devtools/fiber/renderer]: optimize durations resolution ([hoxyq](https://github.com/hoxyq) in [#31118](#31118)) * fix[react-devtools]: update profiling status before receiving response from backend ([hoxyq](https://github.com/hoxyq) in [#31117](#31117)) * fix[react-devtools]: wrap key string in preformatted text html element ([hoxyq](https://github.com/hoxyq) in [#31153](#31153)) * chore[react-devtools]: drop legacy context tests ([hoxyq](https://github.com/hoxyq) in [#31059](#31059)) * chore[react-devtools]: add legacy mode error message to the ignore list for tests ([hoxyq](https://github.com/hoxyq) in [#31060](#31060)) * fix[react-devtools]: request hook initialization inside http server response ([hoxyq](https://github.com/hoxyq) in [#31102](#31102)) * [Flight] Serialize Server Components Props in DEV ([sebmarkbage](https://github.com/sebmarkbage) in [#31105](#31105)) * Add: reload to profile for Fusebox ([EdmondChuiHW](https://github.com/EdmondChuiHW) in [#31021](#31021)) * refactor: allow custom impl of backend realod-to-profile support check ([EdmondChuiHW](https://github.com/EdmondChuiHW) in [#31048](#31048)) * fix: use public instance in Fiber renderer and expose it from getInspectorDataForViewAtPoint ([hoxyq](https://github.com/hoxyq) in [#31068](#31068))
Based on #31049, credits to @EdmondChuiHW.
What is happening here:
backendManager.js
content script can get injected multiple times by the browser. When Frontend is initializing, it will create Store first, and then execute a content script for bootstraping backend manager. If Frontend was destroyed somewhere between these 2 steps, Backend won't be notified, because it is not initialized yet, so it will not unsubscribe listeners correctly. We might end up duplicating listeners, and the next time Frontend is launched, it will report an issues "Cannot add / remove node ...", because same operations are emitted twice.To reproduce 3 you can do the following: