@solidjs/web 2.0.0-experimental.14 → 2.0.0-experimental.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.cjs +26 -3
- package/dist/dev.js +27 -4
- package/dist/server.cjs +243 -30
- package/dist/server.js +244 -31
- package/dist/web.cjs +26 -2
- package/dist/web.js +27 -3
- package/package.json +5 -4
- package/storage/types/src/client.d.ts +1 -0
- package/storage/types/src/index.d.ts +45 -0
- package/storage/types/src/server-mock.d.ts +72 -0
- package/storage/types/storage/src/index.d.ts +2 -0
- package/types/client.d.ts +22 -7
- package/types/server-mock.d.ts +33 -1
- package/types/server.d.ts +22 -18
package/dist/dev.cjs
CHANGED
|
@@ -230,6 +230,13 @@ function use(fn, element, arg) {
|
|
|
230
230
|
function insert(parent, accessor, marker, initial) {
|
|
231
231
|
const multi = marker !== undefined;
|
|
232
232
|
if (multi && !initial) initial = [];
|
|
233
|
+
if (isHydrating(parent) && Array.isArray(initial)) {
|
|
234
|
+
let j = 0;
|
|
235
|
+
for (let i = 0; i < initial.length; i++) {
|
|
236
|
+
if (initial[i].nodeType === 8 && initial[i].nodeValue === "!$") initial[i].remove();else initial[j++] = initial[i];
|
|
237
|
+
}
|
|
238
|
+
initial.length = j;
|
|
239
|
+
}
|
|
233
240
|
if (typeof accessor !== "function") {
|
|
234
241
|
accessor = normalize(accessor, initial, multi, true);
|
|
235
242
|
if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker);
|
|
@@ -256,11 +263,29 @@ function assign(node, props, isSVG, skipChildren, prevProps = {}, skipRef = fals
|
|
|
256
263
|
function hydrate$1(code, element, options = {}) {
|
|
257
264
|
if (globalThis._$HY.done) return render(code, element, [...element.childNodes], options);
|
|
258
265
|
options.renderId ||= "";
|
|
266
|
+
if (!globalThis._$HY.modules) globalThis._$HY.modules = {};
|
|
267
|
+
if (!globalThis._$HY.loading) globalThis._$HY.loading = {};
|
|
259
268
|
solidJs.sharedConfig.completed = globalThis._$HY.completed;
|
|
260
269
|
solidJs.sharedConfig.events = globalThis._$HY.events;
|
|
261
270
|
solidJs.sharedConfig.load = id => globalThis._$HY.r[id];
|
|
262
271
|
solidJs.sharedConfig.has = id => id in globalThis._$HY.r;
|
|
263
272
|
solidJs.sharedConfig.gather = root => gatherHydratable(element, root);
|
|
273
|
+
solidJs.sharedConfig.cleanupFragment = id => {
|
|
274
|
+
const tpl = document.getElementById("pl-" + id);
|
|
275
|
+
if (tpl) {
|
|
276
|
+
let node = tpl.nextSibling;
|
|
277
|
+
while (node) {
|
|
278
|
+
const next = node.nextSibling;
|
|
279
|
+
if (node.nodeType === 8 && node.nodeValue === "pl-" + id) {
|
|
280
|
+
node.remove();
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
node.remove();
|
|
284
|
+
node = next;
|
|
285
|
+
}
|
|
286
|
+
tpl.remove();
|
|
287
|
+
}
|
|
288
|
+
};
|
|
264
289
|
solidJs.sharedConfig.registry = new Map();
|
|
265
290
|
solidJs.sharedConfig.hydrating = true;
|
|
266
291
|
try {
|
|
@@ -276,7 +301,6 @@ function getNextElement(template) {
|
|
|
276
301
|
hydrating = isHydrating();
|
|
277
302
|
if (!hydrating || !(node = solidJs.sharedConfig.registry.get(key = getHydrationKey()))) {
|
|
278
303
|
if (hydrating) {
|
|
279
|
-
solidJs.sharedConfig.done = true;
|
|
280
304
|
throw new Error(`Hydration Mismatch. Unable to find DOM nodes for hydration key: ${key}\n${template ? template().outerHTML : ""}`);
|
|
281
305
|
}
|
|
282
306
|
return template();
|
|
@@ -332,7 +356,7 @@ function runHydrationEvents() {
|
|
|
332
356
|
}
|
|
333
357
|
}
|
|
334
358
|
function isHydrating(node) {
|
|
335
|
-
return solidJs.sharedConfig.hydrating &&
|
|
359
|
+
return solidJs.sharedConfig.hydrating && (!node || node.isConnected);
|
|
336
360
|
}
|
|
337
361
|
function toggleClassKey(node, key, value) {
|
|
338
362
|
const classNames = key.trim().split(/\s+/);
|
|
@@ -414,7 +438,6 @@ function eventHandler(e) {
|
|
|
414
438
|
return node || document;
|
|
415
439
|
}
|
|
416
440
|
});
|
|
417
|
-
if (solidJs.sharedConfig.registry && !solidJs.sharedConfig.done) solidJs.sharedConfig.done = _$HY.done = true;
|
|
418
441
|
if (e.composedPath) {
|
|
419
442
|
const path = e.composedPath();
|
|
420
443
|
retarget(path[0]);
|
package/dist/dev.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createMemo,
|
|
1
|
+
import { createMemo, sharedConfig, createRenderEffect, createRoot, flatten, untrack, omit, $DEVCOMP, enableHydration } from 'solid-js';
|
|
2
2
|
export { Errored, For, Loading, Match, Show, Switch, createComponent, createRenderEffect as effect, getOwner, merge as mergeProps, untrack } from 'solid-js';
|
|
3
3
|
|
|
4
4
|
const Properties = /*#__PURE__*/new Set([
|
|
@@ -229,6 +229,13 @@ function use(fn, element, arg) {
|
|
|
229
229
|
function insert(parent, accessor, marker, initial) {
|
|
230
230
|
const multi = marker !== undefined;
|
|
231
231
|
if (multi && !initial) initial = [];
|
|
232
|
+
if (isHydrating(parent) && Array.isArray(initial)) {
|
|
233
|
+
let j = 0;
|
|
234
|
+
for (let i = 0; i < initial.length; i++) {
|
|
235
|
+
if (initial[i].nodeType === 8 && initial[i].nodeValue === "!$") initial[i].remove();else initial[j++] = initial[i];
|
|
236
|
+
}
|
|
237
|
+
initial.length = j;
|
|
238
|
+
}
|
|
232
239
|
if (typeof accessor !== "function") {
|
|
233
240
|
accessor = normalize(accessor, initial, multi, true);
|
|
234
241
|
if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker);
|
|
@@ -255,11 +262,29 @@ function assign(node, props, isSVG, skipChildren, prevProps = {}, skipRef = fals
|
|
|
255
262
|
function hydrate$1(code, element, options = {}) {
|
|
256
263
|
if (globalThis._$HY.done) return render(code, element, [...element.childNodes], options);
|
|
257
264
|
options.renderId ||= "";
|
|
265
|
+
if (!globalThis._$HY.modules) globalThis._$HY.modules = {};
|
|
266
|
+
if (!globalThis._$HY.loading) globalThis._$HY.loading = {};
|
|
258
267
|
sharedConfig.completed = globalThis._$HY.completed;
|
|
259
268
|
sharedConfig.events = globalThis._$HY.events;
|
|
260
269
|
sharedConfig.load = id => globalThis._$HY.r[id];
|
|
261
270
|
sharedConfig.has = id => id in globalThis._$HY.r;
|
|
262
271
|
sharedConfig.gather = root => gatherHydratable(element, root);
|
|
272
|
+
sharedConfig.cleanupFragment = id => {
|
|
273
|
+
const tpl = document.getElementById("pl-" + id);
|
|
274
|
+
if (tpl) {
|
|
275
|
+
let node = tpl.nextSibling;
|
|
276
|
+
while (node) {
|
|
277
|
+
const next = node.nextSibling;
|
|
278
|
+
if (node.nodeType === 8 && node.nodeValue === "pl-" + id) {
|
|
279
|
+
node.remove();
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
node.remove();
|
|
283
|
+
node = next;
|
|
284
|
+
}
|
|
285
|
+
tpl.remove();
|
|
286
|
+
}
|
|
287
|
+
};
|
|
263
288
|
sharedConfig.registry = new Map();
|
|
264
289
|
sharedConfig.hydrating = true;
|
|
265
290
|
try {
|
|
@@ -275,7 +300,6 @@ function getNextElement(template) {
|
|
|
275
300
|
hydrating = isHydrating();
|
|
276
301
|
if (!hydrating || !(node = sharedConfig.registry.get(key = getHydrationKey()))) {
|
|
277
302
|
if (hydrating) {
|
|
278
|
-
sharedConfig.done = true;
|
|
279
303
|
throw new Error(`Hydration Mismatch. Unable to find DOM nodes for hydration key: ${key}\n${template ? template().outerHTML : ""}`);
|
|
280
304
|
}
|
|
281
305
|
return template();
|
|
@@ -331,7 +355,7 @@ function runHydrationEvents() {
|
|
|
331
355
|
}
|
|
332
356
|
}
|
|
333
357
|
function isHydrating(node) {
|
|
334
|
-
return sharedConfig.hydrating &&
|
|
358
|
+
return sharedConfig.hydrating && (!node || node.isConnected);
|
|
335
359
|
}
|
|
336
360
|
function toggleClassKey(node, key, value) {
|
|
337
361
|
const classNames = key.trim().split(/\s+/);
|
|
@@ -413,7 +437,6 @@ function eventHandler(e) {
|
|
|
413
437
|
return node || document;
|
|
414
438
|
}
|
|
415
439
|
});
|
|
416
|
-
if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = _$HY.done = true;
|
|
417
440
|
if (e.composedPath) {
|
|
418
441
|
const path = e.composedPath();
|
|
419
442
|
retarget(path[0]);
|
package/dist/server.cjs
CHANGED
|
@@ -30,13 +30,16 @@ function createSerializer({
|
|
|
30
30
|
onData,
|
|
31
31
|
onDone,
|
|
32
32
|
scopeId,
|
|
33
|
-
onError
|
|
33
|
+
onError,
|
|
34
|
+
plugins: customPlugins
|
|
34
35
|
}) {
|
|
36
|
+
const defaultPlugins = [web.AbortSignalPlugin,
|
|
37
|
+
web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
|
|
38
|
+
web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin];
|
|
39
|
+
const allPlugins = customPlugins ? [...customPlugins, ...defaultPlugins] : defaultPlugins;
|
|
35
40
|
return new seroval.Serializer({
|
|
36
41
|
scopeId,
|
|
37
|
-
plugins:
|
|
38
|
-
web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
|
|
39
|
-
web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin],
|
|
42
|
+
plugins: allPlugins,
|
|
40
43
|
globalIdentifier: GLOBAL_IDENTIFIER,
|
|
41
44
|
disabledFeatures: ES2017FLAG,
|
|
42
45
|
onData,
|
|
@@ -48,17 +51,102 @@ function getLocalHeaderScript(id) {
|
|
|
48
51
|
return seroval.getCrossReferenceHeader(id) + ';';
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
function resolveAssets(moduleUrl, manifest) {
|
|
55
|
+
if (!manifest) return null;
|
|
56
|
+
const entry = manifest[moduleUrl];
|
|
57
|
+
if (!entry) return null;
|
|
58
|
+
const css = [];
|
|
59
|
+
const js = [];
|
|
60
|
+
const visited = new Set();
|
|
61
|
+
const walk = key => {
|
|
62
|
+
if (visited.has(key)) return;
|
|
63
|
+
visited.add(key);
|
|
64
|
+
const e = manifest[key];
|
|
65
|
+
if (!e) return;
|
|
66
|
+
js.push(e.file);
|
|
67
|
+
if (e.css) for (let i = 0; i < e.css.length; i++) css.push(e.css[i]);
|
|
68
|
+
if (e.imports) for (let i = 0; i < e.imports.length; i++) walk(e.imports[i]);
|
|
69
|
+
};
|
|
70
|
+
walk(moduleUrl);
|
|
71
|
+
return {
|
|
72
|
+
js,
|
|
73
|
+
css
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function registerEntryAssets(manifest) {
|
|
77
|
+
if (!manifest) return;
|
|
78
|
+
const ctx = solidJs.sharedConfig.context;
|
|
79
|
+
if (!ctx?.registerAsset) return;
|
|
80
|
+
for (const key in manifest) {
|
|
81
|
+
if (manifest[key].isEntry) {
|
|
82
|
+
const assets = resolveAssets(key, manifest);
|
|
83
|
+
if (assets) {
|
|
84
|
+
for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]);
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function createAssetTracking() {
|
|
91
|
+
const boundaryModules = new Map();
|
|
92
|
+
const boundaryStyles = new Map();
|
|
93
|
+
const emittedAssets = new Set();
|
|
94
|
+
let currentBoundaryId = null;
|
|
95
|
+
return {
|
|
96
|
+
boundaryModules,
|
|
97
|
+
boundaryStyles,
|
|
98
|
+
emittedAssets,
|
|
99
|
+
get currentBoundaryId() {
|
|
100
|
+
return currentBoundaryId;
|
|
101
|
+
},
|
|
102
|
+
set currentBoundaryId(v) {
|
|
103
|
+
currentBoundaryId = v;
|
|
104
|
+
},
|
|
105
|
+
registerModule(moduleUrl, entryUrl) {
|
|
106
|
+
if (!currentBoundaryId) return;
|
|
107
|
+
let map = boundaryModules.get(currentBoundaryId);
|
|
108
|
+
if (!map) {
|
|
109
|
+
map = {};
|
|
110
|
+
boundaryModules.set(currentBoundaryId, map);
|
|
111
|
+
}
|
|
112
|
+
map[moduleUrl] = entryUrl;
|
|
113
|
+
},
|
|
114
|
+
getBoundaryModules(id) {
|
|
115
|
+
return boundaryModules.get(id) || null;
|
|
116
|
+
},
|
|
117
|
+
getBoundaryStyles(id) {
|
|
118
|
+
return boundaryStyles.get(id) || null;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function applyAssetTracking(context, tracking, manifest) {
|
|
123
|
+
Object.defineProperty(context, "_currentBoundaryId", {
|
|
124
|
+
get() {
|
|
125
|
+
return tracking.currentBoundaryId;
|
|
126
|
+
},
|
|
127
|
+
set(v) {
|
|
128
|
+
tracking.currentBoundaryId = v;
|
|
129
|
+
},
|
|
130
|
+
configurable: true,
|
|
131
|
+
enumerable: true
|
|
132
|
+
});
|
|
133
|
+
context.registerModule = tracking.registerModule;
|
|
134
|
+
context.getBoundaryModules = tracking.getBoundaryModules;
|
|
135
|
+
if (manifest) context.resolveAssets = moduleUrl => resolveAssets(moduleUrl, manifest);
|
|
136
|
+
}
|
|
51
137
|
const VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i;
|
|
52
|
-
const REPLACE_SCRIPT = `function $df(e,n,o,t){if(n=document.getElementById(e),o=document.getElementById("pl-"+e)){for(;o&&8!==o.nodeType&&o.nodeValue!=="pl-"+e;)t=o.nextSibling,o.remove(),o=t;_$HY.done?o.remove():o.replaceWith(n.content)}n.remove(),_$HY.fe(e)}`;
|
|
138
|
+
const REPLACE_SCRIPT = `function $df(e,n,o,t){if(n=document.getElementById(e),o=document.getElementById("pl-"+e)){for(;o&&8!==o.nodeType&&o.nodeValue!=="pl-"+e;)t=o.nextSibling,o.remove(),o=t;_$HY.done?o.remove():o.replaceWith(n.content)}n.remove(),_$HY.fe(e)}function $dfs(e,c){(_$HY.sc=_$HY.sc||{})[e]=c}function $dfc(e){if(--_$HY.sc[e]<=0)delete _$HY.sc[e],$df(e)}`;
|
|
53
139
|
function renderToString(code, options = {}) {
|
|
54
140
|
const {
|
|
55
141
|
renderId = "",
|
|
56
142
|
nonce,
|
|
57
|
-
noScripts
|
|
143
|
+
noScripts,
|
|
144
|
+
manifest
|
|
58
145
|
} = options;
|
|
59
146
|
let scripts = "";
|
|
60
147
|
const serializer = createSerializer({
|
|
61
148
|
scopeId: renderId,
|
|
149
|
+
plugins: options.plugins,
|
|
62
150
|
onData(script) {
|
|
63
151
|
if (noScripts) return;
|
|
64
152
|
if (!scripts) {
|
|
@@ -68,6 +156,7 @@ function renderToString(code, options = {}) {
|
|
|
68
156
|
},
|
|
69
157
|
onError: options.onError
|
|
70
158
|
});
|
|
159
|
+
const tracking = createAssetTracking();
|
|
71
160
|
solidJs.sharedConfig.context = {
|
|
72
161
|
assets: [],
|
|
73
162
|
nonce,
|
|
@@ -75,9 +164,26 @@ function renderToString(code, options = {}) {
|
|
|
75
164
|
resolve: resolveSSRNode,
|
|
76
165
|
ssr: ssr,
|
|
77
166
|
serialize(id, p) {
|
|
78
|
-
|
|
167
|
+
if (solidJs.sharedConfig.context.noHydrate) return;
|
|
168
|
+
if (p != null && typeof p === "object" && (typeof p.then === "function" || typeof p[Symbol.asyncIterator] === "function")) {
|
|
169
|
+
throw new Error("Cannot serialize async value in renderToString (id: " + id + "). " + "Use renderToStream for async data.");
|
|
170
|
+
}
|
|
171
|
+
serializer.write(id, p);
|
|
172
|
+
},
|
|
173
|
+
registerAsset(type, url) {
|
|
174
|
+
if (tracking.currentBoundaryId && type === "style") {
|
|
175
|
+
let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
|
|
176
|
+
if (!styles) {
|
|
177
|
+
styles = new Set();
|
|
178
|
+
tracking.boundaryStyles.set(tracking.currentBoundaryId, styles);
|
|
179
|
+
}
|
|
180
|
+
styles.add(url);
|
|
181
|
+
}
|
|
182
|
+
tracking.emittedAssets.add(url);
|
|
79
183
|
}
|
|
80
184
|
};
|
|
185
|
+
applyAssetTracking(solidJs.sharedConfig.context, tracking, manifest);
|
|
186
|
+
registerEntryAssets(manifest);
|
|
81
187
|
let html = solidJs.createRoot(d => {
|
|
82
188
|
setTimeout(d);
|
|
83
189
|
return resolveSSRSync(escape(code()));
|
|
@@ -87,6 +193,7 @@ function renderToString(code, options = {}) {
|
|
|
87
193
|
solidJs.sharedConfig.context.noHydrate = true;
|
|
88
194
|
serializer.close();
|
|
89
195
|
html = injectAssets(solidJs.sharedConfig.context.assets, html);
|
|
196
|
+
html = injectPreloadLinks(tracking.emittedAssets, html);
|
|
90
197
|
if (scripts.length) html = injectScripts(html, scripts, options.nonce);
|
|
91
198
|
return html;
|
|
92
199
|
}
|
|
@@ -96,10 +203,11 @@ function renderToStream(code, options = {}) {
|
|
|
96
203
|
onCompleteShell,
|
|
97
204
|
onCompleteAll,
|
|
98
205
|
renderId = "",
|
|
99
|
-
noScripts
|
|
206
|
+
noScripts,
|
|
207
|
+
manifest
|
|
100
208
|
} = options;
|
|
101
209
|
let dispose;
|
|
102
|
-
const blockingPromises =
|
|
210
|
+
const blockingPromises = new Set();
|
|
103
211
|
const pushTask = task => {
|
|
104
212
|
if (noScripts) return;
|
|
105
213
|
if (!tasks && !firstFlushed) {
|
|
@@ -124,6 +232,7 @@ function renderToStream(code, options = {}) {
|
|
|
124
232
|
};
|
|
125
233
|
const serializer = createSerializer({
|
|
126
234
|
scopeId: options.renderId,
|
|
235
|
+
plugins: options.plugins,
|
|
127
236
|
onData: pushTask,
|
|
128
237
|
onDone,
|
|
129
238
|
onError: options.onError
|
|
@@ -150,18 +259,38 @@ function renderToStream(code, options = {}) {
|
|
|
150
259
|
let completed = false;
|
|
151
260
|
let shellCompleted = false;
|
|
152
261
|
let scriptFlushed = false;
|
|
262
|
+
let headStyles;
|
|
153
263
|
let timer = null;
|
|
264
|
+
let rootHoles = null;
|
|
265
|
+
let nextHoleId = 0;
|
|
154
266
|
let buffer = {
|
|
155
267
|
write(payload) {
|
|
156
268
|
tmp += payload;
|
|
157
269
|
}
|
|
158
270
|
};
|
|
271
|
+
const tracking = createAssetTracking();
|
|
159
272
|
solidJs.sharedConfig.context = context = {
|
|
160
273
|
async: true,
|
|
161
274
|
assets: [],
|
|
162
275
|
nonce,
|
|
276
|
+
registerAsset(type, url) {
|
|
277
|
+
if (tracking.currentBoundaryId && type === "style") {
|
|
278
|
+
let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
|
|
279
|
+
if (!styles) {
|
|
280
|
+
styles = new Set();
|
|
281
|
+
tracking.boundaryStyles.set(tracking.currentBoundaryId, styles);
|
|
282
|
+
}
|
|
283
|
+
styles.add(url);
|
|
284
|
+
}
|
|
285
|
+
if (!tracking.emittedAssets.has(url)) {
|
|
286
|
+
tracking.emittedAssets.add(url);
|
|
287
|
+
if (firstFlushed && type === "module") {
|
|
288
|
+
buffer.write(`<link rel="modulepreload" href="${url}">`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
},
|
|
163
292
|
block(p) {
|
|
164
|
-
if (!firstFlushed) blockingPromises.
|
|
293
|
+
if (!firstFlushed) blockingPromises.add(p);
|
|
165
294
|
},
|
|
166
295
|
replace(id, payloadFn) {
|
|
167
296
|
if (firstFlushed) return;
|
|
@@ -171,16 +300,12 @@ function renderToStream(code, options = {}) {
|
|
|
171
300
|
const last = html.indexOf(`<!--!$/${id}-->`, first + placeholder.length);
|
|
172
301
|
html = html.slice(0, first) + resolveSSRSync(escape(payloadFn())) + html.slice(last + placeholder.length + 1);
|
|
173
302
|
},
|
|
174
|
-
serialize(id, p,
|
|
175
|
-
|
|
176
|
-
if (!firstFlushed &&
|
|
177
|
-
blockingPromises.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}).catch(e => {
|
|
181
|
-
serializer.write(id, e);
|
|
182
|
-
});
|
|
183
|
-
} else if (!serverOnly) serializer.write(id, p);
|
|
303
|
+
serialize(id, p, deferStream) {
|
|
304
|
+
if (solidJs.sharedConfig.context.noHydrate) return;
|
|
305
|
+
if (!firstFlushed && deferStream && typeof p === "object" && "then" in p) {
|
|
306
|
+
blockingPromises.add(p);
|
|
307
|
+
p.then(d => serializer.write(id, d)).catch(e => serializer.write(id, e));
|
|
308
|
+
} else serializer.write(id, p);
|
|
184
309
|
},
|
|
185
310
|
escape: escape,
|
|
186
311
|
resolve: resolveSSRNode,
|
|
@@ -211,18 +336,33 @@ function renderToStream(code, options = {}) {
|
|
|
211
336
|
const parent = registry.get(parentKey);
|
|
212
337
|
parent.children ||= {};
|
|
213
338
|
parent.children[key] = value !== undefined ? value : "";
|
|
339
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
340
|
+
propagateBoundaryStyles(key, parentKey, tracking);
|
|
214
341
|
item.resolve();
|
|
215
342
|
return;
|
|
216
343
|
}
|
|
217
344
|
if (!completed) {
|
|
218
345
|
if (!firstFlushed) {
|
|
219
346
|
queue(() => html = replacePlaceholder(html, key, value !== undefined ? value : ""));
|
|
347
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
220
348
|
item.resolve(error);
|
|
221
349
|
} else {
|
|
222
|
-
|
|
223
|
-
|
|
350
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
351
|
+
const styles = collectStreamStyles(key, tracking, headStyles);
|
|
352
|
+
if (styles.length) {
|
|
353
|
+
pushTask(`$dfs("${key}",${styles.length})${!scriptFlushed ? ";" + REPLACE_SCRIPT : ""}`);
|
|
354
|
+
scriptFlushed = true;
|
|
355
|
+
writeTasks();
|
|
356
|
+
for (const url of styles) {
|
|
357
|
+
buffer.write(`<link rel="stylesheet" href="${url}" onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
|
|
358
|
+
}
|
|
359
|
+
buffer.write(`<template id="${key}">${value !== undefined ? value : " "}</template>`);
|
|
360
|
+
} else {
|
|
361
|
+
buffer.write(`<template id="${key}">${value !== undefined ? value : " "}</template>`);
|
|
362
|
+
pushTask(`$df("${key}")${!scriptFlushed ? ";" + REPLACE_SCRIPT : ""}`);
|
|
363
|
+
scriptFlushed = true;
|
|
364
|
+
}
|
|
224
365
|
item.resolve(error);
|
|
225
|
-
scriptFlushed = true;
|
|
226
366
|
}
|
|
227
367
|
}
|
|
228
368
|
}
|
|
@@ -230,16 +370,47 @@ function renderToStream(code, options = {}) {
|
|
|
230
370
|
};
|
|
231
371
|
}
|
|
232
372
|
};
|
|
373
|
+
applyAssetTracking(context, tracking, manifest);
|
|
374
|
+
registerEntryAssets(manifest);
|
|
233
375
|
let html = solidJs.createRoot(d => {
|
|
234
376
|
dispose = d;
|
|
235
|
-
|
|
377
|
+
const res = resolveSSRNode(escape(code()));
|
|
378
|
+
if (!res.h.length) return res.t[0];
|
|
379
|
+
rootHoles = [];
|
|
380
|
+
let out = res.t[0];
|
|
381
|
+
for (let i = 0; i < res.h.length; i++) {
|
|
382
|
+
const id = nextHoleId++;
|
|
383
|
+
rootHoles.push({
|
|
384
|
+
id,
|
|
385
|
+
fn: res.h[i]
|
|
386
|
+
});
|
|
387
|
+
out += `<!--rh${id}-->` + res.t[i + 1];
|
|
388
|
+
}
|
|
389
|
+
for (const p of res.p) blockingPromises.add(p);
|
|
390
|
+
return out;
|
|
236
391
|
}, {
|
|
237
392
|
id: renderId
|
|
238
393
|
});
|
|
239
394
|
function doShell() {
|
|
240
395
|
if (shellCompleted) return;
|
|
396
|
+
if (rootHoles) {
|
|
397
|
+
for (const {
|
|
398
|
+
id,
|
|
399
|
+
fn
|
|
400
|
+
} of rootHoles) {
|
|
401
|
+
const marker = `<!--rh${id}-->`;
|
|
402
|
+
const res = resolveSSRNode(fn);
|
|
403
|
+
html = html.replace(marker, !res.h.length ? res.t[0] : "");
|
|
404
|
+
}
|
|
405
|
+
rootHoles = null;
|
|
406
|
+
}
|
|
241
407
|
solidJs.sharedConfig.context = context;
|
|
242
408
|
html = injectAssets(context.assets, html);
|
|
409
|
+
headStyles = new Set();
|
|
410
|
+
for (const url of tracking.emittedAssets) {
|
|
411
|
+
if (url.endsWith(".css")) headStyles.add(url);
|
|
412
|
+
}
|
|
413
|
+
html = injectPreloadLinks(tracking.emittedAssets, html);
|
|
243
414
|
if (tasks.length) html = injectScripts(html, tasks, nonce);
|
|
244
415
|
buffer.write(html);
|
|
245
416
|
tasks = "";
|
|
@@ -290,13 +461,13 @@ function renderToStream(code, options = {}) {
|
|
|
290
461
|
writable = {
|
|
291
462
|
end() {
|
|
292
463
|
writer.releaseLock();
|
|
293
|
-
w.close();
|
|
464
|
+
w.close().catch(() => {});
|
|
294
465
|
resolve();
|
|
295
466
|
}
|
|
296
467
|
};
|
|
297
468
|
buffer = {
|
|
298
469
|
write(payload) {
|
|
299
|
-
writer.write(encoder.encode(payload));
|
|
470
|
+
writer.write(encoder.encode(payload)).catch(() => {});
|
|
300
471
|
}
|
|
301
472
|
};
|
|
302
473
|
buffer.write(tmp);
|
|
@@ -514,9 +685,9 @@ function queue(fn) {
|
|
|
514
685
|
return Promise.resolve().then(fn);
|
|
515
686
|
}
|
|
516
687
|
function allSettled(promises) {
|
|
517
|
-
let
|
|
688
|
+
let size = promises.size;
|
|
518
689
|
return Promise.allSettled(promises).then(() => {
|
|
519
|
-
if (promises.
|
|
690
|
+
if (promises.size !== size) return allSettled(promises);
|
|
520
691
|
return;
|
|
521
692
|
});
|
|
522
693
|
}
|
|
@@ -528,6 +699,48 @@ function injectAssets(assets, html) {
|
|
|
528
699
|
if (index === -1) return html;
|
|
529
700
|
return html.slice(0, index) + out + html.slice(index);
|
|
530
701
|
}
|
|
702
|
+
function injectPreloadLinks(emittedAssets, html, nonce) {
|
|
703
|
+
if (!emittedAssets.size) return html;
|
|
704
|
+
let links = "";
|
|
705
|
+
for (const url of emittedAssets) {
|
|
706
|
+
if (url.endsWith(".css")) {
|
|
707
|
+
links += `<link rel="stylesheet" href="${url}">`;
|
|
708
|
+
} else {
|
|
709
|
+
links += `<link rel="modulepreload" href="${url}">`;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
const index = html.indexOf("</head>");
|
|
713
|
+
if (index === -1) return html;
|
|
714
|
+
return html.slice(0, index) + links + html.slice(index);
|
|
715
|
+
}
|
|
716
|
+
function serializeFragmentAssets(key, boundaryModules, context) {
|
|
717
|
+
const map = boundaryModules.get(key);
|
|
718
|
+
if (!map || !Object.keys(map).length) return;
|
|
719
|
+
context.serialize(key + "_assets", map);
|
|
720
|
+
}
|
|
721
|
+
function propagateBoundaryStyles(childKey, parentKey, tracking) {
|
|
722
|
+
const childStyles = tracking.getBoundaryStyles(childKey);
|
|
723
|
+
if (!childStyles) return;
|
|
724
|
+
let parentStyles = tracking.boundaryStyles.get(parentKey);
|
|
725
|
+
if (!parentStyles) {
|
|
726
|
+
parentStyles = new Set();
|
|
727
|
+
tracking.boundaryStyles.set(parentKey, parentStyles);
|
|
728
|
+
}
|
|
729
|
+
for (const url of childStyles) {
|
|
730
|
+
parentStyles.add(url);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
function collectStreamStyles(key, tracking, headStyles) {
|
|
734
|
+
const styles = tracking.getBoundaryStyles(key);
|
|
735
|
+
if (!styles) return [];
|
|
736
|
+
const result = [];
|
|
737
|
+
for (const url of styles) {
|
|
738
|
+
if (!headStyles || !headStyles.has(url)) {
|
|
739
|
+
result.push(url);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
return result;
|
|
743
|
+
}
|
|
531
744
|
function injectScripts(html, scripts, nonce) {
|
|
532
745
|
const tag = `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts}</script>`;
|
|
533
746
|
const index = html.indexOf("<!--xs-->");
|
|
@@ -618,14 +831,14 @@ function resolveSSRNode(node, result = {
|
|
|
618
831
|
function resolveSSRSync(node) {
|
|
619
832
|
const res = resolveSSRNode(node);
|
|
620
833
|
if (!res.h.length) return res.t[0];
|
|
621
|
-
throw new Error("This value cannot be rendered synchronously. Are you missing a
|
|
834
|
+
throw new Error("This value cannot be rendered synchronously. Are you missing a boundary?");
|
|
622
835
|
}
|
|
623
836
|
const RequestContext = Symbol();
|
|
624
837
|
function getRequestEvent() {
|
|
625
838
|
return globalThis[RequestContext] ? globalThis[RequestContext].getStore() || solidJs.sharedConfig.context && solidJs.sharedConfig.context.event || console.log("RequestEvent is missing. This is most likely due to accessing `getRequestEvent` non-managed async scope in a partially polyfilled environment. Try moving it above all `await` calls.") : undefined;
|
|
626
839
|
}
|
|
627
840
|
function renderToStringAsync(code, options = {}) {
|
|
628
|
-
return renderToStream(code, options).then(
|
|
841
|
+
return new Promise(resolve => renderToStream(code, options).then(resolve));
|
|
629
842
|
}
|
|
630
843
|
function notSup() {
|
|
631
844
|
throw new Error("Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with <Show>.");
|