@solidjs/web 2.0.0-rc.0 → 2.0.0-rc.2
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/README.md +1 -1
- package/dist/dev.cjs +40 -11
- package/dist/dev.js +39 -12
- package/dist/server.cjs +419 -69
- package/dist/server.js +411 -73
- package/dist/web.cjs +37 -11
- package/dist/web.js +36 -12
- package/frames/dist/client.cjs +94 -8
- package/frames/dist/client.dev.cjs +97 -8
- package/frames/dist/client.dev.js +98 -9
- package/frames/dist/client.js +95 -9
- package/frames/dist/server.cjs +266 -56
- package/frames/dist/server.js +267 -57
- package/package.json +4 -3
- package/serialization/dist/decode.cjs +32 -3
- package/serialization/dist/decode.js +33 -4
- package/serialization/dist/serialization.cjs +32 -3
- package/serialization/dist/serialization.js +33 -4
- package/server-functions/dist/client.cjs +196 -8
- package/server-functions/dist/client.js +195 -9
- package/server-functions/dist/server.cjs +201 -36
- package/server-functions/dist/server.dev.cjs +201 -36
- package/server-functions/dist/server.dev.js +199 -37
- package/server-functions/dist/server.js +199 -37
- package/types/core.d.ts +3 -0
- package/types/frames/frame-client.d.ts +18 -0
- package/types/index.d.ts +16 -2
- package/types/jsx.d.ts +9 -0
- package/types/server-functions/client.d.ts +61 -0
- package/types/server-functions/server.d.ts +94 -1
- package/types/server-mock.d.ts +11 -2
- package/types/server.d.ts +23 -2
- package/types-cjs/core.d.cts +3 -0
- package/types-cjs/frames/frame-client.d.cts +18 -0
- package/types-cjs/index.d.cts +16 -2
- package/types-cjs/jsx.d.cts +9 -0
- package/types-cjs/server-functions/client.d.cts +61 -0
- package/types-cjs/server-functions/server.d.cts +94 -1
- package/types-cjs/server-mock.d.cts +11 -2
- package/types-cjs/server.d.cts +23 -2
package/frames/dist/server.cjs
CHANGED
|
@@ -12,6 +12,9 @@ const state = globalThis[STATE] || (globalThis[STATE] = {
|
|
|
12
12
|
function setContainerTraceResolver(fn) {
|
|
13
13
|
state.resolveTrace = fn;
|
|
14
14
|
}
|
|
15
|
+
function setContainerTraceStreamMint(fn) {
|
|
16
|
+
state.streamOf = fn;
|
|
17
|
+
}
|
|
15
18
|
function isContainerTraced(value) {
|
|
16
19
|
const resolve = state.resolveTrace;
|
|
17
20
|
return !!(resolve && value && typeof value === "object" && resolve(value));
|
|
@@ -60,9 +63,10 @@ function materialize(marker) {
|
|
|
60
63
|
}
|
|
61
64
|
function parseTrace(value, ctx) {
|
|
62
65
|
const trace = value[TRACE];
|
|
66
|
+
const sub = trace.subscribe();
|
|
63
67
|
return {
|
|
64
68
|
a: trace.array ? 1 : 0,
|
|
65
|
-
i: ctx.parse(
|
|
69
|
+
i: ctx.parse(state.streamOf ? state.streamOf(sub) : sub)
|
|
66
70
|
};
|
|
67
71
|
}
|
|
68
72
|
const ContainerTracePlugin = {
|
|
@@ -76,9 +80,10 @@ const ContainerTracePlugin = {
|
|
|
76
80
|
},
|
|
77
81
|
async async(value, ctx) {
|
|
78
82
|
const trace = value[TRACE];
|
|
83
|
+
const sub = trace.subscribe();
|
|
79
84
|
return {
|
|
80
85
|
a: trace.array ? 1 : 0,
|
|
81
|
-
i: await ctx.parse(
|
|
86
|
+
i: await ctx.parse(state.streamOf ? state.streamOf(sub) : sub)
|
|
82
87
|
};
|
|
83
88
|
},
|
|
84
89
|
stream: parseTrace
|
|
@@ -103,6 +108,18 @@ const ssrAsyncValue = value => solidJs.createMemo(() => value, {
|
|
|
103
108
|
serialize: false
|
|
104
109
|
});
|
|
105
110
|
|
|
111
|
+
setContainerTraceStreamMint(iterable => {
|
|
112
|
+
const stream = seroval.createStream();
|
|
113
|
+
(async () => {
|
|
114
|
+
try {
|
|
115
|
+
for await (const value of iterable) stream.next(value);
|
|
116
|
+
stream.return(undefined);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
stream.throw(error);
|
|
119
|
+
}
|
|
120
|
+
})();
|
|
121
|
+
return stream;
|
|
122
|
+
});
|
|
106
123
|
const DEFAULT_WEB_PLUGINS = Object.freeze([web.AbortSignalPlugin,
|
|
107
124
|
web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
|
|
108
125
|
web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin,
|
|
@@ -482,6 +499,7 @@ function registerEntryAssets(manifest) {
|
|
|
482
499
|
const assets = resolveAssets(key, manifest);
|
|
483
500
|
if (assets) {
|
|
484
501
|
for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]);
|
|
502
|
+
for (let i = 1; i < assets.js.length; i++) ctx.registerAsset("module", assets.js[i]);
|
|
485
503
|
}
|
|
486
504
|
return;
|
|
487
505
|
}
|
|
@@ -741,7 +759,7 @@ function emitHeadResource(registry, context, tracking, emitResource, nonce, desc
|
|
|
741
759
|
if (!styles) tracking.boundaryStyles.set(tracking.currentBoundaryId, styles = new Set());
|
|
742
760
|
styles.add(entry);
|
|
743
761
|
}
|
|
744
|
-
const markup = `<link${attrHtml}>`;
|
|
762
|
+
const markup = `<link${attrHtml}${nonceAttr(nonce, "style")}>`;
|
|
745
763
|
if (emitResource) emitResource(markup, entry);else {
|
|
746
764
|
registry.eagerHtml += markup;
|
|
747
765
|
entry.emitted = true;
|
|
@@ -839,7 +857,7 @@ function headGroupSignature(winner) {
|
|
|
839
857
|
}
|
|
840
858
|
return sig;
|
|
841
859
|
}
|
|
842
|
-
function renderShellHead(registry, nonce, isPendingFragment) {
|
|
860
|
+
function renderShellHead(registry, nonce, isPendingFragment, noScripts) {
|
|
843
861
|
commitHeadBoundary(registry, "", isPendingFragment);
|
|
844
862
|
registry.shellFlushed = true;
|
|
845
863
|
const winners = resolveHead(registry.committed);
|
|
@@ -849,8 +867,14 @@ function renderShellHead(registry, nonce, isPendingFragment) {
|
|
|
849
867
|
let metas = "";
|
|
850
868
|
let others = "";
|
|
851
869
|
let scripts = "";
|
|
870
|
+
let title = null;
|
|
852
871
|
for (const [identity, winner] of winners) {
|
|
853
872
|
registry.flushed.set(identity, headGroupSignature(winner));
|
|
873
|
+
if (identity === "title") {
|
|
874
|
+
const children = winner.tags[0].props.children;
|
|
875
|
+
title = children == null ? "" : String(children);
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
854
878
|
for (let i = 0; i < winner.tags.length; i++) {
|
|
855
879
|
const t = winner.tags[i];
|
|
856
880
|
const markup = renderHeadTagMarkup(t.tag, t.props, identity, nonce);
|
|
@@ -859,10 +883,12 @@ function renderShellHead(registry, nonce, isPendingFragment) {
|
|
|
859
883
|
}
|
|
860
884
|
return {
|
|
861
885
|
prelude,
|
|
862
|
-
html: registry.eagerHtml + links + metas + others + scripts
|
|
886
|
+
html: registry.eagerHtml + links + metas + others + scripts,
|
|
887
|
+
title,
|
|
888
|
+
noScripts
|
|
863
889
|
};
|
|
864
890
|
}
|
|
865
|
-
function flushHeadFragment(registry, boundary) {
|
|
891
|
+
function flushHeadFragment(registry, boundary, nonce) {
|
|
866
892
|
const groups = commitHeadBoundary(registry, boundary);
|
|
867
893
|
if (!groups.length) return null;
|
|
868
894
|
const winners = resolveHead(registry.committed);
|
|
@@ -893,12 +919,75 @@ function flushHeadFragment(registry, boundary) {
|
|
|
893
919
|
if (v == null || v === false) continue;
|
|
894
920
|
attrs[name] = v === true ? "" : String(v);
|
|
895
921
|
}
|
|
922
|
+
if (nonce && !hasNonceProp(t.props)) {
|
|
923
|
+
const destination = nonceDestination(t.tag, t.props);
|
|
924
|
+
const value = destination && nonce[destination];
|
|
925
|
+
if (value) attrs.nonce = String(value);
|
|
926
|
+
}
|
|
896
927
|
const children = t.props.children;
|
|
897
928
|
ops.push(["a", identity, t.tag, attrs, children == null ? null : String(children)]);
|
|
898
929
|
}
|
|
899
930
|
}
|
|
900
931
|
return ops.length ? ops : null;
|
|
901
932
|
}
|
|
933
|
+
function normalizeNonce(nonce) {
|
|
934
|
+
if (nonce == null) return undefined;
|
|
935
|
+
if (typeof nonce === "string") {
|
|
936
|
+
const attr = nonce ? ` nonce="${escape(nonce, true)}"` : "";
|
|
937
|
+
return {
|
|
938
|
+
script: nonce,
|
|
939
|
+
style: nonce,
|
|
940
|
+
scriptAttr: attr,
|
|
941
|
+
styleAttr: attr
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
const script = nonce.script;
|
|
945
|
+
const style = nonce.style;
|
|
946
|
+
if (!script && !style) return undefined;
|
|
947
|
+
return {
|
|
948
|
+
script,
|
|
949
|
+
style,
|
|
950
|
+
scriptAttr: typeof script === "string" && script ? ` nonce="${escape(script, true)}"` : "",
|
|
951
|
+
styleAttr: typeof style === "string" && style ? ` nonce="${escape(style, true)}"` : ""
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
function asciiLowerCase(value) {
|
|
955
|
+
return value.replace(/[A-Z]/g, c => String.fromCharCode(c.charCodeAt(0) + 32));
|
|
956
|
+
}
|
|
957
|
+
function hasNonceProp(props) {
|
|
958
|
+
for (const name in props) if (name.length === 5 && asciiLowerCase(name) === "nonce" && props[name] != null) return true;
|
|
959
|
+
return false;
|
|
960
|
+
}
|
|
961
|
+
function nonceDestination(tag, props) {
|
|
962
|
+
if (tag === "script") return "script";
|
|
963
|
+
if (tag === "style") return "style";
|
|
964
|
+
if (tag !== "link") return null;
|
|
965
|
+
const rel = props.rel;
|
|
966
|
+
if (typeof rel !== "string") return null;
|
|
967
|
+
const rels = asciiLowerCase(rel).split(/[\t\n\f\r ]+/);
|
|
968
|
+
if (rels.includes("stylesheet")) return "style";
|
|
969
|
+
const isModulePreload = rels.includes("modulepreload");
|
|
970
|
+
if (!isModulePreload && !rels.includes("preload")) return null;
|
|
971
|
+
const as = typeof props.as === "string" ? asciiLowerCase(props.as) : "";
|
|
972
|
+
if (as === "style") return "style";
|
|
973
|
+
if (as === "script") return "script";
|
|
974
|
+
if (!isModulePreload) return null;
|
|
975
|
+
switch (as) {
|
|
976
|
+
case "fetch":
|
|
977
|
+
case "font":
|
|
978
|
+
case "image":
|
|
979
|
+
case "json":
|
|
980
|
+
case "text":
|
|
981
|
+
case "track":
|
|
982
|
+
return null;
|
|
983
|
+
default:
|
|
984
|
+
return "script";
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
function nonceAttr(nonce, destination) {
|
|
988
|
+
if (!nonce || !destination) return "";
|
|
989
|
+
return destination === "script" ? nonce.scriptAttr : nonce.styleAttr;
|
|
990
|
+
}
|
|
902
991
|
function renderHeadAttrHtml(props) {
|
|
903
992
|
let attrs = "";
|
|
904
993
|
for (const name in props) {
|
|
@@ -927,17 +1016,16 @@ function headAttrRecord(props, skipRelHref) {
|
|
|
927
1016
|
function renderHeadTagMarkup(tag, props, identity, nonce) {
|
|
928
1017
|
let attrs = renderHeadAttrHtml(props);
|
|
929
1018
|
if (identity != null) attrs += ` data-dh="${escape(identity, true)}"`;
|
|
930
|
-
if (nonce && (
|
|
1019
|
+
if (nonce && !hasNonceProp(props)) attrs += nonceAttr(nonce, nonceDestination(tag, props));
|
|
931
1020
|
if (tag === "meta" || tag === "link" || tag === "base") return `<${tag}${attrs}>`;
|
|
932
1021
|
let body = props.children == null ? "" : String(props.children);
|
|
933
1022
|
if (tag === "script") body = body.replace(/<\/(script)/gi, "<\\/$1");else if (tag === "style") body = escapeStyleContent(body);else body = escape(body);
|
|
934
1023
|
return `<${tag}${attrs}>${body}</${tag}>`;
|
|
935
1024
|
}
|
|
936
1025
|
const REPLACE_SCRIPT = `function $df(e){return _$HY.f?_$HY.f(e):$dfr(e)}function $dfr(e,n,o,t){if(!(n=document.getElementById(e)))return 0;if(!(o=document.getElementById("pl-"+e)))return(_$HY.dq=_$HY.dq||{})[e]=1,0;for(;o&&(8!==o.nodeType||o.nodeValue!=="pl-"+e);)t=o.nextSibling,o.remove(),o=t;t=o.parentNode,o.replaceWith(n.content),n.remove(),(_$HY.v=_$HY.v||{})[e]=1,_$HY.fe(e,t),_$HY.hp&&_$HY.hp[e]&&($dh(_$HY.hp[e]),delete _$HY.hp[e]),$dfd();return 1}function $dfl(e,o,n){if(!(o=document.getElementById("pl-"+e)))return(_$HY.dlq=_$HY.dlq||{})[e]=1,0;if(o._$fl)return 1;for(n=o.nextSibling;n;){if(8===n.nodeType&&n.nodeValue==="pl-"+e){o.parentNode&&o.parentNode.insertBefore(o.content.cloneNode(!0),n),o._$fl=1,$dfd();return 1}n=n.nextSibling}return 0}function $dflj(e,i){for(i=0;i<e.length;i++)$dfl(e[i])}function $dfd(e,i){if(e=_$HY.dq){_$HY.dq=0;for(i in e)$df(i)}if(e=_$HY.dlq){_$HY.dlq=0;for(i in e)$dfl(i)}}function $dfs(e,c,d){(_$HY.sc=_$HY.sc||{})[e]=c,d&&((_$HY.sd=_$HY.sd||{})[e]=1)}function $dfg(e,g,i,k){if(!(g=_$HY.sg&&_$HY.sg[e]))return;for(i=0;i<g.length;i++)if(_$HY.sc&&_$HY.sc[g[i]]>0)return;for(i=0;i<g.length;i++)k=g[i],delete _$HY.sg[k],$df(k)}function $dfc(e){if(--_$HY.sc[e]<=0){delete _$HY.sc[e],_$HY.sg&&_$HY.sg[e]?$dfg(e):!(_$HY.sd&&_$HY.sd[e])&&$df(e);_$HY.sd&&delete _$HY.sd[e]}}function $dfj(e,i,n){for(i=0;i<e.length;i++)if(_$HY.sc&&_$HY.sc[e[i]]>0){for(n=0;n<e.length;n++)(_$HY.sg=_$HY.sg||{})[e[n]]=e;return}for(i=0;i<e.length;i++)$df(e[i])}`;
|
|
937
|
-
const HEAD_SCRIPT = `function $dha(o,i,e,n){for(i=0;i<o.length;i++)e=o[i],"t"==e[0]?((n=document.querySelector("title"))||(n=document.createElement("title"),document.head.appendChild(n)),n.textContent=e[1],n.setAttribute("data-dh","title")):"r"==e[0]?$dhr(e[1]):(n=document.createElement(e[2]),Object.keys(e[3]).forEach(function(a){n.setAttribute(a,e[3][a])}),null!=e[4]&&(n.textContent=e[4]),n.setAttribute("data-dh",e[1]),document.head.appendChild(n))}function $dhr(v,l,i){for(l=document.head.querySelectorAll("[data-dh]"),i=0;i<l.length;i++)l[i].getAttribute("data-dh")==v&&l[i].remove()}function $dh(o){_$HY.h?_$HY.h(o):$dha(o)}`;
|
|
1026
|
+
const HEAD_SCRIPT = `function $dha(o,i,e,n){for(i=0;i<o.length;i++)e=o[i],"t"==e[0]?((n=document.querySelector("title"))?n.hasAttribute("data-dh")||n.setAttribute("data-dhf",n.textContent):(n=document.createElement("title"),document.head.appendChild(n)),n.textContent=e[1],n.setAttribute("data-dh","title")):"r"==e[0]?$dhr(e[1]):(n=document.createElement(e[2]),Object.keys(e[3]).forEach(function(a){n.setAttribute(a,e[3][a])}),null!=e[4]&&(n.textContent=e[4]),n.setAttribute("data-dh",e[1]),document.head.appendChild(n))}function $dhr(v,l,i){for(l=document.head.querySelectorAll("[data-dh]"),i=0;i<l.length;i++)l[i].getAttribute("data-dh")==v&&l[i].remove()}function $dh(o){_$HY.h?_$HY.h(o):$dha(o)}`;
|
|
938
1027
|
function renderToStream(code, options = {}) {
|
|
939
1028
|
let {
|
|
940
|
-
nonce,
|
|
941
1029
|
onCompleteShell,
|
|
942
1030
|
onCompleteAll,
|
|
943
1031
|
renderId = "",
|
|
@@ -945,6 +1033,7 @@ function renderToStream(code, options = {}) {
|
|
|
945
1033
|
manifest,
|
|
946
1034
|
onHead
|
|
947
1035
|
} = options;
|
|
1036
|
+
const nonce = normalizeNonce(options.nonce);
|
|
948
1037
|
let dispose;
|
|
949
1038
|
let dead = false;
|
|
950
1039
|
const abandon = () => {
|
|
@@ -969,6 +1058,32 @@ function renderToStream(code, options = {}) {
|
|
|
969
1058
|
} catch (_) {}
|
|
970
1059
|
abandon();
|
|
971
1060
|
};
|
|
1061
|
+
const coalesceWrites = (writeRaw, endRaw) => {
|
|
1062
|
+
let buf = "";
|
|
1063
|
+
let scheduled = false;
|
|
1064
|
+
const flush = () => {
|
|
1065
|
+
scheduled = false;
|
|
1066
|
+
if (!buf) return;
|
|
1067
|
+
const out = buf;
|
|
1068
|
+
buf = "";
|
|
1069
|
+
writeRaw(out);
|
|
1070
|
+
};
|
|
1071
|
+
return {
|
|
1072
|
+
write(payload) {
|
|
1073
|
+
buf += payload;
|
|
1074
|
+
if (buf.length >= 16384) return flush();
|
|
1075
|
+
if (!scheduled) {
|
|
1076
|
+
scheduled = true;
|
|
1077
|
+
deferFlush(flush);
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
flush,
|
|
1081
|
+
end() {
|
|
1082
|
+
flush();
|
|
1083
|
+
endRaw();
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
};
|
|
972
1087
|
const guardSink = w => ({
|
|
973
1088
|
write(payload) {
|
|
974
1089
|
if (dead) return;
|
|
@@ -988,6 +1103,23 @@ function renderToStream(code, options = {}) {
|
|
|
988
1103
|
}
|
|
989
1104
|
});
|
|
990
1105
|
const blockingPromises = new Set();
|
|
1106
|
+
const canBatchStubs = !options.serializer && !options.sink;
|
|
1107
|
+
let stubBatch = null;
|
|
1108
|
+
const STUB_BATCH_KEY = "$B";
|
|
1109
|
+
const flushStubBatch = () => {
|
|
1110
|
+
if (!stubBatch) return;
|
|
1111
|
+
const batch = stubBatch;
|
|
1112
|
+
stubBatch = null;
|
|
1113
|
+
if (batch.size === 1) {
|
|
1114
|
+
const [id, p] = batch.entries().next().value;
|
|
1115
|
+
serializer.write(id, p);
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
const obj = {};
|
|
1119
|
+
for (const [id, p] of batch) obj[id] = p;
|
|
1120
|
+
serializer.write(STUB_BATCH_KEY, obj);
|
|
1121
|
+
pushTask(`(b=>{for(var k in b)_$HY.r[k]=b[k];delete _$HY.r["${STUB_BATCH_KEY}"]})(_$HY.r["${STUB_BATCH_KEY}"])`);
|
|
1122
|
+
};
|
|
991
1123
|
let headerEmitted = false;
|
|
992
1124
|
const pushTask = task => {
|
|
993
1125
|
if (noScripts) return;
|
|
@@ -1024,10 +1156,11 @@ function renderToStream(code, options = {}) {
|
|
|
1024
1156
|
buffer.write(renderInlineStyle(styles.inline[i], nonce));
|
|
1025
1157
|
}
|
|
1026
1158
|
if (styles.links.length) {
|
|
1159
|
+
const styleAttr = nonceAttr(nonce, "style");
|
|
1027
1160
|
emitTask(`$dfs("${key}",${styles.links.length},${deferActivation ? 1 : 0})`);
|
|
1028
1161
|
writeTasks();
|
|
1029
1162
|
for (const entry of styles.links) {
|
|
1030
|
-
buffer.write(typeof entry === "string" ? `<link rel="stylesheet" href="${entry}" onload="$dfc('${key}')" onerror="$dfc('${key}')">` : `<link${entry.attrHtml} onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
|
|
1163
|
+
buffer.write(typeof entry === "string" ? `<link rel="stylesheet" href="${entry}"${styleAttr} onload="$dfc('${key}')" onerror="$dfc('${key}')">` : `<link${entry.attrHtml}${styleAttr} onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
|
|
1031
1164
|
}
|
|
1032
1165
|
buffer.write(`<template id="${key}">${value}</template>`);
|
|
1033
1166
|
} else {
|
|
@@ -1042,7 +1175,7 @@ function renderToStream(code, options = {}) {
|
|
|
1042
1175
|
},
|
|
1043
1176
|
asset(type, value) {
|
|
1044
1177
|
if (type === "module") {
|
|
1045
|
-
buffer.write(`<link rel="modulepreload" href="${value}">`);
|
|
1178
|
+
buffer.write(`<link rel="modulepreload" href="${value}"${nonceAttr(nonce, "script")}>`);
|
|
1046
1179
|
} else if (type === "inline-style") {
|
|
1047
1180
|
buffer.write(renderInlineStyle(value, nonce));
|
|
1048
1181
|
} else if (type === "head-tag") {
|
|
@@ -1077,6 +1210,7 @@ function renderToStream(code, options = {}) {
|
|
|
1077
1210
|
context.live.end = null;
|
|
1078
1211
|
end();
|
|
1079
1212
|
}
|
|
1213
|
+
flushStubBatch();
|
|
1080
1214
|
serializer.flush();
|
|
1081
1215
|
}));
|
|
1082
1216
|
}
|
|
@@ -1084,7 +1218,7 @@ function renderToStream(code, options = {}) {
|
|
|
1084
1218
|
const registry = new Map();
|
|
1085
1219
|
const writeTasks = () => {
|
|
1086
1220
|
if (tasks.length && !completed && firstFlushed) {
|
|
1087
|
-
buffer.write(`<script${nonce
|
|
1221
|
+
buffer.write(`<script${nonceAttr(nonce, "script")}>${tasks}</script>`);
|
|
1088
1222
|
tasks = "";
|
|
1089
1223
|
}
|
|
1090
1224
|
timer = null;
|
|
@@ -1138,7 +1272,7 @@ function renderToStream(code, options = {}) {
|
|
|
1138
1272
|
};
|
|
1139
1273
|
solidJs.sharedConfig.context = context = {
|
|
1140
1274
|
async: true,
|
|
1141
|
-
nonce,
|
|
1275
|
+
nonce: options.nonce,
|
|
1142
1276
|
live: {},
|
|
1143
1277
|
registerHeadTags(tags) {
|
|
1144
1278
|
registerHeadTags(headRegistry, context, tracking,
|
|
@@ -1196,10 +1330,18 @@ function renderToStream(code, options = {}) {
|
|
|
1196
1330
|
},
|
|
1197
1331
|
serialize(id, p, deferStream) {
|
|
1198
1332
|
if (solidJs.sharedConfig.context.noHydrate) return;
|
|
1199
|
-
if (!firstFlushed &&
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1333
|
+
if (!firstFlushed && p && typeof p === "object" && "then" in p) {
|
|
1334
|
+
if (deferStream) {
|
|
1335
|
+
blockingPromises.add(p);
|
|
1336
|
+
p.then(d => serializer.write(id, d)).catch(e => serializer.write(id, e));
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
if (canBatchStubs && !shellCompleted) {
|
|
1340
|
+
(stubBatch ||= new Map()).set(id, p);
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
serializer.write(id, p);
|
|
1203
1345
|
},
|
|
1204
1346
|
escape: escape,
|
|
1205
1347
|
resolve: resolveSSRNode,
|
|
@@ -1233,7 +1375,7 @@ function renderToStream(code, options = {}) {
|
|
|
1233
1375
|
queue(flushEnd);
|
|
1234
1376
|
}))
|
|
1235
1377
|
});
|
|
1236
|
-
serializer.write(key + "_fr", p);
|
|
1378
|
+
if (canBatchStubs && !shellCompleted) (stubBatch ||= new Map()).set(key + "_fr", p);else serializer.write(key + "_fr", p);
|
|
1237
1379
|
}
|
|
1238
1380
|
return (value, error) => {
|
|
1239
1381
|
if (registry.has(key)) {
|
|
@@ -1264,9 +1406,9 @@ function renderToStream(code, options = {}) {
|
|
|
1264
1406
|
} else {
|
|
1265
1407
|
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
1266
1408
|
const styles = collectStreamStyles(key, tracking, headStyles);
|
|
1267
|
-
const headOps = error ? null : flushHeadFragment(headRegistry, key);
|
|
1409
|
+
const headOps = error ? null : flushHeadFragment(headRegistry, key, nonce);
|
|
1268
1410
|
if (headOps) emitHeadOps(key, headOps);
|
|
1269
|
-
sink.fragment(key, value !== undefined ? value : " ", {
|
|
1411
|
+
sink.fragment(key, resolveSSRSelectValues(value !== undefined ? value : " "), {
|
|
1270
1412
|
styles,
|
|
1271
1413
|
revealGroup,
|
|
1272
1414
|
error
|
|
@@ -1350,15 +1492,18 @@ function renderToStream(code, options = {}) {
|
|
|
1350
1492
|
function doShell() {
|
|
1351
1493
|
if (shellCompleted) return;
|
|
1352
1494
|
solidJs.sharedConfig.context = context;
|
|
1495
|
+
const blockersBefore = blockingPromises.size;
|
|
1353
1496
|
if (!resolveRootHoles()) return;
|
|
1497
|
+
if (blockingPromises.size !== blockersBefore) return;
|
|
1354
1498
|
if (!headShellReady(headRegistry, p => blockingPromises.add(p))) return;
|
|
1355
1499
|
headStyles = new Set();
|
|
1356
1500
|
for (const url of tracking.emittedAssets) {
|
|
1357
1501
|
if (isCssUrl(url)) headStyles.add(url);
|
|
1358
1502
|
}
|
|
1359
1503
|
serializeRootAssets();
|
|
1360
|
-
|
|
1361
|
-
|
|
1504
|
+
flushStubBatch();
|
|
1505
|
+
const head = renderShellHead(headRegistry, nonce, k => registry.has(k), noScripts);
|
|
1506
|
+
sink.shell(resolveSSRSelectValues(html), {
|
|
1362
1507
|
preloads: tracking.emittedAssets,
|
|
1363
1508
|
inlineStyles: tracking.inlineStyles,
|
|
1364
1509
|
tasks,
|
|
@@ -1378,6 +1523,7 @@ function renderToStream(code, options = {}) {
|
|
|
1378
1523
|
let drainTurn = 0;
|
|
1379
1524
|
const scheduleFlush = fn => {
|
|
1380
1525
|
const attempt = () => {
|
|
1526
|
+
flushStubBatch();
|
|
1381
1527
|
if (registry.size !== lastRegistrySize || drainTurn++ < MIN_DRAIN_TURNS) {
|
|
1382
1528
|
if (registry.size !== lastRegistrySize) drainTurn = 0;
|
|
1383
1529
|
lastRegistrySize = registry.size;
|
|
@@ -1425,22 +1571,18 @@ function renderToStream(code, options = {}) {
|
|
|
1425
1571
|
}
|
|
1426
1572
|
};
|
|
1427
1573
|
writer.closed && writer.closed.catch(failed);
|
|
1428
|
-
writable = {
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
}
|
|
1437
|
-
};
|
|
1438
|
-
buffer = {
|
|
1439
|
-
write(payload) {
|
|
1440
|
-
pendingWrites = pendingWrites.then(() => writer.write(encoder.encode(payload))).catch(failed);
|
|
1441
|
-
}
|
|
1442
|
-
};
|
|
1574
|
+
buffer = writable = coalesceWrites(payload => {
|
|
1575
|
+
pendingWrites = pendingWrites.then(() => writer.write(encoder.encode(payload))).catch(failed);
|
|
1576
|
+
}, () => {
|
|
1577
|
+
pendingWrites.then(() => {
|
|
1578
|
+
ended = true;
|
|
1579
|
+
writer.releaseLock();
|
|
1580
|
+
w.close().catch(() => {});
|
|
1581
|
+
resolve();
|
|
1582
|
+
});
|
|
1583
|
+
});
|
|
1443
1584
|
buffer.write(tmp);
|
|
1585
|
+
buffer.flush();
|
|
1444
1586
|
firstFlushed = true;
|
|
1445
1587
|
if (completed) {
|
|
1446
1588
|
dispose();
|
|
@@ -1470,7 +1612,8 @@ function renderToStream(code, options = {}) {
|
|
|
1470
1612
|
allSettled(blockingPromises).then(() => {
|
|
1471
1613
|
scheduleFlush(() => {
|
|
1472
1614
|
try {
|
|
1473
|
-
|
|
1615
|
+
const blockersBefore = blockingPromises.size;
|
|
1616
|
+
if (!resolveRootHoles() || blockingPromises.size !== blockersBefore || !headShellReady(headRegistry, p => blockingPromises.add(p))) return flush();
|
|
1474
1617
|
} catch (err) {
|
|
1475
1618
|
failRender(err);
|
|
1476
1619
|
return resolve(tmp);
|
|
@@ -1499,8 +1642,10 @@ function renderToStream(code, options = {}) {
|
|
|
1499
1642
|
return;
|
|
1500
1643
|
}
|
|
1501
1644
|
if (!shellCompleted) return flush();
|
|
1502
|
-
|
|
1645
|
+
const sink = guardSink(w);
|
|
1646
|
+
buffer = writable = coalesceWrites(sink.write, sink.end);
|
|
1503
1647
|
buffer.write(tmp);
|
|
1648
|
+
buffer.flush();
|
|
1504
1649
|
firstFlushed = true;
|
|
1505
1650
|
if (completed) {
|
|
1506
1651
|
dispose();
|
|
@@ -2154,6 +2299,12 @@ function ssr(t) {
|
|
|
2154
2299
|
};
|
|
2155
2300
|
return result;
|
|
2156
2301
|
}
|
|
2302
|
+
const CLAIM_PROP = /*#__PURE__*/Symbol.for("dom-expressions.claim-prop");
|
|
2303
|
+
const CLAIMS_STREAM = 1;
|
|
2304
|
+
const CLAIMS_DOCUMENT = 2;
|
|
2305
|
+
function resolveSSRSelectValues(html) {
|
|
2306
|
+
return html;
|
|
2307
|
+
}
|
|
2157
2308
|
function escape(s, attr) {
|
|
2158
2309
|
const t = typeof s;
|
|
2159
2310
|
if (t !== "string") {
|
|
@@ -2175,22 +2326,20 @@ function escape(s, attr) {
|
|
|
2175
2326
|
return escapeSlow(s, attr, i);
|
|
2176
2327
|
}
|
|
2177
2328
|
const ESCAPE_CONTENT = /[&<]/;
|
|
2178
|
-
const ESCAPE_ATTR = /[&"]/;
|
|
2329
|
+
const ESCAPE_ATTR = /[&"<]/;
|
|
2179
2330
|
function escapeSlow(s, attr, start) {
|
|
2180
|
-
|
|
2181
|
-
const delimCode = attr ? 34 : 60;
|
|
2182
|
-
const escDelim = attr ? """ : "<";
|
|
2331
|
+
if (attr) return escapeAttrSlow(s, start);
|
|
2183
2332
|
const c0 = s.charCodeAt(start);
|
|
2184
|
-
let iDelim = c0 ===
|
|
2333
|
+
let iDelim = c0 === 60 ? start : s.indexOf("<", start);
|
|
2185
2334
|
let iAmp = c0 === 38 ? start : s.indexOf("&", start);
|
|
2186
2335
|
let left = 0,
|
|
2187
2336
|
out = "";
|
|
2188
2337
|
while (iDelim >= 0 && iAmp >= 0) {
|
|
2189
2338
|
if (iDelim < iAmp) {
|
|
2190
2339
|
if (left < iDelim) out += s.substring(left, iDelim);
|
|
2191
|
-
out +=
|
|
2340
|
+
out += "<";
|
|
2192
2341
|
left = iDelim + 1;
|
|
2193
|
-
iDelim = s.indexOf(
|
|
2342
|
+
iDelim = s.indexOf("<", left);
|
|
2194
2343
|
} else {
|
|
2195
2344
|
if (left < iAmp) out += s.substring(left, iAmp);
|
|
2196
2345
|
out += "&";
|
|
@@ -2201,9 +2350,9 @@ function escapeSlow(s, attr, start) {
|
|
|
2201
2350
|
if (iDelim >= 0) {
|
|
2202
2351
|
do {
|
|
2203
2352
|
if (left < iDelim) out += s.substring(left, iDelim);
|
|
2204
|
-
out +=
|
|
2353
|
+
out += "<";
|
|
2205
2354
|
left = iDelim + 1;
|
|
2206
|
-
iDelim = s.indexOf(
|
|
2355
|
+
iDelim = s.indexOf("<", left);
|
|
2207
2356
|
} while (iDelim >= 0);
|
|
2208
2357
|
} else while (iAmp >= 0) {
|
|
2209
2358
|
if (left < iAmp) out += s.substring(left, iAmp);
|
|
@@ -2213,6 +2362,36 @@ function escapeSlow(s, attr, start) {
|
|
|
2213
2362
|
}
|
|
2214
2363
|
return left < s.length ? out + s.substring(left) : out;
|
|
2215
2364
|
}
|
|
2365
|
+
function escapeAttrSlow(s, start) {
|
|
2366
|
+
const c0 = s.charCodeAt(start);
|
|
2367
|
+
let iQuot = c0 === 34 ? start : s.indexOf('"', start);
|
|
2368
|
+
let iAmp = c0 === 38 ? start : s.indexOf("&", start);
|
|
2369
|
+
let iLt = c0 === 60 ? start : s.indexOf("<", start);
|
|
2370
|
+
let left = 0,
|
|
2371
|
+
out = "";
|
|
2372
|
+
for (;;) {
|
|
2373
|
+
let i = -1,
|
|
2374
|
+
ent;
|
|
2375
|
+
if (iQuot >= 0) {
|
|
2376
|
+
i = iQuot;
|
|
2377
|
+
ent = """;
|
|
2378
|
+
}
|
|
2379
|
+
if (iAmp >= 0 && (i < 0 || iAmp < i)) {
|
|
2380
|
+
i = iAmp;
|
|
2381
|
+
ent = "&";
|
|
2382
|
+
}
|
|
2383
|
+
if (iLt >= 0 && (i < 0 || iLt < i)) {
|
|
2384
|
+
i = iLt;
|
|
2385
|
+
ent = "<";
|
|
2386
|
+
}
|
|
2387
|
+
if (i < 0) break;
|
|
2388
|
+
if (left < i) out += s.substring(left, i);
|
|
2389
|
+
out += ent;
|
|
2390
|
+
left = i + 1;
|
|
2391
|
+
if (i === iQuot) iQuot = s.indexOf('"', left);else if (i === iAmp) iAmp = s.indexOf("&", left);else iLt = s.indexOf("<", left);
|
|
2392
|
+
}
|
|
2393
|
+
return left < s.length ? out + s.substring(left) : out;
|
|
2394
|
+
}
|
|
2216
2395
|
function tryJoinPlainSSRArray(nodes) {
|
|
2217
2396
|
if (nodes.length === 0) return undefined;
|
|
2218
2397
|
let out = "";
|
|
@@ -2228,6 +2407,7 @@ function tryJoinPlainSSRArray(nodes) {
|
|
|
2228
2407
|
function queue(fn) {
|
|
2229
2408
|
return Promise.resolve().then(fn);
|
|
2230
2409
|
}
|
|
2410
|
+
const deferFlush = typeof setImmediate === "function" ? setImmediate : fn => setTimeout(fn, 0);
|
|
2231
2411
|
function allSettled(promises) {
|
|
2232
2412
|
let size = promises.size;
|
|
2233
2413
|
return Promise.allSettled(promises).then(() => {
|
|
@@ -2236,10 +2416,11 @@ function allSettled(promises) {
|
|
|
2236
2416
|
});
|
|
2237
2417
|
}
|
|
2238
2418
|
function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2239
|
-
const scriptTag = scripts ? `<script${nonce
|
|
2240
|
-
const
|
|
2419
|
+
const scriptTag = scripts ? `<script${nonceAttr(nonce, "script")}>${scripts}</script>` : "";
|
|
2420
|
+
const title = headTags ? headTags.title : null;
|
|
2421
|
+
let headTagsHtml = headTags ? headTags.html : "";
|
|
2241
2422
|
const headPrelude = headTags ? headTags.prelude : "";
|
|
2242
|
-
if (!onHead && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
|
|
2423
|
+
if (!onHead && title == null && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
|
|
2243
2424
|
if (!scriptTag) return html;
|
|
2244
2425
|
const xs = html.indexOf("<!--xs-->");
|
|
2245
2426
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
@@ -2251,15 +2432,33 @@ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, hea
|
|
|
2251
2432
|
html = html.slice(0, at) + headPrelude + html.slice(at);
|
|
2252
2433
|
}
|
|
2253
2434
|
}
|
|
2254
|
-
|
|
2435
|
+
let headIdx = html.indexOf("</head>");
|
|
2255
2436
|
if (headIdx === -1) {
|
|
2256
2437
|
if (onHead) {
|
|
2257
|
-
|
|
2438
|
+
let titleHtml = "";
|
|
2439
|
+
if (title != null) {
|
|
2440
|
+
titleHtml = headTags.noScripts ? `<title data-dh="title">${escape(title)}</title>` : `<script${nonceAttr(nonce, "script")}>(function(x,t){(t=document.querySelector("title"))?(t.hasAttribute("data-dh")||t.setAttribute("data-dhf",t.textContent),t.textContent=x):(document.title=x,t=document.querySelector("title"));t&&t.setAttribute("data-dh","title")})(${JSON.stringify(title).replace(/</g, "\\u003C")})</script>`;
|
|
2441
|
+
}
|
|
2442
|
+
onHead(headPrelude + headTagsHtml + titleHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce));
|
|
2258
2443
|
}
|
|
2259
2444
|
if (!scriptTag) return html;
|
|
2260
2445
|
const xs = html.indexOf("<!--xs-->");
|
|
2261
2446
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
2262
2447
|
}
|
|
2448
|
+
if (title != null) {
|
|
2449
|
+
const winner = escape(title);
|
|
2450
|
+
const open = html.match(/<head(?:\s[^>]*)?>/);
|
|
2451
|
+
const from = open ? open.index + open[0].length : 0;
|
|
2452
|
+
const m = /<title(\s[^>]*)?>([\s\S]*?)<\/title>/.exec(html.slice(from, headIdx));
|
|
2453
|
+
if (m) {
|
|
2454
|
+
const at = from + m.index;
|
|
2455
|
+
const stash = m[2].replace(/"/g, """);
|
|
2456
|
+
html = html.slice(0, at) + `<title${m[1] || ""} data-dh="title" data-dhf="${stash}">${winner}</title>` + html.slice(at + m[0].length);
|
|
2457
|
+
headIdx = html.indexOf("</head>");
|
|
2458
|
+
} else {
|
|
2459
|
+
headTagsHtml = `<title data-dh="title">${winner}</title>` + headTagsHtml;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2263
2462
|
const head = headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce);
|
|
2264
2463
|
if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
|
|
2265
2464
|
const xsIdx = html.indexOf("<!--xs-->");
|
|
@@ -2268,9 +2467,11 @@ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, hea
|
|
|
2268
2467
|
}
|
|
2269
2468
|
function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
2270
2469
|
let head = "";
|
|
2470
|
+
const styleAttr = nonceAttr(nonce, "style");
|
|
2471
|
+
const scriptAttr = nonceAttr(nonce, "script");
|
|
2271
2472
|
if (emittedAssets && emittedAssets.size) {
|
|
2272
2473
|
for (const url of emittedAssets) {
|
|
2273
|
-
head += isCssUrl(url) ? `<link rel="stylesheet" href="${url}">` : `<link rel="modulepreload" href="${url}">`;
|
|
2474
|
+
head += isCssUrl(url) ? `<link rel="stylesheet" href="${url}"${styleAttr}>` : `<link rel="modulepreload" href="${url}"${scriptAttr}>`;
|
|
2274
2475
|
}
|
|
2275
2476
|
}
|
|
2276
2477
|
if (inlineStyles && inlineStyles.size) {
|
|
@@ -2285,7 +2486,9 @@ function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
|
2285
2486
|
function serializeFragmentAssets(key, boundaryModules, context, name = key) {
|
|
2286
2487
|
const map = boundaryModules.get(key);
|
|
2287
2488
|
if (!map || !Object.keys(map).length) return;
|
|
2288
|
-
context.serialize(name + "_assets",
|
|
2489
|
+
context.serialize(name + "_assets", {
|
|
2490
|
+
...map
|
|
2491
|
+
});
|
|
2289
2492
|
}
|
|
2290
2493
|
function propagateBoundaryStyles(childKey, parentKey, tracking) {
|
|
2291
2494
|
const childStyles = tracking.getBoundaryStyles(childKey);
|
|
@@ -2330,12 +2533,15 @@ function escapeStyleContent(content) {
|
|
|
2330
2533
|
}
|
|
2331
2534
|
function renderInlineStyle(entry, nonce) {
|
|
2332
2535
|
let attrs = "";
|
|
2536
|
+
let hasNonce = false;
|
|
2333
2537
|
if (entry.attrs) {
|
|
2334
2538
|
for (const name in entry.attrs) {
|
|
2539
|
+
if (name.length === 5 && asciiLowerCase(name) === "nonce") hasNonce = true;
|
|
2335
2540
|
attrs += ` ${name}="${escape(String(entry.attrs[name]), true)}"`;
|
|
2336
2541
|
}
|
|
2337
2542
|
}
|
|
2338
|
-
|
|
2543
|
+
const nonceHtml = hasNonce ? "" : nonceAttr(nonce, "style");
|
|
2544
|
+
return `<style${nonceHtml} data-asset="${escape(entry.id, true)}"${attrs}>${escapeStyleContent(entry.content)}</style>`;
|
|
2339
2545
|
}
|
|
2340
2546
|
function waitForFragments(registry, key) {
|
|
2341
2547
|
for (const k of [...registry.keys()].reverse()) {
|
|
@@ -2788,6 +2994,7 @@ function renderServerComponent(component, options = {}) {
|
|
|
2788
2994
|
ctx.commit = sink.commit;
|
|
2789
2995
|
ctx.commitEpoch = () => sink.epoch;
|
|
2790
2996
|
ctx.liveHoles = createLiveHoles(sink);
|
|
2997
|
+
ctx.claims = CLAIMS_STREAM;
|
|
2791
2998
|
}
|
|
2792
2999
|
return serverComponentScope(() => component(props));
|
|
2793
3000
|
};
|
|
@@ -3081,6 +3288,7 @@ function createDocumentSlotProps(clientProps, frameId) {
|
|
|
3081
3288
|
return out;
|
|
3082
3289
|
};
|
|
3083
3290
|
fn.$lhSkip = true;
|
|
3291
|
+
fn[CLAIM_PROP] = prop;
|
|
3084
3292
|
getters.set(prop, fn);
|
|
3085
3293
|
}
|
|
3086
3294
|
return fn;
|
|
@@ -3212,6 +3420,7 @@ function frameTransformDirectResult(value, {
|
|
|
3212
3420
|
},
|
|
3213
3421
|
serverOwned(() => {
|
|
3214
3422
|
armDocumentLiveHoles(solidJs.sharedConfig.context);
|
|
3423
|
+
solidJs.sharedConfig.context.claims = CLAIMS_DOCUMENT;
|
|
3215
3424
|
const slotProps = createDocumentSlotProps(props, id);
|
|
3216
3425
|
return serverComponentScope(() => component(slotProps));
|
|
3217
3426
|
}), {
|
|
@@ -3455,6 +3664,7 @@ function createSlotProps(sink, frame) {
|
|
|
3455
3664
|
return slotRange(occurrence);
|
|
3456
3665
|
};
|
|
3457
3666
|
fn.$lhSkip = true;
|
|
3667
|
+
fn[CLAIM_PROP] = prop;
|
|
3458
3668
|
getters.set(prop, fn);
|
|
3459
3669
|
}
|
|
3460
3670
|
return fn;
|