Skip to content

Conversation

@thegreatercurve
Copy link

Summary:

Context

Currently, we're allowing users to pass in a lot of unnecessary options to removeEventListener.

Flow supports all of the AddEventListenerOptions flags for removeEventListener which is too permissive. Below is the DOM spec:

interface EventTarget {
  constructor();

  undefined addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options = {});
  undefined removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options = {});
  boolean dispatchEvent(Event event);
};

dictionary EventListenerOptions {
  boolean capture = false;
};

dictionary AddEventListenerOptions : EventListenerOptions {
  boolean passive;
  boolean once = false;
  AbortSignal signal;
};

https://dom.spec.whatwg.org/#interface-eventtarget

Only capture or boolean should ever be allowed for removeEventListener as a property key in an object or a straightforward boolean.

For reference, here are the related TypeScript types which appear to implement the above correctly.

Diff

This diff corrects the types and brings them more in line with the spec in html/xplat-react/flow/dom.js.flow, and then updates any erroring call sites in Flow.

Differential Revision: D84544559

Summary:
### Context

Currently, we're allowing users to pass in a lot of unnecessary options to `removeEventListener`. 

Flow supports [all of the `AddEventListenerOptions` flags](https://www.internalfb.com/code/fbsource/[af794e4e4e71]/www/html/xplat-react/flow/dom.js.flow?lines=333-341) for `removeEventListener` which is too permissive. Below is the DOM spec:

```
interface EventTarget {
  constructor();

  undefined addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options = {});
  undefined removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options = {});
  boolean dispatchEvent(Event event);
};

dictionary EventListenerOptions {
  boolean capture = false;
};

dictionary AddEventListenerOptions : EventListenerOptions {
  boolean passive;
  boolean once = false;
  AbortSignal signal;
};
```
https://dom.spec.whatwg.org/#interface-eventtarget

Only `capture` or `boolean`  should ever be allowed for `removeEventListener` as a property key in an object or a straightforward boolean.

For reference, here are the related TypeScript types which appear to [implement the above correctly](https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.generated.d.ts#L8-L12). 

### Diff

This diff corrects the types and brings them more in line with the spec in `html/xplat-react/flow/dom.js.flow`, and then updates any erroring call sites in Flow.

Differential Revision: D84544559
@meta-cla meta-cla bot added the CLA Signed label Oct 28, 2025
@meta-codesync
Copy link

meta-codesync bot commented Oct 28, 2025

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

@react-sizebot
Copy link

Comparing: b4455a6...d33ff9f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.68 kB 6.68 kB = 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 605.41 kB 605.41 kB = 107.22 kB 107.21 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 664.38 kB 664.38 kB = 117.09 kB 117.09 kB
facebook-www/ReactDOM-prod.classic.js = 688.25 kB 688.25 kB = 121.13 kB 121.13 kB
facebook-www/ReactDOM-prod.modern.js = 678.67 kB 678.67 kB = 119.48 kB 119.48 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against d33ff9f

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants