@@ -37,6 +37,11 @@ import {
37
37
stringToPrecomputedChunk ,
38
38
clonePrecomputedChunk ,
39
39
} from 'react-server/src/ReactServerStreamConfig' ;
40
+ import {
41
+ resolveResources ,
42
+ setCurrentResources ,
43
+ getCurrentResources ,
44
+ } from 'react-server/src/ReactFizzResources' ;
40
45
41
46
import isAttributeNameSafe from '../shared/isAttributeNameSafe' ;
42
47
import isUnitlessNumber from '../shared/isUnitlessNumber' ;
@@ -78,30 +83,34 @@ import {
78
83
import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals' ;
79
84
const ReactDOMCurrentDispatcher = ReactDOMSharedInternals . Dispatcher ;
80
85
81
- const ReactDOMServerDispatcher = enableFloat
82
- ? {
83
- prefetchDNS,
84
- preconnect,
85
- preload,
86
- preinit,
87
- }
88
- : { } ;
86
+ const ReactDOMServerDispatcher = {
87
+ prefetchDNS,
88
+ preconnect,
89
+ preload,
90
+ preinit,
91
+ } ;
89
92
90
- let currentResources : null | Resources = null ;
91
93
const currentResourcesStack = [ ] ;
92
94
93
- export function prepareToRender ( resources : Resources ) : mixed {
94
- currentResourcesStack . push ( currentResources ) ;
95
- currentResources = resources ;
95
+ function pushResources ( resources : null | Resources ) {
96
+ currentResourcesStack . push ( getCurrentResources ( ) ) ;
97
+ setCurrentResources ( resources ) ;
98
+ }
96
99
97
- const previousHostDispatcher = ReactDOMCurrentDispatcher . current ;
100
+ function popResources ( ) {
101
+ setCurrentResources ( currentResourcesStack . pop ( ) ) ;
102
+ }
103
+
104
+ export function prepareHostDispatcher ( ) {
98
105
ReactDOMCurrentDispatcher . current = ReactDOMServerDispatcher ;
99
- return previousHostDispatcher ;
100
106
}
101
107
102
- export function cleanupAfterRender ( previousDispatcher : mixed ) {
103
- currentResources = currentResourcesStack . pop ( ) ;
104
- ReactDOMCurrentDispatcher . current = previousDispatcher ;
108
+ export function prepareToRender ( resources : Resources ) : mixed {
109
+ pushResources ( resources ) ;
110
+ }
111
+
112
+ export function cleanupAfterRender ( ) {
113
+ popResources ( ) ;
105
114
}
106
115
107
116
// Used to distinguish these contexts from ones used in other renderers.
@@ -4490,16 +4499,18 @@ function getResourceKey(as: string, href: string): string {
4490
4499
}
4491
4500
4492
4501
export function prefetchDNS ( href : string , options ?: mixed ) {
4493
- if ( ! currentResources ) {
4494
- // While we expect that preconnect calls are primarily going to be observed
4495
- // during render because effects and events don't run on the server it is
4496
- // still possible that these get called in module scope. This is valid on
4497
- // the client since there is still a document to interact with but on the
4498
- // server we need a request to associate the call to. Because of this we
4499
- // simply return and do not warn.
4502
+ if ( ! enableFloat ) {
4503
+ return ;
4504
+ }
4505
+ const resources = resolveResources ( ) ;
4506
+ if ( ! resources ) {
4507
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
4508
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
4509
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
4510
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
4511
+ // fetching) and we don't want to warn in those cases.
4500
4512
return ;
4501
4513
}
4502
- const resources = currentResources ;
4503
4514
if ( __DEV__ ) {
4504
4515
if ( typeof href !== 'string' || ! href ) {
4505
4516
console . error (
@@ -4544,17 +4555,19 @@ export function prefetchDNS(href: string, options?: mixed) {
4544
4555
}
4545
4556
}
4546
4557
4547
- export function preconnect ( href : string , options ?: { crossOrigin ?: string } ) {
4548
- if ( ! currentResources ) {
4549
- // While we expect that preconnect calls are primarily going to be observed
4550
- // during render because effects and events don't run on the server it is
4551
- // still possible that these get called in module scope. This is valid on
4552
- // the client since there is still a document to interact with but on the
4553
- // server we need a request to associate the call to. Because of this we
4554
- // simply return and do not warn.
4558
+ export function preconnect ( href : string , options ?: ?{ crossOrigin ?: string } ) {
4559
+ if ( ! enableFloat ) {
4560
+ return ;
4561
+ }
4562
+ const resources = resolveResources ( ) ;
4563
+ if ( ! resources ) {
4564
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
4565
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
4566
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
4567
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
4568
+ // fetching) and we don't want to warn in those cases.
4555
4569
return;
4556
4570
}
4557
- const resources = currentResources ;
4558
4571
if ( __DEV__ ) {
4559
4572
if ( typeof href !== 'string' || ! href ) {
4560
4573
console . error (
@@ -4603,24 +4616,25 @@ export function preconnect(href: string, options?: {crossOrigin?: string}) {
4603
4616
}
4604
4617
}
4605
4618
4606
- type PreloadAs = 'style' | 'font' | 'script' ;
4607
4619
type PreloadOptions = {
4608
- as : PreloadAs ,
4620
+ as : string ,
4609
4621
crossOrigin ?: string ,
4610
4622
integrity ?: string ,
4611
4623
type ?: string ,
4612
4624
} ;
4613
4625
export function preload ( href : string , options : PreloadOptions ) {
4614
- if ( ! currentResources ) {
4615
- // While we expect that preload calls are primarily going to be observed
4616
- // during render because effects and events don't run on the server it is
4617
- // still possible that these get called in module scope. This is valid on
4618
- // the client since there is still a document to interact with but on the
4619
- // server we need a request to associate the call to. Because of this we
4620
- // simply return and do not warn.
4626
+ if ( ! enableFloat ) {
4627
+ return ;
4628
+ }
4629
+ const resources = resolveResources ( ) ;
4630
+ if ( ! resources ) {
4631
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
4632
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
4633
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
4634
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
4635
+ // fetching) and we don't want to warn in those cases.
4621
4636
return ;
4622
4637
}
4623
- const resources = currentResources ;
4624
4638
if ( __DEV__ ) {
4625
4639
if ( typeof href !== 'string' || ! href ) {
4626
4640
console . error (
@@ -4744,24 +4758,26 @@ export function preload(href: string, options: PreloadOptions) {
4744
4758
}
4745
4759
}
4746
4760
4747
- type PreinitAs = 'style' | 'script' ;
4748
4761
type PreinitOptions = {
4749
- as : PreinitAs ,
4762
+ as : string ,
4750
4763
precedence ?: string ,
4751
4764
crossOrigin ?: string ,
4752
4765
integrity ?: string ,
4753
4766
} ;
4754
4767
export function preinit ( href : string , options : PreinitOptions ) : void {
4755
- if ( ! currentResources ) {
4756
- // While we expect that preinit calls are primarily going to be observed
4757
- // during render because effects and events don't run on the server it is
4758
- // still possible that these get called in module scope. This is valid on
4759
- // the client since there is still a document to interact with but on the
4760
- // server we need a request to associate the call to. Because of this we
4761
- // simply return and do not warn.
4768
+ if ( ! enableFloat ) {
4762
4769
return ;
4763
4770
}
4764
- preinitImpl ( currentResources , href, options) ;
4771
+ const resources = resolveResources ( ) ;
4772
+ if ( ! resources ) {
4773
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
4774
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
4775
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
4776
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
4777
+ // fetching) and we don't want to warn in those cases.
4778
+ return;
4779
+ }
4780
+ preinitImpl ( resources , href , options ) ;
4765
4781
}
4766
4782
4767
4783
// On the server, preinit may be called outside of render when sending an
@@ -4983,7 +4999,7 @@ function preinitImpl(
4983
4999
4984
5000
function preloadPropsFromPreloadOptions (
4985
5001
href : string ,
4986
- as : PreloadAs ,
5002
+ as : string ,
4987
5003
options : PreloadOptions ,
4988
5004
) : PreloadProps {
4989
5005
return {
0 commit comments