Skip to content

Fix PushNotificationIOS leaking the previous listener when re-adding the same event type - #59758

Open
seyedmostafahasani wants to merge 3 commits into
react:mainfrom
seyedmostafahasani:fix/push-notification-ios-listener-leak
Open

seyedmostafahasani wants to merge 3 commits into
react:mainfrom
seyedmostafahasani:fix/push-notification-ios-listener-leak

Conversation

@seyedmostafahasani

Copy link
Copy Markdown
Contributor

Summary:

PushNotificationIOS.addEventListener stores its subscription in _notifHandlers, keyed by event type, without checking whether one already exists. Calling it twice for the same type overwrites the first subscription in the map, so removeEventListener can only remove the second one. The first listener stays registered on the emitter, keeps its handler (and everything the handler closes over) alive, and keeps firing.

This change removes any previous subscription for the type before registering the new one, so at most one listener per type is ever registered and removeEventListener always cleans it up. The behavior change is that a second addEventListener for the same type now replaces the earlier handler instead of leaving it active and un-removable.

Changelog:

[IOS] [FIXED] - PushNotificationIOS.addEventListener no longer leaks the previous listener when called again for the same event type

Test Plan:

Added Libraries/PushNotificationIOS/__tests__/PushNotificationIOS-test.js, covering removal, adding the same type twice, and that only the latest handler is invoked.

  • yarn jest packages/react-native/Libraries/PushNotificationIOS: 3 passed
  • With the fix reverted, the double-add and latest-handler tests fail (2 failed, 1 passed), so the tests catch the leak
  • yarn eslint --max-warnings 0 and yarn prettier --check on the changed files: clean

Not run: yarn flow-check and the native/iOS builds.

…ding the same event type

addEventListener stored its subscription in `_notifHandlers` keyed by event type without checking for an existing one. Calling it twice for the same type overwrote the first subscription in the map, so removeEventListener could only remove the second one. The first listener stayed registered on the emitter, kept its handler alive, and kept firing. Remove any previous subscription for the type before registering the new one.
Removes a stray `g` accidentally left after `);` in cancelLocalNotifications by the previous commit.
…ent type

Covers removal, the double-add case that previously leaked the first subscription, and that only the latest handler is invoked.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 2, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Nov 2, 2026

This branch has not been deployed

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

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant