|
1 | 1 | /* eslint-disable dot-notation */ |
2 | 2 |
|
3 | | -const COMMENT_NODE = 8; |
4 | | -const SUSPENSE_START_DATA = '$'; |
5 | | -const SUSPENSE_END_DATA = '/$'; |
6 | | -const SUSPENSE_PENDING_START_DATA = '$?'; |
7 | | -const SUSPENSE_FALLBACK_START_DATA = '$!'; |
8 | | -const LOADED = 'l'; |
9 | | -const ERRORED = 'e'; |
| 3 | +// Shared implementation and constants between the inline script and external |
| 4 | +// runtime instruction sets. |
| 5 | + |
| 6 | +export const COMMENT_NODE = 8; |
| 7 | +export const SUSPENSE_START_DATA = '$'; |
| 8 | +export const SUSPENSE_END_DATA = '/$'; |
| 9 | +export const SUSPENSE_PENDING_START_DATA = '$?'; |
| 10 | +export const SUSPENSE_FALLBACK_START_DATA = '$!'; |
| 11 | +export const LOADED = 'l'; |
| 12 | +export const ERRORED = 'e'; |
10 | 13 |
|
11 | 14 | // TODO: Symbols that are referenced outside this module use dynamic accessor |
12 | 15 | // notation instead of dot notation to prevent Closure's advanced compilation |
@@ -42,106 +45,6 @@ export function clientRenderBoundary( |
42 | 45 | } |
43 | 46 | } |
44 | 47 |
|
45 | | -export function completeBoundaryWithStyles( |
46 | | - suspenseBoundaryID, |
47 | | - contentID, |
48 | | - styles, |
49 | | -) { |
50 | | - // TODO: In the non-inline version of the runtime, these don't need to be read |
51 | | - // from the global scope. |
52 | | - const completeBoundaryImpl = window['$RC']; |
53 | | - const resourceMap = window['$RM']; |
54 | | - |
55 | | - const precedences = new Map(); |
56 | | - const thisDocument = document; |
57 | | - let lastResource, node; |
58 | | - |
59 | | - // Seed the precedence list with existing resources |
60 | | - const nodes = thisDocument.querySelectorAll( |
61 | | - 'link[data-precedence],style[data-precedence]', |
62 | | - ); |
63 | | - for (let i = 0; (node = nodes[i++]); ) { |
64 | | - precedences.set(node.dataset['precedence'], (lastResource = node)); |
65 | | - } |
66 | | - |
67 | | - let i = 0; |
68 | | - const dependencies = []; |
69 | | - let style, href, precedence, attr, loadingState, resourceEl; |
70 | | - |
71 | | - function setStatus(s) { |
72 | | - this['s'] = s; |
73 | | - } |
74 | | - |
75 | | - while ((style = styles[i++])) { |
76 | | - let j = 0; |
77 | | - href = style[j++]; |
78 | | - // We check if this resource is already in our resourceMap and reuse it if so. |
79 | | - // If it is already loaded we don't return it as a depenendency since there is nothing |
80 | | - // to wait for |
81 | | - loadingState = resourceMap.get(href); |
82 | | - if (loadingState) { |
83 | | - if (loadingState['s'] !== 'l') { |
84 | | - dependencies.push(loadingState); |
85 | | - } |
86 | | - continue; |
87 | | - } |
88 | | - |
89 | | - // We construct our new resource element, looping over remaining attributes if any |
90 | | - // setting them to the Element. |
91 | | - resourceEl = thisDocument.createElement('link'); |
92 | | - resourceEl.href = href; |
93 | | - resourceEl.rel = 'stylesheet'; |
94 | | - resourceEl.dataset['precedence'] = precedence = style[j++]; |
95 | | - while ((attr = style[j++])) { |
96 | | - resourceEl.setAttribute(attr, style[j++]); |
97 | | - } |
98 | | - |
99 | | - // We stash a pending promise in our map by href which will resolve or reject |
100 | | - // when the underlying resource loads or errors. We add it to the dependencies |
101 | | - // array to be returned. |
102 | | - loadingState = resourceEl['_p'] = new Promise((re, rj) => { |
103 | | - resourceEl.onload = re; |
104 | | - resourceEl.onerror = rj; |
105 | | - }); |
106 | | - loadingState.then( |
107 | | - setStatus.bind(loadingState, LOADED), |
108 | | - setStatus.bind(loadingState, ERRORED), |
109 | | - ); |
110 | | - resourceMap.set(href, loadingState); |
111 | | - dependencies.push(loadingState); |
112 | | - |
113 | | - // The prior style resource is the last one placed at a given |
114 | | - // precedence or the last resource itself which may be null. |
115 | | - // We grab this value and then update the last resource for this |
116 | | - // precedence to be the inserted element, updating the lastResource |
117 | | - // pointer if needed. |
118 | | - const prior = precedences.get(precedence) || lastResource; |
119 | | - if (prior === lastResource) { |
120 | | - lastResource = resourceEl; |
121 | | - } |
122 | | - precedences.set(precedence, resourceEl); |
123 | | - |
124 | | - // Finally, we insert the newly constructed instance at an appropriate location |
125 | | - // in the Document. |
126 | | - if (prior) { |
127 | | - prior.parentNode.insertBefore(resourceEl, prior.nextSibling); |
128 | | - } else { |
129 | | - const head = thisDocument.head; |
130 | | - head.insertBefore(resourceEl, head.firstChild); |
131 | | - } |
132 | | - } |
133 | | - |
134 | | - Promise.all(dependencies).then( |
135 | | - completeBoundaryImpl.bind(null, suspenseBoundaryID, contentID, ''), |
136 | | - completeBoundaryImpl.bind( |
137 | | - null, |
138 | | - suspenseBoundaryID, |
139 | | - contentID, |
140 | | - 'Resource failed to load', |
141 | | - ), |
142 | | - ); |
143 | | -} |
144 | | - |
145 | 48 | export function completeBoundary(suspenseBoundaryID, contentID, errorDigest) { |
146 | 49 | const contentNode = document.getElementById(contentID); |
147 | 50 | // We'll detach the content node so that regardless of what happens next we don't leave in the tree. |
|
0 commit comments