@solidjs/web 2.0.0-experimental.13 → 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 +249 -36
- package/dist/server.js +245 -32
- 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/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createMemo, sharedConfig, createRoot, ssrHandleError, omit } from 'solid-js';
|
|
2
|
-
export {
|
|
3
|
-
import {
|
|
2
|
+
export { Errored, For, Loading, Match, Repeat, Show, Switch, createComponent, createRenderEffect as effect, getOwner, ssrRunInScope, untrack } from 'solid-js';
|
|
3
|
+
import { Serializer, Feature, getCrossReferenceHeader } from 'seroval';
|
|
4
4
|
import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
|
|
5
5
|
|
|
6
6
|
const Properties = /*#__PURE__*/new Set([
|
|
@@ -29,13 +29,16 @@ function createSerializer({
|
|
|
29
29
|
onData,
|
|
30
30
|
onDone,
|
|
31
31
|
scopeId,
|
|
32
|
-
onError
|
|
32
|
+
onError,
|
|
33
|
+
plugins: customPlugins
|
|
33
34
|
}) {
|
|
35
|
+
const defaultPlugins = [AbortSignalPlugin,
|
|
36
|
+
CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
|
|
37
|
+
FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin];
|
|
38
|
+
const allPlugins = customPlugins ? [...customPlugins, ...defaultPlugins] : defaultPlugins;
|
|
34
39
|
return new Serializer({
|
|
35
40
|
scopeId,
|
|
36
|
-
plugins:
|
|
37
|
-
CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
|
|
38
|
-
FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin],
|
|
41
|
+
plugins: allPlugins,
|
|
39
42
|
globalIdentifier: GLOBAL_IDENTIFIER,
|
|
40
43
|
disabledFeatures: ES2017FLAG,
|
|
41
44
|
onData,
|
|
@@ -47,17 +50,102 @@ function getLocalHeaderScript(id) {
|
|
|
47
50
|
return getCrossReferenceHeader(id) + ';';
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
function resolveAssets(moduleUrl, manifest) {
|
|
54
|
+
if (!manifest) return null;
|
|
55
|
+
const entry = manifest[moduleUrl];
|
|
56
|
+
if (!entry) return null;
|
|
57
|
+
const css = [];
|
|
58
|
+
const js = [];
|
|
59
|
+
const visited = new Set();
|
|
60
|
+
const walk = key => {
|
|
61
|
+
if (visited.has(key)) return;
|
|
62
|
+
visited.add(key);
|
|
63
|
+
const e = manifest[key];
|
|
64
|
+
if (!e) return;
|
|
65
|
+
js.push(e.file);
|
|
66
|
+
if (e.css) for (let i = 0; i < e.css.length; i++) css.push(e.css[i]);
|
|
67
|
+
if (e.imports) for (let i = 0; i < e.imports.length; i++) walk(e.imports[i]);
|
|
68
|
+
};
|
|
69
|
+
walk(moduleUrl);
|
|
70
|
+
return {
|
|
71
|
+
js,
|
|
72
|
+
css
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function registerEntryAssets(manifest) {
|
|
76
|
+
if (!manifest) return;
|
|
77
|
+
const ctx = sharedConfig.context;
|
|
78
|
+
if (!ctx?.registerAsset) return;
|
|
79
|
+
for (const key in manifest) {
|
|
80
|
+
if (manifest[key].isEntry) {
|
|
81
|
+
const assets = resolveAssets(key, manifest);
|
|
82
|
+
if (assets) {
|
|
83
|
+
for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]);
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function createAssetTracking() {
|
|
90
|
+
const boundaryModules = new Map();
|
|
91
|
+
const boundaryStyles = new Map();
|
|
92
|
+
const emittedAssets = new Set();
|
|
93
|
+
let currentBoundaryId = null;
|
|
94
|
+
return {
|
|
95
|
+
boundaryModules,
|
|
96
|
+
boundaryStyles,
|
|
97
|
+
emittedAssets,
|
|
98
|
+
get currentBoundaryId() {
|
|
99
|
+
return currentBoundaryId;
|
|
100
|
+
},
|
|
101
|
+
set currentBoundaryId(v) {
|
|
102
|
+
currentBoundaryId = v;
|
|
103
|
+
},
|
|
104
|
+
registerModule(moduleUrl, entryUrl) {
|
|
105
|
+
if (!currentBoundaryId) return;
|
|
106
|
+
let map = boundaryModules.get(currentBoundaryId);
|
|
107
|
+
if (!map) {
|
|
108
|
+
map = {};
|
|
109
|
+
boundaryModules.set(currentBoundaryId, map);
|
|
110
|
+
}
|
|
111
|
+
map[moduleUrl] = entryUrl;
|
|
112
|
+
},
|
|
113
|
+
getBoundaryModules(id) {
|
|
114
|
+
return boundaryModules.get(id) || null;
|
|
115
|
+
},
|
|
116
|
+
getBoundaryStyles(id) {
|
|
117
|
+
return boundaryStyles.get(id) || null;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function applyAssetTracking(context, tracking, manifest) {
|
|
122
|
+
Object.defineProperty(context, "_currentBoundaryId", {
|
|
123
|
+
get() {
|
|
124
|
+
return tracking.currentBoundaryId;
|
|
125
|
+
},
|
|
126
|
+
set(v) {
|
|
127
|
+
tracking.currentBoundaryId = v;
|
|
128
|
+
},
|
|
129
|
+
configurable: true,
|
|
130
|
+
enumerable: true
|
|
131
|
+
});
|
|
132
|
+
context.registerModule = tracking.registerModule;
|
|
133
|
+
context.getBoundaryModules = tracking.getBoundaryModules;
|
|
134
|
+
if (manifest) context.resolveAssets = moduleUrl => resolveAssets(moduleUrl, manifest);
|
|
135
|
+
}
|
|
50
136
|
const VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i;
|
|
51
|
-
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)}`;
|
|
137
|
+
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)}`;
|
|
52
138
|
function renderToString(code, options = {}) {
|
|
53
139
|
const {
|
|
54
140
|
renderId = "",
|
|
55
141
|
nonce,
|
|
56
|
-
noScripts
|
|
142
|
+
noScripts,
|
|
143
|
+
manifest
|
|
57
144
|
} = options;
|
|
58
145
|
let scripts = "";
|
|
59
146
|
const serializer = createSerializer({
|
|
60
147
|
scopeId: renderId,
|
|
148
|
+
plugins: options.plugins,
|
|
61
149
|
onData(script) {
|
|
62
150
|
if (noScripts) return;
|
|
63
151
|
if (!scripts) {
|
|
@@ -67,6 +155,7 @@ function renderToString(code, options = {}) {
|
|
|
67
155
|
},
|
|
68
156
|
onError: options.onError
|
|
69
157
|
});
|
|
158
|
+
const tracking = createAssetTracking();
|
|
70
159
|
sharedConfig.context = {
|
|
71
160
|
assets: [],
|
|
72
161
|
nonce,
|
|
@@ -74,9 +163,26 @@ function renderToString(code, options = {}) {
|
|
|
74
163
|
resolve: resolveSSRNode,
|
|
75
164
|
ssr: ssr,
|
|
76
165
|
serialize(id, p) {
|
|
77
|
-
|
|
166
|
+
if (sharedConfig.context.noHydrate) return;
|
|
167
|
+
if (p != null && typeof p === "object" && (typeof p.then === "function" || typeof p[Symbol.asyncIterator] === "function")) {
|
|
168
|
+
throw new Error("Cannot serialize async value in renderToString (id: " + id + "). " + "Use renderToStream for async data.");
|
|
169
|
+
}
|
|
170
|
+
serializer.write(id, p);
|
|
171
|
+
},
|
|
172
|
+
registerAsset(type, url) {
|
|
173
|
+
if (tracking.currentBoundaryId && type === "style") {
|
|
174
|
+
let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
|
|
175
|
+
if (!styles) {
|
|
176
|
+
styles = new Set();
|
|
177
|
+
tracking.boundaryStyles.set(tracking.currentBoundaryId, styles);
|
|
178
|
+
}
|
|
179
|
+
styles.add(url);
|
|
180
|
+
}
|
|
181
|
+
tracking.emittedAssets.add(url);
|
|
78
182
|
}
|
|
79
183
|
};
|
|
184
|
+
applyAssetTracking(sharedConfig.context, tracking, manifest);
|
|
185
|
+
registerEntryAssets(manifest);
|
|
80
186
|
let html = createRoot(d => {
|
|
81
187
|
setTimeout(d);
|
|
82
188
|
return resolveSSRSync(escape(code()));
|
|
@@ -86,6 +192,7 @@ function renderToString(code, options = {}) {
|
|
|
86
192
|
sharedConfig.context.noHydrate = true;
|
|
87
193
|
serializer.close();
|
|
88
194
|
html = injectAssets(sharedConfig.context.assets, html);
|
|
195
|
+
html = injectPreloadLinks(tracking.emittedAssets, html);
|
|
89
196
|
if (scripts.length) html = injectScripts(html, scripts, options.nonce);
|
|
90
197
|
return html;
|
|
91
198
|
}
|
|
@@ -95,10 +202,11 @@ function renderToStream(code, options = {}) {
|
|
|
95
202
|
onCompleteShell,
|
|
96
203
|
onCompleteAll,
|
|
97
204
|
renderId = "",
|
|
98
|
-
noScripts
|
|
205
|
+
noScripts,
|
|
206
|
+
manifest
|
|
99
207
|
} = options;
|
|
100
208
|
let dispose;
|
|
101
|
-
const blockingPromises =
|
|
209
|
+
const blockingPromises = new Set();
|
|
102
210
|
const pushTask = task => {
|
|
103
211
|
if (noScripts) return;
|
|
104
212
|
if (!tasks && !firstFlushed) {
|
|
@@ -123,6 +231,7 @@ function renderToStream(code, options = {}) {
|
|
|
123
231
|
};
|
|
124
232
|
const serializer = createSerializer({
|
|
125
233
|
scopeId: options.renderId,
|
|
234
|
+
plugins: options.plugins,
|
|
126
235
|
onData: pushTask,
|
|
127
236
|
onDone,
|
|
128
237
|
onError: options.onError
|
|
@@ -149,18 +258,38 @@ function renderToStream(code, options = {}) {
|
|
|
149
258
|
let completed = false;
|
|
150
259
|
let shellCompleted = false;
|
|
151
260
|
let scriptFlushed = false;
|
|
261
|
+
let headStyles;
|
|
152
262
|
let timer = null;
|
|
263
|
+
let rootHoles = null;
|
|
264
|
+
let nextHoleId = 0;
|
|
153
265
|
let buffer = {
|
|
154
266
|
write(payload) {
|
|
155
267
|
tmp += payload;
|
|
156
268
|
}
|
|
157
269
|
};
|
|
270
|
+
const tracking = createAssetTracking();
|
|
158
271
|
sharedConfig.context = context = {
|
|
159
272
|
async: true,
|
|
160
273
|
assets: [],
|
|
161
274
|
nonce,
|
|
275
|
+
registerAsset(type, url) {
|
|
276
|
+
if (tracking.currentBoundaryId && type === "style") {
|
|
277
|
+
let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
|
|
278
|
+
if (!styles) {
|
|
279
|
+
styles = new Set();
|
|
280
|
+
tracking.boundaryStyles.set(tracking.currentBoundaryId, styles);
|
|
281
|
+
}
|
|
282
|
+
styles.add(url);
|
|
283
|
+
}
|
|
284
|
+
if (!tracking.emittedAssets.has(url)) {
|
|
285
|
+
tracking.emittedAssets.add(url);
|
|
286
|
+
if (firstFlushed && type === "module") {
|
|
287
|
+
buffer.write(`<link rel="modulepreload" href="${url}">`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
},
|
|
162
291
|
block(p) {
|
|
163
|
-
if (!firstFlushed) blockingPromises.
|
|
292
|
+
if (!firstFlushed) blockingPromises.add(p);
|
|
164
293
|
},
|
|
165
294
|
replace(id, payloadFn) {
|
|
166
295
|
if (firstFlushed) return;
|
|
@@ -170,16 +299,12 @@ function renderToStream(code, options = {}) {
|
|
|
170
299
|
const last = html.indexOf(`<!--!$/${id}-->`, first + placeholder.length);
|
|
171
300
|
html = html.slice(0, first) + resolveSSRSync(escape(payloadFn())) + html.slice(last + placeholder.length + 1);
|
|
172
301
|
},
|
|
173
|
-
serialize(id, p,
|
|
174
|
-
|
|
175
|
-
if (!firstFlushed &&
|
|
176
|
-
blockingPromises.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}).catch(e => {
|
|
180
|
-
serializer.write(id, e);
|
|
181
|
-
});
|
|
182
|
-
} else if (!serverOnly) serializer.write(id, p);
|
|
302
|
+
serialize(id, p, deferStream) {
|
|
303
|
+
if (sharedConfig.context.noHydrate) return;
|
|
304
|
+
if (!firstFlushed && deferStream && typeof p === "object" && "then" in p) {
|
|
305
|
+
blockingPromises.add(p);
|
|
306
|
+
p.then(d => serializer.write(id, d)).catch(e => serializer.write(id, e));
|
|
307
|
+
} else serializer.write(id, p);
|
|
183
308
|
},
|
|
184
309
|
escape: escape,
|
|
185
310
|
resolve: resolveSSRNode,
|
|
@@ -210,18 +335,33 @@ function renderToStream(code, options = {}) {
|
|
|
210
335
|
const parent = registry.get(parentKey);
|
|
211
336
|
parent.children ||= {};
|
|
212
337
|
parent.children[key] = value !== undefined ? value : "";
|
|
338
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
339
|
+
propagateBoundaryStyles(key, parentKey, tracking);
|
|
213
340
|
item.resolve();
|
|
214
341
|
return;
|
|
215
342
|
}
|
|
216
343
|
if (!completed) {
|
|
217
344
|
if (!firstFlushed) {
|
|
218
345
|
queue(() => html = replacePlaceholder(html, key, value !== undefined ? value : ""));
|
|
346
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
219
347
|
item.resolve(error);
|
|
220
348
|
} else {
|
|
221
|
-
|
|
222
|
-
|
|
349
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
350
|
+
const styles = collectStreamStyles(key, tracking, headStyles);
|
|
351
|
+
if (styles.length) {
|
|
352
|
+
pushTask(`$dfs("${key}",${styles.length})${!scriptFlushed ? ";" + REPLACE_SCRIPT : ""}`);
|
|
353
|
+
scriptFlushed = true;
|
|
354
|
+
writeTasks();
|
|
355
|
+
for (const url of styles) {
|
|
356
|
+
buffer.write(`<link rel="stylesheet" href="${url}" onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
|
|
357
|
+
}
|
|
358
|
+
buffer.write(`<template id="${key}">${value !== undefined ? value : " "}</template>`);
|
|
359
|
+
} else {
|
|
360
|
+
buffer.write(`<template id="${key}">${value !== undefined ? value : " "}</template>`);
|
|
361
|
+
pushTask(`$df("${key}")${!scriptFlushed ? ";" + REPLACE_SCRIPT : ""}`);
|
|
362
|
+
scriptFlushed = true;
|
|
363
|
+
}
|
|
223
364
|
item.resolve(error);
|
|
224
|
-
scriptFlushed = true;
|
|
225
365
|
}
|
|
226
366
|
}
|
|
227
367
|
}
|
|
@@ -229,16 +369,47 @@ function renderToStream(code, options = {}) {
|
|
|
229
369
|
};
|
|
230
370
|
}
|
|
231
371
|
};
|
|
372
|
+
applyAssetTracking(context, tracking, manifest);
|
|
373
|
+
registerEntryAssets(manifest);
|
|
232
374
|
let html = createRoot(d => {
|
|
233
375
|
dispose = d;
|
|
234
|
-
|
|
376
|
+
const res = resolveSSRNode(escape(code()));
|
|
377
|
+
if (!res.h.length) return res.t[0];
|
|
378
|
+
rootHoles = [];
|
|
379
|
+
let out = res.t[0];
|
|
380
|
+
for (let i = 0; i < res.h.length; i++) {
|
|
381
|
+
const id = nextHoleId++;
|
|
382
|
+
rootHoles.push({
|
|
383
|
+
id,
|
|
384
|
+
fn: res.h[i]
|
|
385
|
+
});
|
|
386
|
+
out += `<!--rh${id}-->` + res.t[i + 1];
|
|
387
|
+
}
|
|
388
|
+
for (const p of res.p) blockingPromises.add(p);
|
|
389
|
+
return out;
|
|
235
390
|
}, {
|
|
236
391
|
id: renderId
|
|
237
392
|
});
|
|
238
393
|
function doShell() {
|
|
239
394
|
if (shellCompleted) return;
|
|
395
|
+
if (rootHoles) {
|
|
396
|
+
for (const {
|
|
397
|
+
id,
|
|
398
|
+
fn
|
|
399
|
+
} of rootHoles) {
|
|
400
|
+
const marker = `<!--rh${id}-->`;
|
|
401
|
+
const res = resolveSSRNode(fn);
|
|
402
|
+
html = html.replace(marker, !res.h.length ? res.t[0] : "");
|
|
403
|
+
}
|
|
404
|
+
rootHoles = null;
|
|
405
|
+
}
|
|
240
406
|
sharedConfig.context = context;
|
|
241
407
|
html = injectAssets(context.assets, html);
|
|
408
|
+
headStyles = new Set();
|
|
409
|
+
for (const url of tracking.emittedAssets) {
|
|
410
|
+
if (url.endsWith(".css")) headStyles.add(url);
|
|
411
|
+
}
|
|
412
|
+
html = injectPreloadLinks(tracking.emittedAssets, html);
|
|
242
413
|
if (tasks.length) html = injectScripts(html, tasks, nonce);
|
|
243
414
|
buffer.write(html);
|
|
244
415
|
tasks = "";
|
|
@@ -289,13 +460,13 @@ function renderToStream(code, options = {}) {
|
|
|
289
460
|
writable = {
|
|
290
461
|
end() {
|
|
291
462
|
writer.releaseLock();
|
|
292
|
-
w.close();
|
|
463
|
+
w.close().catch(() => {});
|
|
293
464
|
resolve();
|
|
294
465
|
}
|
|
295
466
|
};
|
|
296
467
|
buffer = {
|
|
297
468
|
write(payload) {
|
|
298
|
-
writer.write(encoder.encode(payload));
|
|
469
|
+
writer.write(encoder.encode(payload)).catch(() => {});
|
|
299
470
|
}
|
|
300
471
|
};
|
|
301
472
|
buffer.write(tmp);
|
|
@@ -513,9 +684,9 @@ function queue(fn) {
|
|
|
513
684
|
return Promise.resolve().then(fn);
|
|
514
685
|
}
|
|
515
686
|
function allSettled(promises) {
|
|
516
|
-
let
|
|
687
|
+
let size = promises.size;
|
|
517
688
|
return Promise.allSettled(promises).then(() => {
|
|
518
|
-
if (promises.
|
|
689
|
+
if (promises.size !== size) return allSettled(promises);
|
|
519
690
|
return;
|
|
520
691
|
});
|
|
521
692
|
}
|
|
@@ -527,6 +698,48 @@ function injectAssets(assets, html) {
|
|
|
527
698
|
if (index === -1) return html;
|
|
528
699
|
return html.slice(0, index) + out + html.slice(index);
|
|
529
700
|
}
|
|
701
|
+
function injectPreloadLinks(emittedAssets, html, nonce) {
|
|
702
|
+
if (!emittedAssets.size) return html;
|
|
703
|
+
let links = "";
|
|
704
|
+
for (const url of emittedAssets) {
|
|
705
|
+
if (url.endsWith(".css")) {
|
|
706
|
+
links += `<link rel="stylesheet" href="${url}">`;
|
|
707
|
+
} else {
|
|
708
|
+
links += `<link rel="modulepreload" href="${url}">`;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
const index = html.indexOf("</head>");
|
|
712
|
+
if (index === -1) return html;
|
|
713
|
+
return html.slice(0, index) + links + html.slice(index);
|
|
714
|
+
}
|
|
715
|
+
function serializeFragmentAssets(key, boundaryModules, context) {
|
|
716
|
+
const map = boundaryModules.get(key);
|
|
717
|
+
if (!map || !Object.keys(map).length) return;
|
|
718
|
+
context.serialize(key + "_assets", map);
|
|
719
|
+
}
|
|
720
|
+
function propagateBoundaryStyles(childKey, parentKey, tracking) {
|
|
721
|
+
const childStyles = tracking.getBoundaryStyles(childKey);
|
|
722
|
+
if (!childStyles) return;
|
|
723
|
+
let parentStyles = tracking.boundaryStyles.get(parentKey);
|
|
724
|
+
if (!parentStyles) {
|
|
725
|
+
parentStyles = new Set();
|
|
726
|
+
tracking.boundaryStyles.set(parentKey, parentStyles);
|
|
727
|
+
}
|
|
728
|
+
for (const url of childStyles) {
|
|
729
|
+
parentStyles.add(url);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function collectStreamStyles(key, tracking, headStyles) {
|
|
733
|
+
const styles = tracking.getBoundaryStyles(key);
|
|
734
|
+
if (!styles) return [];
|
|
735
|
+
const result = [];
|
|
736
|
+
for (const url of styles) {
|
|
737
|
+
if (!headStyles || !headStyles.has(url)) {
|
|
738
|
+
result.push(url);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return result;
|
|
742
|
+
}
|
|
530
743
|
function injectScripts(html, scripts, nonce) {
|
|
531
744
|
const tag = `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts}</script>`;
|
|
532
745
|
const index = html.indexOf("<!--xs-->");
|
|
@@ -617,14 +830,14 @@ function resolveSSRNode(node, result = {
|
|
|
617
830
|
function resolveSSRSync(node) {
|
|
618
831
|
const res = resolveSSRNode(node);
|
|
619
832
|
if (!res.h.length) return res.t[0];
|
|
620
|
-
throw new Error("This value cannot be rendered synchronously. Are you missing a
|
|
833
|
+
throw new Error("This value cannot be rendered synchronously. Are you missing a boundary?");
|
|
621
834
|
}
|
|
622
835
|
const RequestContext = Symbol();
|
|
623
836
|
function getRequestEvent() {
|
|
624
837
|
return globalThis[RequestContext] ? globalThis[RequestContext].getStore() || sharedConfig.context && 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;
|
|
625
838
|
}
|
|
626
839
|
function renderToStringAsync(code, options = {}) {
|
|
627
|
-
return renderToStream(code, options).then(
|
|
840
|
+
return new Promise(resolve => renderToStream(code, options).then(resolve));
|
|
628
841
|
}
|
|
629
842
|
function notSup() {
|
|
630
843
|
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>.");
|
package/dist/web.cjs
CHANGED
|
@@ -226,6 +226,13 @@ function use(fn, element, arg) {
|
|
|
226
226
|
function insert(parent, accessor, marker, initial) {
|
|
227
227
|
const multi = marker !== undefined;
|
|
228
228
|
if (multi && !initial) initial = [];
|
|
229
|
+
if (isHydrating(parent) && Array.isArray(initial)) {
|
|
230
|
+
let j = 0;
|
|
231
|
+
for (let i = 0; i < initial.length; i++) {
|
|
232
|
+
if (initial[i].nodeType === 8 && initial[i].nodeValue === "!$") initial[i].remove();else initial[j++] = initial[i];
|
|
233
|
+
}
|
|
234
|
+
initial.length = j;
|
|
235
|
+
}
|
|
229
236
|
if (typeof accessor !== "function") {
|
|
230
237
|
accessor = normalize(accessor, initial, multi, true);
|
|
231
238
|
if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker);
|
|
@@ -252,11 +259,29 @@ function assign(node, props, isSVG, skipChildren, prevProps = {}, skipRef = fals
|
|
|
252
259
|
function hydrate$1(code, element, options = {}) {
|
|
253
260
|
if (globalThis._$HY.done) return render(code, element, [...element.childNodes], options);
|
|
254
261
|
options.renderId ||= "";
|
|
262
|
+
if (!globalThis._$HY.modules) globalThis._$HY.modules = {};
|
|
263
|
+
if (!globalThis._$HY.loading) globalThis._$HY.loading = {};
|
|
255
264
|
solidJs.sharedConfig.completed = globalThis._$HY.completed;
|
|
256
265
|
solidJs.sharedConfig.events = globalThis._$HY.events;
|
|
257
266
|
solidJs.sharedConfig.load = id => globalThis._$HY.r[id];
|
|
258
267
|
solidJs.sharedConfig.has = id => id in globalThis._$HY.r;
|
|
259
268
|
solidJs.sharedConfig.gather = root => gatherHydratable(element, root);
|
|
269
|
+
solidJs.sharedConfig.cleanupFragment = id => {
|
|
270
|
+
const tpl = document.getElementById("pl-" + id);
|
|
271
|
+
if (tpl) {
|
|
272
|
+
let node = tpl.nextSibling;
|
|
273
|
+
while (node) {
|
|
274
|
+
const next = node.nextSibling;
|
|
275
|
+
if (node.nodeType === 8 && node.nodeValue === "pl-" + id) {
|
|
276
|
+
node.remove();
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
node.remove();
|
|
280
|
+
node = next;
|
|
281
|
+
}
|
|
282
|
+
tpl.remove();
|
|
283
|
+
}
|
|
284
|
+
};
|
|
260
285
|
solidJs.sharedConfig.registry = new Map();
|
|
261
286
|
solidJs.sharedConfig.hydrating = true;
|
|
262
287
|
try {
|
|
@@ -324,7 +349,7 @@ function runHydrationEvents() {
|
|
|
324
349
|
}
|
|
325
350
|
}
|
|
326
351
|
function isHydrating(node) {
|
|
327
|
-
return solidJs.sharedConfig.hydrating &&
|
|
352
|
+
return solidJs.sharedConfig.hydrating && (!node || node.isConnected);
|
|
328
353
|
}
|
|
329
354
|
function toggleClassKey(node, key, value) {
|
|
330
355
|
const classNames = key.trim().split(/\s+/);
|
|
@@ -406,7 +431,6 @@ function eventHandler(e) {
|
|
|
406
431
|
return node || document;
|
|
407
432
|
}
|
|
408
433
|
});
|
|
409
|
-
if (solidJs.sharedConfig.registry && !solidJs.sharedConfig.done) solidJs.sharedConfig.done = _$HY.done = true;
|
|
410
434
|
if (e.composedPath) {
|
|
411
435
|
const path = e.composedPath();
|
|
412
436
|
retarget(path[0]);
|
package/dist/web.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createMemo, createRoot, flatten, untrack,
|
|
1
|
+
import { createMemo, sharedConfig, createRenderEffect, createRoot, flatten, untrack, omit, 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([
|
|
@@ -225,6 +225,13 @@ function use(fn, element, arg) {
|
|
|
225
225
|
function insert(parent, accessor, marker, initial) {
|
|
226
226
|
const multi = marker !== undefined;
|
|
227
227
|
if (multi && !initial) initial = [];
|
|
228
|
+
if (isHydrating(parent) && Array.isArray(initial)) {
|
|
229
|
+
let j = 0;
|
|
230
|
+
for (let i = 0; i < initial.length; i++) {
|
|
231
|
+
if (initial[i].nodeType === 8 && initial[i].nodeValue === "!$") initial[i].remove();else initial[j++] = initial[i];
|
|
232
|
+
}
|
|
233
|
+
initial.length = j;
|
|
234
|
+
}
|
|
228
235
|
if (typeof accessor !== "function") {
|
|
229
236
|
accessor = normalize(accessor, initial, multi, true);
|
|
230
237
|
if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker);
|
|
@@ -251,11 +258,29 @@ function assign(node, props, isSVG, skipChildren, prevProps = {}, skipRef = fals
|
|
|
251
258
|
function hydrate$1(code, element, options = {}) {
|
|
252
259
|
if (globalThis._$HY.done) return render(code, element, [...element.childNodes], options);
|
|
253
260
|
options.renderId ||= "";
|
|
261
|
+
if (!globalThis._$HY.modules) globalThis._$HY.modules = {};
|
|
262
|
+
if (!globalThis._$HY.loading) globalThis._$HY.loading = {};
|
|
254
263
|
sharedConfig.completed = globalThis._$HY.completed;
|
|
255
264
|
sharedConfig.events = globalThis._$HY.events;
|
|
256
265
|
sharedConfig.load = id => globalThis._$HY.r[id];
|
|
257
266
|
sharedConfig.has = id => id in globalThis._$HY.r;
|
|
258
267
|
sharedConfig.gather = root => gatherHydratable(element, root);
|
|
268
|
+
sharedConfig.cleanupFragment = id => {
|
|
269
|
+
const tpl = document.getElementById("pl-" + id);
|
|
270
|
+
if (tpl) {
|
|
271
|
+
let node = tpl.nextSibling;
|
|
272
|
+
while (node) {
|
|
273
|
+
const next = node.nextSibling;
|
|
274
|
+
if (node.nodeType === 8 && node.nodeValue === "pl-" + id) {
|
|
275
|
+
node.remove();
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
node.remove();
|
|
279
|
+
node = next;
|
|
280
|
+
}
|
|
281
|
+
tpl.remove();
|
|
282
|
+
}
|
|
283
|
+
};
|
|
259
284
|
sharedConfig.registry = new Map();
|
|
260
285
|
sharedConfig.hydrating = true;
|
|
261
286
|
try {
|
|
@@ -323,7 +348,7 @@ function runHydrationEvents() {
|
|
|
323
348
|
}
|
|
324
349
|
}
|
|
325
350
|
function isHydrating(node) {
|
|
326
|
-
return sharedConfig.hydrating &&
|
|
351
|
+
return sharedConfig.hydrating && (!node || node.isConnected);
|
|
327
352
|
}
|
|
328
353
|
function toggleClassKey(node, key, value) {
|
|
329
354
|
const classNames = key.trim().split(/\s+/);
|
|
@@ -405,7 +430,6 @@ function eventHandler(e) {
|
|
|
405
430
|
return node || document;
|
|
406
431
|
}
|
|
407
432
|
});
|
|
408
|
-
if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = _$HY.done = true;
|
|
409
433
|
if (e.composedPath) {
|
|
410
434
|
const path = e.composedPath();
|
|
411
435
|
retarget(path[0]);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidjs/web",
|
|
3
3
|
"description": "Solid's web runtime for the browser and the server",
|
|
4
|
-
"version": "2.0.0-experimental.
|
|
4
|
+
"version": "2.0.0-experimental.15",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://solidjs.com",
|
|
@@ -75,10 +75,10 @@
|
|
|
75
75
|
"seroval-plugins": "^1.1.0"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
|
-
"solid-js": "^2.0.0-experimental.
|
|
78
|
+
"solid-js": "^2.0.0-experimental.15"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"solid-js": "2.0.0-experimental.
|
|
81
|
+
"solid-js": "2.0.0-experimental.15"
|
|
82
82
|
},
|
|
83
83
|
"scripts": {
|
|
84
84
|
"build": "npm-run-all -nl build:*",
|
|
@@ -90,7 +90,8 @@
|
|
|
90
90
|
"types:web": "tsc --project ./tsconfig.build.json",
|
|
91
91
|
"types:copy-web": "ncp ../../node_modules/dom-expressions/src/client.d.ts ./types/client.d.ts && ncp ../../node_modules/dom-expressions/src/server.d.ts ./types/server.d.ts",
|
|
92
92
|
"types:web-storage": "tsc --project ./storage/tsconfig.build.json",
|
|
93
|
-
"test": "vitest run",
|
|
93
|
+
"test": "vitest run && vitest run --config vite.config.server.mjs",
|
|
94
|
+
"test:server": "vitest run --config vite.config.server.mjs",
|
|
94
95
|
"coverage": "vitest run --coverage",
|
|
95
96
|
"test-types": "tsc --project tsconfig.test.json"
|
|
96
97
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "dom-expressions/src/client.js";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { hydrate as hydrateCore } from "./client.js";
|
|
2
|
+
import { JSX, ComponentProps, ValidComponent } from "solid-js";
|
|
3
|
+
export * from "./client.js";
|
|
4
|
+
export { For, Show, Switch, Match, Errored, Loading, merge as mergeProps } from "solid-js";
|
|
5
|
+
export * from "./server-mock.js";
|
|
6
|
+
export declare const isServer: boolean;
|
|
7
|
+
export declare const isDev: boolean;
|
|
8
|
+
export declare const hydrate: typeof hydrateCore;
|
|
9
|
+
/**
|
|
10
|
+
* Renders components somewhere else in the DOM
|
|
11
|
+
*
|
|
12
|
+
* Useful for inserting modals and tooltips outside of an cropping layout. If no mount point is given, the portal is inserted in document.body; it is wrapped in a `<div>` unless the target is document.head or `isSVG` is true. setting `useShadow` to true places the element in a shadow root to isolate styles.
|
|
13
|
+
*
|
|
14
|
+
* @description https://docs.solidjs.com/reference/components/portal
|
|
15
|
+
*/
|
|
16
|
+
export declare function Portal<T extends boolean = false, S extends boolean = false>(props: {
|
|
17
|
+
mount?: Element;
|
|
18
|
+
children: JSX.Element;
|
|
19
|
+
}): Text;
|
|
20
|
+
export type DynamicProps<T extends ValidComponent, P = ComponentProps<T>> = {
|
|
21
|
+
[K in keyof P]: P[K];
|
|
22
|
+
} & {
|
|
23
|
+
component: T | undefined;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Renders an arbitrary component or element with the given props
|
|
27
|
+
*
|
|
28
|
+
* This is a lower level version of the `Dynamic` component, useful for
|
|
29
|
+
* performance optimizations in libraries. Do not use this unless you know
|
|
30
|
+
* what you are doing.
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const element = () => multiline() ? 'textarea' : 'input';
|
|
33
|
+
* createDynamic(element, { value: value() });
|
|
34
|
+
* ```
|
|
35
|
+
* @description https://docs.solidjs.com/reference/components/dynamic
|
|
36
|
+
*/
|
|
37
|
+
export declare function createDynamic<T extends ValidComponent>(component: () => T | undefined, props: ComponentProps<T>): JSX.Element;
|
|
38
|
+
/**
|
|
39
|
+
* Renders an arbitrary custom or native component and passes the other props
|
|
40
|
+
* ```typescript
|
|
41
|
+
* <Dynamic component={multiline() ? 'textarea' : 'input'} value={value()} />
|
|
42
|
+
* ```
|
|
43
|
+
* @description https://docs.solidjs.com/reference/components/dynamic
|
|
44
|
+
*/
|
|
45
|
+
export declare function Dynamic<T extends ValidComponent>(props: DynamicProps<T>): JSX.Element;
|