@askrjs/askr 0.4.0 → 0.4.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +55 -1
  2. package/dist/actions/index.js +4 -4
  3. package/dist/benchmark.js +6 -6
  4. package/dist/boot/index.js +1 -1
  5. package/dist/{boot-DaoTYoCw.js → boot-DUJkrqGs.js} +79 -36
  6. package/dist/{browser-activity-CB8e-V4f.js → browser-activity-2r5gA1Cb.js} +6 -4
  7. package/dist/components/index.js +1 -1
  8. package/dist/{compose-ref-DWzdbxsD.js → compose-ref-ccRU59BM.js} +7 -1
  9. package/dist/control/index.js +1 -1
  10. package/dist/{control-nfpT2fbK.js → control-hr3B0QaD.js} +4 -2
  11. package/dist/{csp-nonce-DwGw1A6Q.js → csp-nonce-D-XM_uuJ.js} +1 -1
  12. package/dist/data/index.js +3 -3
  13. package/dist/{data-BCwClJiF.js → data-BsnOUpQ6.js} +18 -8
  14. package/dist/{data-runtime-C1bFAlba.js → data-runtime-i-RD0Ffm.js} +1 -1
  15. package/dist/{deferred-bEEHHvic.js → deferred-nGZglpj6.js} +5 -5
  16. package/dist/{error-boundary-Bpwofwps.js → error-boundary-ChXoIFVl.js} +2 -2
  17. package/dist/foundations/index.js +2 -2
  18. package/dist/foundations/interactions/index.js +1 -1
  19. package/dist/foundations/state/index.js +1 -1
  20. package/dist/foundations/structures/index.js +2 -2
  21. package/dist/foundations/utilities/index.js +1 -1
  22. package/dist/fx/index.js +2 -2
  23. package/dist/{hooks-BimKStr4.js → hooks-kjLigwDJ.js} +1 -1
  24. package/dist/index.js +5 -5
  25. package/dist/{instance-BAnfmXOR.js → instance-DL-YKrj6.js} +6 -2
  26. package/dist/{interactions-D2BoREb-.js → interactions-B_wfsDQg.js} +5 -1
  27. package/dist/{manifest-CW9gyNBY.js → manifest-BNupb86f.js} +1 -1
  28. package/dist/{navigate-CP_0Zy5U.js → navigate-DsfO12hB.js} +95 -79
  29. package/dist/{portal-DuOKfnLa.js → portal-LYf4cbHd.js} +3 -3
  30. package/dist/{query-registry-WMCN0BJL.js → query-registry-tzSiVrV_.js} +7 -2
  31. package/dist/{render-sync-IC5lMFpq.js → render-sync-Qz-9Hcqw.js} +187 -29
  32. package/dist/{resolution-Cx82-xjW.js → resolution-CF1BqHLm.js} +22 -8
  33. package/dist/{resource-CLjB7RBQ.js → resource-BhcaFqdB.js} +2 -2
  34. package/dist/resources/index.js +25 -27
  35. package/dist/router/index.js +8 -8
  36. package/dist/{scope-CwpVSHVf.js → scope-ila_zaId.js} +2 -2
  37. package/dist/ssg/index.js +43 -14
  38. package/dist/ssr/index.js +2 -2
  39. package/dist/{ssr-DoV-vJ-5.js → ssr-DPfdcq0e.js} +1 -1
  40. package/dist/{ssr-BJ8ug7zH.js → ssr-DueDLmhp.js} +6 -6
  41. package/dist/{state-DWO1KzkX.js → state-i9D4EtY6.js} +19 -1
  42. package/dist/{structures-D4dDMqHX.js → structures-CkehlOT3.js} +1 -1
  43. package/dist/testing/index.js +6 -6
  44. package/dist/{url-CnbfpX0K.js → url-C9xMpMMv.js} +6 -6
  45. package/dist/{verify-hydration-DpVaDnqz.js → verify-hydration-Jh5rnm_w.js} +4 -4
  46. package/package.json +1 -1
@@ -1,17 +1,17 @@
1
- import { A as untrack, F as logger, j as Owner, t as ComponentInstance } from "./instance-BAnfmXOR.js";
1
+ import { A as untrack, I as logger, j as Owner, t as ComponentInstance } from "./instance-DL-YKrj6.js";
2
2
  import { n as readValue } from "./readable-DFWOsTac.js";
3
3
  import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-DRS-qjiN.js";
