The behavior of error boundaries for passive effects that throw during cleanup was recently changed so that React ignores boundaries which are also unmounting in favor of still-mounted boundaries. This commit implements that same behavior for layout effects (useLayoutEffect, componentWillUnmount, and ref-detachment).
The new, skip-unmounting-boundaries behavior is behind a feature flag (`skipUnmountedBoundaries`).
A passive effect's cleanup function may throw after an unmount. Prior to this commit, such an error would be ignored. (React would not notify any error boundaries.) After this commit, React's behavior varies depending on which reconciler fork is being used.
For the old reconciler, React will call componentDidCatch for the nearest unmounted error boundary (if there is one). If there are no unmounted error boundaries, React will still swallow the error because the return pointer has been disconnected, so the normal error handling logic does not know how to traverse the tree to find the nearest still-mounted ancestor.
For the new reconciler, React will skip any unmounted boundaries and look for a still-mounted boundary. If one is found, it will call getDerivedStateFromError and/or componentDidCatch (depending on the type of boundary).
Tests have been added for both reconciler variants for now.
* test: Simulate mouseover in browser
* Fix duplicate onMouseEnter event when relatedTarget is a root
* Test leave as well
Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
* test: Add current behavior for event types of onFocus/onBlur
* fix: onFocus/onBlur have a matching event type
* fix useFocus
* fix: don't compare native event types with react event types
* Add FocusIn/FocusOutEventInterface
* A simpler alternative fix
* Add regression tests
* Always pass React event type and fix beforeinput
Co-authored-by: Dan Abramov <dan.abramov@me.com>
* Remove opaque event type
* Rename type and merge files
* Use literals where we have Flow coverage
* Flowify some plugins
* Remove constants except necessary ones
* Remove capturePhaseEvents and separate events by bubbling
WIP
Refine all logic
Revise types
Fix
Fix conflicts
Fix flags
Fix
Fix
Fix test
Revise
Cleanup
Refine
Deal with replaying
Fix
* Add non delegated listeners unconditionally
* Add media events
* Fix a previously ignored test
* Address feedback
Co-authored-by: Dan Abramov <dan.abramov@me.com>
* Set current update lane priority for user blocking events
* Update to use LanePriority and not use runWithPriority
* Remove unused imports
* Fix tests, and I missed ReactDOMEventListener
* Fix more tests
* Add try/finally and hardcode lane priorities instead
* Also hard code InputContinuousLanePriority in tests
* Remove un-needed exports
* Comment rollbacks
* Effects list rewrite
* Improved deletions approach
Process deletions as we traverse the tree during commit, before we process other effects. This has the result of better mimicking the previous sequencing.
* Made deletions field nullable
* Revert (no longer necessary) change to ReactNative test
* Eagerly set Deletions effect on Fiber when adding child to deletions array
* Initialize deletions array to null
* Null out deletions array instead of splicing 🤡
* Removed TODO comment
* Initial exploration on a did-bailout flag
* fixed the rest of the bugs
* Rolled temporary didBailout attribute into subtreeTag
* addressed comments
* Removed DidBailout subtree tag
* Removed stale comment
* use while loop instead of recursion for siblings
* move bailout flag from while loop
* Removed some unnecessary Deletion effectTags from children
* Move Deletion effect assignment to deletions array initialization
Co-authored-by: Luna <lunaris.ruan@gmail.com>
* add unit test asserting internal hooks state is reset
* Reset internal hooks state before rendering
* reset hooks state on error
* Use expect...toThrow instead of try/catch in test
* reset dev-only hooks state inside resetHooksState
* reset currentlyRenderingComponent to null