7
7
* @flow
8
8
*/
9
9
10
- import type { HostDispatcher } from 'react-dom/src/shared/ReactDOMTypes' ;
11
10
import type { EventPriority } from 'react-reconciler/src/ReactEventPriorities' ;
12
11
import type { DOMEventName } from '../events/DOMEventNames' ;
13
12
import type { Fiber , FiberRoot } from 'react-reconciler/src/ReactInternalTypes' ;
@@ -20,6 +19,7 @@ import type {ReactScopeInstance} from 'shared/ReactTypes';
20
19
import type { AncestorInfoDev } from './validateDOMNesting' ;
21
20
import type { FormStatus } from 'react-dom-bindings/src/shared/ReactDOMFormActions' ;
22
21
import type {
22
+ HostDispatcher ,
23
23
CrossOriginEnum ,
24
24
PreloadImplOptions ,
25
25
PreloadModuleImplOptions ,
@@ -28,6 +28,10 @@ import type {
28
28
PreinitModuleScriptOptions ,
29
29
} from 'react-dom/src/shared/ReactDOMTypes' ;
30
30
31
+ import {
32
+ isAlreadyRendering ,
33
+ flushSync as flushSyncWithoutWarningIfAlreadyRendering ,
34
+ } from 'react-reconciler/src/ReactFiberReconciler' ;
31
35
import { NotPending } from 'react-dom-bindings/src/shared/ReactDOMFormActions' ;
32
36
import { getCurrentRootHostContainer } from 'react-reconciler/src/ReactFiberHostContext' ;
33
37
import { DefaultEventPriority } from 'react-reconciler/src/ReactEventPriorities' ;
@@ -106,6 +110,9 @@ import {listenToAllSupportedEvents} from '../events/DOMPluginEventSystem';
106
110
import { validateLinkPropsForStyleResource } from '../shared/ReactDOMResourceValidation' ;
107
111
import escapeSelectorAttributeValueInsideDoubleQuotes from './escapeSelectorAttributeValueInsideDoubleQuotes' ;
108
112
113
+ import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals' ;
114
+ const ReactDOMCurrentDispatcher = ReactDOMSharedInternals . Dispatcher ;
115
+
109
116
export type Type = string ;
110
117
export type Props = {
111
118
autoFocus ?: boolean ,
@@ -2083,19 +2090,44 @@ function getDocumentFromRoot(root: HoistableRoot): Document {
2083
2090
return root . ownerDocument || root ;
2084
2091
}
2085
2092
2086
- // We want this to be the default dispatcher on ReactDOMSharedInternals but we don't want to mutate
2087
- // internals in Module scope. Instead we export it and Internals will import it. There is already a cycle
2088
- // from Internals -> ReactDOM -> HostConfig -> Internals so this doesn't introduce a new one.
2089
- export const ReactDOMClientDispatcher : HostDispatcher = {
2093
+ const ReactDOMClientDispatcher : HostDispatcher = {
2090
2094
prefetchDNS ,
2091
2095
preconnect ,
2092
2096
preload ,
2093
2097
preloadModule ,
2094
2098
preinitStyle ,
2095
2099
preinitScript ,
2096
2100
preinitModuleScript ,
2101
+ flushSync ,
2102
+ nextDispatcher : null ,
2097
2103
} ;
2098
2104
2105
+ // We register the HostDispatcher on ReactDOMSharedInternals
2106
+ if ( ReactDOMCurrentDispatcher . current === null ) {
2107
+ ReactDOMCurrentDispatcher . current = ReactDOMClientDispatcher ;
2108
+ } else {
2109
+ ReactDOMCurrentDispatcher . current . nextDispatcher = ReactDOMClientDispatcher ;
2110
+ }
2111
+
2112
+ function flushSync < R > (fn: void | (() => R ) ) : void | R {
2113
+ if ( __DEV__ ) {
2114
+ if ( isAlreadyRendering ( ) ) {
2115
+ console . error (
2116
+ 'flushSync was called from inside a lifecycle method. React cannot ' +
2117
+ 'flush when React is already rendering. Consider moving this call to ' +
2118
+ 'a scheduler task or micro task.' ,
2119
+ ) ;
2120
+ }
2121
+ }
2122
+ if ( ReactDOMClientDispatcher . nextDispatcher ) {
2123
+ return ReactDOMClientDispatcher . nextDispatcher . flushSync ( ( ) =>
2124
+ flushSyncWithoutWarningIfAlreadyRendering ( fn ) ,
2125
+ ) ;
2126
+ } else {
2127
+ return flushSyncWithoutWarningIfAlreadyRendering ( fn ) ;
2128
+ }
2129
+ }
2130
+
2099
2131
// We expect this to get inlined. It is a function mostly to communicate the special nature of
2100
2132
// how we resolve the HoistableRoot for ReactDOM.pre*() methods. Because we support calling
2101
2133
// these methods outside of render there is no way to know which Document or ShadowRoot is 'scoped'
@@ -2134,20 +2166,29 @@ function preconnectAs(
2134
2166
}
2135
2167
2136
2168
function prefetchDNS(href: string) {
2169
+ if (ReactDOMClientDispatcher.nextDispatcher) {
2170
+ ReactDOMClientDispatcher.nextDispatcher.prefetchDNS(href);
2171
+ }
2137
2172
if (!enableFloat) {
2138
2173
return;
2139
2174
}
2140
2175
preconnectAs('dns-prefetch', href, null);
2141
2176
}
2142
2177
2143
2178
function preconnect(href: string, crossOrigin?: ?CrossOriginEnum) {
2179
+ if (ReactDOMClientDispatcher.nextDispatcher) {
2180
+ ReactDOMClientDispatcher.nextDispatcher.preconnect(href, crossOrigin);
2181
+ }
2144
2182
if (!enableFloat) {
2145
2183
return;
2146
2184
}
2147
2185
preconnectAs('preconnect', href, crossOrigin);
2148
2186
}
2149
2187
2150
2188
function preload(href: string, as: string, options?: ?PreloadImplOptions) {
2189
+ if (ReactDOMClientDispatcher.nextDispatcher) {
2190
+ ReactDOMClientDispatcher.nextDispatcher.preload(href, as, options);
2191
+ }
2151
2192
if (!enableFloat) {
2152
2193
return;
2153
2194
}
@@ -2228,6 +2269,9 @@ function preload(href: string, as: string, options?: ?PreloadImplOptions) {
2228
2269
}
2229
2270
2230
2271
function preloadModule ( href : string , options ?: ?PreloadModuleImplOptions ) {
2272
+ if ( ReactDOMClientDispatcher . nextDispatcher ) {
2273
+ ReactDOMClientDispatcher . nextDispatcher . preloadModule ( href , options ) ;
2274
+ }
2231
2275
if ( ! enableFloat ) {
2232
2276
return ;
2233
2277
}
@@ -2291,6 +2335,13 @@ function preinitStyle(
2291
2335
precedence : ?string ,
2292
2336
options ?: ?PreinitStyleOptions ,
2293
2337
) {
2338
+ if ( ReactDOMClientDispatcher . nextDispatcher ) {
2339
+ ReactDOMClientDispatcher . nextDispatcher . preinitStyle (
2340
+ href ,
2341
+ precedence ,
2342
+ options ,
2343
+ ) ;
2344
+ }
2294
2345
if ( ! enableFloat ) {
2295
2346
return ;
2296
2347
}
@@ -2367,6 +2418,9 @@ function preinitStyle(
2367
2418
}
2368
2419
2369
2420
function preinitScript ( src : string , options ?: ?PreinitScriptOptions ) {
2421
+ if ( ReactDOMClientDispatcher . nextDispatcher ) {
2422
+ ReactDOMClientDispatcher . nextDispatcher . preinitScript ( src , options ) ;
2423
+ }
2370
2424
if ( ! enableFloat ) {
2371
2425
return ;
2372
2426
}
@@ -2425,6 +2479,9 @@ function preinitModuleScript(
2425
2479
src : string ,
2426
2480
options ?: ?PreinitModuleScriptOptions ,
2427
2481
) {
2482
+ if ( ReactDOMClientDispatcher . nextDispatcher ) {
2483
+ ReactDOMClientDispatcher . nextDispatcher . preinitModuleScript ( src , options ) ;
2484
+ }
2428
2485
if ( ! enableFloat ) {
2429
2486
return ;
2430
2487
}
0 commit comments