-
Notifications
You must be signed in to change notification settings - Fork 51k
Add infrastructure for passive/non-passive event support for future API exploration #15036
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
858608b
0ae3ba3
3bd6176
06f2c3b
bbae02d
68934d8
37224ea
c683859
e7e742f
ccf3884
c9fc178
5d5b972
e186b09
1dff1fc
8f79ee8
159280c
2acacf8
3b67255
5b044cf
8b34efa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -253,14 +253,17 @@ if (__DEV__) { | |
| }; | ||
| } | ||
|
|
||
| function ensureListeningTo(rootContainerElement, registrationName) { | ||
| function ensureListeningTo( | ||
| rootContainerElement: Element | Node, | ||
| registrationName: string, | ||
| ): void { | ||
| const isDocumentOrFragment = | ||
| rootContainerElement.nodeType === DOCUMENT_NODE || | ||
| rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE; | ||
| const doc = isDocumentOrFragment | ||
| ? rootContainerElement | ||
| : rootContainerElement.ownerDocument; | ||
| listenTo(registrationName, doc); | ||
| listenTo(registrationName, doc, true /* isLegacy */); | ||
| } | ||
|
|
||
| function getOwnerDocumentFromRootContainer( | ||
|
|
@@ -494,41 +497,41 @@ export function setInitialProperties( | |
| switch (tag) { | ||
| case 'iframe': | ||
| case 'object': | ||
| trapBubbledEvent(TOP_LOAD, domElement); | ||
| trapBubbledEvent(TOP_LOAD, domElement, true); | ||
| props = rawProps; | ||
| break; | ||
| case 'video': | ||
| case 'audio': | ||
| // Create listener for each media event | ||
| for (let i = 0; i < mediaEventTypes.length; i++) { | ||
| trapBubbledEvent(mediaEventTypes[i], domElement); | ||
| trapBubbledEvent(mediaEventTypes[i], domElement, true); | ||
| } | ||
| props = rawProps; | ||
| break; | ||
| case 'source': | ||
| trapBubbledEvent(TOP_ERROR, domElement); | ||
| trapBubbledEvent(TOP_ERROR, domElement, true); | ||
| props = rawProps; | ||
| break; | ||
| case 'img': | ||
| case 'image': | ||
| case 'link': | ||
| trapBubbledEvent(TOP_ERROR, domElement); | ||
| trapBubbledEvent(TOP_LOAD, domElement); | ||
| trapBubbledEvent(TOP_ERROR, domElement, true); | ||
| trapBubbledEvent(TOP_LOAD, domElement, true); | ||
| props = rawProps; | ||
| break; | ||
| case 'form': | ||
| trapBubbledEvent(TOP_RESET, domElement); | ||
| trapBubbledEvent(TOP_SUBMIT, domElement); | ||
| trapBubbledEvent(TOP_RESET, domElement, true); | ||
| trapBubbledEvent(TOP_SUBMIT, domElement, true); | ||
| props = rawProps; | ||
| break; | ||
| case 'details': | ||
| trapBubbledEvent(TOP_TOGGLE, domElement); | ||
| trapBubbledEvent(TOP_TOGGLE, domElement, true); | ||
| props = rawProps; | ||
| break; | ||
| case 'input': | ||
| ReactDOMInputInitWrapperState(domElement, rawProps); | ||
| props = ReactDOMInputGetHostProps(domElement, rawProps); | ||
| trapBubbledEvent(TOP_INVALID, domElement); | ||
| trapBubbledEvent(TOP_INVALID, domElement, true); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per our discussion, it seems like these code paths will never "want" to get two listeners attached/invoked. So instead of branching deeply and passing an argument through, let's fork the innermost implementation and call the fork from the new code when we want to. That will also likely let us DCE more based on a feature flag. |
||
| // For controlled components we always need to ensure we're listening | ||
| // to onChange. Even if there is no listener. | ||
| ensureListeningTo(rootContainerElement, 'onChange'); | ||
|
|
@@ -540,15 +543,15 @@ export function setInitialProperties( | |
| case 'select': | ||
| ReactDOMSelectInitWrapperState(domElement, rawProps); | ||
| props = ReactDOMSelectGetHostProps(domElement, rawProps); | ||
| trapBubbledEvent(TOP_INVALID, domElement); | ||
| trapBubbledEvent(TOP_INVALID, domElement, true); | ||
| // For controlled components we always need to ensure we're listening | ||
| // to onChange. Even if there is no listener. | ||
| ensureListeningTo(rootContainerElement, 'onChange'); | ||
| break; | ||
| case 'textarea': | ||
| ReactDOMTextareaInitWrapperState(domElement, rawProps); | ||
| props = ReactDOMTextareaGetHostProps(domElement, rawProps); | ||
| trapBubbledEvent(TOP_INVALID, domElement); | ||
| trapBubbledEvent(TOP_INVALID, domElement, true); | ||
| // For controlled components we always need to ensure we're listening | ||
| // to onChange. Even if there is no listener. | ||
| ensureListeningTo(rootContainerElement, 'onChange'); | ||
|
|
@@ -888,34 +891,34 @@ export function diffHydratedProperties( | |
| switch (tag) { | ||
| case 'iframe': | ||
| case 'object': | ||
| trapBubbledEvent(TOP_LOAD, domElement); | ||
| trapBubbledEvent(TOP_LOAD, domElement, true); | ||
| break; | ||
| case 'video': | ||
| case 'audio': | ||
| // Create listener for each media event | ||
| for (let i = 0; i < mediaEventTypes.length; i++) { | ||
| trapBubbledEvent(mediaEventTypes[i], domElement); | ||
| trapBubbledEvent(mediaEventTypes[i], domElement, true); | ||
| } | ||
| break; | ||
| case 'source': | ||
| trapBubbledEvent(TOP_ERROR, domElement); | ||
| trapBubbledEvent(TOP_ERROR, domElement, true); | ||
| break; | ||
| case 'img': | ||
| case 'image': | ||
| case 'link': | ||
| trapBubbledEvent(TOP_ERROR, domElement); | ||
| trapBubbledEvent(TOP_LOAD, domElement); | ||
| trapBubbledEvent(TOP_ERROR, domElement, true); | ||
| trapBubbledEvent(TOP_LOAD, domElement, true); | ||
| break; | ||
| case 'form': | ||
| trapBubbledEvent(TOP_RESET, domElement); | ||
| trapBubbledEvent(TOP_SUBMIT, domElement); | ||
| trapBubbledEvent(TOP_RESET, domElement, true); | ||
| trapBubbledEvent(TOP_SUBMIT, domElement, true); | ||
| break; | ||
| case 'details': | ||
| trapBubbledEvent(TOP_TOGGLE, domElement); | ||
| trapBubbledEvent(TOP_TOGGLE, domElement, true); | ||
| break; | ||
| case 'input': | ||
| ReactDOMInputInitWrapperState(domElement, rawProps); | ||
| trapBubbledEvent(TOP_INVALID, domElement); | ||
| trapBubbledEvent(TOP_INVALID, domElement, true); | ||
| // For controlled components we always need to ensure we're listening | ||
| // to onChange. Even if there is no listener. | ||
| ensureListeningTo(rootContainerElement, 'onChange'); | ||
|
|
@@ -925,14 +928,14 @@ export function diffHydratedProperties( | |
| break; | ||
| case 'select': | ||
| ReactDOMSelectInitWrapperState(domElement, rawProps); | ||
| trapBubbledEvent(TOP_INVALID, domElement); | ||
| trapBubbledEvent(TOP_INVALID, domElement, true); | ||
| // For controlled components we always need to ensure we're listening | ||
| // to onChange. Even if there is no listener. | ||
| ensureListeningTo(rootContainerElement, 'onChange'); | ||
| break; | ||
| case 'textarea': | ||
| ReactDOMTextareaInitWrapperState(domElement, rawProps); | ||
| trapBubbledEvent(TOP_INVALID, domElement); | ||
| trapBubbledEvent(TOP_INVALID, domElement, true); | ||
| // For controlled components we always need to ensure we're listening | ||
| // to onChange. Even if there is no listener. | ||
| ensureListeningTo(rootContainerElement, 'onChange'); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.