Skip to content

Honor skipBubbling in the new EventTarget-based event dispatch#56666

Closed
rubennorte wants to merge 1 commit intofacebook:mainfrom
rubennorte:export-D103200424
Closed

Honor skipBubbling in the new EventTarget-based event dispatch#56666
rubennorte wants to merge 1 commit intofacebook:mainfrom
rubennorte:export-D103200424

Conversation

@rubennorte
Copy link
Copy Markdown
Contributor

Summary:
The feature flag enableNativeEventTargetEventDispatching switches the React Native renderer from the legacy plugin-based event dispatch to a new W3C EventTarget-based dispatch in dispatchNativeEvent.js. The legacy path honors the phasedRegistrationNames.skipBubbling flag declared in view configs by short-circuiting the bubble traversal. The new path was unconditionally setting bubbles: true for any event with a customBubblingEventTypes entry, so topPointerEnter / topPointerLeave (the only events that declare skipBubbling: true today) ended up bubbling to all ancestors, breaking the W3C Pointer Events contract that pointerenter / pointerleave do not bubble.

Map skipBubbling: true to bubbles: false on the synthesized LegacySyntheticEvent. The existing EventTarget.dispatch() bubble loop already short-circuits when event.bubbles is false and target !== eventTarget, so the target's own bubble + capture handlers still fire — only ancestor bubble handlers are suppressed. Capture-phase listeners are unaffected.

Changelog: [internal]

Reviewed By: sammy-SC

Differential Revision: D103200424

Summary:
The feature flag `enableNativeEventTargetEventDispatching` switches the React Native renderer from the legacy plugin-based event dispatch to a new W3C `EventTarget`-based dispatch in `dispatchNativeEvent.js`. The legacy path honors the `phasedRegistrationNames.skipBubbling` flag declared in view configs by short-circuiting the bubble traversal. The new path was unconditionally setting `bubbles: true` for any event with a `customBubblingEventTypes` entry, so `topPointerEnter` / `topPointerLeave` (the only events that declare `skipBubbling: true` today) ended up bubbling to all ancestors, breaking the W3C Pointer Events contract that `pointerenter` / `pointerleave` do not bubble.

Map `skipBubbling: true` to `bubbles: false` on the synthesized `LegacySyntheticEvent`. The existing `EventTarget.dispatch()` bubble loop already short-circuits when `event.bubbles` is `false` and `target !== eventTarget`, so the target's own bubble + capture handlers still fire — only ancestor bubble handlers are suppressed. Capture-phase listeners are unaffected.

Changelog: [internal]

Reviewed By: sammy-SC

Differential Revision: D103200424
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented May 1, 2026

@rubennorte has exported this pull request. If you are a Meta employee, you can view the originating Diff in D103200424.

@react-native-bot
Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @rubennorte in 3446958

When will my fix make it into a release? | How to file a pick request?

@react-native-bot react-native-bot added the Merged This PR has been merged. label May 1, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented May 1, 2026

This pull request has been merged in 3446958.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fb-exported Merged This PR has been merged. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants