@@ -74,7 +74,10 @@ import {validateProperties as validateInputProperties} from '../shared/ReactDOMN
7474import { validateProperties as validateUnknownProperties } from '../shared/ReactDOMUnknownPropertyHook' ;
7575import { REACT_OPAQUE_ID_TYPE } from 'shared/ReactSymbols' ;
7676
77- import { enableTrustedTypesIntegration } from 'shared/ReactFeatureFlags' ;
77+ import {
78+ enableTrustedTypesIntegration ,
79+ enableEagerRootListeners ,
80+ } from 'shared/ReactFeatureFlags' ;
7881import {
7982 listenToReactEvent ,
8083 mediaEventTypes ,
@@ -260,30 +263,32 @@ export function ensureListeningTo(
260263 reactPropEvent : string ,
261264 targetElement : Element | null ,
262265) : void {
263- // If we have a comment node, then use the parent node,
264- // which should be an element.
265- const rootContainerElement =
266- rootContainerInstance . nodeType === COMMENT_NODE
267- ? rootContainerInstance . parentNode
268- : rootContainerInstance ;
269- if ( __DEV__ ) {
270- if (
271- rootContainerElement == null ||
272- ( rootContainerElement . nodeType !== ELEMENT_NODE &&
273- // This is to support rendering into a ShadowRoot:
274- rootContainerElement . nodeType !== DOCUMENT_FRAGMENT_NODE )
275- ) {
276- console . error (
277- 'ensureListeningTo(): received a container that was not an element node. ' +
278- 'This is likely a bug in React. Please file an issue.' ,
279- ) ;
266+ if ( ! enableEagerRootListeners ) {
267+ // If we have a comment node, then use the parent node,
268+ // which should be an element.
269+ const rootContainerElement =
270+ rootContainerInstance . nodeType === COMMENT_NODE
271+ ? rootContainerInstance . parentNode
272+ : rootContainerInstance ;
273+ if ( __DEV__ ) {
274+ if (
275+ rootContainerElement == null ||
276+ ( rootContainerElement . nodeType !== ELEMENT_NODE &&
277+ // This is to support rendering into a ShadowRoot:
278+ rootContainerElement . nodeType !== DOCUMENT_FRAGMENT_NODE )
279+ ) {
280+ console . error (
281+ 'ensureListeningTo(): received a container that was not an element node. ' +
282+ 'This is likely a bug in React. Please file an issue.' ,
283+ ) ;
284+ }
280285 }
286+ listenToReactEvent (
287+ reactPropEvent ,
288+ ( ( rootContainerElement : any ) : Element ) ,
289+ targetElement ,
290+ ) ;
281291 }
282- listenToReactEvent (
283- reactPropEvent ,
284- ( ( rootContainerElement : any ) : Element ) ,
285- targetElement ,
286- ) ;
287292}
288293
289294function getOwnerDocumentFromRootContainer (
@@ -364,7 +369,11 @@ function setInitialDOMProperties(
364369 if ( __DEV__ && typeof nextProp !== 'function' ) {
365370 warnForInvalidEventListener ( propKey , nextProp ) ;
366371 }
367- ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
372+ if ( ! enableEagerRootListeners ) {
373+ ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
374+ } else if ( propKey === 'onScroll' ) {
375+ listenToNonDelegatedEvent ( 'scroll' , domElement ) ;
376+ }
368377 }
369378 } else if ( nextProp != null ) {
370379 setValueForProperty ( domElement , propKey , nextProp , isCustomComponentTag ) ;
@@ -573,9 +582,11 @@ export function setInitialProperties(
573582 // We listen to this event in case to ensure emulated bubble
574583 // listeners still fire for the invalid event.
575584 listenToNonDelegatedEvent ( 'invalid' , domElement ) ;
576- // For controlled components we always need to ensure we're listening
577- // to onChange. Even if there is no listener.
578- ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
585+ if ( ! enableEagerRootListeners ) {
586+ // For controlled components we always need to ensure we're listening
587+ // to onChange. Even if there is no listener.
588+ ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
589+ }
579590 break ;
580591 case 'option' :
581592 ReactDOMOptionValidateProps ( domElement , rawProps ) ;
@@ -587,19 +598,23 @@ export function setInitialProperties(
587598 // We listen to this event in case to ensure emulated bubble
588599 // listeners still fire for the invalid event.
589600 listenToNonDelegatedEvent ( 'invalid' , domElement ) ;
590- // For controlled components we always need to ensure we're listening
591- // to onChange. Even if there is no listener.
592- ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
601+ if ( ! enableEagerRootListeners ) {
602+ // For controlled components we always need to ensure we're listening
603+ // to onChange. Even if there is no listener.
604+ ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
605+ }
593606 break ;
594607 case 'textarea' :
595608 ReactDOMTextareaInitWrapperState ( domElement , rawProps ) ;
596609 props = ReactDOMTextareaGetHostProps ( domElement , rawProps ) ;
597610 // We listen to this event in case to ensure emulated bubble
598611 // listeners still fire for the invalid event.
599612 listenToNonDelegatedEvent ( 'invalid' , domElement ) ;
600- // For controlled components we always need to ensure we're listening
601- // to onChange. Even if there is no listener.
602- ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
613+ if ( ! enableEagerRootListeners ) {
614+ // For controlled components we always need to ensure we're listening
615+ // to onChange. Even if there is no listener.
616+ ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
617+ }
603618 break ;
604619 default :
605620 props = rawProps ;
@@ -817,7 +832,11 @@ export function diffProperties(
817832 if ( __DEV__ && typeof nextProp !== 'function' ) {
818833 warnForInvalidEventListener ( propKey , nextProp ) ;
819834 }
820- ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
835+ if ( ! enableEagerRootListeners ) {
836+ ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
837+ } else if ( propKey === 'onScroll' ) {
838+ listenToNonDelegatedEvent ( 'scroll' , domElement ) ;
839+ }
821840 }
822841 if ( ! updatePayload && lastProp !== nextProp ) {
823842 // This is a special case. If any listener updates we need to ensure
@@ -969,9 +988,11 @@ export function diffHydratedProperties(
969988 // We listen to this event in case to ensure emulated bubble
970989 // listeners still fire for the invalid event.
971990 listenToNonDelegatedEvent ( 'invalid' , domElement ) ;
972- // For controlled components we always need to ensure we're listening
973- // to onChange. Even if there is no listener.
974- ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
991+ if ( ! enableEagerRootListeners ) {
992+ // For controlled components we always need to ensure we're listening
993+ // to onChange. Even if there is no listener.
994+ ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
995+ }
975996 break ;
976997 case 'option' :
977998 ReactDOMOptionValidateProps ( domElement , rawProps ) ;
@@ -981,18 +1002,22 @@ export function diffHydratedProperties(
9811002 // We listen to this event in case to ensure emulated bubble
9821003 // listeners still fire for the invalid event.
9831004 listenToNonDelegatedEvent ( 'invalid' , domElement ) ;
984- // For controlled components we always need to ensure we're listening
985- // to onChange. Even if there is no listener.
986- ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
1005+ if ( ! enableEagerRootListeners ) {
1006+ // For controlled components we always need to ensure we're listening
1007+ // to onChange. Even if there is no listener.
1008+ ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
1009+ }
9871010 break ;
9881011 case 'textarea' :
9891012 ReactDOMTextareaInitWrapperState ( domElement , rawProps ) ;
9901013 // We listen to this event in case to ensure emulated bubble
9911014 // listeners still fire for the invalid event.
9921015 listenToNonDelegatedEvent ( 'invalid' , domElement ) ;
993- // For controlled components we always need to ensure we're listening
994- // to onChange. Even if there is no listener.
995- ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
1016+ if ( ! enableEagerRootListeners ) {
1017+ // For controlled components we always need to ensure we're listening
1018+ // to onChange. Even if there is no listener.
1019+ ensureListeningTo ( rootContainerElement , 'onChange' , domElement ) ;
1020+ }
9961021 break ;
9971022 }
9981023
@@ -1059,7 +1084,9 @@ export function diffHydratedProperties(
10591084 if ( __DEV__ && typeof nextProp !== 'function' ) {
10601085 warnForInvalidEventListener ( propKey , nextProp ) ;
10611086 }
1062- ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
1087+ if ( ! enableEagerRootListeners ) {
1088+ ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
1089+ }
10631090 }
10641091 } else if (
10651092 __DEV__ &&
0 commit comments