5
import {
6
clientRenderBoundary,
7
completeBoundary,
8
+ completeBoundaryWithStyles,
9
completeSegment,
10
listenToFormSubmissionsForReplaying,
11
} from './ReactDOMFizzInstructionSetShared';
12
12
-export {clientRenderBoundary, completeBoundary, completeSegment};
13
-
14
-const resourceMap = new Map();
15
-
16
-// This function is almost identical to the version used by inline scripts
17
-// (ReactDOMFizzInstructionSetInlineSource), with the exception of how we read
18
-// completeBoundary and resourceMap
19
-export function completeBoundaryWithStyles(
20
- suspenseBoundaryID,
21
- contentID,
22
- stylesheetDescriptors,
23
-) {
24
- const precedences = new Map();
25
- const thisDocument = document;
26
- let lastResource, node;
27
-
28
- // Seed the precedence list with existing resources and collect hoistable style tags
29
- const nodes = thisDocument.querySelectorAll(
30
- 'link[data-precedence],style[data-precedence]',
31
- );
32
- const styleTagsToHoist = [];
33
- for (let i = 0; (node = nodes[i++]); ) {
34
- if (node.getAttribute('media') === 'not all') {
35
- styleTagsToHoist.push(node);
36
- } else {
37
- if (node.tagName === 'LINK') {
38
- resourceMap.set(node.getAttribute('href'), node);
39
- }
40
- precedences.set(node.dataset['precedence'], (lastResource = node));
41
- }
42
- }
43
-
44
- let i = 0;
45
- const dependencies = [];
46
- let href, precedence, attr, loadingState, resourceEl, media;
47
-
48
- function cleanupWith(cb) {
49
- this['_p'] = null;
50
- cb();
51
- }
52
-
53
- // Sheets Mode
54
- let sheetMode = true;
55
- while (true) {
56
- if (sheetMode) {
57
- // Sheet Mode iterates over the stylesheet arguments and constructs them if new or checks them for
58
- // dependency if they already existed
59
- const stylesheetDescriptor = stylesheetDescriptors[i++];
60
- if (!stylesheetDescriptor) {
61
- // enter <style> Mode
62
- sheetMode = false;
63
- i = 0;
64
- continue;
65
- }
66
-
67
- let avoidInsert = false;
68
- let j = 0;
69
- href = stylesheetDescriptor[j++];
70
-
71
- if ((resourceEl = resourceMap.get(href))) {
72
- // We have an already inserted stylesheet.
73
- loadingState = resourceEl['_p'];
74
- avoidInsert = true;
75
- } else {
76
- // We haven't already processed this href so we need to construct a stylesheet and hoist it
77
- // We construct it here and attach a loadingState. We also check whether it matches
78
- // media before we include it in the dependency array.
79
- resourceEl = thisDocument.createElement('link');
80
- resourceEl.href = href;
81
- resourceEl.rel = 'stylesheet';
82
- resourceEl.dataset['precedence'] = precedence =
83
- stylesheetDescriptor[j++];
84
- while ((attr = stylesheetDescriptor[j++])) {
85
- resourceEl.setAttribute(attr, stylesheetDescriptor[j++]);
86
- }
87
- loadingState = resourceEl['_p'] = new Promise((resolve, reject) => {
88
- resourceEl.onload = cleanupWith.bind(resourceEl, resolve);
89
- resourceEl.onerror = cleanupWith.bind(resourceEl, reject);
90
- });
91
- // Save this resource element so we can bailout if it is used again
92
- resourceMap.set(href, resourceEl);
93
- }
94
- media = resourceEl.getAttribute('media');
95
- if (loadingState && (!media || window['matchMedia'](media).matches)) {
96
- dependencies.push(loadingState);
97
- }
98
- if (avoidInsert) {
99
- // We have a link that is already in the document. We don't want to fall through to the insert path
100
- continue;
101
- }
102
- } else {
103
- // <style> mode iterates over not-yet-hoisted <style> tags with data-precedence and hoists them.
104
- resourceEl = styleTagsToHoist[i++];
105
- if (!resourceEl) {
106
- // we are done with all style tags
107
- break;
108
- }
109
-
110
- precedence = resourceEl.getAttribute('data-precedence');
111
- resourceEl.removeAttribute('media');
112
- }
113
-
114
- // resourceEl is either a newly constructed <link rel="stylesheet" ...> or a <style> tag requiring hoisting
115
- const prior = precedences.get(precedence) || lastResource;
116
- if (prior === lastResource) {
117
- lastResource = resourceEl;
118
- }
119
- precedences.set(precedence, resourceEl);
120
-
121
- // Finally, we insert the newly constructed instance at an appropriate location
122
- // in the Document.
123
- if (prior) {
124
- prior.parentNode.insertBefore(resourceEl, prior.nextSibling);
125
- } else {
126
- const head = thisDocument.head;
127
- head.insertBefore(resourceEl, head.firstChild);
128
- }
129
- }
130
-
131
- Promise.all(dependencies).then(
132
- completeBoundary.bind(null, suspenseBoundaryID, contentID, ''),
133
- completeBoundary.bind(
134
- null,
135
- suspenseBoundaryID,
136
- contentID,
137
- 'Resource failed to load',
138
- ),
139
- );
140
-}
13
+// This is a string so Closure's advanced compilation mode doesn't mangle it.
14
+// These will be renamed to local references by the external-runtime-plugin.
15
+window['$RM'] = new Map();
16
+window['$RX'] = clientRenderBoundary;
17
+window['$RC'] = completeBoundary;
18
+window['$RR'] = completeBoundaryWithStyles;
19
+window['$RS'] = completeSegment;
20
21
listenToFormSubmissionsForReplaying();