@@ -74,7 +74,10 @@ import {validateProperties as validateInputProperties} from '../shared/ReactDOMN
74
74
import { validateProperties as validateUnknownProperties } from '../shared/ReactDOMUnknownPropertyHook' ;
75
75
import { REACT_OPAQUE_ID_TYPE } from 'shared/ReactSymbols' ;
76
76
77
- import { enableTrustedTypesIntegration } from 'shared/ReactFeatureFlags' ;
77
+ import {
78
+ enableTrustedTypesIntegration ,
79
+ enableEagerRootListeners ,
80
+ } from 'shared/ReactFeatureFlags' ;
78
81
import {
79
82
listenToReactEvent ,
80
83
mediaEventTypes ,
@@ -260,30 +263,32 @@ export function ensureListeningTo(
260
263
reactPropEvent : string ,
261
264
targetElement : Element | null ,
262
265
) : 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
+ }
280
285
}
286
+ listenToReactEvent (
287
+ reactPropEvent ,
288
+ ( ( rootContainerElement : any ) : Element ) ,
289
+ targetElement ,
290
+ ) ;
281
291
}
282
- listenToReactEvent (
283
- reactPropEvent ,
284
- ( ( rootContainerElement : any ) : Element ) ,
285
- targetElement ,
286
- ) ;
287
292
}
288
293
289
294
function getOwnerDocumentFromRootContainer (
@@ -364,7 +369,11 @@ function setInitialDOMProperties(
364
369
if ( __DEV__ && typeof nextProp !== 'function' ) {
365
370
warnForInvalidEventListener ( propKey , nextProp ) ;
366
371
}
367
- ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
372
+ if ( ! enableEagerRootListeners ) {
373
+ ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
374
+ } else if ( propKey === 'onScroll' ) {
375
+ listenToNonDelegatedEvent ( 'scroll' , domElement ) ;
376
+ }
368
377
}
369
378
} else if ( nextProp != null ) {
370
379
setValueForProperty ( domElement , propKey , nextProp , isCustomComponentTag ) ;
@@ -573,9 +582,11 @@ export function setInitialProperties(
573
582
// We listen to this event in case to ensure emulated bubble
574
583
// listeners still fire for the invalid event.
575
584
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
+ }
579
590
break ;
580
591
case 'option' :
581
592
ReactDOMOptionValidateProps ( domElement , rawProps ) ;
@@ -587,19 +598,23 @@ export function setInitialProperties(
587
598
// We listen to this event in case to ensure emulated bubble
588
599
// listeners still fire for the invalid event.
589
600
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
+ }
593
606
break ;
594
607
case 'textarea' :
595
608
ReactDOMTextareaInitWrapperState ( domElement , rawProps ) ;
596
609
props = ReactDOMTextareaGetHostProps ( domElement , rawProps ) ;
597
610
// We listen to this event in case to ensure emulated bubble
598
611
// listeners still fire for the invalid event.
599
612
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
+ }
603
618
break ;
604
619
default :
605
620
props = rawProps ;
@@ -817,7 +832,11 @@ export function diffProperties(
817
832
if ( __DEV__ && typeof nextProp !== 'function' ) {
818
833
warnForInvalidEventListener ( propKey , nextProp ) ;
819
834
}
820
- ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
835
+ if ( ! enableEagerRootListeners ) {
836
+ ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
837
+ } else if ( propKey === 'onScroll' ) {
838
+ listenToNonDelegatedEvent ( 'scroll' , domElement ) ;
839
+ }
821
840
}
822
841
if ( ! updatePayload && lastProp !== nextProp ) {
823
842
// This is a special case. If any listener updates we need to ensure
@@ -969,9 +988,11 @@ export function diffHydratedProperties(
969
988
// We listen to this event in case to ensure emulated bubble
970
989
// listeners still fire for the invalid event.
971
990
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
+ }
975
996
break ;
976
997
case 'option' :
977
998
ReactDOMOptionValidateProps ( domElement , rawProps ) ;
@@ -981,18 +1002,22 @@ export function diffHydratedProperties(
981
1002
// We listen to this event in case to ensure emulated bubble
982
1003
// listeners still fire for the invalid event.
983
1004
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
+ }
987
1010
break ;
988
1011
case 'textarea' :
989
1012
ReactDOMTextareaInitWrapperState ( domElement , rawProps ) ;
990
1013
// We listen to this event in case to ensure emulated bubble
991
1014
// listeners still fire for the invalid event.
992
1015
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
+ }
996
1021
break ;
997
1022
}
998
1023
@@ -1059,7 +1084,9 @@ export function diffHydratedProperties(
1059
1084
if ( __DEV__ && typeof nextProp !== 'function' ) {
1060
1085
warnForInvalidEventListener ( propKey , nextProp ) ;
1061
1086
}
1062
- ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
1087
+ if ( ! enableEagerRootListeners ) {
1088
+ ensureListeningTo ( rootContainerElement , propKey , domElement ) ;
1089
+ }
1063
1090
}
1064
1091
} else if (
1065
1092
__DEV__ &&
0 commit comments