@solidjs/web 2.0.0-beta.30 → 2.0.0-beta.31

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 CHANGED
@@ -172,7 +172,7 @@ function reconcileArrays(parentNode, a, b, marker) {
172
172
 
173
173
  const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
174
174
  const HEAD_ATTR_NAME = /^[a-zA-Z_][a-zA-Z0-9_:.-]*$/;
175
- const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "icon", "stylesheet"]);
175
+ const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "stylesheet"]);
176
176
  const RESOURCE_QUALIFIERS = ["as", "crossorigin", "type", "media", "imagesrcset", "imagesizes"];
177
177
  function evalHeadValue(v) {
178
178
  return typeof v === "function" ? v() : v;
@@ -215,12 +215,14 @@ function replaceableIdentity(tag, props, key, unique) {
215
215
  if (tag === "meta" && props.charset != null) return "charset";
216
216
  if (key != null) return tag + ":key:" + key;
217
217
  if (tag === "meta") {
218
- if (props.name != null) return "meta:name:" + props.name;
219
- if (props.property != null) return "meta:property:" + props.property;
220
- if (props["http-equiv"] != null) return "meta:http-equiv:" + props["http-equiv"];
218
+ for (const ns of ["name", "property", "http-equiv"]) if (props[ns] != null) return "meta:" + ns + ":" + props[ns] + (props.media != null ? ":media=" + props.media : "");
221
219
  return unique;
222
220
  }
223
- if (tag === "link") return "link:" + (props.rel || "") + ":" + (props.href || "");
221
+ if (tag === "link") {
222
+ const rel = props.rel || "";
223
+ if (rel === "icon" || rel === "apple-touch-icon") return "link:" + rel + (props.sizes != null ? ":sizes=" + props.sizes : "") + (props.type != null ? ":type=" + props.type : "");
224
+ return "link:" + rel + ":" + (props.href || "");
225
+ }
224
226
  return unique;
225
227
  }
226
228
  function resolveHead(groups) {
@@ -838,22 +840,26 @@ function flushHeadRegistry() {
838
840
  headOwned.set(identity, els);
839
841
  }
840
842
  }
841
- function renderHeadElement(t, identity, existing) {
842
- for (let i = 0; i < existing.length; i++) {
843
- if (headElementMatches(existing[i], t)) return existing.splice(i, 1)[0];
844
- }
845
- const el = document.createElement(t.tag);
846
- for (const name in t.props) {
843
+ function createHeadElement(tag, props) {
844
+ const el = document.createElement(tag);
845
+ for (const name in props) {
847
846
  if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
848
847
  if (!HEAD_ATTR_NAME.test(name)) {
849
848
  console.warn(`useHead: ignoring invalid attribute name "${name}"`);
850
849
  continue;
851
850
  }
852
- const v = t.props[name];
851
+ const v = props[name];
853
852
  if (v == null || v === false) continue;
854
853
  el.setAttribute(name, v === true ? "" : String(v));
855
854
  }
856
- if (t.props.children != null) el.textContent = String(t.props.children);
855
+ if (props.children != null) el.textContent = String(props.children);
856
+ return el;
857
+ }
858
+ function renderHeadElement(t, identity, existing) {
859
+ for (let i = 0; i < existing.length; i++) {
860
+ if (headElementMatches(existing[i], t)) return existing.splice(i, 1)[0];
861
+ }
862
+ const el = createHeadElement(t.tag, t.props);
857
863
  el.setAttribute("data-dh", identity);
858
864
  document.head.appendChild(el);
859
865
  return el;
@@ -896,23 +902,11 @@ function acquireHeadResource(tag, props) {
896
902
  if (url != null) {
897
903
  if (tag === "link") el = findAssetElement(`link[rel="${props.rel}"]`, "href", url);else if (tag === "script") el = findAssetElement("script[src]", "src", url);else el = findAssetElement("style[href]", "href", url);
898
904
  }
899
- if (!el) {
900
- el = document.createElement(tag);
901
- for (const name in props) {
902
- if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
903
- if (!HEAD_ATTR_NAME.test(name)) continue;
904
- const v = props[name];
905
- if (v == null || v === false) continue;
906
- el.setAttribute(name, v === true ? "" : String(v));
907
- }
908
- if (props.children != null) el.textContent = String(props.children);
909
- document.head.appendChild(el);
910
- }
905
+ if (!el) document.head.appendChild(createHeadElement(tag, props));
911
906
  return noopFn;
912
907
  }
913
908
  function noopFn() {}
914
909
  function useHead(tags) {
915
- const list = Array.isArray(tags) ? tags : [tags];
916
910
  initHeadRegistry();
917
911
  const reg = {
918
912
  seq: -1,
@@ -920,6 +914,8 @@ function useHead(tags) {
920
914
  };
921
915
  const uid = ++headUid;
922
916
  effect(() => {
917
+ let list = typeof tags === "function" ? tags() : tags;
918
+ if (!Array.isArray(list)) list = [list];
923
919
  const replaceable = [];
924
920
  const resources = [];
925
921
  for (let i = 0; i < list.length; i++) {
@@ -1622,19 +1618,29 @@ function portalImpl(props) {
1622
1618
  });
1623
1619
  return treeMarker;
1624
1620
  }
1625
- const COMPONENT_HANDOFF = Symbol.for("dom-expressions.component-handoff");
1626
- function resolveHandoff(next, prev) {
1627
- const handoff = typeof next === "function" && next !== null && next[COMPONENT_HANDOFF];
1628
- return handoff && handoff.take(prev) ? prev : next;
1621
+ const COMPONENT_BINDING = Symbol.for("dom-expressions.component-binding");
1622
+ function bindingOf(value) {
1623
+ return value !== null && (typeof value === "function" || typeof value === "object") && value[COMPONENT_BINDING] || undefined;
1629
1624
  }
1630
1625
  function dynamic(source) {
1631
1626
  let latest = 0;
1627
+ const sites = new Set();
1628
+ const resolveBinding = (next, prev) => {
1629
+ const binding = bindingOf(next);
1630
+ if (!binding) return next;
1631
+ const prevBinding = bindingOf(prev);
1632
+ if (prevBinding && prevBinding.component === binding.component) {
1633
+ for (const deliver of sites) deliver(binding.address);
1634
+ return prev;
1635
+ }
1636
+ return next;
1637
+ };
1632
1638
  const cached = solidJs.createMemo(prev => {
1633
1639
  const next = source();
1634
- if (!next || typeof next.then !== "function") return resolveHandoff(next, prev);
1640
+ if (!next || typeof next.then !== "function") return resolveBinding(next, prev);
1635
1641
  const token = ++latest;
1636
1642
  return {
1637
- then: (onFulfilled, onRejected) => next.then(resolved => onFulfilled(token === latest ? resolveHandoff(resolved, prev) : resolved), onRejected)
1643
+ then: (onFulfilled, onRejected) => next.then(resolved => onFulfilled(token === latest ? resolveBinding(resolved, prev) : resolved), onRejected)
1638
1644
  };
1639
1645
  }, {
1640
1646
  lazy: true
@@ -1644,10 +1650,19 @@ function dynamic(source) {
1644
1650
  const component = cached();
1645
1651
  switch (typeof component) {
1646
1652
  case "function":
1647
- Object.assign(component, {
1648
- [solidJs.$DEVCOMP]: true
1649
- });
1650
- return solidJs.untrack(() => component(props));
1653
+ {
1654
+ Object.assign(component, {
1655
+ [solidJs.$DEVCOMP]: true
1656
+ });
1657
+ const binding = bindingOf(component);
1658
+ if (binding) {
1659
+ const [address, setAddress] = solidJs.createSignal(binding.address);
1660
+ sites.add(setAddress);
1661
+ solidJs.onCleanup(() => sites.delete(setAddress));
1662
+ return solidJs.untrack(() => binding.component(props, address));
1663
+ }
1664
+ return solidJs.untrack(() => component(props));
1665
+ }
1651
1666
  case "string":
1652
1667
  const el = solidJs.sharedConfig.hydrating ? getNextElement() : createElement(component, solidJs.untrack(() => props.is));
1653
1668
  spread(el, props);
@@ -1684,9 +1699,7 @@ _moduleUrl) {
1684
1699
  if ((Comp = solidJs.untrack(comp)) && !solidJs.sharedConfig.hydrating) return Comp(rest);
1685
1700
  const [mounted, setMounted] = solidJs.createSignal(!solidJs.sharedConfig.hydrating);
1686
1701
  const gate = solidJs.createMemo(() => (Comp = comp(), m = mounted(), solidJs.untrack(() => Comp && m ? Comp(rest) : props.fallback)));
1687
- solidJs.onSettled(() => {
1688
- setMounted(true);
1689
- });
1702
+ solidJs.sharedConfig.onHydrationEnd(() => setMounted(true));
1690
1703
  return gate;
1691
1704
  };
1692
1705
  }
package/dist/dev.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createRenderEffect, createMemo, sharedConfig, untrack, runWithOwner, flatten, createRoot, merge, createComponent, omit, createOwner, createSignal, onSettled, $DEVCOMP, enableHydration, enforceLoadingBoundary, flush, getOwner, createEffect } from 'solid-js';
1
+ import { createRenderEffect, createMemo, sharedConfig, untrack, runWithOwner, flatten, createRoot, merge, createComponent, omit, createOwner, createSignal, $DEVCOMP, onCleanup, enableHydration, enforceLoadingBoundary, flush, getOwner, createEffect } from 'solid-js';
2
2
  export { Errored, For, Hydration, Loading, Match, NoHydration, Repeat, Reveal, Show, Switch, createComponent, getOwner, untrack } from 'solid-js';
3
3
 
4
4
  const DOMWithState = {
@@ -171,7 +171,7 @@ function reconcileArrays(parentNode, a, b, marker) {
171
171
 
172
172
  const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
173
173
  const HEAD_ATTR_NAME = /^[a-zA-Z_][a-zA-Z0-9_:.-]*$/;
174
- const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "icon", "stylesheet"]);
174
+ const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "stylesheet"]);
175
175
  const RESOURCE_QUALIFIERS = ["as", "crossorigin", "type", "media", "imagesrcset", "imagesizes"];
176
176
  function evalHeadValue(v) {
177
177
  return typeof v === "function" ? v() : v;
@@ -214,12 +214,14 @@ function replaceableIdentity(tag, props, key, unique) {
214
214
  if (tag === "meta" && props.charset != null) return "charset";
215
215
  if (key != null) return tag + ":key:" + key;
216
216
  if (tag === "meta") {
217
- if (props.name != null) return "meta:name:" + props.name;
218
- if (props.property != null) return "meta:property:" + props.property;
219
- if (props["http-equiv"] != null) return "meta:http-equiv:" + props["http-equiv"];
217
+ for (const ns of ["name", "property", "http-equiv"]) if (props[ns] != null) return "meta:" + ns + ":" + props[ns] + (props.media != null ? ":media=" + props.media : "");
220
218
  return unique;
221
219
  }
222
- if (tag === "link") return "link:" + (props.rel || "") + ":" + (props.href || "");
220
+ if (tag === "link") {
221
+ const rel = props.rel || "";
222
+ if (rel === "icon" || rel === "apple-touch-icon") return "link:" + rel + (props.sizes != null ? ":sizes=" + props.sizes : "") + (props.type != null ? ":type=" + props.type : "");
223
+ return "link:" + rel + ":" + (props.href || "");
224
+ }
223
225
  return unique;
224
226
  }
225
227
  function resolveHead(groups) {
@@ -837,22 +839,26 @@ function flushHeadRegistry() {
837
839
  headOwned.set(identity, els);
838
840
  }
839
841
  }
840
- function renderHeadElement(t, identity, existing) {
841
- for (let i = 0; i < existing.length; i++) {
842
- if (headElementMatches(existing[i], t)) return existing.splice(i, 1)[0];
843
- }
844
- const el = document.createElement(t.tag);
845
- for (const name in t.props) {
842
+ function createHeadElement(tag, props) {
843
+ const el = document.createElement(tag);
844
+ for (const name in props) {
846
845
  if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
847
846
  if (!HEAD_ATTR_NAME.test(name)) {
848
847
  console.warn(`useHead: ignoring invalid attribute name "${name}"`);
849
848
  continue;
850
849
  }
851
- const v = t.props[name];
850
+ const v = props[name];
852
851
  if (v == null || v === false) continue;
853
852
  el.setAttribute(name, v === true ? "" : String(v));
854
853
  }
855
- if (t.props.children != null) el.textContent = String(t.props.children);
854
+ if (props.children != null) el.textContent = String(props.children);
855
+ return el;
856
+ }
857
+ function renderHeadElement(t, identity, existing) {
858
+ for (let i = 0; i < existing.length; i++) {
859
+ if (headElementMatches(existing[i], t)) return existing.splice(i, 1)[0];
860
+ }
861
+ const el = createHeadElement(t.tag, t.props);
856
862
  el.setAttribute("data-dh", identity);
857
863
  document.head.appendChild(el);
858
864
  return el;
@@ -895,23 +901,11 @@ function acquireHeadResource(tag, props) {
895
901
  if (url != null) {
896
902
  if (tag === "link") el = findAssetElement(`link[rel="${props.rel}"]`, "href", url);else if (tag === "script") el = findAssetElement("script[src]", "src", url);else el = findAssetElement("style[href]", "href", url);
897
903
  }
898
- if (!el) {
899
- el = document.createElement(tag);
900
- for (const name in props) {
901
- if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
902
- if (!HEAD_ATTR_NAME.test(name)) continue;
903
- const v = props[name];
904
- if (v == null || v === false) continue;
905
- el.setAttribute(name, v === true ? "" : String(v));
906
- }
907
- if (props.children != null) el.textContent = String(props.children);
908
- document.head.appendChild(el);
909
- }
904
+ if (!el) document.head.appendChild(createHeadElement(tag, props));
910
905
  return noopFn;
911
906
  }
912
907
  function noopFn() {}
913
908
  function useHead(tags) {
914
- const list = Array.isArray(tags) ? tags : [tags];
915
909
  initHeadRegistry();
916
910
  const reg = {
917
911
  seq: -1,
@@ -919,6 +913,8 @@ function useHead(tags) {
919
913
  };
920
914
  const uid = ++headUid;
921
915
  effect(() => {
916
+ let list = typeof tags === "function" ? tags() : tags;
917
+ if (!Array.isArray(list)) list = [list];
922
918
  const replaceable = [];
923
919
  const resources = [];
924
920
  for (let i = 0; i < list.length; i++) {
@@ -1621,19 +1617,29 @@ function portalImpl(props) {
1621
1617
  });
1622
1618
  return treeMarker;
1623
1619
  }
1624
- const COMPONENT_HANDOFF = Symbol.for("dom-expressions.component-handoff");
1625
- function resolveHandoff(next, prev) {
1626
- const handoff = typeof next === "function" && next !== null && next[COMPONENT_HANDOFF];
1627
- return handoff && handoff.take(prev) ? prev : next;
1620
+ const COMPONENT_BINDING = Symbol.for("dom-expressions.component-binding");
1621
+ function bindingOf(value) {
1622
+ return value !== null && (typeof value === "function" || typeof value === "object") && value[COMPONENT_BINDING] || undefined;
1628
1623
  }
1629
1624
  function dynamic(source) {
1630
1625
  let latest = 0;
1626
+ const sites = new Set();
1627
+ const resolveBinding = (next, prev) => {
1628
+ const binding = bindingOf(next);
1629
+ if (!binding) return next;
1630
+ const prevBinding = bindingOf(prev);
1631
+ if (prevBinding && prevBinding.component === binding.component) {
1632
+ for (const deliver of sites) deliver(binding.address);
1633
+ return prev;
1634
+ }
1635
+ return next;
1636
+ };
1631
1637
  const cached = createMemo(prev => {
1632
1638
  const next = source();
1633
- if (!next || typeof next.then !== "function") return resolveHandoff(next, prev);
1639
+ if (!next || typeof next.then !== "function") return resolveBinding(next, prev);
1634
1640
  const token = ++latest;
1635
1641
  return {
1636
- then: (onFulfilled, onRejected) => next.then(resolved => onFulfilled(token === latest ? resolveHandoff(resolved, prev) : resolved), onRejected)
1642
+ then: (onFulfilled, onRejected) => next.then(resolved => onFulfilled(token === latest ? resolveBinding(resolved, prev) : resolved), onRejected)
1637
1643
  };
1638
1644
  }, {
1639
1645
  lazy: true
@@ -1643,10 +1649,19 @@ function dynamic(source) {
1643
1649
  const component = cached();
1644
1650
  switch (typeof component) {
1645
1651
  case "function":
1646
- Object.assign(component, {
1647
- [$DEVCOMP]: true
1648
- });
1649
- return untrack(() => component(props));
1652
+ {
1653
+ Object.assign(component, {
1654
+ [$DEVCOMP]: true
1655
+ });
1656
+ const binding = bindingOf(component);
1657
+ if (binding) {
1658
+ const [address, setAddress] = createSignal(binding.address);
1659
+ sites.add(setAddress);
1660
+ onCleanup(() => sites.delete(setAddress));
1661
+ return untrack(() => binding.component(props, address));
1662
+ }
1663
+ return untrack(() => component(props));
1664
+ }
1650
1665
  case "string":
1651
1666
  const el = sharedConfig.hydrating ? getNextElement() : createElement(component, untrack(() => props.is));
1652
1667
  spread(el, props);
@@ -1683,9 +1698,7 @@ _moduleUrl) {
1683
1698
  if ((Comp = untrack(comp)) && !sharedConfig.hydrating) return Comp(rest);
1684
1699
  const [mounted, setMounted] = createSignal(!sharedConfig.hydrating);
1685
1700
  const gate = createMemo(() => (Comp = comp(), m = mounted(), untrack(() => Comp && m ? Comp(rest) : props.fallback)));
1686
- onSettled(() => {
1687
- setMounted(true);
1688
- });
1701
+ sharedConfig.onHydrationEnd(() => setMounted(true));
1689
1702
  return gate;
1690
1703
  };
1691
1704
  }
package/dist/server.cjs CHANGED
@@ -103,7 +103,7 @@ seroval.Feature.RegExp;
103
103
 
104
104
  const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
105
105
  const HEAD_ATTR_NAME = /^[a-zA-Z_][a-zA-Z0-9_:.-]*$/;
106
- const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "icon", "stylesheet"]);
106
+ const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "stylesheet"]);
107
107
  const RESOURCE_QUALIFIERS = ["as", "crossorigin", "type", "media", "imagesrcset", "imagesizes"];
108
108
  const STYLESHEET_FETCH_META = new Set(["crossorigin", "integrity", "referrerpolicy", "fetchpriority"]);
109
109
  function evalHeadValue(v) {
@@ -147,12 +147,14 @@ function replaceableIdentity(tag, props, key, unique) {
147
147
  if (tag === "meta" && props.charset != null) return "charset";
148
148
  if (key != null) return tag + ":key:" + key;
149
149
  if (tag === "meta") {
150
- if (props.name != null) return "meta:name:" + props.name;
151
- if (props.property != null) return "meta:property:" + props.property;
152
- if (props["http-equiv"] != null) return "meta:http-equiv:" + props["http-equiv"];
150
+ for (const ns of ["name", "property", "http-equiv"]) if (props[ns] != null) return "meta:" + ns + ":" + props[ns] + (props.media != null ? ":media=" + props.media : "");
153
151
  return unique;
154
152
  }
155
- if (tag === "link") return "link:" + (props.rel || "") + ":" + (props.href || "");
153
+ if (tag === "link") {
154
+ const rel = props.rel || "";
155
+ if (rel === "icon" || rel === "apple-touch-icon") return "link:" + rel + (props.sizes != null ? ":sizes=" + props.sizes : "") + (props.type != null ? ":type=" + props.type : "");
156
+ return "link:" + rel + ":" + (props.href || "");
157
+ }
156
158
  return unique;
157
159
  }
158
160
  function resolveHead(groups) {
@@ -344,6 +346,15 @@ function createHeadRegistry() {
344
346
  }
345
347
  function registerHeadTags(registry, context, tracking, emitResource, nonce, tags) {
346
348
  const boundary = context._currentBoundaryId || "";
349
+ if (typeof tags === "function") {
350
+ registry.pending.push({
351
+ boundary,
352
+ list: tags,
353
+ resource: (desc, rel) => emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel)
354
+ });
355
+ return;
356
+ }
357
+ if (!Array.isArray(tags)) tags = [tags];
347
358
  let replaceable = null;
348
359
  for (let i = 0; i < tags.length; i++) {
349
360
  const desc = tags[i];
@@ -431,9 +442,39 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
431
442
  keep.push(reg);
432
443
  continue;
433
444
  }
445
+ let descs = reg.tags;
446
+ if (reg.list) {
447
+ let resolved;
448
+ try {
449
+ resolved = reg.list();
450
+ } catch (err) {
451
+ console.warn(`useHead: error evaluating head group membership`, err);
452
+ continue;
453
+ }
454
+ if (!Array.isArray(resolved)) resolved = [resolved];
455
+ descs = [];
456
+ for (let j = 0; j < resolved.length; j++) {
457
+ const desc = resolved[j];
458
+ if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
459
+ console.warn(`useHead: ignoring non-head tag`, desc);
460
+ continue;
461
+ }
462
+ const cls = classifyHeadTag(desc);
463
+ if (cls.resource) {
464
+ reg.resource(desc, cls.rel);
465
+ } else {
466
+ descs.push(cls.rel !== undefined ? {
467
+ tag: desc.tag,
468
+ props: desc.props,
469
+ key: desc.key,
470
+ rel: cls.rel
471
+ } : desc);
472
+ }
473
+ }
474
+ }
434
475
  const tags = [];
435
- for (let j = 0; j < reg.tags.length; j++) {
436
- const desc = reg.tags[j];
476
+ for (let j = 0; j < descs.length; j++) {
477
+ const desc = descs[j];
437
478
  let props, key;
438
479
  try {
439
480
  props = evalHeadProps(desc.props || {}, desc.rel !== undefined ? {
@@ -582,10 +623,10 @@ function useHead(tags) {
582
623
  console.warn("useHead() called outside of a server render; registration ignored.");
583
624
  return;
584
625
  }
585
- ctx.registerHeadTags(Array.isArray(tags) ? tags : [tags]);
626
+ ctx.registerHeadTags(tags);
586
627
  }
587
628
  const VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i;
588
- 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.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])}`;
629
+ 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])}`;
589
630
  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)}`;
590
631
  function renderToString(code, options = {}) {
591
632
  const {
@@ -668,6 +709,41 @@ function renderToStream(code, options = {}) {
668
709
  onHead
669
710
  } = options;
670
711
  let dispose;
712
+ let dead = false;
713
+ const abandon = () => {
714
+ if (dead) return;
715
+ dead = true;
716
+ completed = true;
717
+ buffer = {
718
+ write() {}
719
+ };
720
+ writable = {
721
+ end() {}
722
+ };
723
+ if (dispose) {
724
+ const d = dispose;
725
+ dispose = () => {};
726
+ d();
727
+ }
728
+ };
729
+ const guardSink = w => ({
730
+ write(payload) {
731
+ if (dead) return;
732
+ try {
733
+ w.write(payload);
734
+ } catch (_) {
735
+ abandon();
736
+ }
737
+ },
738
+ end() {
739
+ if (dead) return;
740
+ try {
741
+ w.end();
742
+ } catch (_) {
743
+ abandon();
744
+ }
745
+ }
746
+ });
671
747
  const blockingPromises = new Set();
672
748
  let headerEmitted = false;
673
749
  const pushTask = task => {
@@ -1011,8 +1087,8 @@ function renderToStream(code, options = {}) {
1011
1087
  }
1012
1088
  function doShell() {
1013
1089
  if (shellCompleted) return;
1014
- if (!resolveRootHoles()) return;
1015
1090
  solidJs.sharedConfig.context = context;
1091
+ if (!resolveRootHoles()) return;
1016
1092
  const assetsHtml = resolveAssetsHtml(context.assets);
1017
1093
  headStyles = new Set();
1018
1094
  for (const url of tracking.emittedAssets) {
@@ -1069,14 +1145,24 @@ function renderToStream(code, options = {}) {
1069
1145
  function flush() {
1070
1146
  allSettled(blockingPromises).then(() => {
1071
1147
  scheduleFlush(() => {
1148
+ if (dead) return resolve();
1072
1149
  doShell();
1073
1150
  if (!shellCompleted) return flush();
1074
1151
  const encoder = new TextEncoder();
1075
1152
  const writer = w.getWriter();
1076
1153
  let pendingWrites = Promise.resolve();
1154
+ let ended = false;
1155
+ const failed = () => {
1156
+ if (!ended) {
1157
+ abandon();
1158
+ resolve();
1159
+ }
1160
+ };
1161
+ writer.closed && writer.closed.catch(failed);
1077
1162
  writable = {
1078
1163
  end() {
1079
1164
  pendingWrites.then(() => {
1165
+ ended = true;
1080
1166
  writer.releaseLock();
1081
1167
  w.close().catch(() => {});
1082
1168
  resolve();
@@ -1085,7 +1171,7 @@ function renderToStream(code, options = {}) {
1085
1171
  };
1086
1172
  buffer = {
1087
1173
  write(payload) {
1088
- pendingWrites = pendingWrites.then(() => writer.write(encoder.encode(payload))).catch(() => {});
1174
+ pendingWrites = pendingWrites.then(() => writer.write(encoder.encode(payload))).catch(failed);
1089
1175
  }
1090
1176
  };
1091
1177
  buffer.write(tmp);
@@ -1128,9 +1214,10 @@ function renderToStream(code, options = {}) {
1128
1214
  function flush() {
1129
1215
  allSettled(blockingPromises).then(() => {
1130
1216
  scheduleFlush(() => {
1217
+ if (dead) return;
1131
1218
  doShell();
1132
1219
  if (!shellCompleted) return flush();
1133
- buffer = writable = w;
1220
+ buffer = writable = guardSink(w);
1134
1221
  buffer.write(tmp);
1135
1222
  firstFlushed = true;
1136
1223
  if (completed) {