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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use browser event names for top-level event types in React DOM #12629

Merged
merged 46 commits into from May 15, 2018

Conversation

Projects
None yet
6 participants
@philipp-spiess
Copy link
Collaborator

philipp-spiess commented Apr 17, 2018

This PR builds on top of the great work of @gaearon in #11894. The main idea is to get rid of all top* strings used to identify internal events and replace them with numerical values which the compiler can inline.

Before merging this, I have two other questions which I've also asked here:

  1. Does it really make sense to prefix all event constants with TOP_? From the comment in https://github.com/facebook/react/blob/master/packages/react-dom/src/events/BrowserEventConstants.js#L10-L16 it's clear that only some of the events are actually listened to at the top level. However the list contains more than that subset (incl. input, invalid, reset, submit, and the media events). With that in mind, I think renaming the module to EventTypes.js or InternalEventTypes.js would be more fitting. What do you think? I know that currently, the top prefix is used everywhere - Is there a reason for that?
  2. I had to make some worrisome changes to modules that contain Native in their name. Specifically when working on the Flow types here and here. Would it make sense to type the internal event type as number | string so we don't need to touch anything on the react-native side? And what part of the changed modules will also be used on the react-native side? Everything inside packages/events?

State of this PR

Besides the open questions, this PR works fine for react-dom. The difference in the bundle size is significant (well, at least enough to land #12507 馃檲):

  • react-dom.production.min.js (UMD_PROD) -1.5% pre, -0.9% post gzip
  • react-dom-test-utils.production.min.js (UMD_PROD) -13.2% pre, -10.2% post gzip
  • react-dom-unstable-native-dependencies.production.min.js (UMD_PROD) -1.2% pre, -0.6% post gzip

All dom related unit tests are green and the fixtures behave as described.

There's currently one failing unit test suite (ReactNativeEvents-test.internal.js). We'll probably need to clearly look at the react-native boundaries here to see how/if we can keep this change to the DOM side.

Some libraries that depend on this private API will need adjustment as well (e.g. this file in react-native-web). Can we do anything to make that easier? We could, for example, create a mapping from the old top* strings to the new numbers as an export in ReactDOMUnstableNativeDependencies. A similar mapping is already needed for ReactTestUtils.js, so we have to maintain it anyhow.

@pull-bot

This comment has been minimized.

Copy link

pull-bot commented Apr 17, 2018

ReactDOM: size: -1.2%, gzip: -0.8%

Details of bundled changes.

Comparing: 1047980...0c6982d

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.development.js +0.2% +0.4% 642.7 KB 643.99 KB 147.67 KB 148.23 KB UMD_DEV
react-dom.production.min.js -1.2% -0.8% 102.3 KB 101.12 KB 32.62 KB 32.36 KB UMD_PROD
react-dom.development.js +0.2% +0.4% 627.06 KB 628.35 KB 143.53 KB 144.15 KB NODE_DEV
react-dom.production.min.js -1.2% -0.9% 100.71 KB 99.53 KB 31.73 KB 31.45 KB NODE_PROD
react-dom-test-utils.development.js +4.5% +4.5% 40.71 KB 42.52 KB 11.68 KB 12.21 KB UMD_DEV
react-dom-test-utils.production.min.js -1.6% -2.5% 10.59 KB 10.42 KB 3.93 KB 3.84 KB UMD_PROD
react-dom-test-utils.development.js +5.1% +5.1% 35.57 KB 37.38 KB 10.26 KB 10.79 KB NODE_DEV
react-dom-test-utils.production.min.js -1.7% -2.6% 9.86 KB 9.69 KB 3.72 KB 3.62 KB NODE_PROD
react-dom-unstable-native-dependencies.development.js +0.4% +0.9% 61.18 KB 61.45 KB 16.02 KB 16.17 KB UMD_DEV
react-dom-unstable-native-dependencies.production.min.js 馃敽+0.5% 馃敽+0.4% 11.31 KB 11.36 KB 3.91 KB 3.92 KB UMD_PROD
react-dom-unstable-native-dependencies.development.js +0.5% +0.9% 56.84 KB 57.11 KB 14.77 KB 14.9 KB NODE_DEV
react-dom-unstable-native-dependencies.production.min.js 馃敽+0.5% 馃敽+0.2% 10.65 KB 10.71 KB 3.67 KB 3.67 KB NODE_PROD
react-dom-server.browser.development.js +0.4% +0.2% 101.58 KB 101.97 KB 26.54 KB 26.6 KB UMD_DEV
react-dom-server.browser.development.js +0.4% +0.2% 90.88 KB 91.27 KB 24.28 KB 24.34 KB NODE_DEV
react-dom-server.node.development.js +0.4% +0.2% 92.8 KB 93.2 KB 24.83 KB 24.88 KB NODE_DEV
ReactDOM-dev.js +0.2% +0.5% 652.26 KB 653.78 KB 146.43 KB 147.13 KB FB_WWW_DEV
ReactDOM-prod.js -0.5% -0.4% 303.85 KB 302.4 KB 55.11 KB 54.91 KB FB_WWW_PROD
ReactTestUtils-dev.js +5.2% +5.1% 36.85 KB 38.75 KB 10.45 KB 10.98 KB FB_WWW_DEV
ReactDOMUnstableNativeDependencies-dev.js +0.4% +0.9% 57.09 KB 57.32 KB 14.56 KB 14.69 KB FB_WWW_DEV
ReactDOMUnstableNativeDependencies-prod.js 馃敽+0.1% 馃敽+0.1% 26.33 KB 26.35 KB 5.37 KB 5.37 KB FB_WWW_PROD
ReactDOMServer-dev.js +0.6% +0.3% 94.43 KB 94.98 KB 24.1 KB 24.17 KB FB_WWW_DEV

Generated by 馃毇 dangerJS

topWheel: 'wheel',
};
export const topLevelTypes: Map<TopLevelTypes, string> = new Map([
[

This comment has been minimized.

@gaearon

gaearon Apr 17, 2018

Member

Note: Map constructor doesn鈥檛 work in IE11 so we鈥檒l need to change this

This comment has been minimized.

@philipp-spiess

philipp-spiess Apr 17, 2018

Collaborator

Ugh. Thanks for pointing that out. Should I just create the nested array structure and loop over it to set the props then or do you have a util function for that? :)

This comment has been minimized.

@gaearon

gaearon Apr 17, 2018

Member

Iterating sounds fine I guess

@gaearon

This comment has been minimized.

Copy link
Member

gaearon commented Apr 17, 2018

Nice work.

I鈥檒l chat to somebody on the team about RN and follow up with you.

Can you give me an idea of how breaking those changes would be for React Native Web? What exactly would they need to change?

@philipp-spiess

This comment has been minimized.

Copy link
Collaborator

philipp-spiess commented Apr 17, 2018

Can you give me an idea of how breaking those changes would be for React Native Web? What exactly would they need to change?

I can only find one file that uses this part of the private API which is injectResponderEventPlugin/index.js. In there, all we'd have to is change the top* strings to the numbers (where an additional private export could help, e.g TopLevelTypes['touchStart'].

Maybe @necolas can skim in here and help me out there as well? I can also sit down and try to make a PR with the hard coded number values and set up an example app :)

@necolas sorry for pinging you here out of context! We're thinking about ways to shrink the react-dom bundle size and getting rid of the top* strings would help quite a bit. We know that react-native-web uses private API to enable some of the react-native specific event plugins and want to make a smooth migration path for your project. I'd gladly set up the PR but we first need to find out the scope of this change. Thanks 鉂わ笍

@philipp-spiess philipp-spiess force-pushed the philipp-spiess:no-top-level-events branch from f0c378c to 4304b8d Apr 17, 2018

@necolas

This comment has been minimized.

Copy link
Contributor

necolas commented Apr 17, 2018

FWIW, these top-level event types used to be available but at some point on the way to flattening the React bundles I had to switch to using the strings which this PR is touching
necolas/react-native-web@44ecbc0#diff-fecd5b3cfaeb4f62d70f4219e850f039

Another option is to upstream some or all of the changes I have to make to the responder plugin event dependencies and then I don't need to know about these event internals anymore

@philipp-spiess

This comment has been minimized.

Copy link
Collaborator

philipp-spiess commented Apr 17, 2018

Thank you for your input @necolas 馃憤

I'm wondering why the ResponderEventPlugin does not define dependencies like the other plugins do. @gaearon Do you think we break anything on the react-native side if we add those?

We'd not have to upstream the changes here. Instead of topLevelType we could make the changes based on nativeEvent.type instead as well.

@gaearon

This comment has been minimized.

Copy link
Member

gaearon commented Apr 17, 2018

We chatted a bit about this today with the team. We won't have time to fix RN ourselves but if you can send PRs to it to also convert to numbers (and then send a PR to fix RNW) then we can take this.

@philipp-spiess

This comment has been minimized.

Copy link
Collaborator

philipp-spiess commented Apr 18, 2018

@gaearon Thanks for discussing this internally.

It seems like the top* event strings are quite scattered in react-native (I could find 126 matches for the regex /("|')top[a-zA-Z]+/ - strangely most of the strings are only used in Java modules and I can't find the C# counter part). To avoid magic numbers everywhere, we could still use the top* strings there and set up a map to the numbers in JavaScript (or, alternatively, support both types number for react-dom and string for react-native).

There are also some event names in react-native that we don't have in TopLevelEventTypes yet (e.g. topMomentumScrollEnd). I wonder if it would be enough to generate a new number whenever the cache misses?

This mapping/hybrid approach would be a more realistic approach since that PR would otherwise be a breaking change (see for example react-native-windows which also depends on the top* strings).

@gaearon

This comment has been minimized.

Copy link
Member

gaearon commented Apr 18, 2018

Have you verified those strings have the same role? It could be that they just picked up a convention but don't actually use it the same way in the event system.

@philipp-spiess

This comment has been minimized.

Copy link
Collaborator

philipp-spiess commented Apr 19, 2018

Events like topMomentumScrollBegin are definitely handled in the event system. The native modules call into receiveEvent with the topLevelType string. From there, it will go to extractEvents which will call the individual event plugins including the ResponderEventPlugin which is now changed to work with number instead of the top* strings.

screen shot 2018-04-19 at 01 19 20

Something that鈥檚 interesting is that the native platforms (iOS, Android) will register their events in these objects.

If we would keep the strings in react-native but use numerical IDs for react-dom, all event plugins that would be used in dom and native (which currently is limited to ResponderEventPlugin) would need to handle both types. That certainly would be the easiest part but handling two event id cases seems very odd.

For example, the isStartish helper will need to look like this:

export function isStartish(topLevelType) {
  return (
    topLevelType === TOP_MOUSE_DOWN ||
    topLevelType === TOP_TOUCH_START ||
    topLevelType === "topMouseDown" ||
    topLevelType === "topTouchStart"
  );
}

And the (few) top* strings would again be part of the dom artifact.

As an alternative, changing the strings to numbers in react-native would be a lot of work (since, as I mentioned, the strings are quire scattered) and we'd have to find a way how we can maintain only one map (TopLevelEventTypes) and use it in iOS and Android.

@gaearon

This comment has been minimized.

Copy link
Member

gaearon commented Apr 19, 2018

Is ResponderEventPlugin only used by RNW? Maybe we could just fork it. RN would have its own version, RNW would have another one, and our repo wouldn鈥檛 have either.

@necolas

This comment has been minimized.

Copy link
Contributor

necolas commented Apr 19, 2018

IIRC that was discussed when React was flattening bundles, and ResponderEventPlugin had too many internal dependencies for it to be practical to handle another way

@gaearon

This comment has been minimized.

Copy link
Member

gaearon commented Apr 19, 2018

Maybe I'm wrong but I don't see anything depending on ResponderEventPlugin on the web at FB.

Does TapEventPlugin depend on it? Even if it does, we are ready to remove those deps now.

@necolas

This comment has been minimized.

Copy link
Contributor

necolas commented Apr 19, 2018

Internal = internal to React

@philipp-spiess

This comment has been minimized.

Copy link
Collaborator

philipp-spiess commented Apr 19, 2018

Yeah ResponderEventPlugin requires a few internal dependencies. That would not be a problem when moving it from packages/events to packages/react-native-renderer (which is also where the other react native event plugins reside).

To make it work as a fork in RNW we'd probably have to add a few exports here.

When doing that, I think we should also move all other web specific event plugins to packages/react-dom so we don't start mixing them up.

@gaearon

This comment has been minimized.

Copy link
Member

gaearon commented Apr 19, 2018

Sorry, I'm not sure I understand what the problem is. Can you describe it in more detail?

@philipp-spiess

This comment has been minimized.

Copy link
Collaborator

philipp-spiess commented Apr 19, 2018

Sorry for not being clear enough. There are essentially two issues here which we're trying to solve: react-native and react-native-web support.

Don't break react-native

I like your idea of moving ResponderEventPlugin away from the commonly shared event code. I suggest we move it into packages/react-native-renderer where the second react native event plugin is also located (so it would still be part of the react GitHub repo but no longer accessible for react-dom

With this change, we don't have to change ResponderEventPlugin and can keep using string event identifiers there without affecting the DOM side. The shared event code (if any) will need to handle both numbers and strings as event IDs but it's up to the renderer to use whatever they want.

Don't break react-native-web

RNW depends on the ResponderEventPlugin so we'll have to make a DOM fork (directly as part of RNW github repo?) to make it work again.

Since this plugin requires some React internal API (helper functions to dispatch events, being able to access the dom top level event types map, etc), we also need to adjust the exported private API of ReactDOMUnstableNativeDependencies so that its possible to implement that event plugin.

So instead of exporting ResponderEventPlugin, ReactDOMUnstableNativeDependencies will now export everything that's required to build-your-own responder plugin.

@gaearon

This comment has been minimized.

Copy link
Member

gaearon commented Apr 19, 2018

Exporting more doesn't sound great. Perhaps we can have two forks in our own repo?

@philipp-spiess

This comment has been minimized.

Copy link
Collaborator

philipp-spiess commented Apr 19, 2018

Exporting more doesn't sound great. Perhaps we can have two forks in our own repo?

Yeah we can do that as well. The question is we want to maintain two forks of this module where the only difference is that they use different event identifiers (well, at least we can upstream the changes from RNW without worrying about breaking RN :D).

@gaearon

This comment has been minimized.

Copy link
Member

gaearon commented Apr 19, 2018

We can review how it looks and then decide. Want to try as a part of this PR?

Maybe it could be in shared folder and have the IDs injected.

@philipp-spiess

This comment has been minimized.

Copy link
Collaborator

philipp-spiess commented Apr 19, 2018

Yup I'll definitely try that! Thank you for your input 馃槉

@dependencies dependencies bot referenced this pull request Jun 11, 2018

Closed

Update yarn.lock #109

philipp-spiess added a commit to philipp-spiess/react that referenced this pull request Jun 12, 2018

Use native event dispatching instead of Simulate or SimulateNative
In facebook#12629 @gaearon suggested that it would be better to drop usage of
`ReactTestUtils.Simulate` and `ReactTestUtils.SimulateNative`. In this
PR I鈥檓 attempting at removing it from a lot of places with only a few
leftovers.

Those leftovers can be categorized into three groups:

1. Anything that tests that `SimulateNative` throws. This is a property
   that native event dispatching doesn鈥檛 have so I can鈥檛 convert that
   easily. Affected test suites: `EventPluginHub-test`,
   `ReactBrowserEventEmitter-test`.
2. Anything that tests `ReactTestUtils` directly. Affected test suites:
   `ReactBrowserEventEmitter-test` (this file has one test that reads
    "should have mouse enter simulated by test utils"),
    `ReactTestUtils-test`.
3. Anything that dispatches a `change` event. The reason here goes a bit
   deeper and is rooted in the way we shim onChange. Usually when using
   native event dispatching, you would set the node鈥檚 `.value` and then
   dispatch the event. However inside [`inputValueTracking.js`][] we
   install a setter on the node鈥檚 `.value` that will ignore the next
   `change` event (I found [this][near-perfect-oninput-shim] article
   from Sophie that explains that this is to avoid onChange when
   updating the value via JavaScript).

All remaining usages of `Simulate` or `SimulateNative` can be avoided
by mounting the containers inside the `document` and dispatching native
events.

Here some remarks:

1. I鈥檓 using `Element#click()` instead of `dispatchEvent`. In the jsdom
   changelog I read that `click()` now properly sets the correct values
   (you can also verify it does the same thing by looking at the
   [source][jsdom-source]).
2. I had to update jsdom in order to get `TouchEvent` constructors
   working (and while doing so also updated jest). There was one
   unexpected surprise: `ReactScheduler-test` was relying on not having
   `window.performance` available. I鈥檝e recreated the previous
   environment by deleting this property from the global object.
3. I was a bit confused that `ReactTestUtils.renderIntoDocument()` does
   not render into the document 馃し鈥

[`inputValueTracking.js`]: https://github.com/facebook/react/blob/392530104c00c25074ce38e1f7e1dd363018c7ce/packages/react-dom/src/client/inputValueTracking.js#L79
[near-perfect-oninput-shim]: https://sophiebits.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html
[jsdom-source]: https://github.com/jsdom/jsdom/blob/45b77f5d21cef74cad278d089937d8462c29acce/lib/jsdom/living/nodes/HTMLElement-impl.js#L43-L76

@dependencies dependencies bot referenced this pull request Jun 12, 2018

Closed

Update yarn.lock #390

gaearon added a commit that referenced this pull request Jun 13, 2018

Use native event dispatching instead of Simulate or SimulateNative (#鈥
鈥13023)

* Use native event dispatching instead of Simulate or SimulateNative

In #12629 @gaearon suggested that it would be better to drop usage of
`ReactTestUtils.Simulate` and `ReactTestUtils.SimulateNative`. In this
PR I鈥檓 attempting at removing it from a lot of places with only a few
leftovers.

Those leftovers can be categorized into three groups:

1. Anything that tests that `SimulateNative` throws. This is a property
   that native event dispatching doesn鈥檛 have so I can鈥檛 convert that
   easily. Affected test suites: `EventPluginHub-test`,
   `ReactBrowserEventEmitter-test`.
2. Anything that tests `ReactTestUtils` directly. Affected test suites:
   `ReactBrowserEventEmitter-test` (this file has one test that reads
    "should have mouse enter simulated by test utils"),
    `ReactTestUtils-test`.
3. Anything that dispatches a `change` event. The reason here goes a bit
   deeper and is rooted in the way we shim onChange. Usually when using
   native event dispatching, you would set the node鈥檚 `.value` and then
   dispatch the event. However inside [`inputValueTracking.js`][] we
   install a setter on the node鈥檚 `.value` that will ignore the next
   `change` event (I found [this][near-perfect-oninput-shim] article
   from Sophie that explains that this is to avoid onChange when
   updating the value via JavaScript).

All remaining usages of `Simulate` or `SimulateNative` can be avoided
by mounting the containers inside the `document` and dispatching native
events.

Here some remarks:

1. I鈥檓 using `Element#click()` instead of `dispatchEvent`. In the jsdom
   changelog I read that `click()` now properly sets the correct values
   (you can also verify it does the same thing by looking at the
   [source][jsdom-source]).
2. I had to update jsdom in order to get `TouchEvent` constructors
   working (and while doing so also updated jest). There was one
   unexpected surprise: `ReactScheduler-test` was relying on not having
   `window.performance` available. I鈥檝e recreated the previous
   environment by deleting this property from the global object.
3. I was a bit confused that `ReactTestUtils.renderIntoDocument()` does
   not render into the document 馃し鈥

[`inputValueTracking.js`]: https://github.com/facebook/react/blob/392530104c00c25074ce38e1f7e1dd363018c7ce/packages/react-dom/src/client/inputValueTracking.js#L79
[near-perfect-oninput-shim]: https://sophiebits.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html
[jsdom-source]: https://github.com/jsdom/jsdom/blob/45b77f5d21cef74cad278d089937d8462c29acce/lib/jsdom/living/nodes/HTMLElement-impl.js#L43-L76

* Make sure contains are unlinked from the document even if the test fails

* Remove unnecessary findDOMNode calls

TejasQ added a commit to TejasQ/react that referenced this pull request Aug 26, 2018

Use browser event names for top-level event types in React DOM (faceb鈥
鈥ok#12629)

* Add TopLevelEventTypes

* Fix `ReactBrowserEventEmitter`

* Fix EventPluginUtils

* Fix TapEventPlugin

* Fix ResponderEventPlugin

* Update ReactDOMFiberComponent

* Fix BeforeInputEventPlugin

* Fix ChangeEventPlugin

* Fix EnterLeaveEventPlugin

* Add missing non top event type used in ChangeEventPlugin

* Fix SelectEventPlugin

* Fix SimpleEventPlugin

* Fix outstanding Flow issues and move TopLevelEventTypes

* Inline a list of all events in `ReactTestUtils`

* Fix tests

* Make it pretty

* Fix completly unrelated typo

* Don鈥檛 use map constructor because of IE11

* Update typings, revert changes to native code

* Make topLevelTypes in ResponderEventPlugin injectable and create DOM and ReactNative variant

* Set proper dependencies for DOMResponderEventPlugin

* Prettify

* Make some react dom tests no longer depend on internal API

* Use factories to create top level speific generic event modules

* Remove unused dependency

* Revert exposed module renaming, hide store creation, and inline dependency decleration

* Add Flow types to createResponderEventPlugin and its consumers

* Remove unused dependency

* Use opaque flow type for TopLevelType

* Add missing semis

* Use raw event names as top level identifer

* Upgrade baylon

This is required for parsing opaque flow types in our CI tests.

* Clean up flow types

* Revert Map changes of ReactBrowserEventEmitter

* Upgrade babel-* packages

Apparently local unit tests also have issues with parsing JavaScript
modules that contain opaque types (not sure why I didn't notice
earlier!?).

* Revert Map changes of SimpleEventPlugin

* Clean up ReactTestUtils

* Add missing semi

* Fix Flow issue

* Make TopLevelType clearer

* Favor for loops

* Explain the new DOMTopLevelEventTypes concept

* Use static injection for Responder plugin types

* Remove null check and rely on flow checks

* Add missing ResponderEventPlugin dependencies

TejasQ added a commit to TejasQ/react that referenced this pull request Aug 26, 2018

Use native event dispatching instead of Simulate or SimulateNative (f鈥
鈥cebook#13023)

* Use native event dispatching instead of Simulate or SimulateNative

In facebook#12629 @gaearon suggested that it would be better to drop usage of
`ReactTestUtils.Simulate` and `ReactTestUtils.SimulateNative`. In this
PR I鈥檓 attempting at removing it from a lot of places with only a few
leftovers.

Those leftovers can be categorized into three groups:

1. Anything that tests that `SimulateNative` throws. This is a property
   that native event dispatching doesn鈥檛 have so I can鈥檛 convert that
   easily. Affected test suites: `EventPluginHub-test`,
   `ReactBrowserEventEmitter-test`.
2. Anything that tests `ReactTestUtils` directly. Affected test suites:
   `ReactBrowserEventEmitter-test` (this file has one test that reads
    "should have mouse enter simulated by test utils"),
    `ReactTestUtils-test`.
3. Anything that dispatches a `change` event. The reason here goes a bit
   deeper and is rooted in the way we shim onChange. Usually when using
   native event dispatching, you would set the node鈥檚 `.value` and then
   dispatch the event. However inside [`inputValueTracking.js`][] we
   install a setter on the node鈥檚 `.value` that will ignore the next
   `change` event (I found [this][near-perfect-oninput-shim] article
   from Sophie that explains that this is to avoid onChange when
   updating the value via JavaScript).

All remaining usages of `Simulate` or `SimulateNative` can be avoided
by mounting the containers inside the `document` and dispatching native
events.

Here some remarks:

1. I鈥檓 using `Element#click()` instead of `dispatchEvent`. In the jsdom
   changelog I read that `click()` now properly sets the correct values
   (you can also verify it does the same thing by looking at the
   [source][jsdom-source]).
2. I had to update jsdom in order to get `TouchEvent` constructors
   working (and while doing so also updated jest). There was one
   unexpected surprise: `ReactScheduler-test` was relying on not having
   `window.performance` available. I鈥檝e recreated the previous
   environment by deleting this property from the global object.
3. I was a bit confused that `ReactTestUtils.renderIntoDocument()` does
   not render into the document 馃し鈥

[`inputValueTracking.js`]: https://github.com/facebook/react/blob/392530104c00c25074ce38e1f7e1dd363018c7ce/packages/react-dom/src/client/inputValueTracking.js#L79
[near-perfect-oninput-shim]: https://sophiebits.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html
[jsdom-source]: https://github.com/jsdom/jsdom/blob/45b77f5d21cef74cad278d089937d8462c29acce/lib/jsdom/living/nodes/HTMLElement-impl.js#L43-L76

* Make sure contains are unlinked from the document even if the test fails

* Remove unnecessary findDOMNode calls
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment