@@ -38,6 +38,11 @@ import {
38
38
stringToPrecomputedChunk ,
39
39
clonePrecomputedChunk ,
40
40
} from 'react-server/src/ReactServerStreamConfig' ;
41
+ import {
42
+ resolveResources ,
43
+ setCurrentResources ,
44
+ getCurrentResources ,
45
+ } from 'react-server/src/ReactFizzResources' ;
41
46
42
47
import isAttributeNameSafe from '../shared/isAttributeNameSafe' ;
43
48
import isUnitlessNumber from '../shared/isUnitlessNumber' ;
@@ -79,30 +84,34 @@ import {
79
84
import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals' ;
80
85
const ReactDOMCurrentDispatcher = ReactDOMSharedInternals . Dispatcher ;
81
86
82
- const ReactDOMServerDispatcher = enableFloat
83
- ? {
84
- prefetchDNS,
85
- preconnect,
86
- preload,
87
- preinit,
88
- }
89
- : { } ;
87
+ const ReactDOMServerDispatcher = {
88
+ prefetchDNS,
89
+ preconnect,
90
+ preload,
91
+ preinit,
92
+ } ;
90
93
91
- let currentResources : null | Resources = null ;
92
94
const currentResourcesStack = [ ] ;
93
95
94
- export function prepareToRender ( resources : Resources ) : mixed {
95
- currentResourcesStack . push ( currentResources ) ;
96
- currentResources = resources ;
96
+ function pushResources ( resources : null | Resources ) {
97
+ currentResourcesStack . push ( getCurrentResources ( ) ) ;
98
+ setCurrentResources ( resources ) ;
99
+ }
97
100
98
- const previousHostDispatcher = ReactDOMCurrentDispatcher . current ;
101
+ function popResources ( ) {
102
+ setCurrentResources ( currentResourcesStack . pop ( ) ) ;
103
+ }
104
+
105
+ export function prepareHostDispatcher ( ) {
99
106
ReactDOMCurrentDispatcher . current = ReactDOMServerDispatcher ;
100
- return previousHostDispatcher ;
101
107
}
102
108
103
- export function cleanupAfterRender ( previousDispatcher : mixed ) {
104
- currentResources = currentResourcesStack . pop ( ) ;
105
- ReactDOMCurrentDispatcher . current = previousDispatcher ;
109
+ export function prepareToRender ( resources : Resources ) : mixed {
110
+ pushResources ( resources ) ;
111
+ }
112
+
113
+ export function cleanupAfterRender ( ) {
114
+ popResources ( ) ;
106
115
}
107
116
108
117
// Used to distinguish these contexts from ones used in other renderers.
@@ -4804,16 +4813,18 @@ function getResourceKey(as: string, href: string): string {
4804
4813
}
4805
4814
4806
4815
export function prefetchDNS ( href : string , options ?: mixed ) {
4807
- if ( ! currentResources ) {
4808
- // While we expect that preconnect calls are primarily going to be observed
4809
- // during render because effects and events don't run on the server it is
4810
- // still possible that these get called in module scope. This is valid on
4811
- // the client since there is still a document to interact with but on the
4812
- // server we need a request to associate the call to. Because of this we
4813
- // simply return and do not warn.
4816
+ if ( ! enableFloat ) {
4817
+ return ;
4818
+ }
4819
+ const resources = resolveResources ( ) ;
4820
+ if ( ! resources ) {
4821
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
4822
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
4823
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
4824
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
4825
+ // fetching) and we don't want to warn in those cases.
4814
4826
return ;
4815
4827
}
4816
- const resources = currentResources ;
4817
4828
if ( __DEV__ ) {
4818
4829
if ( typeof href !== 'string' || ! href ) {
4819
4830
console . error (
@@ -4858,17 +4869,19 @@ export function prefetchDNS(href: string, options?: mixed) {
4858
4869
}
4859
4870
}
4860
4871
4861
- export function preconnect ( href : string , options ?: { crossOrigin ?: string } ) {
4862
- if ( ! currentResources ) {
4863
- // While we expect that preconnect calls are primarily going to be observed
4864
- // during render because effects and events don't run on the server it is
4865
- // still possible that these get called in module scope. This is valid on
4866
- // the client since there is still a document to interact with but on the
4867
- // server we need a request to associate the call to. Because of this we
4868
- // simply return and do not warn.
4872
+ export function preconnect ( href : string , options ?: ?{ crossOrigin ?: string } ) {
4873
+ if ( ! enableFloat ) {
4874
+ return ;
4875
+ }
4876
+ const resources = resolveResources ( ) ;
4877
+ if ( ! resources ) {
4878
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
4879
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
4880
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
4881
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
4882
+ // fetching) and we don't want to warn in those cases.
4869
4883
return;
4870
4884
}
4871
- const resources = currentResources ;
4872
4885
if ( __DEV__ ) {
4873
4886
if ( typeof href !== 'string' || ! href ) {
4874
4887
console . error (
@@ -4917,24 +4930,25 @@ export function preconnect(href: string, options?: {crossOrigin?: string}) {
4917
4930
}
4918
4931
}
4919
4932
4920
- type PreloadAs = 'style' | 'font' | 'script' ;
4921
4933
type PreloadOptions = {
4922
- as : PreloadAs ,
4934
+ as : string ,
4923
4935
crossOrigin ?: string ,
4924
4936
integrity ?: string ,
4925
4937
type ?: string ,
4926
4938
} ;
4927
4939
export function preload ( href : string , options : PreloadOptions ) {
4928
- if ( ! currentResources ) {
4929
- // While we expect that preload calls are primarily going to be observed
4930
- // during render because effects and events don't run on the server it is
4931
- // still possible that these get called in module scope. This is valid on
4932
- // the client since there is still a document to interact with but on the
4933
- // server we need a request to associate the call to. Because of this we
4934
- // simply return and do not warn.
4940
+ if ( ! enableFloat ) {
4941
+ return ;
4942
+ }
4943
+ const resources = resolveResources ( ) ;
4944
+ if ( ! resources ) {
4945
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
4946
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
4947
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
4948
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
4949
+ // fetching) and we don't want to warn in those cases.
4935
4950
return ;
4936
4951
}
4937
- const resources = currentResources ;
4938
4952
if ( __DEV__ ) {
4939
4953
if ( typeof href !== 'string' || ! href ) {
4940
4954
console . error (
@@ -5058,24 +5072,26 @@ export function preload(href: string, options: PreloadOptions) {
5058
5072
}
5059
5073
}
5060
5074
5061
- type PreinitAs = 'style' | 'script' ;
5062
5075
type PreinitOptions = {
5063
- as : PreinitAs ,
5076
+ as : string ,
5064
5077
precedence ?: string ,
5065
5078
crossOrigin ?: string ,
5066
5079
integrity ?: string ,
5067
5080
} ;
5068
5081
export function preinit ( href : string , options : PreinitOptions ) : void {
5069
- if ( ! currentResources ) {
5070
- // While we expect that preinit calls are primarily going to be observed
5071
- // during render because effects and events don't run on the server it is
5072
- // still possible that these get called in module scope. This is valid on
5073
- // the client since there is still a document to interact with but on the
5074
- // server we need a request to associate the call to. Because of this we
5075
- // simply return and do not warn.
5082
+ if ( ! enableFloat ) {
5076
5083
return ;
5077
5084
}
5078
- preinitImpl ( currentResources , href, options) ;
5085
+ const resources = resolveResources ( ) ;
5086
+ if ( ! resources ) {
5087
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
5088
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
5089
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
5090
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
5091
+ // fetching) and we don't want to warn in those cases.
5092
+ return;
5093
+ }
5094
+ preinitImpl ( resources , href , options ) ;
5079
5095
}
5080
5096
5081
5097
// On the server, preinit may be called outside of render when sending an
@@ -5297,7 +5313,7 @@ function preinitImpl(
5297
5313
5298
5314
function preloadPropsFromPreloadOptions (
5299
5315
href : string ,
5300
- as : PreloadAs ,
5316
+ as : string ,
5301
5317
options : PreloadOptions ,
5302
5318
) : PreloadProps {
5303
5319
return {
0 commit comments