56
getResourcesFromRoot,
57
isMarkedHoistable,
58
markNodeAsHoistable,
59
+ markNodeAsPendingLoad,
60
+ clearPendingLoadOnNode,
61
+ isNodePendingLoad,
62
isOwnedInstance,
63
} from './ReactDOMComponentTree';
64
import {
5008
as === 'script' &&
5009
ownerDocument.querySelector(getScriptSelectorFromKey(key))
5010
) {
5008
- // We already have a stylesheet for this key. We don't need to preload it.
5011
+ // We already have a script for this key. We don't need to preload it.
5012
return;
5013
}
5014
const instance = ownerDocument.createElement('link');
5015
setInitialProperties(instance, 'link', preloadProps);
5016
+ if (as === 'style') {
5017
+ // Stash a loading state on the preload link. it will clean itself up once settled
5018
+ markNodeAsPendingLoad(instance);
5019
+ instance.onload = instance.onerror = () => {
5020
+ clearPendingLoadOnNode(instance);
5021
+ };
5022
+ }
5023
markNodeAsHoistable(instance);
5024
(ownerDocument.head: any).appendChild(instance);
5025
}
5367
resource.instance = instance;
5368
resource.state.loading = Loaded | Inserted;
5369
}
5360
- }
5361
-
5362
- if (!preloadPropsMap.has(key)) {
5363
- const preloadProps = preloadPropsFromStylesheet(qualifiedProps);
5364
- preloadPropsMap.set(key, preloadProps);
5365
- if (!instance) {
5366
- preloadStylesheet(
5367
- ownerDocument,
5368
- key,
5369
- preloadProps,
5370
- resource.state,
5371
- );
5370
+ } else {
5371
+ // We don't have an instance we need to preload it instead
5372
+ // $FlowFixMe[incompatible-type] -- the key we use here can only match non module preloads
5373
+ let preloadProps: void | PreloadProps = preloadPropsMap.get(key);
5374
+ if (!preloadProps) {
5375
+ preloadProps = preloadPropsFromStylesheet(qualifiedProps);
5376
+ preloadPropsMap.set(key, preloadProps);
5377
}
5378
+
5379
+ preloadStylesheet(ownerDocument, key, preloadProps, resource.state);
5380
}
5381
}
5382
if (currentProps && currentResource === null) {
5547
preloadProps: PreloadProps,
5548
state: StylesheetState,
5549
) {
5543
- const preloadEl = ownerDocument.querySelector(
5550
+ let instance = ownerDocument.querySelector(
5551
getPreloadStylesheetSelectorFromKey(key),
5552
);
5546
- if (preloadEl) {
5547
- // If we find a preload already it was SSR'd and we won't have an actual
5548
- // loading state to track. For now we will just assume it is loaded
5549
- state.loading = Loaded;
5553
+ if (instance) {
5554
+ if (!isNodePendingLoad(instance)) {
5555
+ // If we find a preload already it was SSR'd and we won't have an actual
5556
+ // loading state to track. For now we will just assume it is loaded
5557
+ state.loading = Loaded;
5558
+ return;
5559
+ } else {
5560
+ // fall through and attach loading listeners
5561
+ }
5562
} else {
5551
- const instance = ownerDocument.createElement('link');
5552
- state.preload = instance;
5553
- instance.addEventListener('load', () => (state.loading |= Loaded));
5554
- instance.addEventListener('error', () => (state.loading |= Errored));
5563
+ instance = ownerDocument.createElement('link');
5564
+ markNodeAsPendingLoad(instance);
5565
+ instance.onload = instance.onerror = clearPendingLoadOnNode.bind(
5566
+ null,
5567
+ instance,
5568
+ );
5569
setInitialProperties(instance, 'link', preloadProps);
5570
markNodeAsHoistable(instance);
5571
(ownerDocument.head: any).appendChild(instance);
5572
}
5573
+ // $FlowFixMe: [incompatible-type] -- if instance is an Element it will also be an HTMLLinkElement
5574
+ state.preload = instance;
5575
+ instance.addEventListener('load', () => (state.loading |= Loaded));
5576
+ instance.addEventListener('error', () => (state.loading |= Errored));
5577
}
5578
5579
function preloadPropsFromStylesheet(