@solidjs/web 2.0.0-beta.32 → 2.0.0-beta.34
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 +58 -16
- package/dist/dev.js +54 -17
- package/dist/server.cjs +714 -75
- package/dist/server.js +711 -78
- package/dist/web.cjs +58 -16
- package/dist/web.js +54 -17
- package/frames/dist/client.cjs +181 -64
- package/frames/dist/client.dev.cjs +185 -64
- package/frames/dist/client.dev.js +183 -62
- package/frames/dist/client.js +179 -62
- package/frames/dist/server.cjs +972 -136
- package/frames/dist/server.js +974 -138
- package/package.json +17 -6
- package/serialization/decode/package.json +20 -0
- package/serialization/dist/decode.cjs +110 -0
- package/serialization/dist/decode.js +104 -0
- package/serialization/dist/serialization.cjs +98 -43
- package/serialization/dist/serialization.js +99 -44
- package/serialization/types/index.d.ts +18 -160
- package/serialization/types/serializer-decode.d.ts +182 -0
- package/serialization/types-cjs/index.d.cts +18 -160
- package/serialization/types-cjs/serializer-decode.d.cts +182 -0
- package/server-functions/dist/client.cjs +101 -105
- package/server-functions/dist/client.js +101 -105
- package/server-functions/dist/server.cjs +131 -107
- package/server-functions/dist/server.dev.cjs +131 -107
- package/server-functions/dist/server.dev.js +132 -108
- package/server-functions/dist/server.js +132 -108
- package/types/client.d.ts +23 -1
- package/types/cookies.d.ts +93 -0
- package/types/core.d.ts +1 -1
- package/types/frames/frame-client.d.ts +26 -0
- package/types/frames/frame-transport.d.ts +1 -1
- package/types/frames/serializer.d.ts +18 -160
- package/types/serializer-decode.d.ts +182 -0
- package/types/serializer.d.ts +18 -160
- package/types/server-functions/client.d.ts +1 -1
- package/types/server-functions/server.d.ts +1 -1
- package/types/server-functions/shared.d.ts +57 -1
- package/types/server.d.ts +21 -1
- package/types-cjs/client.d.cts +23 -1
- package/types-cjs/cookies.d.cts +93 -0
- package/types-cjs/core.d.cts +1 -1
- package/types-cjs/frames/frame-client.d.cts +26 -0
- package/types-cjs/frames/frame-transport.d.cts +1 -1
- package/types-cjs/frames/serializer.d.cts +18 -160
- package/types-cjs/serializer-decode.d.cts +182 -0
- package/types-cjs/serializer.d.cts +18 -160
- package/types-cjs/server-functions/client.d.cts +1 -1
- package/types-cjs/server-functions/server.d.cts +1 -1
- package/types-cjs/server-functions/shared.d.cts +57 -1
- package/types-cjs/server.d.cts +21 -1
package/frames/dist/server.cjs
CHANGED
|
@@ -4,6 +4,98 @@ var solidJs = require('solid-js');
|
|
|
4
4
|
var seroval = require('seroval');
|
|
5
5
|
var web = require('seroval-plugins/web');
|
|
6
6
|
|
|
7
|
+
const STATE = Symbol.for("dom-expressions.container-trace-state");
|
|
8
|
+
const state = globalThis[STATE] || (globalThis[STATE] = {
|
|
9
|
+
materialized: new WeakMap(),
|
|
10
|
+
materializedValues: new WeakSet()
|
|
11
|
+
});
|
|
12
|
+
function setContainerTraceResolver(fn) {
|
|
13
|
+
state.resolveTrace = fn;
|
|
14
|
+
}
|
|
15
|
+
function isContainerTraced(value) {
|
|
16
|
+
const resolve = state.resolveTrace;
|
|
17
|
+
return !!(resolve && value && typeof value === "object" && resolve(value));
|
|
18
|
+
}
|
|
19
|
+
const TRACE = Symbol.for("dom-expressions.container-trace");
|
|
20
|
+
function envelopeContainerTraces(value) {
|
|
21
|
+
if (!state.resolveTrace || value == null || typeof value !== "object") return value;
|
|
22
|
+
const trace = state.resolveTrace(value);
|
|
23
|
+
if (trace) return {
|
|
24
|
+
[TRACE]: trace
|
|
25
|
+
};
|
|
26
|
+
if (Array.isArray(value)) {
|
|
27
|
+
let out = value;
|
|
28
|
+
for (let i = 0; i < value.length; i++) {
|
|
29
|
+
const next = envelopeContainerTraces(value[i]);
|
|
30
|
+
if (next !== value[i]) {
|
|
31
|
+
if (out === value) out = value.slice();
|
|
32
|
+
out[i] = next;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
if (Object.getPrototypeOf(value) === Object.prototype) {
|
|
38
|
+
let out = value;
|
|
39
|
+
for (const key of Object.keys(value)) {
|
|
40
|
+
const next = envelopeContainerTraces(value[key]);
|
|
41
|
+
if (next !== value[key]) {
|
|
42
|
+
if (out === value) out = {
|
|
43
|
+
...value
|
|
44
|
+
};
|
|
45
|
+
out[key] = next;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
function materialize(marker) {
|
|
53
|
+
let value = state.materialized.get(marker.$tr);
|
|
54
|
+
if (value === undefined) {
|
|
55
|
+
value = state.materializeTrace(marker);
|
|
56
|
+
state.materialized.set(marker.$tr, value);
|
|
57
|
+
if (value !== null && typeof value === "object") state.materializedValues.add(value);
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
function parseTrace(value, ctx) {
|
|
62
|
+
const trace = value[TRACE];
|
|
63
|
+
return {
|
|
64
|
+
a: trace.array ? 1 : 0,
|
|
65
|
+
i: ctx.parse(trace.subscribe())
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const ContainerTracePlugin = {
|
|
69
|
+
tag: "dom-expressions/container-trace",
|
|
70
|
+
test(value) {
|
|
71
|
+
return value != null && typeof value === "object" && TRACE in value;
|
|
72
|
+
},
|
|
73
|
+
parse: {
|
|
74
|
+
sync() {
|
|
75
|
+
throw new Error("A reactive container can only be serialized by a streaming serializer.");
|
|
76
|
+
},
|
|
77
|
+
async async(value, ctx) {
|
|
78
|
+
const trace = value[TRACE];
|
|
79
|
+
return {
|
|
80
|
+
a: trace.array ? 1 : 0,
|
|
81
|
+
i: await ctx.parse(trace.subscribe())
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
stream: parseTrace
|
|
85
|
+
},
|
|
86
|
+
serialize(node, ctx) {
|
|
87
|
+
return "{$tr:" + ctx.serialize(node.i) + ",$ta:" + node.a + "}";
|
|
88
|
+
},
|
|
89
|
+
deserialize(node, ctx) {
|
|
90
|
+
const iterable = ctx.deserialize(node.i);
|
|
91
|
+
const marker = {
|
|
92
|
+
$tr: iterable,
|
|
93
|
+
$ta: node.a
|
|
94
|
+
};
|
|
95
|
+
return state.materializeTrace ? materialize(marker) : marker;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
7
99
|
const runWithHydrationScope = (id, fn) => solidJs.runWithOwner(solidJs.createOwner({
|
|
8
100
|
id
|
|
9
101
|
}), fn);
|
|
@@ -11,15 +103,30 @@ const ssrAsyncValue = value => solidJs.createMemo(() => value, {
|
|
|
11
103
|
serialize: false
|
|
12
104
|
});
|
|
13
105
|
|
|
14
|
-
const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
|
|
15
|
-
const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
|
|
16
|
-
const HYDRATION_GLOBAL = "_$HY.r";
|
|
17
106
|
const DEFAULT_WEB_PLUGINS = Object.freeze([web.AbortSignalPlugin,
|
|
18
107
|
web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
|
|
19
|
-
web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin
|
|
108
|
+
web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin,
|
|
109
|
+
ContainerTracePlugin]);
|
|
20
110
|
function resolveSerializerPlugins(customPlugins) {
|
|
21
111
|
return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
|
|
22
112
|
}
|
|
113
|
+
const JSON_CODEC_DISABLED_FEATURES = seroval.Feature.RegExp;
|
|
114
|
+
const JSON_CODEC_DEPTH_LIMIT = 64;
|
|
115
|
+
function resolveCodecOptions({
|
|
116
|
+
plugins,
|
|
117
|
+
disabledFeatures,
|
|
118
|
+
depthLimit
|
|
119
|
+
} = {}) {
|
|
120
|
+
return {
|
|
121
|
+
plugins: resolveSerializerPlugins(plugins),
|
|
122
|
+
disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
|
|
123
|
+
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
|
|
128
|
+
const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
|
|
129
|
+
const HYDRATION_GLOBAL = "_$HY.r";
|
|
23
130
|
function createSerializer(options) {
|
|
24
131
|
return new seroval.Serializer({
|
|
25
132
|
...options,
|
|
@@ -46,34 +153,6 @@ function createHydrationSerializer({
|
|
|
46
153
|
function getLocalHeaderScript(id) {
|
|
47
154
|
return seroval.getCrossReferenceHeader(id) + ";";
|
|
48
155
|
}
|
|
49
|
-
const JSON_CODEC_DISABLED_FEATURES = seroval.Feature.RegExp;
|
|
50
|
-
const JSON_CODEC_DEPTH_LIMIT = 64;
|
|
51
|
-
function resolveCodecOptions({
|
|
52
|
-
plugins,
|
|
53
|
-
disabledFeatures,
|
|
54
|
-
depthLimit
|
|
55
|
-
} = {}) {
|
|
56
|
-
return {
|
|
57
|
-
plugins: resolveSerializerPlugins(plugins),
|
|
58
|
-
disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
|
|
59
|
-
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
function serializeJSON(value, {
|
|
63
|
-
onParse,
|
|
64
|
-
onDone,
|
|
65
|
-
onError,
|
|
66
|
-
...codecOptions
|
|
67
|
-
}) {
|
|
68
|
-
const resolved = resolveCodecOptions(codecOptions);
|
|
69
|
-
return seroval.toCrossJSONStream(value, {
|
|
70
|
-
onParse,
|
|
71
|
-
onDone,
|
|
72
|
-
onError,
|
|
73
|
-
...resolved,
|
|
74
|
-
disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures()
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
156
|
function createJSONSerializer({
|
|
78
157
|
onData,
|
|
79
158
|
onDone,
|
|
@@ -260,7 +339,10 @@ class ChunkReader {
|
|
|
260
339
|
}
|
|
261
340
|
function serializeStream(value, codecOptions) {
|
|
262
341
|
return new ReadableStream({
|
|
263
|
-
start(controller) {
|
|
342
|
+
async start(controller) {
|
|
343
|
+
const {
|
|
344
|
+
serializeJSON
|
|
345
|
+
} = await import('@solidjs/web/serialization');
|
|
264
346
|
serializeJSON(value, {
|
|
265
347
|
...codecOptions,
|
|
266
348
|
onParse(node) {
|
|
@@ -347,7 +429,6 @@ function resolveHead(groups) {
|
|
|
347
429
|
}
|
|
348
430
|
for (const [identity, tags] of byIdentity) {
|
|
349
431
|
if (identity === "title") {
|
|
350
|
-
if (tags.length > 1) console.warn("Multiple <title> tags in one head group; the last one wins.");
|
|
351
432
|
winners.set(identity, {
|
|
352
433
|
seq: group.seq,
|
|
353
434
|
tags: [tags[tags.length - 1]]
|
|
@@ -537,7 +618,6 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
|
|
|
537
618
|
for (let i = 0; i < tags.length; i++) {
|
|
538
619
|
const desc = tags[i];
|
|
539
620
|
if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
|
|
540
|
-
console.warn(`useHead: ignoring non-head tag`, desc);
|
|
541
621
|
continue;
|
|
542
622
|
}
|
|
543
623
|
const cls = classifyHeadTag(desc);
|
|
@@ -589,7 +669,6 @@ function headShellReady(registry, block) {
|
|
|
589
669
|
} : undefined);
|
|
590
670
|
} catch (err) {
|
|
591
671
|
if (pends(err)) continue;
|
|
592
|
-
console.warn(`useHead: error evaluating resource tag props`, err);
|
|
593
672
|
parked.splice(i, 1);
|
|
594
673
|
continue;
|
|
595
674
|
}
|
|
@@ -630,7 +709,6 @@ function emitHeadResource(registry, context, tracking, emitResource, nonce, desc
|
|
|
630
709
|
});
|
|
631
710
|
return;
|
|
632
711
|
}
|
|
633
|
-
console.warn(`useHead: error evaluating resource tag props`, err);
|
|
634
712
|
return;
|
|
635
713
|
}
|
|
636
714
|
const identity = resourceIdentity(desc.tag, props);
|
|
@@ -692,7 +770,6 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
|
|
|
692
770
|
try {
|
|
693
771
|
resolved = reg.list();
|
|
694
772
|
} catch (err) {
|
|
695
|
-
console.warn(`useHead: error evaluating head group membership`, err);
|
|
696
773
|
continue;
|
|
697
774
|
}
|
|
698
775
|
if (!Array.isArray(resolved)) resolved = [resolved];
|
|
@@ -700,7 +777,6 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
|
|
|
700
777
|
for (let j = 0; j < resolved.length; j++) {
|
|
701
778
|
const desc = resolved[j];
|
|
702
779
|
if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
|
|
703
|
-
console.warn(`useHead: ignoring non-head tag`, desc);
|
|
704
780
|
continue;
|
|
705
781
|
}
|
|
706
782
|
const cls = classifyHeadTag(desc);
|
|
@@ -726,12 +802,10 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
|
|
|
726
802
|
} : undefined);
|
|
727
803
|
key = evalHeadValue(desc.key);
|
|
728
804
|
} catch (err) {
|
|
729
|
-
console.warn(`useHead: error evaluating tag props`, err);
|
|
730
805
|
continue;
|
|
731
806
|
}
|
|
732
807
|
const identity = replaceableIdentity(desc.tag, props, key, "u:" + registry.uniq++);
|
|
733
808
|
if ((identity === "base" || identity === "charset") && registry.shellFlushed) {
|
|
734
|
-
console.warn(`useHead: <${desc.tag}> (${identity}) registered after shell flush is ignored`);
|
|
735
809
|
continue;
|
|
736
810
|
}
|
|
737
811
|
tags.push({
|
|
@@ -813,7 +887,6 @@ function flushHeadFragment(registry, boundary) {
|
|
|
813
887
|
for (const name in t.props) {
|
|
814
888
|
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
815
889
|
if (!HEAD_ATTR_NAME.test(name)) {
|
|
816
|
-
console.warn(`useHead: ignoring invalid attribute name "${name}"`);
|
|
817
890
|
continue;
|
|
818
891
|
}
|
|
819
892
|
const v = t.props[name];
|
|
@@ -831,7 +904,6 @@ function renderHeadAttrHtml(props) {
|
|
|
831
904
|
for (const name in props) {
|
|
832
905
|
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
833
906
|
if (!HEAD_ATTR_NAME.test(name)) {
|
|
834
|
-
console.warn(`useHead: ignoring invalid attribute name "${name}"`);
|
|
835
907
|
continue;
|
|
836
908
|
}
|
|
837
909
|
const v = props[name];
|
|
@@ -891,6 +963,12 @@ function renderToStream(code, options = {}) {
|
|
|
891
963
|
d();
|
|
892
964
|
}
|
|
893
965
|
};
|
|
966
|
+
const failRender = err => {
|
|
967
|
+
try {
|
|
968
|
+
options.onError ? options.onError(err) : console.error(err);
|
|
969
|
+
} catch (_) {}
|
|
970
|
+
abandon();
|
|
971
|
+
};
|
|
894
972
|
const guardSink = w => ({
|
|
895
973
|
write(payload) {
|
|
896
974
|
if (dead) return;
|
|
@@ -987,12 +1065,20 @@ function renderToStream(code, options = {}) {
|
|
|
987
1065
|
const serializeRootAssets = () => {
|
|
988
1066
|
if (rootAssetsSerialized) return;
|
|
989
1067
|
rootAssetsSerialized = true;
|
|
990
|
-
serializeFragmentAssets("", tracking.boundaryModules, context);
|
|
1068
|
+
serializeFragmentAssets("", tracking.boundaryModules, context, renderId);
|
|
991
1069
|
};
|
|
1070
|
+
let holds = 0;
|
|
992
1071
|
const flushEnd = () => {
|
|
993
|
-
if (!registry.size) {
|
|
1072
|
+
if (!registry.size && !holds) {
|
|
994
1073
|
serializeRootAssets();
|
|
995
|
-
queue(() => queue(() =>
|
|
1074
|
+
queue(() => queue(() => {
|
|
1075
|
+
if (context.live.end) {
|
|
1076
|
+
const end = context.live.end;
|
|
1077
|
+
context.live.end = null;
|
|
1078
|
+
end();
|
|
1079
|
+
}
|
|
1080
|
+
serializer.flush();
|
|
1081
|
+
}));
|
|
996
1082
|
}
|
|
997
1083
|
};
|
|
998
1084
|
const registry = new Map();
|
|
@@ -1053,6 +1139,7 @@ function renderToStream(code, options = {}) {
|
|
|
1053
1139
|
solidJs.sharedConfig.context = context = {
|
|
1054
1140
|
async: true,
|
|
1055
1141
|
nonce,
|
|
1142
|
+
live: {},
|
|
1056
1143
|
registerHeadTags(tags) {
|
|
1057
1144
|
registerHeadTags(headRegistry, context, tracking,
|
|
1058
1145
|
(markup, gateEntry) => {
|
|
@@ -1089,6 +1176,16 @@ function renderToStream(code, options = {}) {
|
|
|
1089
1176
|
block(p) {
|
|
1090
1177
|
if (!firstFlushed) blockingPromises.add(p);
|
|
1091
1178
|
},
|
|
1179
|
+
hold() {
|
|
1180
|
+
holds++;
|
|
1181
|
+
let released = false;
|
|
1182
|
+
return () => {
|
|
1183
|
+
if (released) return;
|
|
1184
|
+
released = true;
|
|
1185
|
+
holds--;
|
|
1186
|
+
if (!holds) queue(flushEnd);
|
|
1187
|
+
};
|
|
1188
|
+
},
|
|
1092
1189
|
replace(id, payloadFn) {
|
|
1093
1190
|
if (firstFlushed) return;
|
|
1094
1191
|
const placeholder = `<!--!$${id}-->`;
|
|
@@ -1197,6 +1294,7 @@ function renderToStream(code, options = {}) {
|
|
|
1197
1294
|
}
|
|
1198
1295
|
};
|
|
1199
1296
|
applyAssetTracking(context, tracking, manifest, noScripts);
|
|
1297
|
+
context.failRender = failRender;
|
|
1200
1298
|
registerEntryAssets(manifest);
|
|
1201
1299
|
let html = solidJs.createRoot(d => {
|
|
1202
1300
|
dispose = d;
|
|
@@ -1309,7 +1407,12 @@ function renderToStream(code, options = {}) {
|
|
|
1309
1407
|
allSettled(blockingPromises).then(() => {
|
|
1310
1408
|
scheduleFlush(() => {
|
|
1311
1409
|
if (dead) return resolve();
|
|
1312
|
-
|
|
1410
|
+
try {
|
|
1411
|
+
doShell();
|
|
1412
|
+
} catch (err) {
|
|
1413
|
+
failRender(err);
|
|
1414
|
+
return resolve();
|
|
1415
|
+
}
|
|
1313
1416
|
if (!shellCompleted) return flush();
|
|
1314
1417
|
const encoder = new TextEncoder();
|
|
1315
1418
|
const writer = w.getWriter();
|
|
@@ -1366,7 +1469,12 @@ function renderToStream(code, options = {}) {
|
|
|
1366
1469
|
function flush() {
|
|
1367
1470
|
allSettled(blockingPromises).then(() => {
|
|
1368
1471
|
scheduleFlush(() => {
|
|
1369
|
-
|
|
1472
|
+
try {
|
|
1473
|
+
if (!resolveRootHoles() || !headShellReady(headRegistry, p => blockingPromises.add(p))) return flush();
|
|
1474
|
+
} catch (err) {
|
|
1475
|
+
failRender(err);
|
|
1476
|
+
return resolve(tmp);
|
|
1477
|
+
}
|
|
1370
1478
|
queue(flushEnd);
|
|
1371
1479
|
});
|
|
1372
1480
|
});
|
|
@@ -1381,7 +1489,15 @@ function renderToStream(code, options = {}) {
|
|
|
1381
1489
|
allSettled(blockingPromises).then(() => {
|
|
1382
1490
|
scheduleFlush(() => {
|
|
1383
1491
|
if (dead) return;
|
|
1384
|
-
|
|
1492
|
+
try {
|
|
1493
|
+
doShell();
|
|
1494
|
+
} catch (err) {
|
|
1495
|
+
failRender(err);
|
|
1496
|
+
try {
|
|
1497
|
+
w.end();
|
|
1498
|
+
} catch (_) {}
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1385
1501
|
if (!shellCompleted) return flush();
|
|
1386
1502
|
buffer = writable = guardSink(w);
|
|
1387
1503
|
buffer.write(tmp);
|
|
@@ -1413,9 +1529,27 @@ function renderToStream(code, options = {}) {
|
|
|
1413
1529
|
function buildAsyncWrap(err, node) {
|
|
1414
1530
|
const p = solidJs.ssrHandleError(err);
|
|
1415
1531
|
if (!p) return null;
|
|
1532
|
+
if (node.$rw) return {
|
|
1533
|
+
fn: node,
|
|
1534
|
+
p
|
|
1535
|
+
};
|
|
1416
1536
|
const owner = solidJs.getOwner();
|
|
1537
|
+
const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
|
|
1538
|
+
const suppress = node.$lhSuppress || live && (live.suppressed || live.sweeping);
|
|
1539
|
+
if (!owner) {
|
|
1540
|
+
if (suppress) node.$lhSuppress = true;
|
|
1541
|
+
return {
|
|
1542
|
+
fn: node,
|
|
1543
|
+
p
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
const fn = () => solidJs.runWithOwner(owner, node);
|
|
1547
|
+
fn.$rw = true;
|
|
1548
|
+
if (suppress) fn.$lhSuppress = true;
|
|
1549
|
+
if (node.$lhSkip) fn.$lhSkip = true;
|
|
1550
|
+
if (node.$lhBinding) fn.$lhBinding = node.$lhBinding;
|
|
1417
1551
|
return {
|
|
1418
|
-
fn
|
|
1552
|
+
fn,
|
|
1419
1553
|
p
|
|
1420
1554
|
};
|
|
1421
1555
|
}
|
|
@@ -1475,6 +1609,326 @@ function ssrGroupSlot(fn, idx) {
|
|
|
1475
1609
|
}
|
|
1476
1610
|
};
|
|
1477
1611
|
}
|
|
1612
|
+
const holePositionCache = new WeakMap();
|
|
1613
|
+
function holeContentPositions(t) {
|
|
1614
|
+
let cached = holePositionCache.get(t);
|
|
1615
|
+
if (cached) return cached;
|
|
1616
|
+
const pos = [];
|
|
1617
|
+
const openOff = [];
|
|
1618
|
+
const closeOff = [];
|
|
1619
|
+
let inTag = false;
|
|
1620
|
+
let quote = "";
|
|
1621
|
+
let curOpen = null;
|
|
1622
|
+
let scanningName = false;
|
|
1623
|
+
for (let i = 0; i < t.length; i++) {
|
|
1624
|
+
const seg = t[i];
|
|
1625
|
+
let close = -1;
|
|
1626
|
+
const openAtStart = inTag;
|
|
1627
|
+
let reopened = false;
|
|
1628
|
+
for (let j = 0; j < seg.length; j++) {
|
|
1629
|
+
const ch = seg[j];
|
|
1630
|
+
if (quote) {
|
|
1631
|
+
if (ch === quote) quote = "";
|
|
1632
|
+
} else if (inTag) {
|
|
1633
|
+
if (scanningName && (ch === " " || ch === "\t" || ch === "\n" || ch === ">" || ch === "/")) {
|
|
1634
|
+
scanningName = false;
|
|
1635
|
+
curOpen = {
|
|
1636
|
+
seg: i,
|
|
1637
|
+
off: j
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
if (ch === '"' || ch === "'") quote = ch;else if (ch === ">") {
|
|
1641
|
+
inTag = false;
|
|
1642
|
+
if (openAtStart && !reopened && close === -1) close = j;
|
|
1643
|
+
curOpen = null;
|
|
1644
|
+
}
|
|
1645
|
+
} else if (ch === "<") {
|
|
1646
|
+
inTag = true;
|
|
1647
|
+
scanningName = true;
|
|
1648
|
+
reopened = true;
|
|
1649
|
+
curOpen = null;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
if (inTag && scanningName) {
|
|
1653
|
+
scanningName = false;
|
|
1654
|
+
curOpen = {
|
|
1655
|
+
seg: i,
|
|
1656
|
+
off: seg.length
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
closeOff.push(close);
|
|
1660
|
+
openOff.push(inTag && curOpen && curOpen.seg === i ? curOpen.off : -1);
|
|
1661
|
+
if (i < t.length - 1) pos.push(!inTag);
|
|
1662
|
+
}
|
|
1663
|
+
cached = {
|
|
1664
|
+
pos,
|
|
1665
|
+
openOff,
|
|
1666
|
+
closeOff
|
|
1667
|
+
};
|
|
1668
|
+
holePositionCache.set(t, cached);
|
|
1669
|
+
return cached;
|
|
1670
|
+
}
|
|
1671
|
+
function createLiveHoles(sink, scoped) {
|
|
1672
|
+
let nextId = 0;
|
|
1673
|
+
const stamp = typeof solidJs.creationStamp === "function" ? solidJs.creationStamp : () => 0;
|
|
1674
|
+
const inScope = scoped && typeof solidJs.inServerComponentScope === "function" ? solidJs.inServerComponentScope : null;
|
|
1675
|
+
const stripMarkers = html => html.replace(/<!--lh:\/?\d+-->/g, "");
|
|
1676
|
+
function resolveHoleValue(hole) {
|
|
1677
|
+
const result = {
|
|
1678
|
+
t: [""],
|
|
1679
|
+
h: [],
|
|
1680
|
+
p: []
|
|
1681
|
+
};
|
|
1682
|
+
try {
|
|
1683
|
+
resolveSSRNode(hole(), result);
|
|
1684
|
+
} catch (err) {
|
|
1685
|
+
const wrap = buildAsyncWrap(err, hole);
|
|
1686
|
+
if (!wrap) throw err;
|
|
1687
|
+
result.h.push(wrap.fn);
|
|
1688
|
+
result.p.push(wrap.p);
|
|
1689
|
+
result.t.push("");
|
|
1690
|
+
}
|
|
1691
|
+
return result;
|
|
1692
|
+
}
|
|
1693
|
+
function closeChildren(b) {
|
|
1694
|
+
for (const c of b.children) {
|
|
1695
|
+
c.closed = true;
|
|
1696
|
+
if (c.key) sink.closeBinding(c.key);
|
|
1697
|
+
closeChildren(c);
|
|
1698
|
+
}
|
|
1699
|
+
b.children.length = 0;
|
|
1700
|
+
}
|
|
1701
|
+
const engine = {
|
|
1702
|
+
suppressed: 0,
|
|
1703
|
+
sweeping: false,
|
|
1704
|
+
parent: null,
|
|
1705
|
+
recordStamp: 0,
|
|
1706
|
+
gateHit: false,
|
|
1707
|
+
content(hole) {
|
|
1708
|
+
if (hole.$lhSuppress) {
|
|
1709
|
+
const r = {
|
|
1710
|
+
t: [""],
|
|
1711
|
+
h: [],
|
|
1712
|
+
p: []
|
|
1713
|
+
};
|
|
1714
|
+
engine.suppressed++;
|
|
1715
|
+
try {
|
|
1716
|
+
try {
|
|
1717
|
+
resolveSSRNode(hole(), r);
|
|
1718
|
+
} catch (err) {
|
|
1719
|
+
const wrap = buildAsyncWrap(err, hole);
|
|
1720
|
+
if (wrap) {
|
|
1721
|
+
r.h.push(wrap.fn);
|
|
1722
|
+
r.p.push(wrap.p);
|
|
1723
|
+
r.t.push("");
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
} finally {
|
|
1727
|
+
engine.suppressed--;
|
|
1728
|
+
}
|
|
1729
|
+
const b = hole.$lhBinding;
|
|
1730
|
+
if (b && !b.closed && !r.h.length && !engine.sweeping) {
|
|
1731
|
+
b.last = stripMarkers(r.t[0]);
|
|
1732
|
+
}
|
|
1733
|
+
return r.h.length ? r : r.t[0];
|
|
1734
|
+
}
|
|
1735
|
+
if (engine.suppressed || engine.sweeping) return null;
|
|
1736
|
+
if (hole.$lhSkip) return null;
|
|
1737
|
+
if (inScope && !inScope()) return null;
|
|
1738
|
+
const recordsBefore = engine.recordStamp;
|
|
1739
|
+
const ownersBefore = stamp();
|
|
1740
|
+
const owner = solidJs.getOwner();
|
|
1741
|
+
const b = {
|
|
1742
|
+
key: null,
|
|
1743
|
+
children: [],
|
|
1744
|
+
last: null,
|
|
1745
|
+
closed: false,
|
|
1746
|
+
sweep() {
|
|
1747
|
+
if (b.closed) return;
|
|
1748
|
+
const prevSweeping = engine.sweeping;
|
|
1749
|
+
engine.sweeping = true;
|
|
1750
|
+
engine.gateHit = false;
|
|
1751
|
+
const sweepOwnersBefore = stamp();
|
|
1752
|
+
let res;
|
|
1753
|
+
try {
|
|
1754
|
+
res = owner ? solidJs.runWithOwner(owner, () => resolveHoleValue(hole)) : resolveHoleValue(hole);
|
|
1755
|
+
} catch (err) {
|
|
1756
|
+
b.closed = true;
|
|
1757
|
+
sink.closeBinding(b.key);
|
|
1758
|
+
sink.error(b.key, String(err && err.message || err));
|
|
1759
|
+
return;
|
|
1760
|
+
} finally {
|
|
1761
|
+
engine.sweeping = prevSweeping;
|
|
1762
|
+
}
|
|
1763
|
+
if (engine.gateHit || stamp() !== sweepOwnersBefore) {
|
|
1764
|
+
b.closed = true;
|
|
1765
|
+
sink.closeBinding(b.key);
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
if (res.h.length) return;
|
|
1769
|
+
const html = res.t[0];
|
|
1770
|
+
if (b.last === null || html === b.last) return;
|
|
1771
|
+
b.last = html;
|
|
1772
|
+
closeChildren(b);
|
|
1773
|
+
sink.hole(b.key, html);
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
if (engine.parent) engine.parent.children.push(b);
|
|
1777
|
+
const prevParent = engine.parent;
|
|
1778
|
+
engine.parent = b;
|
|
1779
|
+
let value;
|
|
1780
|
+
let escalated = null;
|
|
1781
|
+
try {
|
|
1782
|
+
value = hole();
|
|
1783
|
+
} catch (err) {
|
|
1784
|
+
const wrap = buildAsyncWrap(err, hole);
|
|
1785
|
+
if (!wrap) {
|
|
1786
|
+
engine.parent = prevParent;
|
|
1787
|
+
closeChildren(b);
|
|
1788
|
+
return "";
|
|
1789
|
+
}
|
|
1790
|
+
escalated = wrap;
|
|
1791
|
+
}
|
|
1792
|
+
if (!escalated && (typeof value === "function" && value.$lhSkip || value !== null && typeof value === "object" && value.$slot)) {
|
|
1793
|
+
engine.parent = prevParent;
|
|
1794
|
+
const r = {
|
|
1795
|
+
t: [""],
|
|
1796
|
+
h: [],
|
|
1797
|
+
p: []
|
|
1798
|
+
};
|
|
1799
|
+
engine.suppressed++;
|
|
1800
|
+
try {
|
|
1801
|
+
resolveSSRNode(value, r);
|
|
1802
|
+
} finally {
|
|
1803
|
+
engine.suppressed--;
|
|
1804
|
+
}
|
|
1805
|
+
return r.h.length ? r : r.t[0];
|
|
1806
|
+
}
|
|
1807
|
+
let res;
|
|
1808
|
+
if (escalated) {
|
|
1809
|
+
closeChildren(b);
|
|
1810
|
+
escalated.fn.$lhSuppress = true;
|
|
1811
|
+
escalated.fn.$lhBinding = b;
|
|
1812
|
+
res = {
|
|
1813
|
+
t: ["", ""],
|
|
1814
|
+
h: [escalated.fn],
|
|
1815
|
+
p: [escalated.p]
|
|
1816
|
+
};
|
|
1817
|
+
} else {
|
|
1818
|
+
res = {
|
|
1819
|
+
t: [""],
|
|
1820
|
+
h: [],
|
|
1821
|
+
p: []
|
|
1822
|
+
};
|
|
1823
|
+
try {
|
|
1824
|
+
resolveSSRNode(value, res);
|
|
1825
|
+
} catch (_) {
|
|
1826
|
+
engine.parent = prevParent;
|
|
1827
|
+
closeChildren(b);
|
|
1828
|
+
return "";
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
engine.parent = prevParent;
|
|
1832
|
+
if (engine.recordStamp !== recordsBefore || stamp() !== ownersBefore) {
|
|
1833
|
+
return res.h.length ? res : res.t[0];
|
|
1834
|
+
}
|
|
1835
|
+
const id = nextId++;
|
|
1836
|
+
const key = b.key = "lh:" + id;
|
|
1837
|
+
const open = `<!--lh:${id}-->`;
|
|
1838
|
+
const close = `<!--lh:/${id}-->`;
|
|
1839
|
+
if (!res.h.length) {
|
|
1840
|
+
b.last = stripMarkers(res.t[0]);
|
|
1841
|
+
sink.openBinding(key, b);
|
|
1842
|
+
return open + res.t[0] + close;
|
|
1843
|
+
}
|
|
1844
|
+
const t = res.t.slice();
|
|
1845
|
+
t[0] = open + t[0];
|
|
1846
|
+
t[t.length - 1] += close;
|
|
1847
|
+
sink.openBinding(key, b);
|
|
1848
|
+
return {
|
|
1849
|
+
t,
|
|
1850
|
+
h: res.h,
|
|
1851
|
+
p: res.p
|
|
1852
|
+
};
|
|
1853
|
+
},
|
|
1854
|
+
mint() {
|
|
1855
|
+
return nextId++;
|
|
1856
|
+
},
|
|
1857
|
+
active() {
|
|
1858
|
+
return !inScope || inScope();
|
|
1859
|
+
},
|
|
1860
|
+
attr(cap) {
|
|
1861
|
+
const owner = solidJs.getOwner();
|
|
1862
|
+
const b = {
|
|
1863
|
+
key: "lha:" + cap.id,
|
|
1864
|
+
children: [],
|
|
1865
|
+
last: cap.base,
|
|
1866
|
+
closed: false,
|
|
1867
|
+
sweep() {
|
|
1868
|
+
if (b.closed) return;
|
|
1869
|
+
const prevSweeping = engine.sweeping;
|
|
1870
|
+
engine.sweeping = true;
|
|
1871
|
+
engine.gateHit = false;
|
|
1872
|
+
const sweepOwnersBefore = stamp();
|
|
1873
|
+
let html = "";
|
|
1874
|
+
try {
|
|
1875
|
+
let group = null;
|
|
1876
|
+
let groupVal = null;
|
|
1877
|
+
const run = () => {
|
|
1878
|
+
for (const part of cap.parts) {
|
|
1879
|
+
if (typeof part === "string") {
|
|
1880
|
+
html += part;
|
|
1881
|
+
continue;
|
|
1882
|
+
}
|
|
1883
|
+
let v;
|
|
1884
|
+
if (part.g) {
|
|
1885
|
+
if (group !== part.g) {
|
|
1886
|
+
group = part.g;
|
|
1887
|
+
groupVal = part.g();
|
|
1888
|
+
}
|
|
1889
|
+
v = groupVal[part.i];
|
|
1890
|
+
} else {
|
|
1891
|
+
v = part.f();
|
|
1892
|
+
}
|
|
1893
|
+
const vt = typeof v;
|
|
1894
|
+
if (vt === "string" || vt === "number") html += v;
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1897
|
+
owner ? solidJs.runWithOwner(owner, run) : run();
|
|
1898
|
+
} catch (err) {
|
|
1899
|
+
if (solidJs.ssrHandleError(err, true)) return;
|
|
1900
|
+
b.closed = true;
|
|
1901
|
+
sink.closeBinding(b.key);
|
|
1902
|
+
sink.error("lha:" + cap.id, String(err && err.message || err));
|
|
1903
|
+
return;
|
|
1904
|
+
} finally {
|
|
1905
|
+
engine.sweeping = prevSweeping;
|
|
1906
|
+
}
|
|
1907
|
+
if (engine.gateHit || stamp() !== sweepOwnersBefore) {
|
|
1908
|
+
b.closed = true;
|
|
1909
|
+
sink.closeBinding(b.key);
|
|
1910
|
+
return;
|
|
1911
|
+
}
|
|
1912
|
+
if (html === b.last) return;
|
|
1913
|
+
const before = attrNames(b.last);
|
|
1914
|
+
const after = attrNames(html);
|
|
1915
|
+
const removed = before.filter(n => !after.includes(n));
|
|
1916
|
+
b.last = html;
|
|
1917
|
+
sink.attr(String(cap.id), html, removed);
|
|
1918
|
+
}
|
|
1919
|
+
};
|
|
1920
|
+
sink.openBinding(b.key, b);
|
|
1921
|
+
}
|
|
1922
|
+
};
|
|
1923
|
+
return engine;
|
|
1924
|
+
}
|
|
1925
|
+
function attrNames(text) {
|
|
1926
|
+
const names = [];
|
|
1927
|
+
const re = /(?:^|\s)([^\s=/>"']+)(?:="[^"]*")?/g;
|
|
1928
|
+
let m;
|
|
1929
|
+
while (m = re.exec(text)) names.push(m[1]);
|
|
1930
|
+
return names;
|
|
1931
|
+
}
|
|
1478
1932
|
function ssr(t) {
|
|
1479
1933
|
const len = arguments.length;
|
|
1480
1934
|
if (len === 1) return {
|
|
@@ -1485,13 +1939,54 @@ function ssr(t) {
|
|
|
1485
1939
|
let lastGroup = null;
|
|
1486
1940
|
let lastGroupVal = null;
|
|
1487
1941
|
let lastGroupIdx = 0;
|
|
1942
|
+
const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
|
|
1943
|
+
const hp = live ? holeContentPositions(t) : null;
|
|
1944
|
+
let lastOpen = null;
|
|
1945
|
+
let cap = null;
|
|
1946
|
+
if (live && hp.openOff[0] >= 0) lastOpen = {
|
|
1947
|
+
r: null,
|
|
1948
|
+
seg: -1,
|
|
1949
|
+
off: hp.openOff[0]
|
|
1950
|
+
};
|
|
1951
|
+
const captureStart = () => {
|
|
1952
|
+
if (cap) return true;
|
|
1953
|
+
if (!lastOpen || live.suppressed || live.sweeping || !live.active()) return false;
|
|
1954
|
+
if (lastOpen.r !== result || result !== null && lastOpen.seg !== result.t.length - 1) {
|
|
1955
|
+
return false;
|
|
1956
|
+
}
|
|
1957
|
+
const id = live.mint();
|
|
1958
|
+
const inject = ` data-lha="${id}"`;
|
|
1959
|
+
let prefix;
|
|
1960
|
+
if (result === null) {
|
|
1961
|
+
s = s.slice(0, lastOpen.off) + inject + s.slice(lastOpen.off);
|
|
1962
|
+
prefix = s.slice(lastOpen.off + inject.length);
|
|
1963
|
+
} else {
|
|
1964
|
+
const seg = result.t[lastOpen.seg];
|
|
1965
|
+
result.t[lastOpen.seg] = seg.slice(0, lastOpen.off) + inject + seg.slice(lastOpen.off);
|
|
1966
|
+
prefix = result.t[lastOpen.seg].slice(lastOpen.off + inject.length);
|
|
1967
|
+
}
|
|
1968
|
+
cap = {
|
|
1969
|
+
id,
|
|
1970
|
+
parts: [prefix],
|
|
1971
|
+
base: prefix
|
|
1972
|
+
};
|
|
1973
|
+
return true;
|
|
1974
|
+
};
|
|
1488
1975
|
for (let i = 1; i < len; i++) {
|
|
1489
1976
|
const hole = arguments[i];
|
|
1490
1977
|
const ht = typeof hole;
|
|
1491
1978
|
if (ht === "string") {
|
|
1492
1979
|
if (result === null) s += hole;else result.t[result.t.length - 1] += hole;
|
|
1980
|
+
if (cap) {
|
|
1981
|
+
cap.parts.push(hole);
|
|
1982
|
+
cap.base += hole;
|
|
1983
|
+
}
|
|
1493
1984
|
} else if (ht === "number") {
|
|
1494
1985
|
if (result === null) s += hole;else result.t[result.t.length - 1] += hole;
|
|
1986
|
+
if (cap) {
|
|
1987
|
+
cap.parts.push("" + hole);
|
|
1988
|
+
cap.base += hole;
|
|
1989
|
+
}
|
|
1495
1990
|
} else if (hole == null || ht === "boolean") ; else if (ht === "function" && hole.$g) {
|
|
1496
1991
|
let value;
|
|
1497
1992
|
let hasValue = false;
|
|
@@ -1515,7 +2010,14 @@ function ssr(t) {
|
|
|
1515
2010
|
if (Array.isArray(lastGroupVal)) {
|
|
1516
2011
|
value = lastGroupVal[lastGroupIdx++];
|
|
1517
2012
|
hasValue = true;
|
|
2013
|
+
if (live && !hp.pos[i - 1] && captureStart()) {
|
|
2014
|
+
cap.parts.push({
|
|
2015
|
+
g: hole,
|
|
2016
|
+
i: lastGroupIdx - 1
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
1518
2019
|
} else {
|
|
2020
|
+
cap = null;
|
|
1519
2021
|
result.h.push(ssrGroupSlot(lastGroupVal.fn, lastGroupIdx++));
|
|
1520
2022
|
result.p.push(lastGroupVal.p);
|
|
1521
2023
|
result.t.push("");
|
|
@@ -1525,6 +2027,7 @@ function ssr(t) {
|
|
|
1525
2027
|
const vt = typeof value;
|
|
1526
2028
|
if (vt === "string" || vt === "number") {
|
|
1527
2029
|
if (result === null) s += value;else result.t[result.t.length - 1] += value;
|
|
2030
|
+
if (cap && !hp.pos[i - 1]) cap.base += value;
|
|
1528
2031
|
} else if (value == null || vt === "boolean") ; else if (result !== null) {
|
|
1529
2032
|
resolveSSRNode(value, result);
|
|
1530
2033
|
} else {
|
|
@@ -1542,19 +2045,67 @@ function ssr(t) {
|
|
|
1542
2045
|
}
|
|
1543
2046
|
}
|
|
1544
2047
|
}
|
|
1545
|
-
} else if (result !== null) {
|
|
1546
|
-
resolveSSRNode(hole, result);
|
|
1547
2048
|
} else if (ht === "function") {
|
|
1548
|
-
|
|
1549
|
-
if (
|
|
1550
|
-
|
|
1551
|
-
t
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
2049
|
+
let liveNode = null;
|
|
2050
|
+
if (live && hp.pos[i - 1] && (liveNode = live.content(hole)) !== null) {
|
|
2051
|
+
if (typeof liveNode === "string") {
|
|
2052
|
+
if (result === null) s += liveNode;else result.t[result.t.length - 1] += liveNode;
|
|
2053
|
+
} else {
|
|
2054
|
+
if (result === null) {
|
|
2055
|
+
result = {
|
|
2056
|
+
t: [s],
|
|
2057
|
+
h: [],
|
|
2058
|
+
p: []
|
|
2059
|
+
};
|
|
2060
|
+
s = "";
|
|
2061
|
+
}
|
|
2062
|
+
resolveSSRNode(liveNode, result);
|
|
2063
|
+
}
|
|
2064
|
+
} else if (result !== null) {
|
|
2065
|
+
const inTag = live && !hp.pos[i - 1];
|
|
2066
|
+
const capturing = inTag && captureStart();
|
|
2067
|
+
const li = capturing ? result.t.length - 1 : 0;
|
|
2068
|
+
const before = capturing ? result.t[li].length : 0;
|
|
2069
|
+
if (live) live.suppressed++;
|
|
2070
|
+
try {
|
|
2071
|
+
resolveSSRNode(hole, result);
|
|
2072
|
+
} finally {
|
|
2073
|
+
if (live) live.suppressed--;
|
|
2074
|
+
}
|
|
2075
|
+
if (capturing) {
|
|
2076
|
+
if (result.t.length - 1 === li) {
|
|
2077
|
+
cap.base += result.t[li].slice(before);
|
|
2078
|
+
cap.parts.push({
|
|
2079
|
+
f: hole
|
|
2080
|
+
});
|
|
2081
|
+
} else {
|
|
2082
|
+
cap = null;
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
} else {
|
|
2086
|
+
const capturing = live && !hp.pos[i - 1] && captureStart();
|
|
2087
|
+
const r = tryResolveFunctionHole(hole);
|
|
2088
|
+
if (typeof r === "string") {
|
|
2089
|
+
s += r;
|
|
2090
|
+
if (capturing) {
|
|
2091
|
+
cap.base += r;
|
|
2092
|
+
cap.parts.push({
|
|
2093
|
+
f: hole
|
|
2094
|
+
});
|
|
2095
|
+
}
|
|
2096
|
+
} else {
|
|
2097
|
+
if (capturing) cap = null;
|
|
2098
|
+
result = {
|
|
2099
|
+
t: [s],
|
|
2100
|
+
h: [],
|
|
2101
|
+
p: []
|
|
2102
|
+
};
|
|
2103
|
+
s = "";
|
|
2104
|
+
appendResolvedNode(result, r);
|
|
2105
|
+
}
|
|
1557
2106
|
}
|
|
2107
|
+
} else if (result !== null) {
|
|
2108
|
+
resolveSSRNode(hole, result);
|
|
1558
2109
|
} else {
|
|
1559
2110
|
const r = tryResolveString(hole);
|
|
1560
2111
|
if (typeof r === "string") {
|
|
@@ -1570,6 +2121,32 @@ function ssr(t) {
|
|
|
1570
2121
|
}
|
|
1571
2122
|
}
|
|
1572
2123
|
const next = t[i];
|
|
2124
|
+
if (live) {
|
|
2125
|
+
if (cap) {
|
|
2126
|
+
const co = hp.closeOff[i];
|
|
2127
|
+
if (co >= 0) {
|
|
2128
|
+
const tail = next.slice(0, co);
|
|
2129
|
+
cap.parts.push(tail);
|
|
2130
|
+
cap.base += tail;
|
|
2131
|
+
live.attr(cap);
|
|
2132
|
+
cap = null;
|
|
2133
|
+
} else {
|
|
2134
|
+
cap.parts.push(next);
|
|
2135
|
+
cap.base += next;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
if (hp.openOff[i] >= 0) {
|
|
2139
|
+
lastOpen = result === null ? {
|
|
2140
|
+
r: null,
|
|
2141
|
+
seg: -1,
|
|
2142
|
+
off: s.length + hp.openOff[i]
|
|
2143
|
+
} : {
|
|
2144
|
+
r: result,
|
|
2145
|
+
seg: result.t.length - 1,
|
|
2146
|
+
off: result.t[result.t.length - 1].length + hp.openOff[i]
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
1573
2150
|
if (result === null) s += next;else result.t[result.t.length - 1] += next;
|
|
1574
2151
|
}
|
|
1575
2152
|
if (result === null) return {
|
|
@@ -1705,10 +2282,10 @@ function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
|
1705
2282
|
}
|
|
1706
2283
|
return head;
|
|
1707
2284
|
}
|
|
1708
|
-
function serializeFragmentAssets(key, boundaryModules, context) {
|
|
2285
|
+
function serializeFragmentAssets(key, boundaryModules, context, name = key) {
|
|
1709
2286
|
const map = boundaryModules.get(key);
|
|
1710
2287
|
if (!map || !Object.keys(map).length) return;
|
|
1711
|
-
context.serialize(
|
|
2288
|
+
context.serialize(name + "_assets", map);
|
|
1712
2289
|
}
|
|
1713
2290
|
function propagateBoundaryStyles(childKey, parentKey, tracking) {
|
|
1714
2291
|
const childStyles = tracking.getBoundaryStyles(childKey);
|
|
@@ -1802,7 +2379,6 @@ function tryResolveString(node) {
|
|
|
1802
2379
|
merge: node
|
|
1803
2380
|
};
|
|
1804
2381
|
if (node.t === undefined) {
|
|
1805
|
-
console.warn(`Unrecognized value. Skipped inserting`, node);
|
|
1806
2382
|
return "";
|
|
1807
2383
|
}
|
|
1808
2384
|
return Array.isArray(node.t) ? node.t[0] : node.t;
|
|
@@ -1827,13 +2403,19 @@ function resolveSSRNode(node, result = {
|
|
|
1827
2403
|
if (t === "string" || t === "number") {
|
|
1828
2404
|
result.t[result.t.length - 1] += node;
|
|
1829
2405
|
} else if (node == null || t === "boolean") ; else if (Array.isArray(node)) {
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
2406
|
+
const slotLive = node.$slot && solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
|
|
2407
|
+
if (slotLive) slotLive.suppressed++;
|
|
2408
|
+
try {
|
|
2409
|
+
let prevNonObj = false;
|
|
2410
|
+
for (let i = 0, len = node.length; i < len; i++) {
|
|
2411
|
+
const item = node[i];
|
|
2412
|
+
const itemNonObj = item !== null && typeof item !== "object";
|
|
2413
|
+
if (!top && prevNonObj && itemNonObj) result.t[result.t.length - 1] += `<!--!$-->`;
|
|
2414
|
+
prevNonObj = itemNonObj;
|
|
2415
|
+
resolveSSRNode(item, result);
|
|
2416
|
+
}
|
|
2417
|
+
} finally {
|
|
2418
|
+
if (slotLive) slotLive.suppressed--;
|
|
1837
2419
|
}
|
|
1838
2420
|
} else if (t === "object") {
|
|
1839
2421
|
if (node.h) {
|
|
@@ -1845,16 +2427,22 @@ function resolveSSRNode(node, result = {
|
|
|
1845
2427
|
}
|
|
1846
2428
|
} else if (node.t !== undefined) {
|
|
1847
2429
|
result.t[result.t.length - 1] += node.t;
|
|
1848
|
-
} else
|
|
2430
|
+
} else ;
|
|
1849
2431
|
} else if (t === "function") {
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
2432
|
+
const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
|
|
2433
|
+
let liveNode = null;
|
|
2434
|
+
if (live && (liveNode = live.content(node)) !== null) {
|
|
2435
|
+
if (typeof liveNode === "string") result.t[result.t.length - 1] += liveNode;else resolveSSRNode(liveNode, result);
|
|
2436
|
+
} else {
|
|
2437
|
+
try {
|
|
2438
|
+
resolveSSRNode(node(), result);
|
|
2439
|
+
} catch (err) {
|
|
2440
|
+
const wrap = buildAsyncWrap(err, node);
|
|
2441
|
+
if (wrap) {
|
|
2442
|
+
result.h.push(wrap.fn);
|
|
2443
|
+
result.p.push(wrap.p);
|
|
2444
|
+
result.t.push("");
|
|
2445
|
+
}
|
|
1858
2446
|
}
|
|
1859
2447
|
}
|
|
1860
2448
|
}
|
|
@@ -1889,7 +2477,7 @@ function parseServerComponent(value, ctx) {
|
|
|
1889
2477
|
address: ctx.parse(value[SERVER_COMPONENT_ADDRESS])
|
|
1890
2478
|
};
|
|
1891
2479
|
}
|
|
1892
|
-
const ServerComponentPlugin =
|
|
2480
|
+
const ServerComponentPlugin = {
|
|
1893
2481
|
tag: "dom-expressions/server-component",
|
|
1894
2482
|
test(value) {
|
|
1895
2483
|
return typeof value === "function" && SERVER_COMPONENT in value;
|
|
@@ -1913,18 +2501,17 @@ const ServerComponentPlugin = /*#__PURE__*/seroval.createPlugin({
|
|
|
1913
2501
|
ctx.deserialize(node.address);
|
|
1914
2502
|
return globalThis._$SC.r(id);
|
|
1915
2503
|
}
|
|
1916
|
-
}
|
|
2504
|
+
};
|
|
1917
2505
|
function flightCodec(codec) {
|
|
1918
2506
|
const plugins = codec && codec.plugins || [];
|
|
1919
|
-
|
|
1920
|
-
if (plugin && plugin.tag === "dom-expressions/server-component") return codec;
|
|
1921
|
-
}
|
|
2507
|
+
if (plugins.some(plugin => plugin && plugin.tag === ServerComponentPlugin.tag)) return codec;
|
|
1922
2508
|
return {
|
|
1923
2509
|
...codec,
|
|
1924
2510
|
plugins: [...plugins, ServerComponentPlugin]
|
|
1925
2511
|
};
|
|
1926
2512
|
}
|
|
1927
2513
|
|
|
2514
|
+
const scopeStamp = typeof solidJs.creationStamp === "function" ? solidJs.creationStamp : () => 0;
|
|
1928
2515
|
function serverOwned(render) {
|
|
1929
2516
|
return solidJs.NoHydration ? solidJs.NoHydration({
|
|
1930
2517
|
get children() {
|
|
@@ -2149,6 +2736,26 @@ function createFrameSink(emit, frame) {
|
|
|
2149
2736
|
html
|
|
2150
2737
|
});
|
|
2151
2738
|
},
|
|
2739
|
+
hole(key, html) {
|
|
2740
|
+
emit({
|
|
2741
|
+
type: "hole",
|
|
2742
|
+
id,
|
|
2743
|
+
version,
|
|
2744
|
+
key,
|
|
2745
|
+
html
|
|
2746
|
+
});
|
|
2747
|
+
},
|
|
2748
|
+
attr(key, attrs, removed) {
|
|
2749
|
+
const chunk = {
|
|
2750
|
+
type: "attr",
|
|
2751
|
+
id,
|
|
2752
|
+
version,
|
|
2753
|
+
key,
|
|
2754
|
+
attrs
|
|
2755
|
+
};
|
|
2756
|
+
if (removed && removed.length) chunk.removed = removed;
|
|
2757
|
+
emit(chunk);
|
|
2758
|
+
},
|
|
2152
2759
|
openBinding(key, b) {
|
|
2153
2760
|
bindings.set(key, b);
|
|
2154
2761
|
},
|
|
@@ -2180,6 +2787,7 @@ function renderServerComponent(component, options = {}) {
|
|
|
2180
2787
|
if (ctx) {
|
|
2181
2788
|
ctx.commit = sink.commit;
|
|
2182
2789
|
ctx.commitEpoch = () => sink.epoch;
|
|
2790
|
+
ctx.liveHoles = createLiveHoles(sink);
|
|
2183
2791
|
}
|
|
2184
2792
|
return serverComponentScope(() => component(props));
|
|
2185
2793
|
};
|
|
@@ -2240,7 +2848,8 @@ function frameStream(makeCode, options) {
|
|
|
2240
2848
|
}
|
|
2241
2849
|
function slotRange(occurrence) {
|
|
2242
2850
|
return {
|
|
2243
|
-
t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end
|
|
2851
|
+
t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end-->`,
|
|
2852
|
+
$slot: true
|
|
2244
2853
|
};
|
|
2245
2854
|
}
|
|
2246
2855
|
const OCCURRENCE_UNSAFE = /[^A-Za-z0-9_.-]/g;
|
|
@@ -2288,14 +2897,28 @@ function tapFirstYield(iterable) {
|
|
|
2288
2897
|
}
|
|
2289
2898
|
};
|
|
2290
2899
|
}
|
|
2900
|
+
function suppressedFill(render) {
|
|
2901
|
+
const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
|
|
2902
|
+
if (!live) return render();
|
|
2903
|
+
live.suppressed++;
|
|
2904
|
+
try {
|
|
2905
|
+
return render();
|
|
2906
|
+
} finally {
|
|
2907
|
+
live.suppressed--;
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2291
2910
|
function createDocumentSlotProps(clientProps, frameId) {
|
|
2292
2911
|
const counts = Object.create(null);
|
|
2293
2912
|
const getters = new Map();
|
|
2294
|
-
const range = (occurrence, content) =>
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2913
|
+
const range = (occurrence, content) => {
|
|
2914
|
+
const r = [{
|
|
2915
|
+
t: `<!--slot:${occurrence}:start-->`
|
|
2916
|
+
}, content, {
|
|
2917
|
+
t: `<!--slot:${occurrence}:end-->`
|
|
2918
|
+
}];
|
|
2919
|
+
r.$slot = true;
|
|
2920
|
+
return r;
|
|
2921
|
+
};
|
|
2299
2922
|
const zoneOwner = solidJs.getOwner ? solidJs.getOwner() : null;
|
|
2300
2923
|
const scoped = (occurrence, render) => {
|
|
2301
2924
|
const id = `sc-${frameId}-${occurrence}-`;
|
|
@@ -2318,27 +2941,68 @@ function createDocumentSlotProps(clientProps, frameId) {
|
|
|
2318
2941
|
if (!fn) {
|
|
2319
2942
|
fn = (...callArgs) => {
|
|
2320
2943
|
if (callArgs.length === 0 || callArgs[0] === undefined) {
|
|
2321
|
-
return scoped(prop, () => {
|
|
2944
|
+
return suppressedFill(() => scoped(prop, () => {
|
|
2322
2945
|
const value = clientProps[prop];
|
|
2323
2946
|
return range(prop, typeof value === "function" ? value() : value);
|
|
2324
|
-
});
|
|
2947
|
+
}));
|
|
2325
2948
|
}
|
|
2326
2949
|
const raw = callArgs[0];
|
|
2327
2950
|
const occurrence = occurrenceId(prop, raw, counts);
|
|
2328
2951
|
const slot = clientProps[prop];
|
|
2329
2952
|
if (typeof slot !== "function") return range(occurrence, undefined);
|
|
2330
2953
|
const resolved = {};
|
|
2954
|
+
const liveArgs = solidJs.sharedConfig.context && solidJs.sharedConfig.context.live && solidJs.sharedConfig.context.live.args;
|
|
2331
2955
|
const vals = {};
|
|
2956
|
+
const evals = {};
|
|
2957
|
+
const states = {};
|
|
2958
|
+
const minted = {};
|
|
2332
2959
|
for (const key of Object.keys(raw)) {
|
|
2333
2960
|
if (key === "$key") continue;
|
|
2334
|
-
|
|
2335
|
-
|
|
2961
|
+
const desc = Object.getOwnPropertyDescriptor(raw, key);
|
|
2962
|
+
let evaluate = null;
|
|
2963
|
+
let value;
|
|
2964
|
+
if (desc.get) {
|
|
2965
|
+
const get = desc.get;
|
|
2966
|
+
evaluate = () => unwrapThunks(get.call(raw));
|
|
2967
|
+
} else {
|
|
2968
|
+
value = desc.value;
|
|
2969
|
+
if (typeof value === "function") {
|
|
2970
|
+
const fn = value;
|
|
2971
|
+
evaluate = () => unwrapThunks(fn);
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
if (evaluate) {
|
|
2975
|
+
evals[key] = evaluate;
|
|
2976
|
+
const stampBefore = scopeStamp();
|
|
2977
|
+
try {
|
|
2978
|
+
value = evaluate();
|
|
2979
|
+
states[key] = {
|
|
2980
|
+
settled: true,
|
|
2981
|
+
last: value
|
|
2982
|
+
};
|
|
2983
|
+
} catch (err) {
|
|
2984
|
+
const blocked = solidJs.ssrHandleError && solidJs.ssrHandleError(err);
|
|
2985
|
+
if (!blocked) throw err;
|
|
2986
|
+
const state = states[key] = {
|
|
2987
|
+
settled: false,
|
|
2988
|
+
last: undefined
|
|
2989
|
+
};
|
|
2990
|
+
value = retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
|
|
2991
|
+
state.settled = true;
|
|
2992
|
+
state.last = v;
|
|
2993
|
+
if (liveArgs) liveArgs.commit();
|
|
2994
|
+
});
|
|
2995
|
+
}
|
|
2996
|
+
if (scopeStamp() !== stampBefore) minted[key] = true;
|
|
2997
|
+
}
|
|
2336
2998
|
vals[key] = value;
|
|
2337
2999
|
}
|
|
2338
3000
|
const regions = [];
|
|
2339
3001
|
for (const key of Object.keys(vals)) {
|
|
2340
3002
|
const value = vals[key];
|
|
2341
|
-
if (
|
|
3003
|
+
if (isContainerTraced(value)) {
|
|
3004
|
+
resolved[key] = value;
|
|
3005
|
+
} else if (isServerContent(value)) {
|
|
2342
3006
|
const childId = `${frameId}.${occurrence}.${key}`;
|
|
2343
3007
|
const region = {
|
|
2344
3008
|
key,
|
|
@@ -2377,7 +3041,7 @@ function createDocumentSlotProps(clientProps, frameId) {
|
|
|
2377
3041
|
resolved[key] = value;
|
|
2378
3042
|
}
|
|
2379
3043
|
}
|
|
2380
|
-
const out = scoped(occurrence, () => range(occurrence, slot(resolved)));
|
|
3044
|
+
const out = suppressedFill(() => scoped(occurrence, () => range(occurrence, slot(resolved))));
|
|
2381
3045
|
const unused = regions.filter(r => !r.used);
|
|
2382
3046
|
if (solidJs.sharedConfig.context) {
|
|
2383
3047
|
const args = {};
|
|
@@ -2390,17 +3054,33 @@ function createDocumentSlotProps(clientProps, frameId) {
|
|
|
2390
3054
|
};
|
|
2391
3055
|
continue;
|
|
2392
3056
|
}
|
|
2393
|
-
if (isServerContent(value)) continue;
|
|
2394
|
-
args[key] = value;
|
|
3057
|
+
if (!isContainerTraced(value) && isServerContent(value)) continue;
|
|
3058
|
+
args[key] = envelopeContainerTraces(value);
|
|
2395
3059
|
}
|
|
2396
|
-
solidJs.sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`,
|
|
3060
|
+
solidJs.sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`, {
|
|
3061
|
+
...args
|
|
3062
|
+
});
|
|
2397
3063
|
for (const region of unused) {
|
|
2398
3064
|
region.locked = true;
|
|
2399
3065
|
solidJs.sharedConfig.context.serialize(`sc:region:${region.childId}`, resolveRegionHtml(solidJs.sharedConfig.context, region.value));
|
|
2400
3066
|
}
|
|
3067
|
+
if (liveArgs) {
|
|
3068
|
+
for (const key of Object.keys(evals)) {
|
|
3069
|
+
if (regions.some(r => r.key === key)) continue;
|
|
3070
|
+
if (minted[key]) continue;
|
|
3071
|
+
const ledgerKey = `${frameId}:${occurrence}:${key}`;
|
|
3072
|
+
openArgBinding(liveArgs, ledgerKey, occurrence, key, evals[key], states[key], value => {
|
|
3073
|
+
args[key] = envelopeContainerTraces(value);
|
|
3074
|
+
liveArgs.slot(frameId, occurrence, {
|
|
3075
|
+
...args
|
|
3076
|
+
});
|
|
3077
|
+
});
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
2401
3080
|
}
|
|
2402
3081
|
return out;
|
|
2403
3082
|
};
|
|
3083
|
+
fn.$lhSkip = true;
|
|
2404
3084
|
getters.set(prop, fn);
|
|
2405
3085
|
}
|
|
2406
3086
|
return fn;
|
|
@@ -2414,6 +3094,113 @@ function frameElementOpen(id) {
|
|
|
2414
3094
|
return `<${FRAME_TAG} ${FRAME_ID_ATTR}="${escaped}" style="display:contents">`;
|
|
2415
3095
|
}
|
|
2416
3096
|
const FRAME_ELEMENT_CLOSE = `</${FRAME_TAG}>`;
|
|
3097
|
+
function armDocumentLiveHoles(ctx) {
|
|
3098
|
+
if (!ctx || ctx.liveHoles !== undefined) return;
|
|
3099
|
+
const live = ctx.live;
|
|
3100
|
+
if (live && live.holes !== undefined) {
|
|
3101
|
+
ctx.liveHoles = live.holes;
|
|
3102
|
+
if (live.holes) {
|
|
3103
|
+
ctx.commit = live.commit;
|
|
3104
|
+
ctx.commitEpoch = live.commitEpoch;
|
|
3105
|
+
}
|
|
3106
|
+
return;
|
|
3107
|
+
}
|
|
3108
|
+
if (!live || !ctx.async || ctx.noHydrate || !ctx.serialize || typeof ReadableStream !== "function") {
|
|
3109
|
+
ctx.liveHoles = null;
|
|
3110
|
+
if (live) live.holes = null;
|
|
3111
|
+
return;
|
|
3112
|
+
}
|
|
3113
|
+
const bindings = new Map();
|
|
3114
|
+
let epoch = 0;
|
|
3115
|
+
let sweepScheduled = false;
|
|
3116
|
+
let closed = false;
|
|
3117
|
+
const sweep = () => {
|
|
3118
|
+
epoch++;
|
|
3119
|
+
for (const b of [...bindings.values()]) {
|
|
3120
|
+
try {
|
|
3121
|
+
b.sweep();
|
|
3122
|
+
} catch (_) {
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
};
|
|
3126
|
+
const scheduleSweep = () => {
|
|
3127
|
+
if (closed || sweepScheduled || !bindings.size) return;
|
|
3128
|
+
sweepScheduled = true;
|
|
3129
|
+
queueMicrotask(() => {
|
|
3130
|
+
sweepScheduled = false;
|
|
3131
|
+
if (!closed) sweep();
|
|
3132
|
+
});
|
|
3133
|
+
};
|
|
3134
|
+
let channel;
|
|
3135
|
+
ctx.serialize("sc:live", new ReadableStream({
|
|
3136
|
+
start(c) {
|
|
3137
|
+
channel = c;
|
|
3138
|
+
}
|
|
3139
|
+
}));
|
|
3140
|
+
const push = op => {
|
|
3141
|
+
if (!closed) channel.enqueue(op);
|
|
3142
|
+
};
|
|
3143
|
+
ctx.liveHoles = live.holes = createLiveHoles({
|
|
3144
|
+
openBinding(key, b) {
|
|
3145
|
+
bindings.set(key, b);
|
|
3146
|
+
},
|
|
3147
|
+
closeBinding(key) {
|
|
3148
|
+
bindings.delete(key);
|
|
3149
|
+
},
|
|
3150
|
+
hole(key, html) {
|
|
3151
|
+
push({
|
|
3152
|
+
type: "hole",
|
|
3153
|
+
key,
|
|
3154
|
+
html
|
|
3155
|
+
});
|
|
3156
|
+
},
|
|
3157
|
+
attr(key, attrs, removed) {
|
|
3158
|
+
const op = {
|
|
3159
|
+
type: "attr",
|
|
3160
|
+
key,
|
|
3161
|
+
attrs
|
|
3162
|
+
};
|
|
3163
|
+
if (removed && removed.length) op.removed = removed;
|
|
3164
|
+
push(op);
|
|
3165
|
+
},
|
|
3166
|
+
error(key, error) {
|
|
3167
|
+
push({
|
|
3168
|
+
type: "error",
|
|
3169
|
+
key,
|
|
3170
|
+
error
|
|
3171
|
+
});
|
|
3172
|
+
},
|
|
3173
|
+
commit: scheduleSweep,
|
|
3174
|
+
get epoch() {
|
|
3175
|
+
return epoch;
|
|
3176
|
+
}
|
|
3177
|
+
}, true);
|
|
3178
|
+
ctx.commit = live.commit = scheduleSweep;
|
|
3179
|
+
ctx.commitEpoch = live.commitEpoch = () => epoch;
|
|
3180
|
+
live.args = {
|
|
3181
|
+
openBinding(key, b) {
|
|
3182
|
+
bindings.set(key, b);
|
|
3183
|
+
},
|
|
3184
|
+
closeBinding(key) {
|
|
3185
|
+
bindings.delete(key);
|
|
3186
|
+
},
|
|
3187
|
+
slot(fid, occurrence, args) {
|
|
3188
|
+
push({
|
|
3189
|
+
type: "slot",
|
|
3190
|
+
fid,
|
|
3191
|
+
key: occurrence,
|
|
3192
|
+
args
|
|
3193
|
+
});
|
|
3194
|
+
},
|
|
3195
|
+
commit: scheduleSweep
|
|
3196
|
+
};
|
|
3197
|
+
live.end = () => {
|
|
3198
|
+
if (closed) return;
|
|
3199
|
+
if (bindings.size) sweep();
|
|
3200
|
+
closed = true;
|
|
3201
|
+
channel.close();
|
|
3202
|
+
};
|
|
3203
|
+
}
|
|
2417
3204
|
function frameTransformDirectResult(value, {
|
|
2418
3205
|
id,
|
|
2419
3206
|
args
|
|
@@ -2424,6 +3211,7 @@ function frameTransformDirectResult(value, {
|
|
|
2424
3211
|
t: frameElementOpen(id)
|
|
2425
3212
|
},
|
|
2426
3213
|
serverOwned(() => {
|
|
3214
|
+
armDocumentLiveHoles(solidJs.sharedConfig.context);
|
|
2427
3215
|
const slotProps = createDocumentSlotProps(props, id);
|
|
2428
3216
|
return serverComponentScope(() => component(slotProps));
|
|
2429
3217
|
}), {
|
|
@@ -2487,60 +3275,48 @@ function retryArgUntilSettled(evaluate, blocked, key, occurrence, onSettle) {
|
|
|
2487
3275
|
blocked.then(retry, retry);
|
|
2488
3276
|
});
|
|
2489
3277
|
}
|
|
2490
|
-
function openArgBinding(sink,
|
|
3278
|
+
function openArgBinding(sink, ledgerKey, occurrence, key, evaluate, state, emit) {
|
|
2491
3279
|
const owner = solidJs.getOwner();
|
|
2492
|
-
|
|
2493
|
-
const reEmit = value => {
|
|
2494
|
-
const ref = `arg:${occurrence}:${key}@${sink.nextArgRef(ledgerKey)}`;
|
|
2495
|
-
sink.mintRef(ref);
|
|
2496
|
-
ctx.serialize(ref, value);
|
|
2497
|
-
args[key] = {
|
|
2498
|
-
$ref: ref
|
|
2499
|
-
};
|
|
2500
|
-
sink.slot(occurrence, {
|
|
2501
|
-
...args
|
|
2502
|
-
});
|
|
2503
|
-
};
|
|
2504
|
-
const binding = {
|
|
3280
|
+
sink.openBinding(ledgerKey, {
|
|
2505
3281
|
sweep() {
|
|
2506
3282
|
if (!state.settled) return;
|
|
2507
3283
|
let value;
|
|
3284
|
+
const stampBefore = scopeStamp();
|
|
2508
3285
|
try {
|
|
2509
3286
|
value = owner ? solidJs.runWithOwner(owner, evaluate) : evaluate();
|
|
2510
3287
|
} catch (err) {
|
|
2511
3288
|
const blocked = solidJs.ssrHandleError && solidJs.ssrHandleError(err);
|
|
2512
3289
|
if (!blocked) {
|
|
2513
3290
|
sink.closeBinding(ledgerKey);
|
|
2514
|
-
|
|
3291
|
+
emit(Promise.reject(err instanceof Error ? err : new Error(String(err))));
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
if (scopeStamp() !== stampBefore) {
|
|
3295
|
+
sink.closeBinding(ledgerKey);
|
|
2515
3296
|
return;
|
|
2516
3297
|
}
|
|
2517
3298
|
state.settled = false;
|
|
2518
|
-
|
|
3299
|
+
emit(retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
|
|
2519
3300
|
state.settled = true;
|
|
2520
3301
|
state.last = v;
|
|
2521
3302
|
sink.commit();
|
|
2522
3303
|
}));
|
|
2523
3304
|
return;
|
|
2524
3305
|
}
|
|
3306
|
+
if (scopeStamp() !== stampBefore) {
|
|
3307
|
+
sink.closeBinding(ledgerKey);
|
|
3308
|
+
return;
|
|
3309
|
+
}
|
|
2525
3310
|
if (value === state.last) return;
|
|
2526
3311
|
state.last = value;
|
|
2527
3312
|
if (isServerContent(value)) {
|
|
2528
3313
|
sink.closeBinding(ledgerKey);
|
|
2529
|
-
|
|
3314
|
+
emit(Promise.reject(contentArgError(key, occurrence)));
|
|
2530
3315
|
return;
|
|
2531
3316
|
}
|
|
2532
|
-
|
|
2533
|
-
if (value == null || t === "string" || t === "number" || t === "boolean") {
|
|
2534
|
-
args[key] = value;
|
|
2535
|
-
sink.slot(occurrence, {
|
|
2536
|
-
...args
|
|
2537
|
-
});
|
|
2538
|
-
} else {
|
|
2539
|
-
reEmit(value);
|
|
2540
|
-
}
|
|
3317
|
+
emit(value);
|
|
2541
3318
|
}
|
|
2542
|
-
};
|
|
2543
|
-
sink.openBinding(ledgerKey, binding);
|
|
3319
|
+
});
|
|
2544
3320
|
}
|
|
2545
3321
|
function createSlotProps(sink, frame) {
|
|
2546
3322
|
const counts = Object.create(null);
|
|
@@ -2558,6 +3334,17 @@ function createSlotProps(sink, frame) {
|
|
|
2558
3334
|
if (callArgs.length === 0 || callArgs[0] === undefined) {
|
|
2559
3335
|
return slotRange(prop);
|
|
2560
3336
|
}
|
|
3337
|
+
const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
|
|
3338
|
+
if (live) {
|
|
3339
|
+
if (live.sweeping) {
|
|
3340
|
+
live.gateHit = true;
|
|
3341
|
+
return {
|
|
3342
|
+
t: "",
|
|
3343
|
+
$slot: true
|
|
3344
|
+
};
|
|
3345
|
+
}
|
|
3346
|
+
live.recordStamp++;
|
|
3347
|
+
}
|
|
2561
3348
|
const raw = callArgs[0];
|
|
2562
3349
|
const occurrence = occurrenceId(prop, raw, counts);
|
|
2563
3350
|
const args = {};
|
|
@@ -2576,6 +3363,7 @@ function createSlotProps(sink, frame) {
|
|
|
2576
3363
|
let evaluate = null;
|
|
2577
3364
|
let value;
|
|
2578
3365
|
let state = null;
|
|
3366
|
+
const stampBefore = scopeStamp();
|
|
2579
3367
|
try {
|
|
2580
3368
|
if (desc.get) {
|
|
2581
3369
|
const get = desc.get;
|
|
@@ -2603,6 +3391,7 @@ function createSlotProps(sink, frame) {
|
|
|
2603
3391
|
sink.commit();
|
|
2604
3392
|
});
|
|
2605
3393
|
}
|
|
3394
|
+
const mintedEval = scopeStamp() !== stampBefore;
|
|
2606
3395
|
const t = typeof value;
|
|
2607
3396
|
if (value == null || t === "string" || t === "number" || t === "boolean") {
|
|
2608
3397
|
args[key] = value;
|
|
@@ -2610,7 +3399,7 @@ function createSlotProps(sink, frame) {
|
|
|
2610
3399
|
settled: true,
|
|
2611
3400
|
last: value
|
|
2612
3401
|
};
|
|
2613
|
-
} else if (isServerContent(value)) {
|
|
3402
|
+
} else if (!isContainerTraced(value) && isServerContent(value)) {
|
|
2614
3403
|
const resolved = ctx.resolve(value);
|
|
2615
3404
|
if (resolved.h.length) {
|
|
2616
3405
|
throw new Error("Async server content in a slot arg needs a boundary (arg '" + key + "' of " + occurrence + "). Wrap the async read in a <Suspense>, or move it above the slot.");
|
|
@@ -2621,7 +3410,7 @@ function createSlotProps(sink, frame) {
|
|
|
2621
3410
|
};
|
|
2622
3411
|
} else {
|
|
2623
3412
|
const ref = `arg:${occurrence}:${key}`;
|
|
2624
|
-
ctx.serialize(ref, value);
|
|
3413
|
+
ctx.serialize(ref, envelopeContainerTraces(value));
|
|
2625
3414
|
args[key] = {
|
|
2626
3415
|
$ref: ref
|
|
2627
3416
|
};
|
|
@@ -2630,7 +3419,7 @@ function createSlotProps(sink, frame) {
|
|
|
2630
3419
|
last: value
|
|
2631
3420
|
};
|
|
2632
3421
|
}
|
|
2633
|
-
if (evaluate && state) opened.push({
|
|
3422
|
+
if (evaluate && state && !mintedEval) opened.push({
|
|
2634
3423
|
key,
|
|
2635
3424
|
evaluate,
|
|
2636
3425
|
state
|
|
@@ -2644,10 +3433,28 @@ function createSlotProps(sink, frame) {
|
|
|
2644
3433
|
});
|
|
2645
3434
|
const ctx = solidJs.sharedConfig.context;
|
|
2646
3435
|
for (const b of opened) {
|
|
2647
|
-
|
|
3436
|
+
const key = b.key;
|
|
3437
|
+
const ledgerKey = `${occurrence}:${key}`;
|
|
3438
|
+
openArgBinding(sink, ledgerKey, occurrence, key, b.evaluate, b.state, value => {
|
|
3439
|
+
const t = typeof value;
|
|
3440
|
+
if (value == null || t === "string" || t === "number" || t === "boolean") {
|
|
3441
|
+
args[key] = value;
|
|
3442
|
+
} else {
|
|
3443
|
+
const ref = `arg:${occurrence}:${key}@${sink.nextArgRef(ledgerKey)}`;
|
|
3444
|
+
sink.mintRef(ref);
|
|
3445
|
+
ctx.serialize(ref, envelopeContainerTraces(value));
|
|
3446
|
+
args[key] = {
|
|
3447
|
+
$ref: ref
|
|
3448
|
+
};
|
|
3449
|
+
}
|
|
3450
|
+
sink.slot(occurrence, {
|
|
3451
|
+
...args
|
|
3452
|
+
});
|
|
3453
|
+
});
|
|
2648
3454
|
}
|
|
2649
3455
|
return slotRange(occurrence);
|
|
2650
3456
|
};
|
|
3457
|
+
fn.$lhSkip = true;
|
|
2651
3458
|
getters.set(prop, fn);
|
|
2652
3459
|
}
|
|
2653
3460
|
return fn;
|
|
@@ -2679,16 +3486,27 @@ function serverComponentResponse(component, options = {}, init = {}) {
|
|
|
2679
3486
|
version
|
|
2680
3487
|
}
|
|
2681
3488
|
});
|
|
3489
|
+
let closed = false;
|
|
2682
3490
|
const body = new ReadableStream({
|
|
2683
3491
|
start(controller) {
|
|
2684
3492
|
stream.pipe({
|
|
2685
3493
|
write(chunk) {
|
|
2686
|
-
|
|
3494
|
+
if (closed) return;
|
|
3495
|
+
try {
|
|
3496
|
+
controller.enqueue(createChunk(JSON.stringify(chunk)));
|
|
3497
|
+
} catch (_) {
|
|
3498
|
+
closed = true;
|
|
3499
|
+
}
|
|
2687
3500
|
},
|
|
2688
3501
|
end() {
|
|
3502
|
+
if (closed) return;
|
|
3503
|
+
closed = true;
|
|
2689
3504
|
controller.close();
|
|
2690
3505
|
}
|
|
2691
3506
|
});
|
|
3507
|
+
},
|
|
3508
|
+
cancel() {
|
|
3509
|
+
closed = true;
|
|
2692
3510
|
}
|
|
2693
3511
|
});
|
|
2694
3512
|
return new Response(body, {
|
|
@@ -2772,9 +3590,17 @@ function frameFlightResponse({
|
|
|
2772
3590
|
headers.set(FRAME_STREAM_HEADER, primary ? primary.id : "");
|
|
2773
3591
|
headers.set("X-Content-Raw", "1");
|
|
2774
3592
|
headers.set(SINGLE_FLIGHT_HEADER, "true");
|
|
3593
|
+
let closed = false;
|
|
2775
3594
|
const body = new ReadableStream({
|
|
2776
3595
|
async start(controller) {
|
|
2777
|
-
const write = chunk =>
|
|
3596
|
+
const write = chunk => {
|
|
3597
|
+
if (closed) return;
|
|
3598
|
+
try {
|
|
3599
|
+
controller.enqueue(createChunk(JSON.stringify(chunk)));
|
|
3600
|
+
} catch (_) {
|
|
3601
|
+
closed = true;
|
|
3602
|
+
}
|
|
3603
|
+
};
|
|
2778
3604
|
try {
|
|
2779
3605
|
for (const {
|
|
2780
3606
|
id,
|
|
@@ -2801,10 +3627,19 @@ function frameFlightResponse({
|
|
|
2801
3627
|
});
|
|
2802
3628
|
}
|
|
2803
3629
|
}
|
|
2804
|
-
|
|
3630
|
+
if (!closed) {
|
|
3631
|
+
closed = true;
|
|
3632
|
+
controller.close();
|
|
3633
|
+
}
|
|
2805
3634
|
} catch (err) {
|
|
2806
|
-
|
|
3635
|
+
if (!closed) {
|
|
3636
|
+
closed = true;
|
|
3637
|
+
controller.error(err);
|
|
3638
|
+
}
|
|
2807
3639
|
}
|
|
3640
|
+
},
|
|
3641
|
+
cancel() {
|
|
3642
|
+
closed = true;
|
|
2808
3643
|
}
|
|
2809
3644
|
});
|
|
2810
3645
|
return new Response(body, {
|
|
@@ -2813,6 +3648,7 @@ function frameFlightResponse({
|
|
|
2813
3648
|
});
|
|
2814
3649
|
}
|
|
2815
3650
|
|
|
3651
|
+
setContainerTraceResolver(solidJs.getProjectionTrace);
|
|
2816
3652
|
function asyncArg(value) {
|
|
2817
3653
|
return value;
|
|
2818
3654
|
}
|