4
- import { v as clarifyRenderOverflow } from "./hooks-BimKStr4.js";
5
- import { r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-DwGw1A6Q.js";
4
+ import { v as clarifyRenderOverflow } from "./hooks-kjLigwDJ.js";
5
+ import { r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-D-XM_uuJ.js";
6
6
  import { C as withHydrationRenderUrl, T as SSRDataMissingError, _ as createPageRenderEnvelope, b as isPageRenderEnvelope, f as startRenderPhase$1, m as stopRenderPhase$1, r as getCurrentRenderData, t as configureRenderContextProvider, w as withPageFramework, y as isEmptyPageRenderEnvelope } from "./render-context-DGHnEveC.js";
7
- import { o as functionChildOutput, s as normalizeChildren } from "./error-boundary-Bpwofwps.js";
7
+ import { o as functionChildOutput, s as normalizeChildren } from "./error-boundary-ChXoIFVl.js";
8
8
  import { n as isPromiseLike } from "./promise-Dz8iIHAm.js";
9
- import { d as DEFERRED_BOUNDARY, i as dehydrateDataRuntime, p as isDeferred } from "./query-registry-WMCN0BJL.js";
10
- import { ft as getRouteHydrationMetadata, ht as validateRouteHydrationData } from "./resolution-Cx82-xjW.js";
11
- import { a as SSR_PORTAL_HOST, n as Portal, o as comparePortalWriterOrder, s as createSSRPortalAnchorToken, t as DefaultPortal } from "./portal-DuOKfnLa.js";
12
- import { t as createDataRuntime } from "./data-runtime-C1bFAlba.js";
13
- import { d as isCustomElementName, o as isUnsafeUrlAttribute, s as rejectUnsafeUrlAttribute, u as getPublicAttributeName } from "./url-CnbfpX0K.js";
14
- import { d as booleanAttributeValue, f as isSkippedProp, h as styleValueText, l as isPropertyOnlyProp, m as normalizeStylePropertyName, p as keepsFalseValue, r as sanitizeCssValue, t as SSR_RENDER_DATA_ATTR } from "./ssr-DoV-vJ-5.js";
9
+ import { d as DEFERRED_BOUNDARY, i as dehydrateDataRuntime, p as isDeferred } from "./query-registry-tzSiVrV_.js";
10
+ import { ft as getRouteHydrationMetadata, ht as validateRouteHydrationData } from "./resolution-CF1BqHLm.js";
11
+ import { a as SSR_PORTAL_HOST, n as Portal, o as comparePortalWriterOrder, s as createSSRPortalAnchorToken, t as DefaultPortal } from "./portal-LYf4cbHd.js";
12
+ import { t as createDataRuntime } from "./data-runtime-i-RD0Ffm.js";
13
+ import { d as isCustomElementName, o as isUnsafeUrlAttribute, s as rejectUnsafeUrlAttribute, u as getPublicAttributeName } from "./url-C9xMpMMv.js";
14
+ import { d as booleanAttributeValue, f as isSkippedProp, h as styleValueText, l as isPropertyOnlyProp, m as normalizeStylePropertyName, p as keepsFalseValue, r as sanitizeCssValue, t as SSR_RENDER_DATA_ATTR } from "./ssr-DPfdcq0e.js";
15
15
  //#region src/ssr/escape.ts
16
16
  /**
17
17
  * HTML escaping utilities for SSR
@@ -321,7 +321,7 @@ const REDACTED_DEFERRED_ERROR = "Deferred value rejected.";
321
321
  function exposedDeferredError(error) {
322
322
  return error instanceof Error && error.expose === true ? error.message : REDACTED_DEFERRED_ERROR;
323
323
  }
324
- function hydrationReplacer(_key, value) {
324
+ function hydrationReplacer(value) {
325
325
  if (!isDeferred(value)) return value;
326
326
  if (value.state === "fulfilled") return {
327
327
  [DEFERRED_PAYLOAD]: "fulfilled",
@@ -368,7 +368,23 @@ function serializeHydrationRenderData(data, runtime) {
368
368
  const routeHydration = getRouteHydrationMetadata(payload.framework);
369
369
  if (routeHydration) validateRouteHydrationData(payload.route, routeHydration.r);
370
370
  if (isEmptyPageRenderEnvelope(payload)) return "";
371
- return `<script type="application/json" ${SSR_RENDER_DATA_ATTR}="true">${JSON.stringify(payload, hydrationReplacer).replace(/</g, "\\u003C").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")}<\/script>`;
371
+ const deferredPaths = [];
372
+ const paths = /* @__PURE__ */ new WeakMap();
373
+ let hasDeferredMarker = false;
374
+ return `<script type="application/json" ${SSR_RENDER_DATA_ATTR}="true">${JSON.stringify({
375
+ ...payload,
376
+ get deferredPaths() {
377
+ return deferredPaths.length > 0 || hasDeferredMarker ? deferredPaths : void 0;
378
+ }
379
+ }, function(key, value) {
380
+ if (key === DEFERRED_PAYLOAD && (value === "fulfilled" || value === "rejected")) hasDeferredMarker = true;
381
+ const parentPath = paths.get(this);
382
+ const path = parentPath ? [...parentPath, key] : [];
383
+ if (isDeferred(value)) deferredPaths.push(path);
384
+ const encoded = hydrationReplacer(value);
385
+ if (encoded && typeof encoded === "object") paths.set(encoded, path);
386
+ return encoded;
387
+ }).replace(/</g, "\\u003C").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")}<\/script>`;
372
388
  }
373
389
  //#endregion
374
390
  //#region src/ssr/sink.ts
@@ -457,6 +473,16 @@ var StreamSink = class {
457
473
  //#region src/ssr/attrs.ts
458
474
  const ESCAPED_ATTR_VALUE_CACHE_LIMIT = 512;
459
475
  const escapedAttrValueCache = /* @__PURE__ */ new Map();
476
+ function readReferenceAttributeCell(cell) {
477
+ const descriptor = cell && Object.getOwnPropertyDescriptor(cell, "value");
478
+ if (!descriptor || !("value" in descriptor) || descriptor.value !== void 0 && typeof descriptor.value !== "string") throw new TypeError("SSR reference attribute cells require a string or undefined data value.");
479
+ return descriptor.value;
480
+ }
481
+ function renderReferenceAttributeCell(name, cell, sink) {
482
+ const value = readReferenceAttributeCell(cell);
483
+ if (value === void 0) return;
484
+ sink.write(" " + name + "=\"" + getEscapedAttrValue(value) + "\"");
485
+ }
460
486
  function isEventHandler(key) {
461
487
  return key.length >= 2 && key.slice(0, 2).toLowerCase() === "on";
462
488
  }
@@ -473,13 +499,13 @@ function resolvePropValue(value) {
473
499
  * element whose attributes are inspected before they are written. Returns
474
500
  * `props` itself when nothing needs reading.
475
501
  */
476
- function resolveReactiveAttributeProps(props) {
502
+ function resolveReactiveAttributeProps(props, referenceCells) {
477
503
  if (!props || typeof props !== "object") return props;
478
504
  let resolved = null;
479
505
  const propsObj = props;
480
506
  for (const key in propsObj) {
481
507
  const value = propsObj[key];
482
- if (typeof value !== "function" || isSkippedProp(key) || isEventHandler(key)) continue;
508
+ if (typeof value !== "function" || isSkippedProp(key) || isEventHandler(key) || referenceCells && Object.prototype.hasOwnProperty.call(referenceCells, key)) continue;
483
509
  resolved ??= { ...propsObj };
484
510
  resolved[key] = resolvePropValue(value);
485
511
  }
@@ -506,7 +532,7 @@ function getEscapedAttrValue(value) {
506
532
  * object values on custom elements) have no markup and are left out; the
507
533
  * client applies them when it hydrates.
508
534
  */
509
- function renderAttrsDirect(props, sink, tagName = "") {
535
+ function renderAttrsDirect(props, sink, tagName = "", referenceCells) {
510
536
  if (!props || typeof props !== "object") return;
511
537
  const customElement = isCustomElementName(tagName);
512
538
  const propsObj = props;
@@ -514,6 +540,14 @@ function renderAttrsDirect(props, sink, tagName = "") {
514
540
  if (isSkippedProp(key) || key === "dangerouslySetInnerHTML") continue;
515
541
  if (isEventHandler(key)) continue;
516
542
  if (key.charCodeAt(0) === 95) continue;
543
+ if (referenceCells && Object.prototype.hasOwnProperty.call(referenceCells, key)) {
544
+ if (key !== "aria-labelledby" && key !== "aria-describedby" && key !== "aria-controls") throw new TypeError("SSR reference attribute cells only support derived ARIA references.");
545
+ const cell = referenceCells[key];
546
+ readReferenceAttributeCell(cell);
547
+ if (sink.writeReferenceAttribute) sink.writeReferenceAttribute(key, cell);
548
+ else renderReferenceAttributeCell(key, cell, sink);
549
+ continue;
550
+ }
517
551
  const value = resolvePropValue(propsObj[key]);
518
552
  if (isPropertyOnlyProp(tagName, key, value)) continue;
519
553
  if (value !== null && typeof value === "object" && key.startsWith("attr:")) continue;
@@ -674,6 +708,9 @@ function stopRenderPhase() {
674
708
  * render contains preloaded resource slots. Portal hosts write tokens that
675
709
  * are replaced with their final content once the render root completes.
676
710
  */
711
+ const CHILDREN_BEFORE_ATTRS = Symbol.for("askr.ssr.children-before-attrs");
712
+ const ATTRIBUTE_ROOT = Symbol.for("askr.ssr.attribute-root");
713
+ const ATTRIBUTE_CELLS = Symbol.for("askr.ssr.attribute-cells");
677
714
  /**
678
715
  * Collects writes so they can be published or dropped. An ErrorBoundary's
679
716
  * subtree renders into one first, so markup from a subtree that then throws
@@ -685,24 +722,38 @@ var BufferedSink = class {
685
722
  }
686
723
  write(html) {
687
724
  if (html) this.operations.push({
688
- portalHost: false,
725
+ kind: "text",
689
726
  text: html
690
727
  });
691
728
  }
692
729
  writePortalHost(token) {
693
730
  this.operations.push({
694
- portalHost: true,
731
+ kind: "portal",
695
732
  text: token
696
733
  });
697
734
  }
735
+ writeReferenceAttribute(name, cell) {
736
+ this.operations.push({
737
+ kind: "reference",
738
+ name,
739
+ cell
740
+ });
741
+ }
742
+ beginAttributeRoot() {
743
+ this.operations.push({ kind: "root" });
744
+ }
698
745
  /** The buffered markup, without portal host tokens. */
699
746
  html() {
700
747
  let html = "";
701
- for (const operation of this.operations) if (!operation.portalHost) html += operation.text;
748
+ for (const operation of this.operations) if (operation.kind === "text") html += operation.text;
702
749
  return html;
703
750
  }
704
751
  publishTo(sink) {
705
- for (const operation of this.operations) if (operation.portalHost && sink.writePortalHost) sink.writePortalHost(operation.text);
752
+ for (const operation of this.operations) if (operation.kind === "root") sink.beginAttributeRoot?.();
753
+ else if (operation.kind === "reference") {
754
+ if (sink.writeReferenceAttribute) sink.writeReferenceAttribute(operation.name, operation.cell);
755
+ else sink.write(referenceAttributeToken(operation.name, operation.cell));
756
+ } else if (operation.kind === "portal" && sink.writePortalHost) sink.writePortalHost(operation.text);
706
757
  else sink.write(operation.text);
707
758
  }
708
759
  };
@@ -720,8 +771,14 @@ var PortalSink = class {
720
771
  writePortalHost(token) {
721
772
  (this.buffered ??= []).push(token);
722
773
  }
774
+ beginAttributeRoot() {
775
+ this.buffered ??= [];
776
+ }
777
+ writeReferenceAttribute(name, cell) {
778
+ (this.buffered ??= []).push(referenceAttributeToken(name, cell));
779
+ }
723
780
  flush(ctx) {
724
- if (this.buffered) this.sink.write(resolvePortals(this.buffered.join(""), ctx));
781
+ if (this.buffered) this.sink.write(resolveReferenceAttributes(resolvePortals(this.buffered.join(""), ctx)));
725
782
  }
726
783
  };
727
784
  let current = null;
@@ -761,11 +818,18 @@ function componentOutput(value) {
761
818
  }
762
819
  function renderComponent(fn, props, sink) {
763
820
  const render = state();
821
+ const destination = sink;
822
+ const attributeRoot = props[ATTRIBUTE_ROOT] === true ? new BufferedSink() : null;
823
+ if (attributeRoot) {
824
+ attributeRoot.beginAttributeRoot();
825
+ sink = attributeRoot;
826
+ }
764
827
  let owner = render.owner;
765
828
  for (;;) {
766
829
  const instance = new ComponentInstance(owner, fn, props);
767
830
  instance.server = true;
768
831
  instance.serverContext = render.ctx;
832
+ if (attributeRoot) render.attributeRoots.add(instance);
769
833
  const output = runComponent(instance);
770
834
  const resources = getCurrentRenderData()?.resources;
771
835
  if (instance.serverResourceKeys.length && resources && Object.keys(resources).some((key) => /^r:\d+$/.test(key))) sink.write(`<!--askr-resource:${instance.serverResourceKeys.join(",")}-->`);
@@ -779,6 +843,7 @@ function renderComponent(fn, props, sink) {
779
843
  }
780
844
  if (!instance.boundary) {
781
845
  withOwner(instance, () => renderValue(componentOutput(output), sink));
846
+ attributeRoot?.publishTo(destination);
782
847
  return;
783
848
  }
784
849
  const buffer = new BufferedSink();
@@ -796,9 +861,11 @@ function renderComponent(fn, props, sink) {
796
861
  } finally {
797
862
  reportBoundaryCleanupErrors(cleanupErrors);
798
863
  }
864
+ attributeRoot?.publishTo(destination);
799
865
  return;
800
866
  }
801
867
  buffer.publishTo(sink);
868
+ attributeRoot?.publishTo(destination);
802
869
  return;
803
870
  }
804
871
  }
@@ -890,19 +957,35 @@ function renderChild(child, sink) {
890
957
  function assertElementName(name) {
891
958
  if (!/^[A-Za-z][A-Za-z0-9._:-]*$/.test(name)) throw new TypeError(`Invalid SSR element name: ${JSON.stringify(name)}`);
892
959
  }
960
+ /** Resolve only inputs needed to choose the child's parsing/selection context. */
961
+ function resolveEarlyContextProps(props, names) {
962
+ const descriptors = Object.getOwnPropertyDescriptors(props);
963
+ for (const name of names) {
964
+ if (!(name in props)) continue;
965
+ const value = props[name];
966
+ descriptors[name] = {
967
+ value: typeof value === "function" ? untrack(() => readValue(value)) : value,
968
+ enumerable: descriptors[name]?.enumerable ?? true,
969
+ configurable: true,
970
+ writable: true
971
+ };
972
+ }
973
+ return Object.create(Object.getPrototypeOf(props), descriptors);
974
+ }
893
975
  function renderElement(tag, props, sink) {
894
976
  assertElementName(tag);
895
977
  if (VOID_ELEMENTS.has(tag)) {
896
978
  sink.write("<" + tag);
897
- renderAttrsDirect(props, sink, tag);
979
+ renderHostAttrs(props, sink, tag);
898
980
  sink.write(" />");
899
981
  return;
900
982
  }
901
983
  const render = state();
984
+ const childrenBeforeAttrs = props[CHILDREN_BEFORE_ATTRS] === true;
902
985
  const parentNamespace = render.namespace;
903
986
  const lower = tag.toLowerCase();
904
987
  const namespace = getElementNamespace(parentNamespace, lower);
905
- let elementProps = lower === "annotation-xml" || namespace === "html" && (lower === "select" || lower === "option" && parentNamespace === "select") ? resolveReactiveAttributeProps(props) ?? props : props;
988
+ let elementProps = lower === "annotation-xml" || namespace === "html" && (lower === "select" || lower === "option" && parentNamespace === "select") ? childrenBeforeAttrs ? resolveEarlyContextProps(props, lower === "annotation-xml" ? ["encoding"] : lower === "select" ? ["value", "multiple"] : ["value"]) : resolveReactiveAttributeProps(props, referenceCellsFor(props)) ?? props : props;
906
989
  const selection = render.selectSelections[render.selectSelections.length - 1];
907
990
  let renderedChildren = null;
908
991
  if (lower === "option" && parentNamespace === "select" && selection) {
@@ -917,14 +1000,27 @@ function renderElement(tag, props, sink) {
917
1000
  } else value = String(own);
918
1001
  const selected = selection.values.has(value) && (selection.multiple || !selection.matched);
919
1002
  if (selected) selection.matched = true;
920
- elementProps = {
1003
+ if (childrenBeforeAttrs) {
1004
+ const descriptors = Object.getOwnPropertyDescriptors(elementProps);
1005
+ descriptors.selected = {
1006
+ value: selected,
1007
+ enumerable: true,
1008
+ configurable: true,
1009
+ writable: true
1010
+ };
1011
+ elementProps = Object.create(Object.getPrototypeOf(elementProps), descriptors);
1012
+ } else elementProps = {
921
1013
  ...elementProps,
922
1014
  selected
923
1015
  };
924
1016
  }
925
1017
  if (renderedChildren) {
1018
+ if (childrenBeforeAttrs) {
1019
+ writeBufferedElement(tag, elementProps, null, sink, renderedChildren);
1020
+ return;
1021
+ }
926
1022
  sink.write("<" + tag);
927
- renderAttrsDirect(elementProps, sink, tag);
1023
+ renderHostAttrs(elementProps, sink, tag);
928
1024
  sink.write(">");
929
1025
  renderedChildren.publishTo(sink);
930
1026
  sink.write("</" + tag + ">");
@@ -943,7 +1039,7 @@ function renderElement(tag, props, sink) {
943
1039
  }
944
1040
  const rawText = getRawTextElementInContext(parentNamespace, namespace, lower);
945
1041
  try {
946
- withNamespace(getChildNamespace(parentNamespace, namespace, lower, elementProps), () => writeElement(tag, elementProps, rawText, sink));
1042
+ withNamespace(getChildNamespace(parentNamespace, namespace, lower, elementProps), () => writeElement(tag, elementProps, rawText, sink, childrenBeforeAttrs));
947
1043
  } finally {
948
1044
  if (nextSelection) render.selectSelections.pop();
949
1045
  }
@@ -1029,9 +1125,24 @@ function optionTextValue(html) {
1029
1125
  }
1030
1126
  return text;
1031
1127
  }
1032
- function writeElement(tag, props, rawText, sink) {
1128
+ function writeBufferedElement(tag, props, rawText, sink, children) {
1129
+ const opening = new BufferedSink();
1130
+ opening.write("<" + tag);
1131
+ renderHostAttrs(props, opening, rawText === null ? tag : void 0);
1132
+ opening.write(">");
1133
+ opening.publishTo(sink);
1134
+ children.publishTo(sink);
1135
+ sink.write("</" + tag + ">");
1136
+ }
1137
+ function writeElement(tag, props, rawText, sink, childrenBeforeAttrs) {
1138
+ if (childrenBeforeAttrs) {
1139
+ const children = new BufferedSink();
1140
+ writeContent(props, rawText, children);
1141
+ writeBufferedElement(tag, props, rawText, sink, children);
1142
+ return;
1143
+ }
1033
1144
  sink.write("<" + tag);
1034
- renderAttrsDirect(props, sink, rawText === null ? tag : void 0);
1145
+ renderHostAttrs(props, sink, rawText === null ? tag : void 0);
1035
1146
  sink.write(">");
1036
1147
  writeContent(props, rawText, sink);
1037
1148
  sink.write("</" + tag + ">");
@@ -1108,6 +1219,49 @@ function flattenText(value, element) {
1108
1219
  visit(value);
1109
1220
  return out;
1110
1221
  }
1222
+ function referenceCellsFor(props) {
1223
+ const cells = props[ATTRIBUTE_CELLS];
1224
+ if (!cells || typeof cells !== "object") return void 0;
1225
+ const render = state();
1226
+ for (let owner = render.owner; owner; owner = owner.parent) if (render.attributeRoots.has(owner)) return cells;
1227
+ }
1228
+ function renderHostAttrs(props, sink, tag) {
1229
+ const cells = referenceCellsFor(props);
1230
+ if (!cells) {
1231
+ renderAttrsDirect(props, sink, tag);
1232
+ return;
1233
+ }
1234
+ renderAttrsDirect(props, {
1235
+ write: (html) => sink.write(html),
1236
+ writeReferenceAttribute: (name, cell) => {
1237
+ if (sink.writeReferenceAttribute) sink.writeReferenceAttribute(name, cell);
1238
+ else sink.write(referenceAttributeToken(name, cell));
1239
+ }
1240
+ }, tag, cells);
1241
+ }
1242
+ function referenceAttributeToken(name, cell) {
1243
+ const render = state();
1244
+ readReferenceAttributeCell(cell);
1245
+ if (render.referenceAttributeNonce === null) {
1246
+ const nonce = globalThis.crypto.getRandomValues(/* @__PURE__ */ new Uint32Array(4));
1247
+ render.referenceAttributeNonce = Array.from(nonce, (part) => part.toString(16).padStart(8, "0")).join("");
1248
+ }
1249
+ const token = `<!--askr-attribute:${render.referenceAttributeNonce}:${render.nextReferenceAttribute++}-->`;
1250
+ render.referenceAttributes.set(token, {
1251
+ name,
1252
+ cell
1253
+ });
1254
+ return token;
1255
+ }
1256
+ function resolveReferenceAttributes(html) {
1257
+ let resolved = html;
1258
+ for (const [token, { name, cell }] of state().referenceAttributes) {
1259
+ const sink = new StringSink();
1260
+ renderReferenceAttributeCell(name, cell, sink);
1261
+ resolved = resolved.replace(token, () => sink.toString());
1262
+ }
1263
+ return resolved;
1264
+ }
1111
1265
  function renderToString(value, namespace) {
1112
1266
  const sink = new StringSink();
1113
1267
  withNamespace(namespace, () => renderValue(value, sink));
@@ -1143,7 +1297,11 @@ function withServerRender(ctx, fn) {
1143
1297
  owner,
1144
1298
  namespace: "html",
1145
1299
  portalNamespaces: /* @__PURE__ */ new Map(),
1146
- selectSelections: []
1300
+ selectSelections: [],
1301
+ attributeRoots: /* @__PURE__ */ new WeakSet(),
1302
+ referenceAttributes: /* @__PURE__ */ new Map(),
1303
+ referenceAttributeNonce: null,
1304
+ nextReferenceAttribute: 0
1147
1305
  };
1148
1306
  let result;
1149
1307
  try {
@@ -1211,7 +1369,7 @@ function renderToStringSync(component, props, options) {
1211
1369
  const sink = new StringSink();
1212
1370
  renderValue(rootElement(component, props ?? {}, nonce), sink);
1213
1371
  sink.end();
1214
- const html = resolvePortals(sink.toString(), ctx);
1372
+ const html = resolveReferenceAttributes(resolvePortals(sink.toString(), ctx));
1215
1373
  options?.onContext?.(ctx);
1216
1374
  return html + serializeHydrationRenderData(ctx.hydrationData ?? void 0, ctx.dataRuntime);
1217
1375
  });
@@ -1,10 +1,10 @@
1
1
  import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-DRS-qjiN.js";
2
- import { r as currentAppRuntime } from "./hooks-BimKStr4.js";
3
- import { r as readScope, t as defineScope } from "./scope-CwpVSHVf.js";
2
+ import { r as currentAppRuntime } from "./hooks-kjLigwDJ.js";
3
+ import { r as readScope, t as defineScope } from "./scope-ila_zaId.js";
4
4
  import { S as replacePageRoute, n as getActiveRenderContext, w as withPageFramework } from "./render-context-DGHnEveC.js";
5
5
  import { n as isPromiseLike } from "./promise-Dz8iIHAm.js";
6
- import { c as withTelemetry, l as jsonTransportPropertyPath, p as isDeferred, t as createQueryPrefetchContext, u as validateJsonTransportValue } from "./query-registry-WMCN0BJL.js";
7
- import { c as resolveNavigationUrl, i as formatNavigationUrl } from "./url-CnbfpX0K.js";
6
+ import { c as withTelemetry, l as jsonTransportPropertyPath, p as isDeferred, t as createQueryPrefetchContext, u as validateJsonTransportValue } from "./query-registry-tzSiVrV_.js";
7
+ import { c as resolveNavigationUrl, i as formatNavigationUrl } from "./url-C9xMpMMv.js";
8
8
  //#region src/router/route-hydration.ts
9
9
  function isDeferredHydrationValue(value) {
10
10
  return isDeferred(value);
@@ -71,7 +71,7 @@ function guardOmissions(value, omissions, route, path = "$") {
71
71
  if (cached) return cached;
72
72
  const guarded = new Proxy(value, { get(target, property, receiver) {
73
73
  if (typeof property === "string") {
74
- const omitted = omissions[property];
74
+ const omitted = Object.prototype.hasOwnProperty.call(omissions, property) ? omissions[property] : void 0;
75
75
  if (omitted && !Object.prototype.hasOwnProperty.call(target, property)) omittedRead(route, propertyPath(path, property));
76
76
  const child = Reflect.get(target, property, receiver);
77
77
  return omitted === 1 ? child : guardOmissions(child, omitted, route, propertyPath(path, property));
@@ -276,6 +276,15 @@ function formatCatchAllCapture(parts) {
276
276
  if (parts.length === 1) return decodePathSegment(parts[0]);
277
277
  return "/" + parts.map(decodePathSegment).join("/");
278
278
  }
279
+ function setCapturedParameter(params, name, value) {
280
+ if (name === "__proto__") Object.defineProperty(params, name, {
281
+ value,
282
+ enumerable: true,
283
+ configurable: true,
284
+ writable: true
285
+ });
286
+ else params[name] = value;
287
+ }
279
288
  /**
280
289
  * Match pre-split URL parts against pre-parsed route segments.
281
290
  *
@@ -308,11 +317,11 @@ function matchSegments(urlParts, segments) {
308
317
  if (!staticSegmentMatches(seg.value, part)) return null;
309
318
  } else if (seg.kind === "splat") {
310
319
  if (params === null) params = {};
311
- params[seg.value] = normalizeCapturedSplatParts(urlParts.slice(i).map(decodePathSegment)).join("/");
320
+ setCapturedParameter(params, seg.value, normalizeCapturedSplatParts(urlParts.slice(i).map(decodePathSegment)).join("/"));
312
321
  return params;
313
322
  } else {
314
323
  if (params === null) params = {};
315
- if (seg.kind === "param") params[seg.value] = decodePathSegment(part);
324
+ if (seg.kind === "param") setCapturedParameter(params, seg.value, decodePathSegment(part));
316
325
  else params["*"] = decodePathSegment(part);
317
326
  }
318
327
  }
@@ -702,7 +711,12 @@ function makeQuery(search) {
702
711
  },
703
712
  toJSON() {
704
713
  const output = {};
705
- for (const [key, values] of mapping.entries()) output[key] = values.length > 1 ? [...values] : values[0];
714
+ for (const [key, values] of mapping.entries()) Object.defineProperty(output, key, {
715
+ value: values.length > 1 ? [...values] : values[0],
716
+ enumerable: true,
717
+ configurable: true,
718
+ writable: true
719
+ });
706
720
  return output;
707
721
  }
708
722
  });
@@ -1,6 +1,6 @@
1
- import { A as untrack, F as logger, N as runWithOwner, S as queueTask, d as recordUndo } from "./instance-BAnfmXOR.js";
1
+ import { A as untrack, I as logger, N as runWithOwner, S as queueTask, d as recordUndo } from "./instance-DL-YKrj6.js";
2
2
  import { t as brandSnapshotSource } from "./snapshot-Cjx4N988.js";
3
- import { c as onCommit, i as currentComponent, n as createSource, o as hookSlot, r as currentAppRuntime, s as notify, u as readSource } from "./hooks-BimKStr4.js";
3
+ import { c as onCommit, i as currentComponent, n as createSource, o as hookSlot, r as currentAppRuntime, s as notify, u as readSource } from "./hooks-kjLigwDJ.js";
4
4
  import { T as SSRDataMissingError, a as getResourceVerificationSnapshot, h as throwSSRDataMissing, i as getNextRenderKey, n as getActiveRenderContext, o as isHydrationVerificationRender, r as getCurrentRenderData, s as recordResourceVerificationSnapshot } from "./render-context-DGHnEveC.js";
5
5
  import { n as isPromiseLike } from "./promise-Dz8iIHAm.js";
6
6
  //#region src/core/api/resource-cell.ts
@@ -1,7 +1,7 @@
1
- import { S as queueTask } from "../instance-BAnfmXOR.js";
2
- import { c as onCommit, i as currentComponent, n as createSource, o as hookSlot, s as notify, u as readSource } from "../hooks-BimKStr4.js";
3
- import { a as routeActive, c as watch, i as on, n as windowFocused, o as task, r as capture, s as timer, t as documentVisible } from "../browser-activity-CB8e-V4f.js";
4
- import { t as resource } from "../resource-CLjB7RBQ.js";
1
+ import { S as queueTask } from "../instance-DL-YKrj6.js";
2
+ import { c as onCommit, i as currentComponent, n as createSource, o as hookSlot, s as notify, u as readSource } from "../hooks-kjLigwDJ.js";
3
+ import { a as routeActive, c as watch, i as on, n as windowFocused, o as task, r as capture, s as timer, t as documentVisible } from "../browser-activity-2r5gA1Cb.js";
4
+ import { t as resource } from "../resource-BhcaFqdB.js";
5
5
  //#region src/core/api/stream.ts
6
6
  /**
7
7
  * stream(): a component-owned async iterable. It connects after the render
@@ -74,6 +74,17 @@ async function consume(slot, generation, iterable) {
74
74
  publish(slot);
75
75
  }
76
76
  }
77
+ function failGeneration(slot, generation, error) {
78
+ if (!isCurrent(slot, generation)) return;
79
+ stopGeneration(generation);
80
+ if (slot.disposed || slot.current !== generation || slot.generation !== generation.id) return;
81
+ slot.current = null;
82
+ slot.snapshot.status = "error";
83
+ slot.snapshot.pending = false;
84
+ slot.snapshot.stale = slot.hasValue;
85
+ slot.snapshot.error = toError(error);
86
+ publish(slot);
87
+ }
77
88
  function startSlot(slot) {
78
89
  if (!slot.activated || slot.disposed) return;
79
90
  const previous = slot.current;
@@ -94,23 +105,11 @@ function startSlot(slot) {
94
105
  try {
95
106
  result = slot.source({ signal: generation.controller.signal });
96
107
  } catch (error) {
97
- if (!isCurrent(slot, generation)) return;
98
- slot.current = null;
99
- slot.snapshot.status = "error";
100
- slot.snapshot.pending = false;
101
- slot.snapshot.stale = slot.hasValue;
102
- slot.snapshot.error = toError(error);
103
- publish(slot);
108
+ failGeneration(slot, generation, error);
104
109
  return;
105
110
  }
106
111
  Promise.resolve(result).then((iterable) => consume(slot, generation, iterable)).catch((error) => {
107
- if (!isCurrent(slot, generation)) return;
108
- slot.current = null;
109
- slot.snapshot.status = "error";
110
- slot.snapshot.pending = false;
111
- slot.snapshot.stale = slot.hasValue;
112
- slot.snapshot.error = toError(error);
113
- publish(slot);
112
+ failGeneration(slot, generation, error);
114
113
  });
115
114
  }
116
115
  function queueStart(slot) {
@@ -152,9 +151,7 @@ function createSlot(source, options) {
152
151
  const slot = {
153
152
  kind: "stream",
154
153
  source,
155
- pendingSource: source,
156
154
  deps: (options.deps ?? []).slice(),
157
- pendingDeps: (options.deps ?? []).slice(),
158
155
  snapshot,
159
156
  generation: 0,
160
157
  current: null,
@@ -190,12 +187,12 @@ function requireStreamOwner() {
190
187
  if (!instance) throw new Error("[Askr] stream() must be called during component render inside an app.");
191
188
  return instance;
192
189
  }
193
- function commitSlot(instance, slot) {
194
- const depsChanged = !depsEqual(slot.deps, slot.pendingDeps);
190
+ function commitSlot(instance, slot, source, deps) {
191
+ const depsChanged = !depsEqual(slot.deps, deps);
195
192
  const firstCommit = !slot.activated;
196
193
  slot.owner = instance;
197
- slot.source = slot.pendingSource;
198
- slot.deps = slot.pendingDeps;
194
+ slot.source = source;
195
+ slot.deps = deps;
199
196
  if (firstCommit) slot.activated = true;
200
197
  if (!slot.cleanupRegistered) {
201
198
  slot.cleanupRegistered = true;
@@ -217,9 +214,10 @@ function stream(sourceOrGetter, connectOrOptions, drivenOptions) {
217
214
  function createStream(instance, source, options) {
218
215
  const slot = hookSlot(instance, "stream", () => createSlot(source, options));
219
216
  readSource(slot.readers);
220
- slot.pendingSource = source;
221
- slot.pendingDeps = (options.deps ?? []).slice();
222
- if (!instance.server) onCommit(instance, () => commitSlot(instance, slot));
217
+ if (!instance.server) {
218
+ const deps = (options.deps ?? []).slice();
219
+ onCommit(instance, () => commitSlot(instance, slot, source, deps));
220
+ }
223
221
  return slot.snapshot;
224
222
  }
225
223
  //#endregion
@@ -1,12 +1,12 @@
1
1
  import { n as jsx } from "../jsx-runtime-C4idqHY0.js";
2
- import { C as currentRoute, a as nextHistoryIndex, b as syncRegisteredRouteSnapshot, c as reconcileRouteMeta, f as saveScrollPosition, g as parseTargetUrl, h as getWindowHref, i as commitHistoryIndex, l as resolveRouteMeta, m as getRegisteredAppsSnapshot, n as navigate, p as getCurrentHref, r as navigateToPublicHref, u as serializeRouteMeta, v as setCurrentRouteLocation, w as onRouteChange, x as toDocumentUrl, y as syncAppRegistrationLocation } from "../navigate-CP_0Zy5U.js";
3
- import { f as defer, p as isDeferred } from "../query-registry-WMCN0BJL.js";
4
- import { M as getActiveRouteBasePath, a as resolveRouteRequest, at as lazyRouteData, b as addLogicalRouteBasePath, c as forbidden, ct as encodePathSegment, d as unauthorized, et as Outlet, f as currentAuth, it as lazy, l as notFound, o as allow, ot as RouteDataLoadError, s as deny, u as redirect, v as matchRoute, x as addRouteBasePath } from "../resolution-Cx82-xjW.js";
5
- import { n as createRouteRegistry } from "../manifest-CW9gyNBY.js";
6
- import { a as group, c as route, i as fallback, n as resolveDeferredValues, o as index, r as routeData, s as page, t as Resolve } from "../deferred-bEEHHvic.js";
7
- import { a as isSafeHref, r as assertPathHrefStaysOnOrigin } from "../url-CnbfpX0K.js";
8
- import { o as mergeProps } from "../compose-ref-DWzdbxsD.js";
9
- import { t as applyInteractionPolicy } from "../interactions-D2BoREb-.js";
2
+ import { C as currentRoute, a as nextHistoryIndex, b as syncRegisteredRouteSnapshot, c as reconcileRouteMeta, f as saveScrollPosition, g as parseTargetUrl, h as getWindowHref, i as commitHistoryIndex, l as resolveRouteMeta, m as getRegisteredAppsSnapshot, n as navigate, p as getCurrentHref, r as navigateToPublicHref, u as serializeRouteMeta, v as setCurrentRouteLocation, w as onRouteChange, x as toDocumentUrl, y as syncAppRegistrationLocation } from "../navigate-DsfO12hB.js";
3
+ import { f as defer, p as isDeferred } from "../query-registry-tzSiVrV_.js";
4
+ import { M as getActiveRouteBasePath, a as resolveRouteRequest, at as lazyRouteData, b as addLogicalRouteBasePath, c as forbidden, ct as encodePathSegment, d as unauthorized, et as Outlet, f as currentAuth, it as lazy, l as notFound, o as allow, ot as RouteDataLoadError, s as deny, u as redirect, v as matchRoute, x as addRouteBasePath } from "../resolution-CF1BqHLm.js";
5
+ import { n as createRouteRegistry } from "../manifest-BNupb86f.js";
6
+ import { a as group, c as route, i as fallback, n as resolveDeferredValues, o as index, r as routeData, s as page, t as Resolve } from "../deferred-nGZglpj6.js";
7
+ import { a as isSafeHref, r as assertPathHrefStaysOnOrigin } from "../url-C9xMpMMv.js";
8
+ import { o as mergeProps } from "../compose-ref-ccRU59BM.js";
9
+ import { t as applyInteractionPolicy } from "../interactions-B_wfsDQg.js";
10
10
  //#region src/router/route-query.ts
11
11
  function getRouteQueryHistoryMode(options) {
12
12
  if (options.history) return options.history;
@@ -1,6 +1,6 @@
1
- import { M as getOwner } from "./instance-BAnfmXOR.js";
1
+ import { M as getOwner } from "./instance-DL-YKrj6.js";
2
2
  import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-DRS-qjiN.js";
3
- import { i as currentComponent } from "./hooks-BimKStr4.js";
3
+ import { i as currentComponent } from "./hooks-kjLigwDJ.js";
4
4
  //#region src/core/api/scope.ts
5
5
  /**
6
6
  * Lexical scopes. A scope's provider is a component that records its value