eclipsa 0.1.4 → 0.1.5

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 (45) hide show
  1. package/{action-CgM3EJUS.mjs → action-DqgkV3zb.mjs} +1584 -996
  2. package/action-DqgkV3zb.mjs.map +1 -0
  3. package/{client-COjBNTyt.mjs → client-DKPmN-wJ.mjs} +126 -40
  4. package/client-DKPmN-wJ.mjs.map +1 -0
  5. package/{component-D_nEtZ69.d.mts → component-yvTtnI00.d.mts} +2 -2
  6. package/core/client/mod.d.mts +2 -2
  7. package/core/client/mod.mjs +3 -3
  8. package/core/dev-client/mod.d.mts +1 -1
  9. package/core/dev-client/mod.mjs +10 -5
  10. package/core/dev-client/mod.mjs.map +1 -1
  11. package/core/internal.d.mts +2 -2
  12. package/core/internal.mjs +2 -2
  13. package/core/prod-client/mod.d.mts +3 -3
  14. package/core/prod-client/mod.mjs +4 -4
  15. package/{internal-Csbm0Qnv.d.mts → internal-CHYAJznU.d.mts} +116 -72
  16. package/jsx/jsx-dev-runtime.d.mts +8 -2
  17. package/jsx/jsx-dev-runtime.mjs +2 -2
  18. package/jsx/jsx-runtime.d.mts +1 -1
  19. package/jsx/mod.d.mts +1 -1
  20. package/jsx/mod.mjs +1 -1
  21. package/{jsx-dev-runtime-CY60yQJY.mjs → jsx-dev-runtime-DpbWQ4Q0.mjs} +8 -3
  22. package/jsx-dev-runtime-DpbWQ4Q0.mjs.map +1 -0
  23. package/{mod-DLb8ple9.d.mts → mod-aLmFvMYF.d.mts} +4 -4
  24. package/mod.d.mts +20 -38
  25. package/mod.mjs +19 -145
  26. package/mod.mjs.map +1 -1
  27. package/package.json +6 -2
  28. package/{signal-B7AfIKrr.d.mts → signal-CosyYdtA.d.mts} +1 -1
  29. package/{signal-CJtquEfo.mjs → signal-DBzloBrN.mjs} +2 -2
  30. package/{signal-CJtquEfo.mjs.map → signal-DBzloBrN.mjs.map} +1 -1
  31. package/ssr-CRg57Wn2.mjs +157 -0
  32. package/ssr-CRg57Wn2.mjs.map +1 -0
  33. package/ssr-D8F-DtCv.d.mts +37 -0
  34. package/{types-BCEY9lGp.d.mts → types-Cu9gFlEY.d.mts} +6 -2
  35. package/{types-DKpefD_u.d.mts → types-DDeNM8UH.d.mts} +1 -1
  36. package/vite/build/runtime.d.mts +4 -0
  37. package/vite/build/runtime.mjs +4 -0
  38. package/vite/mod.mjs +257 -38
  39. package/vite/mod.mjs.map +1 -1
  40. package/web-utils/mod.d.mts +1 -1
  41. package/web-utils/mod.mjs +2 -2
  42. package/action-CgM3EJUS.mjs.map +0 -1
  43. package/client-COjBNTyt.mjs.map +0 -1
  44. package/jsx-dev-runtime-CY60yQJY.mjs.map +0 -1
  45. /package/{jsx-runtime-BFDPoxFn.d.mts → jsx-runtime-QIK6ADiK.d.mts} +0 -0
@@ -1,4 +1,4 @@
1
- import { i as jsxDEV, n as isSSRAttrValue, r as isSSRTemplate } from "./jsx-dev-runtime-CY60yQJY.mjs";
1
+ import { a as jsxDEV, i as isSSRTemplate, n as isSSRAttrValue, r as isSSRRawValue } from "./jsx-dev-runtime-DpbWQ4Q0.mjs";
2
2
  //#region \0rolldown/runtime.js
3
3
  var __defProp = Object.defineProperty;
4
4
  var __exportAll = (all, no_symbols) => {
@@ -20,6 +20,15 @@ const noSerialize = (value) => {
20
20
  };
21
21
  const isNoSerialize = (value) => canNoSerialize(value) && noSerializeValues.has(value);
22
22
  //#endregion
23
+ //#region core/shared.ts
24
+ const IS_BROWSER = typeof window !== "undefined" && typeof document !== "undefined";
25
+ const IS_SSR = !IS_BROWSER;
26
+ const isPlainObject = (value) => {
27
+ if (!value || typeof value !== "object") return false;
28
+ const proto = Object.getPrototypeOf(value);
29
+ return proto === Object.prototype || proto === null;
30
+ };
31
+ //#endregion
23
32
  //#region core/serialize.ts
24
33
  const DEFAULT_MAX_DEPTH = 64;
25
34
  const DEFAULT_MAX_ENTRIES = 1e4;
@@ -28,11 +37,6 @@ const RESERVED_KEYS = new Set([
28
37
  "constructor",
29
38
  "prototype"
30
39
  ]);
31
- const isPlainObject$2 = (value) => {
32
- if (!value || typeof value !== "object") return false;
33
- const proto = Object.getPrototypeOf(value);
34
- return proto === Object.prototype || proto === null;
35
- };
36
40
  const getSerializedObjectTag = (value) => Object.prototype.toString.call(value);
37
41
  const getSerializedConstructorName = (value) => {
38
42
  const constructor = value.constructor;
@@ -143,7 +147,7 @@ const serializeUnknown = (value, state, stack, depth) => {
143
147
  entries: [...value].map((entry) => serializeUnknown(entry, state, stack, depth + 1))
144
148
  };
145
149
  }
146
- if (isPlainObject$2(value)) {
150
+ if (isPlainObject(value)) {
147
151
  assertSafeObject(value);
148
152
  const descriptors = Object.entries(value);
149
153
  state.entryCount += descriptors.length + 1;
@@ -248,9 +252,8 @@ const APP_HOOKS_ELEMENT_ID = "eclipsa-app-hooks";
248
252
  const PUBLIC_ERROR_KEY = Symbol.for("eclipsa.public-error");
249
253
  let requestContextStorage = null;
250
254
  let clientHooks = {};
251
- const isBrowserRuntime = () => typeof window !== "undefined" && typeof document !== "undefined";
252
255
  const getAsyncLocalStorageConstructor = () => {
253
- if (isBrowserRuntime() || typeof process === "undefined") return null;
256
+ if (IS_BROWSER || typeof process === "undefined") return null;
254
257
  const asyncHooks = process.getBuiltinModule?.("node:async_hooks");
255
258
  return typeof asyncHooks?.AsyncLocalStorage === "function" ? asyncHooks.AsyncLocalStorage : null;
256
259
  };
@@ -260,11 +263,6 @@ const getRequestContextStorage = () => {
260
263
  requestContextStorage ??= new AsyncLocalStorageCtor();
261
264
  return requestContextStorage;
262
265
  };
263
- const isPlainObject$1 = (value) => {
264
- if (!value || typeof value !== "object") return false;
265
- const proto = Object.getPrototypeOf(value);
266
- return proto === Object.prototype || proto === null;
267
- };
268
266
  const normalizePublicError = (value) => {
269
267
  if (value && typeof value === "object") {
270
268
  const message = value.message;
@@ -357,7 +355,7 @@ const resolveReroute = (reroute, request, pathname, baseUrl) => {
357
355
  if (!resolved) return pathname;
358
356
  return (resolved instanceof URL ? resolved : new URL(String(resolved), url)).pathname;
359
357
  };
360
- const toPublicError = (error) => error && typeof error === "object" && error[PUBLIC_ERROR_KEY] && isPlainObject$1(error[PUBLIC_ERROR_KEY]) ? error[PUBLIC_ERROR_KEY] : normalizePublicError(error);
358
+ const toPublicError = (error) => error && typeof error === "object" && error[PUBLIC_ERROR_KEY] && isPlainObject(error[PUBLIC_ERROR_KEY]) ? error[PUBLIC_ERROR_KEY] : normalizePublicError(error);
361
359
  const markPublicError = (error, publicError) => {
362
360
  if (!error || typeof error !== "object" && typeof error !== "function") return error;
363
361
  Object.defineProperty(error, PUBLIC_ERROR_KEY, {
@@ -586,6 +584,17 @@ const renderRouteMetadataHead = (metadata) => {
586
584
  return elements;
587
585
  };
588
586
  //#endregion
587
+ //#region core/router-shared.ts
588
+ const ROUTE_LINK_ATTR = "data-e-link";
589
+ const ROUTE_DATA_ENDPOINT = "/__eclipsa/route-data";
590
+ const ROUTE_DATA_REQUEST_HEADER = "x-eclipsa-route-data";
591
+ const ROUTE_MANIFEST_ELEMENT_ID = "eclipsa-route-manifest";
592
+ const ROUTE_PREFETCH_ATTR = "data-e-link-prefetch";
593
+ const ROUTE_PREFLIGHT_ENDPOINT = "/__eclipsa/route-preflight";
594
+ const ROUTE_PREFLIGHT_REQUEST_HEADER = "x-eclipsa-route-preflight";
595
+ const ROUTE_RPC_URL_HEADER = "x-eclipsa-route-url";
596
+ const ROUTE_REPLACE_ATTR = "data-e-link-replace";
597
+ //#endregion
589
598
  //#region core/loader.ts
590
599
  var loader_exports = /* @__PURE__ */ __exportAll({
591
600
  __eclipsaLoader: () => __eclipsaLoader,
@@ -678,8 +687,12 @@ const parseJsonLoaderResponse = async (response) => {
678
687
  return deserializePublicValue(body.value);
679
688
  };
680
689
  const invokeLoader = async (id) => {
690
+ const currentRouteUrl = typeof window !== "undefined" ? window.location.href : null;
681
691
  return parseJsonLoaderResponse(await fetch(`/__eclipsa/loader/${encodeURIComponent(id)}`, {
682
- headers: { accept: LOADER_CONTENT_TYPE },
692
+ headers: {
693
+ accept: LOADER_CONTENT_TYPE,
694
+ ...currentRouteUrl ? { [ROUTE_RPC_URL_HEADER]: currentRouteUrl } : {}
695
+ },
683
696
  method: "GET"
684
697
  }));
685
698
  };
@@ -812,6 +825,7 @@ const __eclipsaLoader = (id, middlewares, handler) => {
812
825
  //#endregion
813
826
  //#region core/internal.ts
814
827
  const COMPONENT_META_KEY = Symbol.for("eclipsa.component-meta");
828
+ const EXTERNAL_COMPONENT_META_KEY = Symbol.for("eclipsa.external-component-meta");
815
829
  const LAZY_META_KEY = Symbol.for("eclipsa.lazy-meta");
816
830
  const NAVIGATE_META_KEY = Symbol.for("eclipsa.navigate-meta");
817
831
  const SIGNAL_META_KEY = Symbol.for("eclipsa.signal-meta");
@@ -829,6 +843,7 @@ const __eclipsaComponent = (component, symbol, captures, projectionSlots, option
829
843
  value: {
830
844
  symbol,
831
845
  captures,
846
+ ...options?.external ? { external: options.external } : {},
832
847
  ...options?.optimizedRoot ? { optimizedRoot: true } : {},
833
848
  ...projectionSlots ? { projectionSlots } : {}
834
849
  },
@@ -875,6 +890,19 @@ const getLazyMeta = (value) => {
875
890
  if (typeof value !== "function") return null;
876
891
  return value[LAZY_META_KEY] ?? null;
877
892
  };
893
+ const setExternalComponentMeta = (target, meta) => {
894
+ Object.defineProperty(target, EXTERNAL_COMPONENT_META_KEY, {
895
+ configurable: true,
896
+ enumerable: false,
897
+ value: meta,
898
+ writable: true
899
+ });
900
+ return target;
901
+ };
902
+ const getExternalComponentMeta = (value) => {
903
+ if (typeof value !== "function") return null;
904
+ return value[EXTERNAL_COMPONENT_META_KEY] ?? null;
905
+ };
878
906
  const setNavigateMeta = (target) => {
879
907
  Object.defineProperty(target, NAVIGATE_META_KEY, {
880
908
  configurable: true,
@@ -1005,17 +1033,7 @@ const getSignalMeta = (value) => {
1005
1033
  return value[SIGNAL_META_KEY] ?? null;
1006
1034
  };
1007
1035
  //#endregion
1008
- //#region core/router-shared.ts
1009
- const ROUTE_LINK_ATTR = "data-e-link";
1010
- const ROUTE_DATA_ENDPOINT = "/__eclipsa/route-data";
1011
- const ROUTE_DATA_REQUEST_HEADER = "x-eclipsa-route-data";
1012
- const ROUTE_MANIFEST_ELEMENT_ID = "eclipsa-route-manifest";
1013
- const ROUTE_PREFETCH_ATTR = "data-e-link-prefetch";
1014
- const ROUTE_PREFLIGHT_ENDPOINT = "/__eclipsa/route-preflight";
1015
- const ROUTE_PREFLIGHT_REQUEST_HEADER = "x-eclipsa-route-preflight";
1016
- const ROUTE_REPLACE_ATTR = "data-e-link-replace";
1017
- //#endregion
1018
- //#region core/runtime.ts
1036
+ //#region core/runtime/constants.ts
1019
1037
  const CONTAINER_STACK_KEY = Symbol.for("eclipsa.container-stack");
1020
1038
  const CONTEXT_VALUE_STACK_KEY = Symbol.for("eclipsa.context-value-stack");
1021
1039
  const FRAME_STACK_KEY = Symbol.for("eclipsa.frame-stack");
@@ -1047,15 +1065,18 @@ const RENDER_REFERENCE_KIND = "render";
1047
1065
  const REF_SIGNAL_ATTR = "data-e-ref";
1048
1066
  const STREAM_STATE_KEY = "__eclipsa_stream";
1049
1067
  const PENDING_RESUME_LINK_KEY = "__eclipsa_pending_route_link";
1050
- const BIND_VALUE_PROP = "bind:value";
1051
- const BIND_CHECKED_PROP = "bind:checked";
1052
1068
  const BIND_VALUE_ATTR = "data-e-bind-value";
1053
1069
  const BIND_CHECKED_ATTR = "data-e-bind-checked";
1054
1070
  const CLIENT_INSERT_OWNER_SYMBOL = "$client-insert-root";
1055
1071
  const CLIENT_INSERT_OWNER_ID_PREFIX = "$insert:";
1056
- const DOM_TEXT_NODE = 3;
1057
- const DOM_COMMENT_NODE = 8;
1058
- const DOM_SHOW_COMMENT = 128;
1072
+ const EXTERNAL_ROOT_ATTR = "data-e-external-root";
1073
+ const EXTERNAL_ROOT_COMPONENT_ATTR = "data-e-external-component";
1074
+ const EXTERNAL_ROOT_KIND_ATTR = "data-e-external-kind";
1075
+ const getExternalSlotTag = (_kind) => "e-slot-host";
1076
+ //#endregion
1077
+ //#region core/runtime/dom.ts
1078
+ const managedElementAttributes = /* @__PURE__ */ new WeakMap();
1079
+ const insertMarkerNodeCounts = /* @__PURE__ */ new WeakMap();
1059
1080
  const getDomContexts = (value) => {
1060
1081
  const contexts = [];
1061
1082
  if (!value || typeof value !== "object" && typeof value !== "function") return contexts;
@@ -1086,34 +1107,6 @@ const isHTMLTextAreaElementNode = (value) => isDomInstance(value, "HTMLTextAreaE
1086
1107
  const isTextEntryElement = (value) => isHTMLInputElementNode(value) || isHTMLTextAreaElementNode(value);
1087
1108
  const isHTMLAnchorElementNode = (value) => isDomInstance(value, "HTMLAnchorElement");
1088
1109
  const isHTMLFormElementNode = (value) => isDomInstance(value, "HTMLFormElement");
1089
- const COMPONENT_BOUNDARY_PROPS_CHANGED = Symbol.for("eclipsa.component-boundary-props-changed");
1090
- const COMPONENT_BOUNDARY_SYMBOL_CHANGED = Symbol.for("eclipsa.component-boundary-symbol-changed");
1091
- const isMissingGeneratedScopeReferenceError = (error) => error instanceof ReferenceError && /\b__scope\b/.test(error.message);
1092
- const toRuntimeError = (error) => error instanceof Error ? error : new Error(typeof error === "string" ? error : String(error));
1093
- const areShallowEqualRenderProps = (previous, next) => {
1094
- if (previous === next) return true;
1095
- if (!previous || !next) return !previous && !next;
1096
- const previousKeys = Object.keys(previous);
1097
- const nextKeys = Object.keys(next);
1098
- if (previousKeys.length !== nextKeys.length) return false;
1099
- for (const key of previousKeys) if (!Object.hasOwn(next, key) || !Object.is(previous[key], next[key])) return false;
1100
- for (const hiddenKey of [ROUTE_PARAMS_PROP, ROUTE_ERROR_PROP]) {
1101
- const previousHas = Object.hasOwn(previous, hiddenKey);
1102
- if (previousHas !== Object.hasOwn(next, hiddenKey)) return false;
1103
- if (previousHas && !Object.is(previous[hiddenKey], next[hiddenKey])) return false;
1104
- }
1105
- return true;
1106
- };
1107
- const wrapGeneratedScopeReferenceError = (error, context) => {
1108
- const baseError = toRuntimeError(error);
1109
- if (!isMissingGeneratedScopeReferenceError(baseError)) return baseError;
1110
- const location = [context.componentId ? `component "${context.componentId}"` : null, context.symbolId ? `symbol "${context.symbolId}"` : null].filter(Boolean).join(", ");
1111
- const wrapped = new Error(`Eclipsa runtime failed while ${context.phase}${location ? ` ${location}` : ""}. The generated resumable symbol referenced "__scope" outside its valid scope. This usually means a same-file helper was transformed incorrectly during symbol compilation. Inline that helper into the component as a workaround. Original error: ${baseError.message}`, { cause: baseError });
1112
- wrapped.name = "EclipsaRuntimeError";
1113
- return wrapped;
1114
- };
1115
- const resolvedRuntimeSymbols = /* @__PURE__ */ new WeakMap();
1116
- const managedElementAttributes = /* @__PURE__ */ new WeakMap();
1117
1110
  const listNodeChildren = (node) => Array.from(node?.childNodes ?? []);
1118
1111
  const getElementAttributeNames = (element) => {
1119
1112
  const withGetAttributeNames = element;
@@ -1142,21 +1135,6 @@ const hasElementAttribute = (element, name) => {
1142
1135
  if (attributes instanceof Map) return attributes.has(name);
1143
1136
  return null;
1144
1137
  };
1145
- const insertMarkerNodeCounts = /* @__PURE__ */ new WeakMap();
1146
- const getResolvedRuntimeSymbols = (container) => {
1147
- const existing = resolvedRuntimeSymbols.get(container);
1148
- if (existing) return existing;
1149
- const created = /* @__PURE__ */ new Map();
1150
- resolvedRuntimeSymbols.set(container, created);
1151
- return created;
1152
- };
1153
- const invalidateRuntimeSymbolCaches = (container, symbolIds) => {
1154
- const resolved = getResolvedRuntimeSymbols(container);
1155
- for (const symbolId of symbolIds) {
1156
- container.imports.delete(symbolId);
1157
- resolved.delete(symbolId);
1158
- }
1159
- };
1160
1138
  const cloneManagedAttributeSnapshot = (element) => new Set(getElementAttributeNames(element));
1161
1139
  const replaceManagedAttributeSnapshot = (element, names) => {
1162
1140
  managedElementAttributes.set(element, new Set(names));
@@ -1187,20 +1165,148 @@ const rememberInsertMarkerRange = (marker, nodes) => {
1187
1165
  for (const _node of nodes) count += 1;
1188
1166
  insertMarkerNodeCounts.set(marker, count);
1189
1167
  };
1190
- const withResumeHmrTimestamp = (url, timestamp) => {
1191
- const parsed = new URL(url, "http://localhost");
1192
- parsed.searchParams.set("t", timestamp.toString());
1193
- return `${parsed.pathname}${parsed.search}${parsed.hash}`;
1168
+ const getRememberedInsertMarkerNodeCount = (marker) => marker ? insertMarkerNodeCounts.get(marker) ?? 0 : 0;
1169
+ const setRememberedInsertMarkerNodeCount = (marker, count) => {
1170
+ insertMarkerNodeCounts.set(marker, count);
1194
1171
  };
1195
- const canBustRuntimeSymbolUrl = (url) => parseSymbolIdFromUrl(url) !== null;
1196
- const bustRuntimeSymbolUrls = (container, symbolIds, timestamp) => {
1197
- for (const symbolId of symbolIds) {
1198
- const current = container.symbols.get(symbolId);
1199
- if (!current || !canBustRuntimeSymbolUrl(current)) continue;
1200
- container.symbols.set(symbolId, withResumeHmrTimestamp(current, timestamp));
1172
+ const getBoundaryChildren = (start, end) => {
1173
+ const nodes = [];
1174
+ let cursor = start.nextSibling;
1175
+ while (cursor && cursor !== end) {
1176
+ nodes.push(cursor);
1177
+ cursor = cursor.nextSibling;
1201
1178
  }
1179
+ return nodes;
1202
1180
  };
1203
- const isRenderObject = (value) => typeof value === "object" && value !== null && "type" in value && "props" in value;
1181
+ const getNodePath = (root, target) => {
1182
+ if (root === target) return [];
1183
+ const path = [];
1184
+ let cursor = target;
1185
+ while (cursor && cursor !== root) {
1186
+ const parent = cursor.parentNode;
1187
+ if (!parent) return null;
1188
+ const index = Array.prototype.indexOf.call(parent.childNodes, cursor);
1189
+ if (index < 0) return null;
1190
+ path.unshift(index);
1191
+ cursor = parent;
1192
+ }
1193
+ return cursor === root ? path : null;
1194
+ };
1195
+ const getNodeByPath = (root, path) => {
1196
+ let cursor = root;
1197
+ for (const index of path) {
1198
+ const childNodes = cursor ? cursor.childNodes ?? void 0 : void 0;
1199
+ cursor = (childNodes && ("item" in childNodes ? childNodes.item(index) : childNodes[index] ?? null)) ?? null;
1200
+ if (!cursor) return null;
1201
+ }
1202
+ return cursor;
1203
+ };
1204
+ const getElementPath = (root, target) => {
1205
+ if (root === target) return [];
1206
+ const path = [];
1207
+ let cursor = target;
1208
+ while (cursor && cursor !== root) {
1209
+ const parent = cursor.parentElement;
1210
+ if (!parent) return null;
1211
+ const index = Array.prototype.indexOf.call(parent.children, cursor);
1212
+ if (index < 0) return null;
1213
+ path.unshift(index);
1214
+ cursor = parent;
1215
+ }
1216
+ return cursor === root ? path : null;
1217
+ };
1218
+ const getElementByPath = (root, path) => {
1219
+ let cursor = root;
1220
+ for (const index of path) {
1221
+ const children = cursor ? cursor.children ?? void 0 : void 0;
1222
+ cursor = (children && ("item" in children ? children.item(index) : children[index] ?? null)) ?? null;
1223
+ if (!cursor) return null;
1224
+ }
1225
+ return cursor;
1226
+ };
1227
+ const restoreFocusTarget = (doc, nextActive, snapshot) => {
1228
+ const restore = () => {
1229
+ if (!nextActive.isConnected) return false;
1230
+ nextActive.focus({ preventScroll: true });
1231
+ if (isTextEntryElement(nextActive) && snapshot.selectionStart !== null && snapshot.selectionStart !== void 0) nextActive.setSelectionRange(snapshot.selectionStart, snapshot.selectionEnd ?? snapshot.selectionStart, snapshot.selectionDirection ?? void 0);
1232
+ return doc.activeElement === nextActive;
1233
+ };
1234
+ if (restore()) return;
1235
+ const win = doc.defaultView;
1236
+ if (!win) return;
1237
+ let remainingAttempts = 3;
1238
+ const retry = () => {
1239
+ if (remainingAttempts <= 0) return;
1240
+ remainingAttempts--;
1241
+ const run = () => {
1242
+ if (restore()) return;
1243
+ retry();
1244
+ };
1245
+ if (typeof win.requestAnimationFrame === "function") {
1246
+ win.requestAnimationFrame(() => run());
1247
+ return;
1248
+ }
1249
+ win.setTimeout(run, 16);
1250
+ };
1251
+ retry();
1252
+ };
1253
+ const captureBoundaryFocus = (doc, start, end) => {
1254
+ const activeElement = doc.activeElement;
1255
+ if (!isHTMLElementNode(activeElement)) return null;
1256
+ const topLevelNodes = getBoundaryChildren(start, end);
1257
+ for (let index = 0; index < topLevelNodes.length; index += 1) {
1258
+ const candidate = topLevelNodes[index];
1259
+ if (candidate !== activeElement && (!isElementNode(candidate) || !candidate.contains(activeElement))) continue;
1260
+ const innerPath = getNodePath(candidate, activeElement);
1261
+ if (!innerPath) continue;
1262
+ return {
1263
+ path: [index, ...innerPath],
1264
+ selectionDirection: isTextEntryElement(activeElement) ? activeElement.selectionDirection : null,
1265
+ selectionEnd: isTextEntryElement(activeElement) ? activeElement.selectionEnd : null,
1266
+ selectionStart: isTextEntryElement(activeElement) ? activeElement.selectionStart : null
1267
+ };
1268
+ }
1269
+ return null;
1270
+ };
1271
+ const restoreBoundaryFocus = (doc, start, end, snapshot) => {
1272
+ if (!snapshot) return;
1273
+ const [topLevelIndex, ...innerPath] = snapshot.path;
1274
+ const root = getBoundaryChildren(start, end)[topLevelIndex];
1275
+ if (!root) return;
1276
+ const nextActive = innerPath.length > 0 ? getNodeByPath(root, innerPath) : root;
1277
+ if (!isHTMLElementNode(nextActive)) return;
1278
+ restoreFocusTarget(doc, nextActive, snapshot);
1279
+ };
1280
+ const captureDocumentFocus = (doc, focusSource) => {
1281
+ const candidate = isHTMLElementNode(focusSource) ? focusSource : isHTMLElementNode(doc.activeElement) ? doc.activeElement : null;
1282
+ if (!candidate) return null;
1283
+ const path = getElementPath(doc.body, candidate);
1284
+ if (!path) return null;
1285
+ return {
1286
+ path,
1287
+ selectionDirection: isTextEntryElement(candidate) ? candidate.selectionDirection : null,
1288
+ selectionEnd: isTextEntryElement(candidate) ? candidate.selectionEnd : null,
1289
+ selectionStart: isTextEntryElement(candidate) ? candidate.selectionStart : null
1290
+ };
1291
+ };
1292
+ const shouldSkipPendingFocusRestore = (doc, pending) => {
1293
+ const activeElement = doc.activeElement;
1294
+ if (!isHTMLElementNode(activeElement)) return false;
1295
+ if (activeElement === doc.body || !activeElement.isConnected || !doc.body.contains(activeElement)) return false;
1296
+ const activePath = getElementPath(doc.body, activeElement);
1297
+ if (!activePath) return false;
1298
+ if (activePath.length !== pending.snapshot.path.length) return true;
1299
+ return activePath.some((index, position) => index !== pending.snapshot.path[position]);
1300
+ };
1301
+ const restorePendingFocus$1 = (doc, pending) => {
1302
+ if (!pending) return;
1303
+ if (shouldSkipPendingFocusRestore(doc, pending)) return;
1304
+ const nextActive = getElementByPath(doc.body, pending.snapshot.path);
1305
+ if (!isHTMLElementNode(nextActive)) return;
1306
+ restoreFocusTarget(doc, nextActive, pending.snapshot);
1307
+ };
1308
+ //#endregion
1309
+ //#region core/runtime/globals.ts
1204
1310
  const getContainerStack = () => {
1205
1311
  const globalRecord = globalThis;
1206
1312
  const existing = globalRecord[CONTAINER_STACK_KEY];
@@ -1245,58 +1351,19 @@ const getAsyncSignalSnapshotCache = () => {
1245
1351
  globalRecord[ASYNC_SIGNAL_SNAPSHOT_CACHE_KEY] = created;
1246
1352
  return created;
1247
1353
  };
1248
- const readAsyncSignalSnapshot = (id, container = getCurrentContainer()) => container?.asyncSignalStates.get(id) ?? container?.asyncSignalSnapshotCache.get(id) ?? getAsyncSignalSnapshotCache().get(id);
1249
- const writeAsyncSignalSnapshot = (id, value, container = getCurrentContainer()) => {
1354
+ const readAsyncSignalSnapshot$1 = (id, container) => container?.asyncSignalStates.get(id) ?? container?.asyncSignalSnapshotCache.get(id) ?? getAsyncSignalSnapshotCache().get(id);
1355
+ const writeAsyncSignalSnapshot$1 = (id, value, container) => {
1250
1356
  container?.asyncSignalStates.set(id, value);
1251
1357
  container?.asyncSignalSnapshotCache.set(id, value);
1252
1358
  if (!container) getAsyncSignalSnapshotCache().set(id, value);
1253
1359
  };
1254
- const getCurrentFrame = () => {
1255
- const stack = getFrameStack();
1256
- return stack.length > 0 ? stack[stack.length - 1] : null;
1257
- };
1258
- const shouldReconnectDetachedInsertMarkers = (container) => {
1259
- const frame = getCurrentFrame();
1260
- if (!container || !frame || frame.container !== container) return true;
1261
- return frame.projectionState.reuseExistingDom;
1262
- };
1263
- const hasScopedStyles = (frame) => !!frame && frame.scopedStyles.length > 0;
1264
- const getScopedStyleRootSelector = (scopeId) => `[${SCOPED_STYLE_ATTR}="${escapeAttr(scopeId)}"]`;
1265
- const wrapScopedStyleCss = (scopeId, cssText) => `@scope (${getScopedStyleRootSelector(scopeId)}) {\n${cssText}\n}`;
1266
- const renderScopedStyleString = (scopeId, style) => {
1267
- const attrParts = Object.entries(style.attributes).filter(([, value]) => value !== false && value !== void 0 && value !== null).map(([name, value]) => value === true ? name : `${name}="${escapeAttr(String(value))}"`);
1268
- return `<style${attrParts.length > 0 ? ` ${attrParts.join(" ")}` : ""}>${escapeText(wrapScopedStyleCss(scopeId, style.cssText))}</style>`;
1269
- };
1270
- const renderScopedStyleNode = (container, scopeId, style) => {
1271
- const element = createElementNode(container.doc, "style");
1272
- for (const [name, value] of Object.entries(style.attributes)) {
1273
- if (value === false || value === void 0 || value === null) continue;
1274
- if (value === true) {
1275
- element.setAttribute(name, "");
1276
- continue;
1277
- }
1278
- element.setAttribute(name, String(value));
1279
- }
1280
- element.appendChild(container.doc.createTextNode(wrapScopedStyleCss(scopeId, style.cssText)));
1281
- return element;
1282
- };
1283
- const renderFrameScopedStylesToString = (frame) => frame.scopedStyles.map((style) => renderScopedStyleString(frame.component.scopeId, style)).join("");
1284
- const renderFrameScopedStylesToNodes = (frame, container) => frame.scopedStyles.map((style) => renderScopedStyleNode(container, frame.component.scopeId, style));
1285
- const registerRuntimeScopedStyle = (cssText, attributes = {}) => {
1286
- const frame = getCurrentFrame();
1287
- if (!frame || frame.component.id === ROOT_COMPONENT_ID) throw new Error("useStyleScoped() can only be used while rendering a component.");
1288
- if (cssText.length === 0) return;
1289
- if (frame.scopedStyles.find((entry) => entry.cssText === cssText && JSON.stringify(entry.attributes) === JSON.stringify(attributes))) return;
1290
- frame.scopedStyles.push({
1291
- attributes: { ...attributes },
1292
- cssText
1293
- });
1294
- };
1295
- const normalizeRoutePath = (pathname) => {
1296
- const normalizedPath = pathname.trim() || "/";
1297
- const withLeadingSlash = normalizedPath.startsWith("/") ? normalizedPath : `/${normalizedPath}`;
1298
- if (withLeadingSlash.length > 1 && withLeadingSlash.endsWith("/")) return withLeadingSlash.slice(0, -1);
1299
- return withLeadingSlash;
1360
+ //#endregion
1361
+ //#region core/runtime/routes.ts
1362
+ const normalizeRoutePath = (pathname) => {
1363
+ const normalizedPath = pathname.trim() || "/";
1364
+ const withLeadingSlash = normalizedPath.startsWith("/") ? normalizedPath : `/${normalizedPath}`;
1365
+ if (withLeadingSlash.length > 1 && withLeadingSlash.endsWith("/")) return withLeadingSlash.slice(0, -1);
1366
+ return withLeadingSlash;
1300
1367
  };
1301
1368
  const parseLocationHref = (href) => new URL(href, "http://localhost");
1302
1369
  const createStandaloneLocation = () => ({
@@ -1328,6 +1395,10 @@ const createRouterLocation = (router) => ({
1328
1395
  }
1329
1396
  });
1330
1397
  const EMPTY_ROUTE_PARAMS = Object.freeze({});
1398
+ const ROUTE_DOCUMENT_FALLBACK = Object.freeze({
1399
+ document: true,
1400
+ ok: false
1401
+ });
1331
1402
  const splitRoutePath = (pathname) => normalizeRoutePath(pathname).split("/").filter(Boolean);
1332
1403
  const matchRouteSegments = (segments, pathnameSegments, routeIndex = 0, pathIndex = 0, params = {}) => {
1333
1404
  if (routeIndex >= segments.length) return pathIndex >= pathnameSegments.length ? params : null;
@@ -1377,11 +1448,11 @@ const matchRouteManifest = (manifest, pathname) => {
1377
1448
  return null;
1378
1449
  };
1379
1450
  const scoreSpecialManifestEntry = (entry, pathname) => {
1380
- const pathnameSegments = splitRoutePath(pathname);
1451
+ const pathSegments = splitRoutePath(pathname);
1381
1452
  let score = 0;
1382
- for (let index = 0; index < entry.segments.length && index < pathnameSegments.length; index += 1) {
1453
+ for (let index = 0; index < entry.segments.length && index < pathSegments.length; index += 1) {
1383
1454
  const segment = entry.segments[index];
1384
- const pathnameSegment = pathnameSegments[index];
1455
+ const pathnameSegment = pathSegments[index];
1385
1456
  if (segment.kind === "static") {
1386
1457
  if (segment.value !== pathnameSegment) break;
1387
1458
  score += 10;
@@ -1411,116 +1482,223 @@ const findSpecialManifestEntry = (manifest, pathname, kind) => {
1411
1482
  }
1412
1483
  return best;
1413
1484
  };
1414
- const routeCacheKey = (pathname, variant = "page") => `${normalizeRoutePath(pathname)}::${variant}`;
1415
- const routePrefetchKey = (url) => `${normalizeRoutePath(url.pathname)}${url.search}`;
1416
- const isLoaderSignalId = (id) => id.startsWith("$loader:");
1417
- let currentEffect = null;
1418
- let currentCleanupSlot = null;
1419
- const withoutTrackedEffect = (fn) => {
1420
- const previous = currentEffect;
1421
- currentEffect = null;
1422
- try {
1423
- return fn();
1424
- } finally {
1425
- currentEffect = previous;
1426
- }
1485
+ const resolvePageRouteMatch = (manifest, pathname) => {
1486
+ const matched = matchRouteManifest(manifest, pathname);
1487
+ return matched?.entry.page ? matched : null;
1427
1488
  };
1428
- const createCleanupSlot = () => ({ callbacks: [] });
1429
- const withCleanupSlot = (slot, fn) => {
1430
- const previous = currentCleanupSlot;
1431
- currentCleanupSlot = slot;
1432
- try {
1433
- return fn();
1434
- } finally {
1435
- currentCleanupSlot = previous;
1436
- }
1489
+ const resolveNotFoundRouteMatch = (manifest, pathname) => {
1490
+ const matched = findSpecialManifestEntry(manifest, pathname, "notFound");
1491
+ return matched?.entry.notFound ? matched : null;
1437
1492
  };
1438
- const disposeCleanupSlot = (slot) => {
1439
- if (!slot || slot.callbacks.length === 0) return;
1440
- const callbacks = [...slot.callbacks].reverse();
1441
- slot.callbacks.length = 0;
1442
- let firstError = null;
1443
- const previous = currentCleanupSlot;
1444
- currentCleanupSlot = null;
1445
- try {
1446
- for (const callback of callbacks) try {
1447
- withoutTrackedEffect(callback);
1448
- } catch (error) {
1449
- firstError ??= error;
1450
- }
1451
- } finally {
1452
- currentCleanupSlot = previous;
1453
- }
1454
- if (firstError) throw firstError;
1493
+ const resolveRoutableMatch = (manifest, pathname) => {
1494
+ const matched = matchRouteManifest(manifest, pathname);
1495
+ if (matched?.entry.page) return {
1496
+ kind: "page",
1497
+ matched
1498
+ };
1499
+ if (matched) return null;
1500
+ const notFoundMatch = resolveNotFoundRouteMatch(manifest, pathname);
1501
+ if (!notFoundMatch) return null;
1502
+ return {
1503
+ kind: "not-found",
1504
+ matched: notFoundMatch
1505
+ };
1455
1506
  };
1456
- const resetComponentRenderEffects = (component) => {
1457
- disposeCleanupSlot(component.renderEffectCleanupSlot);
1458
- component.renderEffectCleanupSlot = createCleanupSlot();
1507
+ const resolveCurrentRouteManifestEntry = (router) => {
1508
+ const currentPath = normalizeRoutePath(router.currentPath.value);
1509
+ const matched = matchRouteManifest(router.manifest, currentPath);
1510
+ if (matched?.entry.page) return matched.entry;
1511
+ return findSpecialManifestEntry(router.manifest, currentPath, "notFound")?.entry ?? null;
1459
1512
  };
1460
- const syncEffectOnlyLocalSignalPreference = (component) => {
1461
- component.prefersEffectOnlyLocalSignalWrites = component.optimizedRoot === true;
1513
+ const getRouteModuleUrl = (entry, variant = "page") => variant === "page" ? entry.page : variant === "loading" ? entry.loading : variant === "error" ? entry.error : entry.notFound;
1514
+ const isRouteDataSuccess = (body) => body.ok === true && typeof body.finalHref === "string" && typeof body.finalPathname === "string" && (body.kind === "page" || body.kind === "not-found") && !!body.loaders && typeof body.loaders === "object";
1515
+ const isRouteSlot = (value) => typeof value === "object" && value !== null && "__eclipsa_type" in value && value.__eclipsa_type === "route-slot";
1516
+ const createRouteSlot = (route, startLayoutIndex) => {
1517
+ const slot = {
1518
+ __eclipsa_type: ROUTE_SLOT_TYPE,
1519
+ pathname: route.pathname,
1520
+ startLayoutIndex
1521
+ };
1522
+ Object.defineProperty(slot, ROUTE_SLOT_ROUTE_KEY, {
1523
+ configurable: true,
1524
+ enumerable: false,
1525
+ value: route,
1526
+ writable: true
1527
+ });
1528
+ return slot;
1462
1529
  };
1463
- const clearEffectSignals = (effect) => {
1464
- for (const signal of effect.signals) signal.effects.delete(effect);
1465
- effect.signals.clear();
1530
+ const resolveRouteSlot = (container, slot) => {
1531
+ const route = slot[ROUTE_SLOT_ROUTE_KEY] ?? container?.router?.loadedRoutes.get(routeCacheKey(slot.pathname, "page"));
1532
+ if (!route) return null;
1533
+ return createRouteElement(route, slot.startLayoutIndex);
1466
1534
  };
1467
- const collectTrackedDependencies = (effect, fn) => {
1468
- clearEffectSignals(effect);
1469
- currentEffect = effect;
1470
- try {
1471
- fn();
1472
- } finally {
1473
- currentEffect = null;
1474
- }
1535
+ const defineHiddenRouteProp = (props, key, value) => {
1536
+ Object.defineProperty(props, key, {
1537
+ configurable: true,
1538
+ enumerable: false,
1539
+ value,
1540
+ writable: true
1541
+ });
1475
1542
  };
1476
- const runWithoutDependencyTracking = (fn) => {
1477
- const previousEffect = currentEffect;
1478
- currentEffect = null;
1479
- try {
1480
- return fn();
1481
- } finally {
1482
- currentEffect = previousEffect;
1483
- }
1543
+ const createRouteRenderProps = (route, props) => {
1544
+ const nextProps = { ...props };
1545
+ defineHiddenRouteProp(nextProps, ROUTE_PARAMS_PROP, route.params);
1546
+ defineHiddenRouteProp(nextProps, ROUTE_ERROR_PROP, route.error);
1547
+ return nextProps;
1484
1548
  };
1485
- const trackWatchDependencies = (dependencies, errorLabel = "useWatch") => {
1486
- for (const dependency of dependencies) {
1487
- if (typeof dependency === "function") {
1488
- dependency();
1489
- continue;
1490
- }
1491
- if (!getSignalMeta(dependency)) throw new TypeError(`${errorLabel} dependencies must be signals or getter functions.`);
1492
- dependency.value;
1549
+ const createRouteElement = (route, startLayoutIndex = 0) => {
1550
+ if (startLayoutIndex >= route.layouts.length) return jsxDEV(route.page.renderer, createRouteRenderProps(route, {}), null, false, {});
1551
+ let children = null;
1552
+ for (let index = route.layouts.length - 1; index >= startLayoutIndex; index -= 1) {
1553
+ const layout = route.layouts[index];
1554
+ children = jsxDEV(layout.renderer, createRouteRenderProps(route, { children: createRouteSlot(route, index + 1) }), null, false, {});
1493
1555
  }
1556
+ return children;
1494
1557
  };
1495
- const runWatchCallback = (effect, cleanupSlot, fn, dependencies) => {
1496
- disposeCleanupSlot(cleanupSlot);
1497
- if (!dependencies) {
1498
- collectTrackedDependencies(effect, () => {
1499
- withCleanupSlot(cleanupSlot, fn);
1500
- });
1501
- return;
1558
+ const routeCacheKey = (pathname, variant = "page") => `${normalizeRoutePath(pathname)}::${variant}`;
1559
+ const routePrefetchKey = (url) => `${normalizeRoutePath(url.pathname)}${url.search}`;
1560
+ const isLoaderSignalId = (id) => id.startsWith("$loader:");
1561
+ //#endregion
1562
+ //#region core/runtime/ssr.ts
1563
+ const EVENT_PROP_REGEX = /^on([A-Z].+)$/;
1564
+ const DANGEROUSLY_SET_INNER_HTML_PROP = "dangerouslySetInnerHTML";
1565
+ const TEXT_ESCAPE_REGEX = /[&<>]/;
1566
+ const ATTR_ESCAPE_REGEX = /[&<>'"]/;
1567
+ const escapeString = (value, mode) => {
1568
+ const escapePattern = mode === "attr" ? ATTR_ESCAPE_REGEX : TEXT_ESCAPE_REGEX;
1569
+ const firstMatch = value.search(escapePattern);
1570
+ if (firstMatch < 0) return value;
1571
+ let output = "";
1572
+ let lastIndex = 0;
1573
+ for (let index = firstMatch; index < value.length; index += 1) {
1574
+ let escaped = null;
1575
+ switch (value.charCodeAt(index)) {
1576
+ case 34:
1577
+ escaped = mode === "attr" ? "&quot;" : null;
1578
+ break;
1579
+ case 38:
1580
+ escaped = "&amp;";
1581
+ break;
1582
+ case 39:
1583
+ escaped = mode === "attr" ? "&#39;" : null;
1584
+ break;
1585
+ case 60:
1586
+ escaped = "&lt;";
1587
+ break;
1588
+ case 62:
1589
+ escaped = "&gt;";
1590
+ break;
1591
+ }
1592
+ if (!escaped) continue;
1593
+ output += value.slice(lastIndex, index);
1594
+ output += escaped;
1595
+ lastIndex = index + 1;
1502
1596
  }
1503
- collectTrackedDependencies(effect, () => {
1504
- trackWatchDependencies(dependencies);
1505
- });
1506
- withCleanupSlot(cleanupSlot, fn);
1597
+ return output + value.slice(lastIndex);
1507
1598
  };
1508
- const createLocalWatchRunner = (effect, cleanupSlot, fn, dependencies) => () => {
1509
- runWatchCallback(effect, cleanupSlot, fn, dependencies);
1599
+ const escapeText = (value) => escapeString(value, "text");
1600
+ const escapeAttr = (value) => escapeString(value, "attr");
1601
+ const resolveDangerouslySetInnerHTML = (value) => value === false || value === void 0 || value === null ? null : String(value);
1602
+ const toEventName = (propName) => {
1603
+ const matched = propName.match(EVENT_PROP_REGEX);
1604
+ if (!matched) return null;
1605
+ const [first, ...rest] = matched[1];
1606
+ return `${first.toLowerCase()}${rest.join("")}`;
1510
1607
  };
1511
- const isPlainObject = (value) => {
1512
- if (!value || typeof value !== "object") return false;
1513
- const proto = Object.getPrototypeOf(value);
1514
- return proto === Object.prototype || proto === null;
1608
+ const isDangerouslySetInnerHTMLProp = (propName) => propName === DANGEROUSLY_SET_INNER_HTML_PROP;
1609
+ const createSSRRenderer = ({ getCurrentContainer, isProjectionSlot, isRouteSlot, renderProjectionSlotToString, renderStringNode, resolveRouteSlot }) => {
1610
+ const renderSSRAttr = (name, value) => {
1611
+ if (name === "key") return "";
1612
+ if (value === false || value === void 0 || value === null) return "";
1613
+ if (value === true) return ` ${name}`;
1614
+ return ` ${name}="${escapeAttr(String(value))}"`;
1615
+ };
1616
+ const renderSSRTemplateNode = (template) => {
1617
+ let output = template.strings[0] ?? "";
1618
+ for (let index = 0; index < template.values.length; index += 1) {
1619
+ const value = template.values[index];
1620
+ output += isSSRAttrValue(value) ? renderSSRAttr(value.name, value.value) : renderSSRValue(value);
1621
+ output += template.strings[index + 1] ?? "";
1622
+ }
1623
+ return output;
1624
+ };
1625
+ const renderStringArray = (values) => {
1626
+ let output = "";
1627
+ for (let index = 0; index < values.length; index += 1) {
1628
+ const value = values[index];
1629
+ if (Array.isArray(value)) {
1630
+ output += renderStringArray(value);
1631
+ continue;
1632
+ }
1633
+ if (value === false || value === null || value === void 0) continue;
1634
+ if (typeof value === "string") {
1635
+ output += escapeText(value);
1636
+ continue;
1637
+ }
1638
+ if (typeof value === "number" || typeof value === "boolean") {
1639
+ output += escapeText(String(value));
1640
+ continue;
1641
+ }
1642
+ if (isSSRRawValue(value)) {
1643
+ output += value.value;
1644
+ continue;
1645
+ }
1646
+ if (isSSRTemplate(value)) {
1647
+ output += renderSSRTemplateNode(value);
1648
+ continue;
1649
+ }
1650
+ if (isProjectionSlot(value)) {
1651
+ output += renderProjectionSlotToString(value);
1652
+ continue;
1653
+ }
1654
+ if (isRouteSlot(value)) {
1655
+ const routeElement = resolveRouteSlot(getCurrentContainer(), value);
1656
+ if (routeElement) output += renderStringNode(routeElement);
1657
+ continue;
1658
+ }
1659
+ output += renderStringNode(value);
1660
+ }
1661
+ return output;
1662
+ };
1663
+ const renderSSRValue = (value) => {
1664
+ if (value === false || value === null || value === void 0) return "";
1665
+ if (Array.isArray(value)) return renderStringArray(value);
1666
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return escapeText(String(value));
1667
+ if (isSSRRawValue(value)) return value.value;
1668
+ if (isSSRTemplate(value)) return renderSSRTemplateNode(value);
1669
+ if (isProjectionSlot(value)) return renderProjectionSlotToString(value);
1670
+ if (isRouteSlot(value)) {
1671
+ const routeElement = resolveRouteSlot(getCurrentContainer(), value);
1672
+ return routeElement ? renderStringNode(routeElement) : "";
1673
+ }
1674
+ return renderStringNode(value);
1675
+ };
1676
+ const renderSSRMap = (value, renderItem) => {
1677
+ if (Array.isArray(value)) {
1678
+ let output = "";
1679
+ for (let index = 0; index < value.length; index += 1) {
1680
+ if (!(index in value)) continue;
1681
+ output += renderItem(value[index], index);
1682
+ }
1683
+ return output;
1684
+ }
1685
+ return value.map(renderItem).join("");
1686
+ };
1687
+ return {
1688
+ renderSSRAttr,
1689
+ renderSSRValue,
1690
+ renderSSRMap
1691
+ };
1515
1692
  };
1516
- const isProjectionSlot = (value) => isPlainObject(value) && value.__eclipsa_type === PROJECTION_SLOT_TYPE;
1517
- const createProjectionSlot = (componentId, name, occurrence, source) => ({
1518
- __eclipsa_type: PROJECTION_SLOT_TYPE,
1519
- componentId,
1520
- name,
1521
- occurrence,
1522
- source
1523
- });
1693
+ //#endregion
1694
+ //#region core/runtime/markers.ts
1695
+ const COMPONENT_BOUNDARY_PROPS_CHANGED = Symbol.for("eclipsa.component-boundary-props-changed");
1696
+ const COMPONENT_BOUNDARY_SYMBOL_CHANGED = Symbol.for("eclipsa.component-boundary-symbol-changed");
1697
+ const INSERT_MARKER_PREFIX = "ec:i:";
1698
+ const COMPONENT_BOUNDARY_MARKER_REGEX = /^ec:c:(.+):(start|end)$/;
1699
+ const KEYED_RANGE_MARKER_REGEX = /^ec:k:([^:]+):([^:]+):(start|end)$/;
1700
+ const PROJECTION_SLOT_MARKER_REGEX = /^ec:s:([^:]+):([^:]+):(\d+):(start|end)$/;
1701
+ const INSERT_MARKER_REGEX = /^ec:i:(.+)$/;
1524
1702
  const encodeProjectionSlotName = (value) => encodeURIComponent(value);
1525
1703
  const decodeProjectionSlotName = (value) => decodeURIComponent(value);
1526
1704
  const encodeKeyedRangeToken = (value) => encodeURIComponent(String(value));
@@ -1531,12 +1709,28 @@ const decodeKeyedRangeToken = (value) => {
1531
1709
  return value;
1532
1710
  }
1533
1711
  };
1534
- const createProjectionSlotMarker = (componentId, name, occurrence, kind) => `ec:s:${componentId}:${encodeProjectionSlotName(name)}:${occurrence}:${kind}`;
1535
- const createKeyedRangeMarker = (value, kind) => `ec:k:${encodeKeyedRangeToken(value)}:${kind}`;
1536
- const COMPONENT_BOUNDARY_MARKER_REGEX = /^ec:c:(.+):(start|end)$/;
1537
- const INSERT_MARKER_REGEX = /^ec:i:(.+)$/;
1538
- const KEYED_RANGE_MARKER_REGEX = /^ec:k:([^:]+):(start|end)$/;
1539
- const PROJECTION_SLOT_MARKER_REGEX = /^ec:s:([^:]+):([^:]+):(\d+):(start|end)$/;
1712
+ const createComponentBoundaryMarker = (componentId, kind) => `ec:c:${componentId}:${kind}`;
1713
+ const createComponentBoundaryHtmlComment = (componentId, kind) => `<!--${createComponentBoundaryMarker(componentId, kind)}-->`;
1714
+ const setComponentBoundaryChangeFlags = (start, options) => {
1715
+ start[COMPONENT_BOUNDARY_PROPS_CHANGED] = options?.propsChanged === true;
1716
+ start[COMPONENT_BOUNDARY_SYMBOL_CHANGED] = options?.symbolChanged === true;
1717
+ };
1718
+ const didComponentBoundaryPropsChange = (start) => Boolean(start[COMPONENT_BOUNDARY_PROPS_CHANGED]);
1719
+ const didComponentBoundarySymbolChange = (start) => Boolean(start[COMPONENT_BOUNDARY_SYMBOL_CHANGED]);
1720
+ const didComponentBoundaryChange = (start) => didComponentBoundaryPropsChange(start) || didComponentBoundarySymbolChange(start);
1721
+ const createComponentBoundaryPair = (doc, componentId, options) => {
1722
+ const start = doc.createComment(createComponentBoundaryMarker(componentId, "start"));
1723
+ const end = doc.createComment(createComponentBoundaryMarker(componentId, "end"));
1724
+ setComponentBoundaryChangeFlags(start, options);
1725
+ return {
1726
+ end,
1727
+ start
1728
+ };
1729
+ };
1730
+ const createProjectionSlotRangeKey = (componentId, name, occurrence) => `${componentId}:${encodeProjectionSlotName(name)}:${occurrence}`;
1731
+ const createProjectionSlotMarker = (componentId, name, occurrence, kind) => `ec:s:${createProjectionSlotRangeKey(componentId, name, occurrence)}:${kind}`;
1732
+ const createKeyedRangeMarker = (scope, value, kind) => `ec:k:${encodeKeyedRangeToken(scope)}:${encodeKeyedRangeToken(value)}:${kind}`;
1733
+ const createInsertMarker = (key) => `${INSERT_MARKER_PREFIX}${key}`;
1540
1734
  const parseComponentBoundaryMarker = (value) => {
1541
1735
  const matched = value.match(COMPONENT_BOUNDARY_MARKER_REGEX);
1542
1736
  if (!matched) return null;
@@ -1550,8 +1744,8 @@ const parseProjectionSlotMarker = (value) => {
1550
1744
  if (!matched) return null;
1551
1745
  return {
1552
1746
  componentId: matched[1],
1747
+ key: createProjectionSlotRangeKey(matched[1], decodeProjectionSlotName(matched[2]), Number(matched[3])),
1553
1748
  kind: matched[4],
1554
- key: `${matched[1]}:${matched[2]}:${matched[3]}`,
1555
1749
  name: decodeProjectionSlotName(matched[2]),
1556
1750
  occurrence: Number(matched[3])
1557
1751
  };
@@ -1560,8 +1754,9 @@ const parseKeyedRangeMarker = (value) => {
1560
1754
  const matched = value.match(KEYED_RANGE_MARKER_REGEX);
1561
1755
  if (!matched) return null;
1562
1756
  return {
1563
- key: decodeKeyedRangeToken(matched[1]),
1564
- kind: matched[2]
1757
+ scope: decodeKeyedRangeToken(matched[1]),
1758
+ key: decodeKeyedRangeToken(matched[2]),
1759
+ kind: matched[3]
1565
1760
  };
1566
1761
  };
1567
1762
  const parseInsertMarker = (value) => {
@@ -1569,274 +1764,512 @@ const parseInsertMarker = (value) => {
1569
1764
  if (!matched) return null;
1570
1765
  return { key: matched[1] };
1571
1766
  };
1572
- const getRenderComponentTypeRef = (value) => {
1573
- if (typeof value !== "function") return null;
1574
- return value[RENDER_COMPONENT_TYPE_KEY] ?? null;
1575
- };
1576
- const createMaterializedRenderComponentType = (container, symbol, scopeId) => {
1577
- const component = __eclipsaComponent(((props) => {
1578
- const module = getResolvedRuntimeSymbols(container).get(symbol);
1579
- if (!module) throw new Error(`Missing preloaded render component symbol ${symbol}.`);
1580
- return module.default(materializeScope(container, scopeId), props);
1581
- }), symbol, () => materializeScope(container, scopeId));
1582
- Object.defineProperty(component, RENDER_COMPONENT_TYPE_KEY, {
1583
- configurable: true,
1584
- enumerable: false,
1585
- value: {
1586
- scopeId,
1587
- symbol
1588
- },
1589
- writable: true
1590
- });
1591
- return component;
1592
- };
1593
- const serializeRenderObjectReference = (container, value) => {
1594
- if (typeof value.type === "function" && !getComponentMeta(value.type)) {
1595
- const resolved = resolveRenderable(value.type(value.props));
1596
- if (!isRenderObject(resolved)) throw new TypeError("Only resumable component render objects can be serialized.");
1597
- return serializeRenderObjectReference(container, resolved);
1598
- }
1599
- const evaluatedProps = evaluateProps(value.props);
1600
- const key = value.key ?? null;
1601
- const metadata = value.metadata ?? null;
1602
- if (typeof value.type === "string") return {
1603
- __eclipsa_type: "ref",
1604
- data: [
1605
- "element",
1606
- value.type,
1607
- null,
1608
- serializeRuntimeValue(container, evaluatedProps),
1609
- serializeRuntimeValue(container, key),
1610
- value.isStatic,
1611
- serializeRuntimeValue(container, metadata)
1612
- ],
1613
- kind: RENDER_REFERENCE_KIND,
1614
- token: "jsx"
1767
+ //#endregion
1768
+ //#region core/runtime/serialization.ts
1769
+ const createRuntimeSerialization = ({ createProjectionSlot, ensureRouterState, ensureRuntimeElementId, evaluateProps, findRuntimeElement, getResolvedRuntimeSymbols, isPlainObject, isProjectionSlot, isRenderObject, isRouteSlot, loadSymbol, materializeScope, materializeSymbolReference, registerScope, registerSerializedScope, resolveRenderable }) => {
1770
+ const getRenderComponentTypeRef = (value) => {
1771
+ if (typeof value !== "function") return null;
1772
+ return value[RENDER_COMPONENT_TYPE_KEY] ?? null;
1615
1773
  };
1616
- const meta = getComponentMeta(value.type);
1617
- if (!meta) throw new TypeError("Only resumable component render objects can be serialized.");
1618
- return {
1619
- __eclipsa_type: "ref",
1620
- data: [
1621
- "component",
1622
- meta.symbol,
1623
- registerScope(container, meta.captures()),
1624
- serializeRuntimeValue(container, evaluatedProps),
1625
- serializeRuntimeValue(container, key),
1626
- value.isStatic,
1627
- serializeRuntimeValue(container, metadata)
1628
- ],
1629
- kind: RENDER_REFERENCE_KIND,
1630
- token: "jsx"
1774
+ const createMaterializedRenderComponentType = (container, symbol, scopeId) => {
1775
+ const component = __eclipsaComponent(((props) => {
1776
+ const module = getResolvedRuntimeSymbols(container).get(symbol);
1777
+ if (!module) throw new Error(`Missing preloaded render component symbol ${symbol}.`);
1778
+ return module.default(materializeScope(container, scopeId), props);
1779
+ }), symbol, () => materializeScope(container, scopeId));
1780
+ Object.defineProperty(component, RENDER_COMPONENT_TYPE_KEY, {
1781
+ configurable: true,
1782
+ enumerable: false,
1783
+ value: {
1784
+ scopeId,
1785
+ symbol
1786
+ },
1787
+ writable: true
1788
+ });
1789
+ return component;
1631
1790
  };
1632
- };
1633
- const deserializeRenderObjectReference = (container, data) => {
1634
- if (!Array.isArray(data) || data.length !== 7) throw new TypeError("Render references require a seven-part payload.");
1635
- const [variant, typeValue, scopeValue, propsValue, keyValue, isStaticValue, metadataValue] = data;
1636
- if (variant !== "element" && variant !== "component") throw new TypeError(`Unsupported render reference variant "${String(variant)}".`);
1637
- if (typeof isStaticValue !== "boolean") throw new TypeError("Render references require a boolean static flag.");
1638
- const props = deserializeRuntimeValue(container, propsValue);
1639
- const key = deserializeRuntimeValue(container, keyValue);
1640
- const metadata = deserializeRuntimeValue(container, metadataValue);
1641
- if (!props || typeof props !== "object") throw new TypeError("Render references require object props.");
1642
- if (variant === "element") {
1643
- if (typeof typeValue !== "string") throw new TypeError("Element render references require a string tag name.");
1791
+ const serializeRenderObjectReference = (container, value) => {
1792
+ if (typeof value.type === "function" && !getComponentMeta(value.type)) {
1793
+ const resolved = resolveRenderable(value.type(value.props));
1794
+ if (!isRenderObject(resolved)) throw new TypeError("Only resumable component render objects can be serialized.");
1795
+ return serializeRenderObjectReference(container, resolved);
1796
+ }
1797
+ const evaluatedProps = evaluateProps(value.props);
1798
+ const key = value.key ?? null;
1799
+ const isStatic = value.isStatic === true;
1800
+ const metadata = value.metadata ?? null;
1801
+ if (typeof value.type === "string") return {
1802
+ __eclipsa_type: "ref",
1803
+ data: [
1804
+ "element",
1805
+ value.type,
1806
+ null,
1807
+ serializeRuntimeValue(container, evaluatedProps),
1808
+ serializeRuntimeValue(container, key),
1809
+ isStatic,
1810
+ serializeRuntimeValue(container, metadata)
1811
+ ],
1812
+ kind: RENDER_REFERENCE_KIND,
1813
+ token: "jsx"
1814
+ };
1815
+ const meta = getComponentMeta(value.type);
1816
+ if (!meta) throw new TypeError("Only resumable component render objects can be serialized.");
1644
1817
  return {
1645
- isStatic: isStaticValue,
1818
+ __eclipsa_type: "ref",
1819
+ data: [
1820
+ "component",
1821
+ meta.symbol,
1822
+ registerScope(container, meta.captures()),
1823
+ serializeRuntimeValue(container, evaluatedProps),
1824
+ serializeRuntimeValue(container, key),
1825
+ isStatic,
1826
+ serializeRuntimeValue(container, metadata)
1827
+ ],
1828
+ kind: RENDER_REFERENCE_KIND,
1829
+ token: "jsx"
1830
+ };
1831
+ };
1832
+ const deserializeRenderObjectReference = (container, data) => {
1833
+ if (!Array.isArray(data) || data.length !== 7) throw new TypeError("Render references require a seven-part payload.");
1834
+ const [variant, typeValue, scopeValue, propsValue, keyValue, isStaticValue, metadataValue] = data;
1835
+ if (variant !== "element" && variant !== "component") throw new TypeError(`Unsupported render reference variant "${String(variant)}".`);
1836
+ if (typeof isStaticValue !== "boolean" && isStaticValue !== null && isStaticValue !== void 0) throw new TypeError("Render references require a boolean static flag.");
1837
+ const isStatic = isStaticValue === true;
1838
+ const props = deserializeRuntimeValue(container, propsValue);
1839
+ const key = deserializeRuntimeValue(container, keyValue);
1840
+ const metadata = deserializeRuntimeValue(container, metadataValue);
1841
+ if (!props || typeof props !== "object") throw new TypeError("Render references require object props.");
1842
+ if (variant === "element") {
1843
+ if (typeof typeValue !== "string") throw new TypeError("Element render references require a string tag name.");
1844
+ return {
1845
+ isStatic,
1846
+ key: key ?? void 0,
1847
+ metadata: metadata ?? void 0,
1848
+ props,
1849
+ type: typeValue
1850
+ };
1851
+ }
1852
+ if (typeof typeValue !== "string" || typeof scopeValue !== "string") throw new TypeError("Component render references require a symbol id and scope id.");
1853
+ return {
1854
+ isStatic,
1646
1855
  key: key ?? void 0,
1647
1856
  metadata: metadata ?? void 0,
1648
1857
  props,
1649
- type: typeValue
1858
+ type: createMaterializedRenderComponentType(container, typeValue, scopeValue)
1650
1859
  };
1651
- }
1652
- if (typeof typeValue !== "string" || typeof scopeValue !== "string") throw new TypeError("Component render references require a symbol id and scope id.");
1860
+ };
1861
+ const preloadResumableValue = async (container, value, seen = /* @__PURE__ */ new Set()) => {
1862
+ if (value === null || value === void 0 || value === false) return;
1863
+ if (seen.has(value)) return;
1864
+ if (typeof value === "function") {
1865
+ const renderComponentRef = getRenderComponentTypeRef(value);
1866
+ if (!renderComponentRef) return;
1867
+ seen.add(value);
1868
+ await loadSymbol(container, renderComponentRef.symbol);
1869
+ for (const capturedValue of materializeScope(container, renderComponentRef.scopeId)) await preloadResumableValue(container, capturedValue, seen);
1870
+ return;
1871
+ }
1872
+ if (Array.isArray(value)) {
1873
+ seen.add(value);
1874
+ for (const entry of value) await preloadResumableValue(container, entry, seen);
1875
+ return;
1876
+ }
1877
+ if (typeof Node !== "undefined" && value instanceof Node) return;
1878
+ if (isProjectionSlot(value)) return;
1879
+ if (isRenderObject(value)) {
1880
+ seen.add(value);
1881
+ await preloadResumableValue(container, value.type, seen);
1882
+ await preloadResumableValue(container, evaluateProps(value.props), seen);
1883
+ return;
1884
+ }
1885
+ if (!isPlainObject(value)) return;
1886
+ seen.add(value);
1887
+ for (const entry of Object.values(value)) await preloadResumableValue(container, entry, seen);
1888
+ };
1889
+ const serializeRuntimeValue = (container, value) => serializePublicValue(value, { serializeReference(candidate) {
1890
+ const signalMeta = getSignalMeta(candidate);
1891
+ if (signalMeta) return {
1892
+ __eclipsa_type: "ref",
1893
+ kind: "signal",
1894
+ token: signalMeta.id
1895
+ };
1896
+ if (getNavigateMeta(candidate)) return {
1897
+ __eclipsa_type: "ref",
1898
+ kind: "navigate",
1899
+ token: "navigate"
1900
+ };
1901
+ const actionMeta = getActionHandleMeta(candidate);
1902
+ if (actionMeta) return {
1903
+ __eclipsa_type: "ref",
1904
+ kind: "action",
1905
+ token: actionMeta.id
1906
+ };
1907
+ const actionHookMeta = getActionHookMeta(candidate);
1908
+ if (actionHookMeta) return {
1909
+ __eclipsa_type: "ref",
1910
+ kind: "action-hook",
1911
+ token: actionHookMeta.id
1912
+ };
1913
+ const loaderMeta = getLoaderHandleMeta(candidate);
1914
+ if (loaderMeta) return {
1915
+ __eclipsa_type: "ref",
1916
+ kind: "loader",
1917
+ token: loaderMeta.id
1918
+ };
1919
+ const loaderHookMeta = getLoaderHookMeta(candidate);
1920
+ if (loaderHookMeta) return {
1921
+ __eclipsa_type: "ref",
1922
+ kind: "loader-hook",
1923
+ token: loaderHookMeta.id
1924
+ };
1925
+ const contextReference = getRuntimeContextReference(candidate);
1926
+ if (contextReference) return {
1927
+ __eclipsa_type: "ref",
1928
+ data: serializeRuntimeValue(container, {
1929
+ defaultValue: contextReference.defaultValue,
1930
+ hasDefault: contextReference.hasDefault
1931
+ }),
1932
+ kind: contextReference.kind,
1933
+ token: contextReference.id
1934
+ };
1935
+ if (isRouteSlot(candidate)) return {
1936
+ __eclipsa_type: "ref",
1937
+ data: serializePublicValue(candidate.startLayoutIndex),
1938
+ kind: "route-slot",
1939
+ token: candidate.pathname
1940
+ };
1941
+ if (isProjectionSlot(candidate)) return {
1942
+ __eclipsa_type: "ref",
1943
+ data: serializeRuntimeValue(container, candidate.source),
1944
+ kind: PROJECTION_SLOT_TYPE,
1945
+ token: JSON.stringify([
1946
+ candidate.componentId,
1947
+ candidate.name,
1948
+ candidate.occurrence
1949
+ ])
1950
+ };
1951
+ if (isRenderObject(candidate)) return serializeRenderObjectReference(container, candidate);
1952
+ const lazyMeta = getLazyMeta(candidate);
1953
+ if (lazyMeta) return {
1954
+ __eclipsa_type: "ref",
1955
+ data: lazyMeta.captures().map((entry) => serializeRuntimeValue(container, entry)),
1956
+ kind: "symbol",
1957
+ token: lazyMeta.symbol
1958
+ };
1959
+ if (typeof Element !== "undefined" && candidate instanceof Element) return {
1960
+ __eclipsa_type: "ref",
1961
+ kind: "dom",
1962
+ token: ensureRuntimeElementId(container, candidate)
1963
+ };
1964
+ return null;
1965
+ } });
1966
+ const deserializeRuntimeValue = (container, value) => deserializePublicValue(value, { deserializeReference(reference) {
1967
+ if (reference.kind === "navigate") return ensureRouterState(container).navigate;
1968
+ if (reference.kind === "action") {
1969
+ const action = container.actions.get(reference.token);
1970
+ if (!action) throw new Error(`Missing action handle ${reference.token}.`);
1971
+ return action;
1972
+ }
1973
+ if (reference.kind === "action-hook") {
1974
+ const actionHook = getRegisteredActionHook(reference.token);
1975
+ if (!actionHook) throw new Error(`Missing action hook ${reference.token}.`);
1976
+ return actionHook;
1977
+ }
1978
+ if (reference.kind === "loader") {
1979
+ const loader = container.loaders.get(reference.token);
1980
+ if (!loader) throw new Error(`Missing loader handle ${reference.token}.`);
1981
+ return loader;
1982
+ }
1983
+ if (reference.kind === "loader-hook") {
1984
+ const loaderHook = getRegisteredLoaderHook(reference.token);
1985
+ if (!loaderHook) throw new Error(`Missing loader hook ${reference.token}.`);
1986
+ return loaderHook;
1987
+ }
1988
+ if (reference.kind === "context" || reference.kind === "context-provider") {
1989
+ const decoded = reference.data === void 0 ? null : deserializeRuntimeValue(container, reference.data);
1990
+ const hasDefault = decoded?.hasDefault === true;
1991
+ const descriptor = {
1992
+ defaultValue: hasDefault ? decoded?.defaultValue : void 0,
1993
+ hasDefault,
1994
+ id: reference.token
1995
+ };
1996
+ return reference.kind === "context" ? materializeRuntimeContext(descriptor) : materializeRuntimeContextProvider(descriptor);
1997
+ }
1998
+ if (reference.kind === "route-slot") {
1999
+ const startLayoutIndex = reference.data === void 0 ? 0 : deserializePublicValue(reference.data);
2000
+ if (typeof startLayoutIndex !== "number" || !Number.isInteger(startLayoutIndex)) throw new TypeError("Route slot references require an integer start layout index.");
2001
+ return {
2002
+ __eclipsa_type: ROUTE_SLOT_TYPE,
2003
+ pathname: reference.token,
2004
+ startLayoutIndex
2005
+ };
2006
+ }
2007
+ if (reference.kind === "projection-slot") {
2008
+ let componentId = "";
2009
+ let name = "";
2010
+ let occurrence = 0;
2011
+ try {
2012
+ const parsed = JSON.parse(reference.token);
2013
+ if (!Array.isArray(parsed) || parsed.length !== 3 || typeof parsed[0] !== "string" || typeof parsed[1] !== "string" || typeof parsed[2] !== "number") throw new Error("invalid projection slot token");
2014
+ componentId = parsed[0];
2015
+ name = parsed[1];
2016
+ occurrence = parsed[2];
2017
+ } catch {
2018
+ throw new TypeError("Projection slot references require a component id, name, and occurrence.");
2019
+ }
2020
+ return createProjectionSlot(componentId, name, occurrence, deserializeRuntimeValue(container, reference.data));
2021
+ }
2022
+ if (reference.kind === "signal") {
2023
+ const record = container.signals.get(reference.token);
2024
+ if (!record) throw new Error(`Missing signal ${reference.token}.`);
2025
+ return record.handle;
2026
+ }
2027
+ if (reference.kind === "symbol") {
2028
+ if (!reference.data || !Array.isArray(reference.data)) throw new TypeError("Symbol references require an encoded scope array.");
2029
+ const scopeId = registerSerializedScope(container, reference.data);
2030
+ return materializeSymbolReference(container, reference.token, scopeId);
2031
+ }
2032
+ if (reference.kind === "render") return deserializeRenderObjectReference(container, reference.data);
2033
+ if (reference.kind === "dom") {
2034
+ const element = findRuntimeElement(container, reference.token);
2035
+ if (!element) throw new Error(`Missing DOM reference ${reference.token}.`);
2036
+ return element;
2037
+ }
2038
+ throw new TypeError(`Unsupported runtime reference kind "${reference.kind}".`);
2039
+ } });
1653
2040
  return {
1654
- isStatic: isStaticValue,
1655
- key: key ?? void 0,
1656
- metadata: metadata ?? void 0,
1657
- props,
1658
- type: createMaterializedRenderComponentType(container, typeValue, scopeValue)
2041
+ deserializeRuntimeValue,
2042
+ preloadResumableValue,
2043
+ serializeRuntimeValue
1659
2044
  };
1660
2045
  };
1661
- const preloadResumableValue = async (container, value, seen = /* @__PURE__ */ new Set()) => {
1662
- if (value === null || value === void 0 || value === false) return;
1663
- if (seen.has(value)) return;
1664
- if (typeof value === "function") {
1665
- const renderComponentRef = getRenderComponentTypeRef(value);
1666
- if (!renderComponentRef) return;
1667
- seen.add(value);
1668
- await loadSymbol(container, renderComponentRef.symbol);
1669
- for (const capturedValue of materializeScope(container, renderComponentRef.scopeId)) await preloadResumableValue(container, capturedValue, seen);
1670
- return;
2046
+ //#endregion
2047
+ //#region core/runtime.ts
2048
+ const isMissingGeneratedScopeReferenceError = (error) => error instanceof ReferenceError && /\b__scope\b/.test(error.message);
2049
+ const toRuntimeError = (error) => error instanceof Error ? error : new Error(typeof error === "string" ? error : String(error));
2050
+ const areShallowEqualRenderProps = (previous, next) => {
2051
+ if (previous === next) return true;
2052
+ if (!previous || !next) return !previous && !next;
2053
+ const previousKeys = Object.keys(previous);
2054
+ const nextKeys = Object.keys(next);
2055
+ if (previousKeys.length !== nextKeys.length) return false;
2056
+ for (const key of previousKeys) if (!Object.hasOwn(next, key) || !Object.is(previous[key], next[key])) return false;
2057
+ for (const hiddenKey of [ROUTE_PARAMS_PROP, ROUTE_ERROR_PROP]) {
2058
+ const previousHas = Object.hasOwn(previous, hiddenKey);
2059
+ if (previousHas !== Object.hasOwn(next, hiddenKey)) return false;
2060
+ if (previousHas && !Object.is(previous[hiddenKey], next[hiddenKey])) return false;
1671
2061
  }
1672
- if (Array.isArray(value)) {
1673
- seen.add(value);
1674
- for (const entry of value) await preloadResumableValue(container, entry, seen);
1675
- return;
2062
+ return true;
2063
+ };
2064
+ const wrapGeneratedScopeReferenceError = (error, context) => {
2065
+ const baseError = toRuntimeError(error);
2066
+ if (!isMissingGeneratedScopeReferenceError(baseError)) return baseError;
2067
+ const location = [context.componentId ? `component "${context.componentId}"` : null, context.symbolId ? `symbol "${context.symbolId}"` : null].filter(Boolean).join(", ");
2068
+ const wrapped = new Error(`Eclipsa runtime failed while ${context.phase}${location ? ` ${location}` : ""}. The generated resumable symbol referenced "__scope" outside its valid scope. This usually means a same-file helper was transformed incorrectly during symbol compilation. Inline that helper into the component as a workaround. Original error: ${baseError.message}`, { cause: baseError });
2069
+ wrapped.name = "EclipsaRuntimeError";
2070
+ return wrapped;
2071
+ };
2072
+ const resolvedRuntimeSymbols = /* @__PURE__ */ new WeakMap();
2073
+ const getResolvedRuntimeSymbols = (container) => {
2074
+ const existing = resolvedRuntimeSymbols.get(container);
2075
+ if (existing) return existing;
2076
+ const created = /* @__PURE__ */ new Map();
2077
+ resolvedRuntimeSymbols.set(container, created);
2078
+ return created;
2079
+ };
2080
+ const invalidateRuntimeSymbolCaches = (container, symbolIds) => {
2081
+ const resolved = getResolvedRuntimeSymbols(container);
2082
+ for (const symbolId of symbolIds) {
2083
+ container.imports.delete(symbolId);
2084
+ resolved.delete(symbolId);
1676
2085
  }
1677
- if (typeof Node !== "undefined" && value instanceof Node) return;
1678
- if (isProjectionSlot(value)) return;
1679
- if (isRenderObject(value)) {
1680
- seen.add(value);
1681
- await preloadResumableValue(container, value.type, seen);
1682
- await preloadResumableValue(container, evaluateProps(value.props), seen);
1683
- return;
2086
+ };
2087
+ const withResumeHmrTimestamp = (url, timestamp) => {
2088
+ const parsed = new URL(url, "http://localhost");
2089
+ parsed.searchParams.set("t", timestamp.toString());
2090
+ return `${parsed.pathname}${parsed.search}${parsed.hash}`;
2091
+ };
2092
+ const canBustRuntimeSymbolUrl = (url) => parseSymbolIdFromUrl(url) !== null;
2093
+ const bustRuntimeSymbolUrls = (container, symbolIds, timestamp) => {
2094
+ for (const symbolId of symbolIds) {
2095
+ const current = container.symbols.get(symbolId);
2096
+ if (!current || !canBustRuntimeSymbolUrl(current)) continue;
2097
+ container.symbols.set(symbolId, withResumeHmrTimestamp(current, timestamp));
1684
2098
  }
1685
- if (!isPlainObject(value)) return;
1686
- seen.add(value);
1687
- for (const entry of Object.values(value)) await preloadResumableValue(container, entry, seen);
1688
2099
  };
1689
- const serializeRuntimeValue = (container, value) => serializePublicValue(value, { serializeReference(candidate) {
1690
- const signalMeta = getSignalMeta(candidate);
1691
- if (signalMeta) return {
1692
- __eclipsa_type: "ref",
1693
- kind: "signal",
1694
- token: signalMeta.id
1695
- };
1696
- if (getNavigateMeta(candidate)) return {
1697
- __eclipsa_type: "ref",
1698
- kind: "navigate",
1699
- token: "navigate"
1700
- };
1701
- const actionMeta = getActionHandleMeta(candidate);
1702
- if (actionMeta) return {
1703
- __eclipsa_type: "ref",
1704
- kind: "action",
1705
- token: actionMeta.id
1706
- };
1707
- const actionHookMeta = getActionHookMeta(candidate);
1708
- if (actionHookMeta) return {
1709
- __eclipsa_type: "ref",
1710
- kind: "action-hook",
1711
- token: actionHookMeta.id
1712
- };
1713
- const loaderMeta = getLoaderHandleMeta(candidate);
1714
- if (loaderMeta) return {
1715
- __eclipsa_type: "ref",
1716
- kind: "loader",
1717
- token: loaderMeta.id
1718
- };
1719
- const loaderHookMeta = getLoaderHookMeta(candidate);
1720
- if (loaderHookMeta) return {
1721
- __eclipsa_type: "ref",
1722
- kind: "loader-hook",
1723
- token: loaderHookMeta.id
1724
- };
1725
- const contextReference = getRuntimeContextReference(candidate);
1726
- if (contextReference) return {
1727
- __eclipsa_type: "ref",
1728
- data: serializeRuntimeValue(container, {
1729
- defaultValue: contextReference.defaultValue,
1730
- hasDefault: contextReference.hasDefault
1731
- }),
1732
- kind: contextReference.kind,
1733
- token: contextReference.id
1734
- };
1735
- if (isRouteSlot(candidate)) return {
1736
- __eclipsa_type: "ref",
1737
- data: serializePublicValue(candidate.startLayoutIndex),
1738
- kind: "route-slot",
1739
- token: candidate.pathname
1740
- };
1741
- if (isProjectionSlot(candidate)) return {
1742
- __eclipsa_type: "ref",
1743
- data: serializeRuntimeValue(container, candidate.source),
1744
- kind: PROJECTION_SLOT_TYPE,
1745
- token: JSON.stringify([
1746
- candidate.componentId,
1747
- candidate.name,
1748
- candidate.occurrence
1749
- ])
1750
- };
1751
- if (isRenderObject(candidate)) return serializeRenderObjectReference(container, candidate);
1752
- const lazyMeta = getLazyMeta(candidate);
1753
- if (lazyMeta) return {
1754
- __eclipsa_type: "ref",
1755
- data: lazyMeta.captures().map((entry) => serializeRuntimeValue(container, entry)),
1756
- kind: "symbol",
1757
- token: lazyMeta.symbol
1758
- };
1759
- if (isElementNode(candidate)) return {
1760
- __eclipsa_type: "ref",
1761
- kind: "dom",
1762
- token: ensureRuntimeElementId(container, candidate)
1763
- };
1764
- return null;
1765
- } });
1766
- const deserializeRuntimeValue = (container, value) => deserializePublicValue(value, { deserializeReference(reference) {
1767
- if (reference.kind === "navigate") return ensureRouterState(container).navigate;
1768
- if (reference.kind === "action") {
1769
- const action = container.actions.get(reference.token);
1770
- if (!action) throw new Error(`Missing action handle ${reference.token}.`);
1771
- return action;
1772
- }
1773
- if (reference.kind === "action-hook") {
1774
- const actionHook = getRegisteredActionHook(reference.token);
1775
- if (!actionHook) throw new Error(`Missing action hook ${reference.token}.`);
1776
- return actionHook;
1777
- }
1778
- if (reference.kind === "loader") {
1779
- const loader = container.loaders.get(reference.token);
1780
- if (!loader) throw new Error(`Missing loader handle ${reference.token}.`);
1781
- return loader;
1782
- }
1783
- if (reference.kind === "loader-hook") {
1784
- const loaderHook = getRegisteredLoaderHook(reference.token);
1785
- if (!loaderHook) throw new Error(`Missing loader hook ${reference.token}.`);
1786
- return loaderHook;
1787
- }
1788
- if (reference.kind === "context" || reference.kind === "context-provider") {
1789
- const decoded = reference.data === void 0 ? null : deserializeRuntimeValue(container, reference.data);
1790
- const hasDefault = decoded?.hasDefault === true;
1791
- const descriptor = {
1792
- defaultValue: hasDefault ? decoded?.defaultValue : void 0,
1793
- hasDefault,
1794
- id: reference.token
1795
- };
1796
- return reference.kind === "context" ? materializeRuntimeContext(descriptor) : materializeRuntimeContextProvider(descriptor);
2100
+ const isRenderObject = (value) => typeof value === "object" && value !== null && "type" in value && "props" in value;
2101
+ const readAsyncSignalSnapshot = (id, container = getCurrentContainer()) => readAsyncSignalSnapshot$1(id, container);
2102
+ const writeAsyncSignalSnapshot = (id, value, container = getCurrentContainer()) => {
2103
+ writeAsyncSignalSnapshot$1(id, value, container);
2104
+ };
2105
+ const getCurrentFrame = () => {
2106
+ const stack = getFrameStack();
2107
+ return stack.length > 0 ? stack[stack.length - 1] : null;
2108
+ };
2109
+ const shouldReconnectDetachedInsertMarkers = (container) => {
2110
+ const frame = getCurrentFrame();
2111
+ if (!container || !frame || frame.container !== container) return true;
2112
+ return frame.projectionState.reuseExistingDom;
2113
+ };
2114
+ const hasScopedStyles = (frame) => !!frame && frame.scopedStyles.length > 0;
2115
+ const getScopedStyleRootSelector = (scopeId) => `[${SCOPED_STYLE_ATTR}="${escapeAttr(scopeId)}"]`;
2116
+ const wrapScopedStyleCss = (scopeId, cssText) => `@scope (${getScopedStyleRootSelector(scopeId)}) {\n${cssText}\n}`;
2117
+ const renderScopedStyleString = (scopeId, style) => {
2118
+ const attrParts = Object.entries(style.attributes).filter(([, value]) => value !== false && value !== void 0 && value !== null).map(([name, value]) => value === true ? name : `${name}="${escapeAttr(String(value))}"`);
2119
+ return `<style${attrParts.length > 0 ? ` ${attrParts.join(" ")}` : ""}>${escapeText(wrapScopedStyleCss(scopeId, style.cssText))}</style>`;
2120
+ };
2121
+ const renderScopedStyleNode = (container, scopeId, style) => {
2122
+ const element = createElementNode(container.doc, "style");
2123
+ for (const [name, value] of Object.entries(style.attributes)) {
2124
+ if (value === false || value === void 0 || value === null) continue;
2125
+ if (value === true) {
2126
+ element.setAttribute(name, "");
2127
+ continue;
2128
+ }
2129
+ element.setAttribute(name, String(value));
1797
2130
  }
1798
- if (reference.kind === "route-slot") {
1799
- const startLayoutIndex = reference.data === void 0 ? 0 : deserializePublicValue(reference.data);
1800
- if (typeof startLayoutIndex !== "number" || !Number.isInteger(startLayoutIndex)) throw new TypeError("Route slot references require an integer start layout index.");
1801
- return {
1802
- __eclipsa_type: ROUTE_SLOT_TYPE,
1803
- pathname: reference.token,
1804
- startLayoutIndex
1805
- };
2131
+ element.appendChild(container.doc.createTextNode(wrapScopedStyleCss(scopeId, style.cssText)));
2132
+ return element;
2133
+ };
2134
+ const renderFrameScopedStylesToString = (frame) => frame.scopedStyles.map((style) => renderScopedStyleString(frame.component.scopeId, style)).join("");
2135
+ const renderFrameScopedStylesToNodes = (frame, container) => frame.scopedStyles.map((style) => renderScopedStyleNode(container, frame.component.scopeId, style));
2136
+ const registerRuntimeScopedStyle = (cssText, attributes = {}) => {
2137
+ const frame = getCurrentFrame();
2138
+ if (!frame || frame.component.id === "$root") throw new Error("useStyleScoped() can only be used while rendering a component.");
2139
+ if (cssText.length === 0) return;
2140
+ if (frame.scopedStyles.find((entry) => entry.cssText === cssText && JSON.stringify(entry.attributes) === JSON.stringify(attributes))) return;
2141
+ frame.scopedStyles.push({
2142
+ attributes: { ...attributes },
2143
+ cssText
2144
+ });
2145
+ };
2146
+ let currentEffect = null;
2147
+ let currentCleanupSlot = null;
2148
+ const withoutTrackedEffect = (fn) => {
2149
+ const previous = currentEffect;
2150
+ currentEffect = null;
2151
+ try {
2152
+ return fn();
2153
+ } finally {
2154
+ currentEffect = previous;
1806
2155
  }
1807
- if (reference.kind === PROJECTION_SLOT_TYPE) {
1808
- let componentId = "";
1809
- let name = "";
1810
- let occurrence = 0;
1811
- try {
1812
- const parsed = JSON.parse(reference.token);
1813
- if (!Array.isArray(parsed) || parsed.length !== 3 || typeof parsed[0] !== "string" || typeof parsed[1] !== "string" || typeof parsed[2] !== "number") throw new Error("invalid projection slot token");
1814
- componentId = parsed[0];
1815
- name = parsed[1];
1816
- occurrence = parsed[2];
1817
- } catch {
1818
- throw new TypeError("Projection slot references require a component id, name, and occurrence.");
2156
+ };
2157
+ const createCleanupSlot = () => ({ callbacks: [] });
2158
+ const withCleanupSlot = (slot, fn) => {
2159
+ const previous = currentCleanupSlot;
2160
+ currentCleanupSlot = slot;
2161
+ try {
2162
+ return fn();
2163
+ } finally {
2164
+ currentCleanupSlot = previous;
2165
+ }
2166
+ };
2167
+ const disposeCleanupSlot = (slot) => {
2168
+ if (!slot || slot.callbacks.length === 0) return;
2169
+ const callbacks = [...slot.callbacks].reverse();
2170
+ slot.callbacks.length = 0;
2171
+ let firstError = null;
2172
+ const previous = currentCleanupSlot;
2173
+ currentCleanupSlot = null;
2174
+ try {
2175
+ for (const callback of callbacks) try {
2176
+ withoutTrackedEffect(callback);
2177
+ } catch (error) {
2178
+ firstError ??= error;
1819
2179
  }
1820
- return createProjectionSlot(componentId, name, occurrence, deserializeRuntimeValue(container, reference.data));
2180
+ } finally {
2181
+ currentCleanupSlot = previous;
1821
2182
  }
1822
- if (reference.kind === "signal") {
1823
- const record = container.signals.get(reference.token);
1824
- if (!record) throw new Error(`Missing signal ${reference.token}.`);
1825
- return record.handle;
2183
+ if (firstError) throw firstError;
2184
+ };
2185
+ const resetComponentRenderEffects = (component) => {
2186
+ disposeCleanupSlot(component.renderEffectCleanupSlot);
2187
+ component.renderEffectCleanupSlot = createCleanupSlot();
2188
+ };
2189
+ const syncEffectOnlyLocalSignalPreference = (component) => {
2190
+ component.prefersEffectOnlyLocalSignalWrites = component.optimizedRoot === true;
2191
+ };
2192
+ const clearEffectSignals = (effect) => {
2193
+ for (const signal of effect.signals) signal.effects.delete(effect);
2194
+ effect.signals.clear();
2195
+ };
2196
+ const collectTrackedDependencies = (effect, fn) => {
2197
+ clearEffectSignals(effect);
2198
+ currentEffect = effect;
2199
+ try {
2200
+ fn();
2201
+ } finally {
2202
+ currentEffect = null;
2203
+ }
2204
+ };
2205
+ const runWithoutDependencyTracking = (fn) => {
2206
+ const previousEffect = currentEffect;
2207
+ currentEffect = null;
2208
+ try {
2209
+ return fn();
2210
+ } finally {
2211
+ currentEffect = previousEffect;
1826
2212
  }
1827
- if (reference.kind === "symbol") {
1828
- if (!reference.data || !Array.isArray(reference.data)) throw new TypeError("Symbol references require an encoded scope array.");
1829
- const scopeId = registerSerializedScope(container, reference.data);
1830
- return materializeSymbolReference(container, reference.token, scopeId);
2213
+ };
2214
+ const trackWatchDependencies = (dependencies, errorLabel = "useWatch") => {
2215
+ for (const dependency of dependencies) {
2216
+ if (typeof dependency === "function") {
2217
+ dependency();
2218
+ continue;
2219
+ }
2220
+ if (!getSignalMeta(dependency)) throw new TypeError(`${errorLabel} dependencies must be signals or getter functions.`);
2221
+ dependency.value;
1831
2222
  }
1832
- if (reference.kind === RENDER_REFERENCE_KIND) return deserializeRenderObjectReference(container, reference.data);
1833
- if (reference.kind === "dom") {
1834
- const element = findRuntimeElement(container, reference.token);
1835
- if (!element) throw new Error(`Missing DOM reference ${reference.token}.`);
1836
- return element;
2223
+ };
2224
+ const runWatchCallback = (effect, cleanupSlot, fn, dependencies) => {
2225
+ disposeCleanupSlot(cleanupSlot);
2226
+ if (!dependencies) {
2227
+ collectTrackedDependencies(effect, () => {
2228
+ withCleanupSlot(cleanupSlot, fn);
2229
+ });
2230
+ return;
1837
2231
  }
1838
- throw new TypeError(`Unsupported runtime reference kind "${reference.kind}".`);
1839
- } });
2232
+ collectTrackedDependencies(effect, () => {
2233
+ trackWatchDependencies(dependencies);
2234
+ });
2235
+ withCleanupSlot(cleanupSlot, fn);
2236
+ };
2237
+ const createLocalWatchRunner = (effect, cleanupSlot, fn, dependencies) => () => {
2238
+ runWatchCallback(effect, cleanupSlot, fn, dependencies);
2239
+ };
2240
+ const isProjectionSlot = (value) => isPlainObject(value) && value.__eclipsa_type === "projection-slot";
2241
+ const createProjectionSlot = (componentId, name, occurrence, source) => ({
2242
+ __eclipsa_type: PROJECTION_SLOT_TYPE,
2243
+ componentId,
2244
+ name,
2245
+ occurrence,
2246
+ source
2247
+ });
2248
+ let runtimeSerialization = null;
2249
+ const getRuntimeSerialization = () => {
2250
+ runtimeSerialization ??= createRuntimeSerialization({
2251
+ createProjectionSlot,
2252
+ ensureRouterState,
2253
+ ensureRuntimeElementId,
2254
+ evaluateProps,
2255
+ findRuntimeElement,
2256
+ getResolvedRuntimeSymbols,
2257
+ isPlainObject,
2258
+ isProjectionSlot,
2259
+ isRenderObject,
2260
+ isRouteSlot,
2261
+ loadSymbol,
2262
+ materializeScope,
2263
+ materializeSymbolReference,
2264
+ registerScope,
2265
+ registerSerializedScope,
2266
+ resolveRenderable: (value) => resolveRenderable(value)
2267
+ });
2268
+ return runtimeSerialization;
2269
+ };
2270
+ const preloadResumableValue = (container, value, seen = /* @__PURE__ */ new Set()) => getRuntimeSerialization().preloadResumableValue(container, value, seen);
2271
+ const serializeRuntimeValue = (container, value) => getRuntimeSerialization().serializeRuntimeValue(container, value);
2272
+ const deserializeRuntimeValue = (container, value) => getRuntimeSerialization().deserializeRuntimeValue(container, value);
1840
2273
  const findNextNumericId = (ids, prefix) => {
1841
2274
  let nextId = 0;
1842
2275
  for (const id of ids) {
@@ -1882,11 +2315,11 @@ const restoreSignalRefs = (container, root) => {
1882
2315
  if (!record) return;
1883
2316
  writeSignalValue(container, record, element);
1884
2317
  };
1885
- if (isElementNode(root) && root.getAttribute(REF_SIGNAL_ATTR)) assignElement(root);
2318
+ if (isElementNode(root) && root.getAttribute("data-e-ref")) assignElement(root);
1886
2319
  const visitDescendants = (node) => {
1887
2320
  for (const child of listNodeChildren(node)) {
1888
2321
  if (!isElementNode(child)) continue;
1889
- if (child.getAttribute(REF_SIGNAL_ATTR)) assignElement(child);
2322
+ if (child.getAttribute("data-e-ref")) assignElement(child);
1890
2323
  visitDescendants(child);
1891
2324
  }
1892
2325
  };
@@ -1962,7 +2395,7 @@ const preloadComponentProps = async (container, meta, props) => {
1962
2395
  }
1963
2396
  await preloadResumableValue(container, entries);
1964
2397
  };
1965
- const createContainer = (symbols, doc, asyncSignalSnapshotCache) => ({
2398
+ const createContainer = (symbols, doc, asyncSignalSnapshotCache, externalRenderCache) => ({
1966
2399
  actions: /* @__PURE__ */ new Map(),
1967
2400
  actionStates: /* @__PURE__ */ new Map(),
1968
2401
  asyncSignalStates: /* @__PURE__ */ new Map(),
@@ -1973,6 +2406,7 @@ const createContainer = (symbols, doc, asyncSignalSnapshotCache) => ({
1973
2406
  dirtyFlushQueued: false,
1974
2407
  doc,
1975
2408
  eventDispatchPromise: null,
2409
+ externalRenderCache: externalRenderCache ?? /* @__PURE__ */ new Map(),
1976
2410
  id: `rt${globalThis[CONTAINER_ID_KEY] = (globalThis[CONTAINER_ID_KEY] ?? 0) + 1}`,
1977
2411
  imports: /* @__PURE__ */ new Map(),
1978
2412
  interactivePrefetchCheckQueued: false,
@@ -2061,7 +2495,7 @@ const ensureSignalRecord = (container, id, initialValue) => {
2061
2495
  container.signals.set(id, record);
2062
2496
  return record;
2063
2497
  };
2064
- const isRouterSignalId = (id) => id === ROUTER_CURRENT_PATH_SIGNAL_ID || id === ROUTER_CURRENT_URL_SIGNAL_ID || id === ROUTER_IS_NAVIGATING_SIGNAL_ID;
2498
+ const isRouterSignalId = (id) => id === "$router:path" || id === "$router:url" || id === "$router:isNavigating";
2065
2499
  const isAtomSignalId = (id) => id.startsWith("a");
2066
2500
  const createStandaloneNavigate = () => {
2067
2501
  const navigate = (async (href, options) => {
@@ -2260,6 +2694,8 @@ const createFrame = (container, component, mode, options) => ({
2260
2694
  container,
2261
2695
  effectCleanupSlot: options?.effectCleanupSlot ?? component.renderEffectCleanupSlot,
2262
2696
  insertCursor: 0,
2697
+ keyedRangeCursor: 0,
2698
+ keyedRangeScopeStack: [],
2263
2699
  mountCallbacks: [],
2264
2700
  mode,
2265
2701
  projectionState: {
@@ -2274,7 +2710,7 @@ const createFrame = (container, component, mode, options) => ({
2274
2710
  watchCursor: 0
2275
2711
  });
2276
2712
  const createComponentId = (container, parentId, childIndex) => {
2277
- if (!parentId || parentId === ROOT_COMPONENT_ID) return `c${childIndex}`;
2713
+ if (!parentId || parentId === "$root") return `c${childIndex}`;
2278
2714
  return `${parentId}.${childIndex}`;
2279
2715
  };
2280
2716
  const getOrCreateComponentState = (container, id, symbol, parentId) => {
@@ -2287,6 +2723,11 @@ const getOrCreateComponentState = (container, id, symbol, parentId) => {
2287
2723
  const component = {
2288
2724
  active: false,
2289
2725
  didMount: false,
2726
+ external: void 0,
2727
+ externalSlotHtml: null,
2728
+ externalSlotDom: null,
2729
+ externalInstance: void 0,
2730
+ externalMeta: null,
2290
2731
  id,
2291
2732
  mountCleanupSlots: [],
2292
2733
  optimizedRoot: false,
@@ -2313,10 +2754,15 @@ const resetComponentForSymbolChange = (container, component, meta) => {
2313
2754
  disposeCleanupSlot(component.renderEffectCleanupSlot);
2314
2755
  component.renderEffectCleanupSlot = createCleanupSlot();
2315
2756
  component.didMount = false;
2757
+ component.external = meta.external;
2758
+ component.externalSlotHtml = null;
2759
+ component.externalSlotDom = null;
2316
2760
  component.optimizedRoot = meta.optimizedRoot === true;
2317
2761
  component.prefersEffectOnlyLocalSignalWrites = false;
2318
2762
  component.projectionSlots = meta.projectionSlots ?? null;
2319
2763
  component.rawProps = null;
2764
+ component.externalInstance = void 0;
2765
+ component.externalMeta = null;
2320
2766
  component.scopeId = registerScope(container, meta.captures());
2321
2767
  component.signalIds = [];
2322
2768
  component.suspensePromise = null;
@@ -2342,6 +2788,7 @@ const getOrCreateWatchState = (container, id, componentId) => {
2342
2788
  id,
2343
2789
  mode: "dynamic",
2344
2790
  pending: null,
2791
+ resumed: false,
2345
2792
  run: null,
2346
2793
  scopeId: registerScope(container, []),
2347
2794
  symbol: "",
@@ -2404,7 +2851,18 @@ const getOrCreateVisibleState = (container, id, componentId) => {
2404
2851
  const clearComponentSubscriptions = (container, componentId) => {
2405
2852
  for (const record of container.signals.values()) record.subscribers.delete(componentId);
2406
2853
  };
2854
+ const disposeExternalComponentInstance = (component) => {
2855
+ if (!component.externalMeta || component.externalInstance === void 0) {
2856
+ component.externalInstance = void 0;
2857
+ component.externalMeta = null;
2858
+ return;
2859
+ }
2860
+ component.externalMeta.unmount(component.externalInstance);
2861
+ component.externalInstance = void 0;
2862
+ component.externalMeta = null;
2863
+ };
2407
2864
  const disposeComponentMountCleanups = (component) => {
2865
+ disposeExternalComponentInstance(component);
2408
2866
  disposeCleanupSlot(component.renderEffectCleanupSlot);
2409
2867
  component.renderEffectCleanupSlot = createCleanupSlot();
2410
2868
  const cleanupSlots = [...component.mountCleanupSlots].reverse();
@@ -2583,6 +3041,41 @@ const scheduleMountCallbacks = (container, component, callbacks) => {
2583
3041
  });
2584
3042
  });
2585
3043
  };
3044
+ const scheduleExternalComponentMount = (container, component, external, props) => {
3045
+ if (component.didMount) return;
3046
+ component.didMount = true;
3047
+ scheduleMicrotask(() => {
3048
+ const host = getExternalRoot(component);
3049
+ if (!host) return;
3050
+ withClientContainer(container, async () => {
3051
+ syncExternalProjectionSlotDom(container, component, props, host);
3052
+ await syncExternalComponentInstance(component, external, props, host);
3053
+ syncExternalProjectionSlotDom(container, component, props, host);
3054
+ rebindExternalHost(container, host);
3055
+ scheduleExternalHostRebind(container, host);
3056
+ await flushDirtyComponents(container);
3057
+ scheduleVisibleCallbacksCheck(container);
3058
+ });
3059
+ });
3060
+ };
3061
+ const rebindExternalHost = (container, host) => {
3062
+ if (!host.parentNode || !("querySelectorAll" in host.parentNode)) return;
3063
+ bindComponentBoundaries(container, host.parentNode);
3064
+ restoreSignalRefs(container, host.parentNode);
3065
+ bindRouterLinks(container, host.parentNode);
3066
+ };
3067
+ const scheduleExternalHostRebind = (container, host) => {
3068
+ const schedule = container.doc?.defaultView?.setTimeout?.bind(container.doc.defaultView) ?? (typeof setTimeout === "function" ? setTimeout : null);
3069
+ if (!schedule) return;
3070
+ for (const delay of [
3071
+ 0,
3072
+ 16,
3073
+ 100
3074
+ ]) schedule(() => {
3075
+ if (!host.isConnected) return;
3076
+ rebindExternalHost(container, host);
3077
+ }, delay);
3078
+ };
2586
3079
  const collectProjectionSlotRanges = (roots) => {
2587
3080
  const starts = /* @__PURE__ */ new Map();
2588
3081
  const ranges = /* @__PURE__ */ new Map();
@@ -2608,8 +3101,8 @@ const collectComponentBoundaryIds = (roots) => {
2608
3101
  const ids = /* @__PURE__ */ new Set();
2609
3102
  const visit = (node) => {
2610
3103
  if (typeof Comment !== "undefined" ? node instanceof Comment : node.nodeType === 8) {
2611
- const matched = node.data.match(/^ec:c:(.+):(start|end)$/);
2612
- if (matched) ids.add(matched[1]);
3104
+ const marker = parseComponentBoundaryMarker(node.data);
3105
+ if (marker) ids.add(marker.id);
2613
3106
  }
2614
3107
  for (const child of Array.from(node.childNodes ?? [])) visit(child);
2615
3108
  };
@@ -2637,6 +3130,7 @@ const collectComponentBoundaryRanges = (roots) => {
2637
3130
  for (const root of roots) visit(root);
2638
3131
  return ranges;
2639
3132
  };
3133
+ const createKeyedRangeIdentity = (scope, key) => JSON.stringify([scope, key]);
2640
3134
  const collectKeyedRangeRanges = (roots) => {
2641
3135
  const starts = /* @__PURE__ */ new Map();
2642
3136
  const ranges = /* @__PURE__ */ new Map();
@@ -2644,13 +3138,16 @@ const collectKeyedRangeRanges = (roots) => {
2644
3138
  if (typeof Comment !== "undefined" ? node instanceof Comment : node.nodeType === 8) {
2645
3139
  const commentNode = node;
2646
3140
  const marker = parseKeyedRangeMarker(commentNode.data);
2647
- if (marker) if (marker.kind === "start") starts.set(marker.key, commentNode);
2648
- else {
2649
- const startNode = starts.get(marker.key);
2650
- if (startNode) ranges.set(marker.key, {
2651
- end: commentNode,
2652
- start: startNode
2653
- });
3141
+ if (marker) {
3142
+ const identity = createKeyedRangeIdentity(marker.scope, marker.key);
3143
+ if (marker.kind === "start") starts.set(identity, commentNode);
3144
+ else {
3145
+ const startNode = starts.get(identity);
3146
+ if (startNode) ranges.set(identity, {
3147
+ end: commentNode,
3148
+ start: startNode
3149
+ });
3150
+ }
2654
3151
  }
2655
3152
  }
2656
3153
  for (const child of Array.from(node.childNodes ?? [])) visit(child);
@@ -2668,12 +3165,45 @@ const collectBoundaryRangeNodes = (start, end) => {
2668
3165
  }
2669
3166
  return [];
2670
3167
  };
3168
+ const canReuseNodeAsIs = (current, next) => {
3169
+ if (current.nodeType !== next.nodeType) return false;
3170
+ if (current.nodeType === 3 && next.nodeType === 3) return current.textContent === next.textContent;
3171
+ if ((typeof Comment !== "undefined" ? current instanceof Comment : current.nodeType === 8) && (typeof Comment !== "undefined" ? next instanceof Comment : next.nodeType === 8)) {
3172
+ const currentComment = current;
3173
+ const nextComment = next;
3174
+ const currentBoundary = parseComponentBoundaryMarker(currentComment.data);
3175
+ const nextBoundary = parseComponentBoundaryMarker(nextComment.data);
3176
+ if (currentBoundary || nextBoundary) {
3177
+ if (!currentBoundary || !nextBoundary) return false;
3178
+ if (currentBoundary.id !== nextBoundary.id || currentBoundary.kind !== nextBoundary.kind) return false;
3179
+ return nextBoundary.kind !== "start" || !didComponentBoundaryChange(nextComment);
3180
+ }
3181
+ return currentComment.data === nextComment.data;
3182
+ }
3183
+ if (!isElementNode(current) || !isElementNode(next) || current.tagName !== next.tagName) return false;
3184
+ const currentNames = current.getAttributeNames();
3185
+ const nextNames = next.getAttributeNames();
3186
+ if (currentNames.length !== nextNames.length) return false;
3187
+ for (const name of currentNames) if (current.getAttribute(name) !== next.getAttribute(name)) return false;
3188
+ if (isHTMLInputElementNode(current) && isHTMLInputElementNode(next) && current.checked !== next.checked) return false;
3189
+ if ("value" in current && "value" in next && current.value !== next.value) return false;
3190
+ const currentChildren = Array.from(current.childNodes);
3191
+ const nextChildren = Array.from(next.childNodes);
3192
+ if (currentChildren.length !== nextChildren.length) return false;
3193
+ for (let index = 0; index < currentChildren.length; index += 1) if (!canReuseNodeAsIs(currentChildren[index], nextChildren[index])) return false;
3194
+ return true;
3195
+ };
3196
+ const canReuseNodeSequenceAsIs = (currentNodes, nextNodes) => {
3197
+ if (currentNodes.length !== nextNodes.length) return false;
3198
+ for (let index = 0; index < currentNodes.length; index += 1) if (!canReuseNodeAsIs(currentNodes[index], nextNodes[index])) return false;
3199
+ return true;
3200
+ };
2671
3201
  const preserveComponentBoundaryContentsInRoots = (currentRoots, nextRoots) => {
2672
3202
  const currentRanges = collectComponentBoundaryRanges(currentRoots);
2673
3203
  const nextRanges = collectComponentBoundaryRanges(nextRoots);
2674
3204
  const preservedComponentIds = /* @__PURE__ */ new Set();
2675
3205
  for (const [id, nextRange] of nextRanges) {
2676
- if (Boolean(nextRange.start[COMPONENT_BOUNDARY_SYMBOL_CHANGED] || nextRange.start[COMPONENT_BOUNDARY_PROPS_CHANGED])) continue;
3206
+ if (didComponentBoundaryChange(nextRange.start)) continue;
2677
3207
  const currentRange = currentRanges.get(id);
2678
3208
  if (!currentRange) continue;
2679
3209
  const movedRoots = collectBoundaryRangeNodes(currentRange.start, currentRange.end);
@@ -2746,29 +3276,44 @@ const preserveKeyedRangeContentsInRoots = (currentRoots, nextRoots) => {
2746
3276
  for (const [key, nextRange] of nextRanges) {
2747
3277
  const currentRange = currentRanges.get(key);
2748
3278
  if (!currentRange) continue;
2749
- const movedRoots = collectBoundaryRangeNodes(currentRange.start, currentRange.end);
2750
- if (movedRoots.length === 0) continue;
2751
- const replacementParent = nextRange.start.parentNode;
2752
- if (!replacementParent) continue;
2753
- for (const node of movedRoots) replacementParent.insertBefore(node, nextRange.start);
2754
- let cursor = nextRange.start;
2755
- while (cursor) {
2756
- const nextSibling = cursor.nextSibling;
2757
- if (typeof cursor.remove === "function") cursor.remove();
2758
- else cursor.parentNode?.removeChild(cursor);
2759
- if (cursor === nextRange.end) break;
2760
- cursor = nextSibling;
3279
+ const currentBodyRoots = getBoundaryChildren(currentRange.start, currentRange.end);
3280
+ const nextBodyRoots = getBoundaryChildren(nextRange.start, nextRange.end);
3281
+ if (canReuseNodeSequenceAsIs(currentBodyRoots, nextBodyRoots)) {
3282
+ const movedRoots = collectBoundaryRangeNodes(currentRange.start, currentRange.end);
3283
+ if (movedRoots.length === 0) continue;
3284
+ const replacementParent = nextRange.start.parentNode;
3285
+ if (!replacementParent) continue;
3286
+ for (const node of movedRoots) replacementParent.insertBefore(node, nextRange.start);
3287
+ let cursor = nextRange.start;
3288
+ while (cursor) {
3289
+ const nextSibling = cursor.nextSibling;
3290
+ if (typeof cursor.remove === "function") cursor.remove();
3291
+ else cursor.parentNode?.removeChild(cursor);
3292
+ if (cursor === nextRange.end) break;
3293
+ cursor = nextSibling;
3294
+ }
3295
+ for (const componentId of collectComponentBoundaryIds(movedRoots)) preservedComponentIds.add(componentId);
3296
+ continue;
2761
3297
  }
2762
- for (const componentId of collectComponentBoundaryIds(movedRoots)) preservedComponentIds.add(componentId);
3298
+ if (currentBodyRoots.length === 0 && nextBodyRoots.length === 0) continue;
3299
+ for (const componentId of preserveReusableContentInRoots(currentBodyRoots, nextBodyRoots)) preservedComponentIds.add(componentId);
2763
3300
  }
2764
3301
  return preservedComponentIds;
2765
3302
  };
2766
3303
  const canMatchReusableRoot = (current, next) => {
2767
3304
  if (current.nodeType !== next.nodeType) return false;
2768
3305
  if ((typeof Comment !== "undefined" ? current instanceof Comment : current.nodeType === 8) && (typeof Comment !== "undefined" ? next instanceof Comment : next.nodeType === 8)) return current.data === next.data;
2769
- if (current.nodeType === DOM_TEXT_NODE && next.nodeType === DOM_TEXT_NODE) return true;
3306
+ if (current.nodeType === 3 && next.nodeType === 3) return true;
2770
3307
  return isElementNode(current) && isElementNode(next) && current.tagName === next.tagName;
2771
3308
  };
3309
+ const preserveExternalRootContents = (current, next) => {
3310
+ if (!isElementNode(current) || !isElementNode(next)) return null;
3311
+ if (current.getAttribute("data-e-external-root") !== "true" || next.getAttribute("data-e-external-root") !== "true") return null;
3312
+ if (next.childNodes.length > 0) return /* @__PURE__ */ new Set();
3313
+ const movedRoots = [...current.childNodes];
3314
+ for (const node of movedRoots) next.appendChild(node);
3315
+ return collectComponentBoundaryIds(movedRoots);
3316
+ };
2772
3317
  const preserveInsertMarkerContentsInRoots = (currentRoots, nextRoots) => {
2773
3318
  const preservedComponentIds = /* @__PURE__ */ new Set();
2774
3319
  const preserveLists = (currentChildren, nextChildren) => {
@@ -2787,7 +3332,7 @@ const preserveInsertMarkerContentsInRoots = (currentRoots, nextRoots) => {
2787
3332
  }
2788
3333
  if (markerIndex < 0) continue;
2789
3334
  const currentMarker = currentChildren[markerIndex];
2790
- const explicitCount = insertMarkerNodeCounts.get(currentMarker);
3335
+ const explicitCount = getRememberedInsertMarkerNodeCount(currentMarker);
2791
3336
  if (explicitCount === void 0) {
2792
3337
  currentIndex = markerIndex + 1;
2793
3338
  continue;
@@ -2799,7 +3344,7 @@ const preserveInsertMarkerContentsInRoots = (currentRoots, nextRoots) => {
2799
3344
  continue;
2800
3345
  }
2801
3346
  for (const node of movedRoots) nextChild.parentNode?.insertBefore(node, nextChild);
2802
- insertMarkerNodeCounts.set(nextChild, movedRoots.length);
3347
+ setRememberedInsertMarkerNodeCount(nextChild, movedRoots.length);
2803
3348
  for (const componentId of collectComponentBoundaryIds(movedRoots)) preservedComponentIds.add(componentId);
2804
3349
  currentIndex = markerIndex + 1;
2805
3350
  continue;
@@ -2811,7 +3356,15 @@ const preserveInsertMarkerContentsInRoots = (currentRoots, nextRoots) => {
2811
3356
  }
2812
3357
  if (matchedIndex < 0) continue;
2813
3358
  const currentChild = currentChildren[matchedIndex];
2814
- if (isElementNode(currentChild) && isElementNode(nextChild)) preserveLists(Array.from(currentChild.childNodes), Array.from(nextChild.childNodes));
3359
+ if (isElementNode(currentChild) && isElementNode(nextChild)) {
3360
+ const preservedExternalRootIds = preserveExternalRootContents(currentChild, nextChild);
3361
+ if (preservedExternalRootIds) {
3362
+ for (const componentId of preservedExternalRootIds) preservedComponentIds.add(componentId);
3363
+ currentIndex = matchedIndex + 1;
3364
+ continue;
3365
+ }
3366
+ preserveLists(Array.from(currentChild.childNodes), Array.from(nextChild.childNodes));
3367
+ }
2815
3368
  currentIndex = matchedIndex + 1;
2816
3369
  }
2817
3370
  };
@@ -2819,9 +3372,10 @@ const preserveInsertMarkerContentsInRoots = (currentRoots, nextRoots) => {
2819
3372
  return preservedComponentIds;
2820
3373
  };
2821
3374
  const preserveReusableContentInRoots = (currentRoots, nextRoots, options) => {
2822
- const preservedComponentIds = preserveComponentBoundaryContentsInRoots(currentRoots, nextRoots);
2823
- if (options?.preserveProjectionSlots ?? true) for (const componentId of preserveProjectionSlotContentsInRoots(currentRoots, nextRoots)) preservedComponentIds.add(componentId);
3375
+ const preservedComponentIds = /* @__PURE__ */ new Set();
2824
3376
  for (const componentId of preserveKeyedRangeContentsInRoots(currentRoots, nextRoots)) preservedComponentIds.add(componentId);
3377
+ for (const componentId of preserveComponentBoundaryContentsInRoots(currentRoots, nextRoots)) preservedComponentIds.add(componentId);
3378
+ if (options?.preserveProjectionSlots ?? true) for (const componentId of preserveProjectionSlotContentsInRoots(currentRoots, nextRoots)) preservedComponentIds.add(componentId);
2825
3379
  for (const componentId of preserveInsertMarkerContentsInRoots(currentRoots, nextRoots)) preservedComponentIds.add(componentId);
2826
3380
  return preservedComponentIds;
2827
3381
  };
@@ -2895,7 +3449,7 @@ const replaceInsertRangeOwnedNodes = (currentMarker, currentOwnedNodes, nextOwne
2895
3449
  }
2896
3450
  for (const node of nextOwnedNodes) parent.insertBefore(node, currentMarker);
2897
3451
  rememberManagedAttributesForNodes(parent.childNodes);
2898
- insertMarkerNodeCounts.set(currentMarker, nextOwnedNodes.length);
3452
+ setRememberedInsertMarkerNodeCount(currentMarker, nextOwnedNodes.length);
2899
3453
  return true;
2900
3454
  };
2901
3455
  const getPatchOpaqueRangeToken = (node, kind) => {
@@ -2914,7 +3468,7 @@ const getPatchOpaqueRangeToken = (node, kind) => {
2914
3468
  const keyedRange = parseKeyedRangeMarker(comment.data);
2915
3469
  if (keyedRange?.kind === kind) return {
2916
3470
  rangeKind: "keyed",
2917
- token: `keyed:${keyedRange.key}`
3471
+ token: `keyed:${createKeyedRangeIdentity(keyedRange.scope, keyedRange.key)}`
2918
3472
  };
2919
3473
  return null;
2920
3474
  };
@@ -2933,7 +3487,7 @@ const collectPatchSequenceUnits = (nodes) => {
2933
3487
  });
2934
3488
  continue;
2935
3489
  }
2936
- const ownedNodeCount = insertMarkerNodeCounts.get(node) ?? 0;
3490
+ const ownedNodeCount = getRememberedInsertMarkerNodeCount(node);
2937
3491
  let remaining = ownedNodeCount;
2938
3492
  while (remaining > 0) {
2939
3493
  const previous = units[units.length - 1];
@@ -2995,14 +3549,14 @@ const tryPatchNodeSequenceInPlace = (currentNodes, nextNodes) => {
2995
3549
  if (currentUnit.token !== nextUnit.token && (hasStructuredPatchUnits(currentOwnedNodes) || hasStructuredPatchUnits(nextOwnedNodes))) return false;
2996
3550
  if (currentOwnedNodes.length > 0 || nextOwnedNodes.length > 0 || currentUnit.nodeCount !== nextUnit.nodeCount) if (!tryPatchNodeSequenceInPlace(currentOwnedNodes, nextOwnedNodes)) {
2997
3551
  if (!replaceInsertRangeOwnedNodes(currentUnit.marker, currentOwnedNodes, nextOwnedNodes)) return false;
2998
- } else insertMarkerNodeCounts.set(currentUnit.marker, nextOwnedNodes.length);
3552
+ } else setRememberedInsertMarkerNodeCount(currentUnit.marker, nextOwnedNodes.length);
2999
3553
  continue;
3000
3554
  }
3001
3555
  if (currentUnit.kind === "opaque-range" && nextUnit.kind === "opaque-range") {
3002
3556
  if (currentUnit.token !== nextUnit.token || currentUnit.rangeKind !== nextUnit.rangeKind) return false;
3003
3557
  if (currentUnit.rangeKind === "component-boundary") {
3004
- if (Boolean(nextUnit.start[COMPONENT_BOUNDARY_SYMBOL_CHANGED])) return false;
3005
- if (Boolean(nextUnit.start[COMPONENT_BOUNDARY_PROPS_CHANGED])) {
3558
+ if (didComponentBoundarySymbolChange(nextUnit.start)) return false;
3559
+ if (didComponentBoundaryPropsChange(nextUnit.start)) {
3006
3560
  const nextRangeNodes = nextUnit.bodyNodes;
3007
3561
  if (!tryPatchBoundaryContentsInPlace(currentUnit.start, currentUnit.end, nextRangeNodes)) replaceBoundaryContents(currentUnit.start, currentUnit.end, nextRangeNodes);
3008
3562
  }
@@ -3019,11 +3573,11 @@ const tryPatchNodeSequenceInPlace = (currentNodes, nextNodes) => {
3019
3573
  };
3020
3574
  const patchNodeInPlace = (current, next) => {
3021
3575
  if (current.nodeType !== next.nodeType) return false;
3022
- if (current.nodeType === DOM_TEXT_NODE && next.nodeType === DOM_TEXT_NODE) {
3576
+ if (current.nodeType === 3 && next.nodeType === 3) {
3023
3577
  if (current.textContent !== next.textContent) current.textContent = next.textContent;
3024
3578
  return true;
3025
3579
  }
3026
- if (current.nodeType === DOM_COMMENT_NODE && next.nodeType === DOM_COMMENT_NODE) {
3580
+ if (current.nodeType === 8 && next.nodeType === 8) {
3027
3581
  const currentComment = current;
3028
3582
  const nextComment = next;
3029
3583
  const currentIsProjectionSlot = !!parseProjectionSlotMarker(currentComment.data);
@@ -3044,235 +3598,43 @@ const patchNodeInPlace = (current, next) => {
3044
3598
  return tryPatchElementShellInPlace(current, next);
3045
3599
  };
3046
3600
  const tryPatchBoundaryContentsInPlace = (start, end, nextNodes) => {
3047
- return tryPatchNodeSequenceInPlace(getBoundaryChildren(start, end), nextNodes);
3048
- };
3049
- const getBoundaryChildren = (start, end) => {
3050
- const nodes = [];
3051
- let cursor = start.nextSibling;
3052
- while (cursor && cursor !== end) {
3053
- nodes.push(cursor);
3054
- cursor = cursor.nextSibling;
3055
- }
3056
- return nodes;
3057
- };
3058
- const collectMountedBoundaryDescendants = (component) => component.start && component.end ? collectComponentBoundaryIds(getBoundaryChildren(component.start, component.end)) : /* @__PURE__ */ new Set();
3059
- const collectMountedDescendantComponentIds = (container, component) => expandComponentIdsToDescendants(container, collectMountedBoundaryDescendants(component));
3060
- const collectProjectionSlotComponentIds = (roots) => {
3061
- const preserved = /* @__PURE__ */ new Set();
3062
- for (const range of collectProjectionSlotRanges(roots).values()) for (const componentId of collectComponentBoundaryIds(getBoundaryChildren(range.start, range.end))) preserved.add(componentId);
3063
- return preserved;
3064
- };
3065
- const collectPreservedProjectionSlotComponentIds = (container, start, end) => expandComponentIdsToDescendants(container, collectProjectionSlotComponentIds(getBoundaryChildren(start, end)));
3066
- const getNodePath = (root, target) => {
3067
- if (root === target) return [];
3068
- const path = [];
3069
- let cursor = target;
3070
- while (cursor && cursor !== root) {
3071
- const parent = cursor.parentNode;
3072
- if (!parent) return null;
3073
- const index = Array.prototype.indexOf.call(parent.childNodes, cursor);
3074
- if (index < 0) return null;
3075
- path.unshift(index);
3076
- cursor = parent;
3077
- }
3078
- return cursor === root ? path : null;
3079
- };
3080
- const getNodeByPath = (root, path) => {
3081
- let cursor = root;
3082
- for (const index of path) {
3083
- const childNodes = cursor ? cursor.childNodes ?? void 0 : void 0;
3084
- cursor = (childNodes && ("item" in childNodes ? childNodes.item(index) : childNodes[index] ?? null)) ?? null;
3085
- if (!cursor) return null;
3086
- }
3087
- return cursor;
3088
- };
3089
- const getElementPath = (root, target) => {
3090
- if (root === target) return [];
3091
- const path = [];
3092
- let cursor = target;
3093
- while (cursor && cursor !== root) {
3094
- const parent = cursor.parentElement;
3095
- if (!parent) return null;
3096
- const index = Array.prototype.indexOf.call(parent.children, cursor);
3097
- if (index < 0) return null;
3098
- path.unshift(index);
3099
- cursor = parent;
3100
- }
3101
- return cursor === root ? path : null;
3102
- };
3103
- const getElementByPath = (root, path) => {
3104
- let cursor = root;
3105
- for (const index of path) {
3106
- const children = cursor ? cursor.children ?? void 0 : void 0;
3107
- cursor = (children && ("item" in children ? children.item(index) : children[index] ?? null)) ?? null;
3108
- if (!cursor) return null;
3109
- }
3110
- return cursor;
3111
- };
3112
- const captureBoundaryFocus = (doc, start, end) => {
3113
- const activeElement = doc.activeElement;
3114
- if (!isHTMLElementNode(activeElement)) return null;
3115
- const topLevelNodes = getBoundaryChildren(start, end);
3116
- for (let i = 0; i < topLevelNodes.length; i++) {
3117
- const candidate = topLevelNodes[i];
3118
- if (candidate !== activeElement && (!isElementNode(candidate) || !candidate.contains(activeElement))) continue;
3119
- const innerPath = getNodePath(candidate, activeElement);
3120
- if (!innerPath) continue;
3121
- return {
3122
- path: [i, ...innerPath],
3123
- selectionDirection: isTextEntryElement(activeElement) ? activeElement.selectionDirection : null,
3124
- selectionEnd: isTextEntryElement(activeElement) ? activeElement.selectionEnd : null,
3125
- selectionStart: isTextEntryElement(activeElement) ? activeElement.selectionStart : null
3126
- };
3127
- }
3128
- return null;
3129
- };
3130
- const restoreBoundaryFocus = (doc, start, end, snapshot) => {
3131
- if (!snapshot) return;
3132
- const [topLevelIndex, ...innerPath] = snapshot.path;
3133
- const root = getBoundaryChildren(start, end)[topLevelIndex];
3134
- if (!root) return;
3135
- const nextActive = innerPath.length > 0 ? getNodeByPath(root, innerPath) : root;
3136
- if (!isHTMLElementNode(nextActive)) return;
3137
- restoreFocusTarget(doc, nextActive, snapshot);
3138
- };
3139
- const restoreFocusTarget = (doc, nextActive, snapshot) => {
3140
- const restore = () => {
3141
- if (!nextActive.isConnected) return false;
3142
- nextActive.focus({ preventScroll: true });
3143
- if (isTextEntryElement(nextActive) && snapshot.selectionStart !== null && snapshot.selectionStart !== void 0) nextActive.setSelectionRange(snapshot.selectionStart, snapshot.selectionEnd ?? snapshot.selectionStart, snapshot.selectionDirection ?? void 0);
3144
- return doc.activeElement === nextActive;
3145
- };
3146
- if (restore()) return;
3147
- const win = doc.defaultView;
3148
- if (!win) return;
3149
- let remainingAttempts = 3;
3150
- const retry = () => {
3151
- if (remainingAttempts <= 0) return;
3152
- remainingAttempts--;
3153
- const run = () => {
3154
- if (restore()) return;
3155
- retry();
3156
- };
3157
- if (typeof win.requestAnimationFrame === "function") {
3158
- win.requestAnimationFrame(() => run());
3159
- return;
3160
- }
3161
- win.setTimeout(run, 16);
3162
- };
3163
- retry();
3164
- };
3165
- const captureDocumentFocus = (doc, focusSource) => {
3166
- const candidate = isHTMLElementNode(focusSource) ? focusSource : isHTMLElementNode(doc.activeElement) ? doc.activeElement : null;
3167
- if (!candidate) return null;
3168
- const path = getElementPath(doc.body, candidate);
3169
- if (!path) return null;
3170
- return {
3171
- path,
3172
- selectionDirection: isTextEntryElement(candidate) ? candidate.selectionDirection : null,
3173
- selectionEnd: isTextEntryElement(candidate) ? candidate.selectionEnd : null,
3174
- selectionStart: isTextEntryElement(candidate) ? candidate.selectionStart : null
3175
- };
3601
+ return tryPatchNodeSequenceInPlace(getBoundaryChildren(start, end), nextNodes);
3602
+ };
3603
+ const collectMountedBoundaryDescendants = (component) => component.start && component.end ? collectComponentBoundaryIds(getBoundaryChildren(component.start, component.end)) : /* @__PURE__ */ new Set();
3604
+ const collectMountedDescendantComponentIds = (container, component) => expandComponentIdsToDescendants(container, collectMountedBoundaryDescendants(component));
3605
+ const collectProjectionSlotComponentIds = (roots) => {
3606
+ const preserved = /* @__PURE__ */ new Set();
3607
+ for (const range of collectProjectionSlotRanges(roots).values()) for (const componentId of collectComponentBoundaryIds(getBoundaryChildren(range.start, range.end))) preserved.add(componentId);
3608
+ return preserved;
3176
3609
  };
3610
+ const collectPreservedProjectionSlotComponentIds = (container, start, end) => expandComponentIdsToDescendants(container, collectProjectionSlotComponentIds(getBoundaryChildren(start, end)));
3177
3611
  const capturePendingFocusRestore = (container, focusSource) => {
3178
3612
  if (!container.doc) return null;
3179
3613
  const snapshot = captureDocumentFocus(container.doc, focusSource);
3180
3614
  if (!snapshot) return null;
3181
3615
  return { snapshot };
3182
3616
  };
3183
- const shouldSkipPendingFocusRestore = (container, pending) => {
3184
- if (!container.doc) return false;
3185
- const activeElement = container.doc.activeElement;
3186
- if (!isHTMLElementNode(activeElement)) return false;
3187
- if (activeElement === container.doc.body || !activeElement.isConnected || !container.doc.body.contains(activeElement)) return false;
3188
- const activePath = getElementPath(container.doc.body, activeElement);
3189
- if (!activePath) return false;
3190
- if (activePath.length !== pending.snapshot.path.length) return true;
3191
- return activePath.some((index, position) => index !== pending.snapshot.path[position]);
3192
- };
3193
3617
  const restorePendingFocus = (container, pending) => {
3194
3618
  if (!pending || !container.doc) return;
3195
- if (shouldSkipPendingFocusRestore(container, pending)) return;
3196
- const nextActive = getElementByPath(container.doc.body, pending.snapshot.path);
3197
- if (!isHTMLElementNode(nextActive)) return;
3198
- restoreFocusTarget(container.doc, nextActive, pending.snapshot);
3199
- };
3200
- const EVENT_PROP_REGEX = /^on([A-Z].+)$/;
3201
- const DANGEROUSLY_SET_INNER_HTML_PROP = "dangerouslySetInnerHTML";
3202
- const resolveDangerouslySetInnerHTML = (value) => value === false || value === void 0 || value === null ? null : String(value);
3203
- const toEventName = (propName) => {
3204
- const matched = propName.match(EVENT_PROP_REGEX);
3205
- if (!matched) return null;
3206
- const [first, ...rest] = matched[1];
3207
- return `${first.toLowerCase()}${rest.join("")}`;
3208
- };
3209
- const TEXT_ESCAPE_REGEX = /[&<>]/;
3210
- const ATTR_ESCAPE_REGEX = /[&<>'"]/;
3211
- const escapeString = (value, mode) => {
3212
- const escapePattern = mode === "attr" ? ATTR_ESCAPE_REGEX : TEXT_ESCAPE_REGEX;
3213
- const firstMatch = value.search(escapePattern);
3214
- if (firstMatch < 0) return value;
3215
- let output = "";
3216
- let lastIndex = 0;
3217
- for (let index = firstMatch; index < value.length; index += 1) {
3218
- let escaped = null;
3219
- switch (value.charCodeAt(index)) {
3220
- case 34:
3221
- escaped = mode === "attr" ? "&quot;" : null;
3222
- break;
3223
- case 38:
3224
- escaped = "&amp;";
3225
- break;
3226
- case 39:
3227
- escaped = mode === "attr" ? "&#39;" : null;
3228
- break;
3229
- case 60:
3230
- escaped = "&lt;";
3231
- break;
3232
- case 62:
3233
- escaped = "&gt;";
3234
- break;
3235
- }
3236
- if (!escaped) continue;
3237
- output += value.slice(lastIndex, index);
3238
- output += escaped;
3239
- lastIndex = index + 1;
3240
- }
3241
- return output + value.slice(lastIndex);
3242
- };
3243
- const escapeText = (value) => escapeString(value, "text");
3244
- const escapeAttr = (value) => escapeString(value, "attr");
3245
- const renderSSRAttr = (name, value) => {
3246
- if (value === false || value === void 0 || value === null) return "";
3247
- if (value === true) return ` ${name}`;
3248
- return ` ${name}="${escapeAttr(String(value))}"`;
3249
- };
3250
- const renderStringArray = (values) => {
3251
- let output = "";
3252
- for (let index = 0; index < values.length; index += 1) output += renderStringNode(values[index]);
3253
- return output;
3254
- };
3255
- const renderSSRTemplateValue = (value) => {
3256
- if (value === false || value === null || value === void 0) return "";
3257
- if (Array.isArray(value)) return renderStringArray(value);
3258
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return escapeText(String(value));
3259
- if (isSSRTemplate(value)) return renderSSRTemplateNode(value);
3260
- if (isProjectionSlot(value)) return renderProjectionSlotToString(value);
3261
- if (isRouteSlot(value)) {
3262
- const routeElement = resolveRouteSlot(getCurrentContainer(), value);
3263
- return routeElement ? renderStringNode(routeElement) : "";
3264
- }
3265
- return renderStringNode(value);
3266
- };
3267
- const renderSSRTemplateNode = (template) => {
3268
- let output = template.strings[0] ?? "";
3269
- for (let index = 0; index < template.values.length; index += 1) {
3270
- const value = template.values[index];
3271
- output += isSSRAttrValue(value) ? renderSSRAttr(value.name, value.value) : renderSSRTemplateValue(value);
3272
- output += template.strings[index + 1] ?? "";
3273
- }
3274
- return output;
3619
+ restorePendingFocus$1(container.doc, pending);
3620
+ };
3621
+ let ssrRenderer = null;
3622
+ const getSSRRenderer = () => {
3623
+ ssrRenderer ??= createSSRRenderer({
3624
+ getCurrentContainer,
3625
+ isProjectionSlot: (value) => isProjectionSlot(value),
3626
+ isRouteSlot: (value) => isRouteSlot(value),
3627
+ renderProjectionSlotToString: (value) => renderProjectionSlotToString(value),
3628
+ renderStringNode,
3629
+ resolveRouteSlot: (container, slot) => resolveRouteSlot(container, slot)
3630
+ });
3631
+ return ssrRenderer;
3275
3632
  };
3633
+ const renderSSRAttr = (name, value) => getSSRRenderer().renderSSRAttr(name, value);
3634
+ const renderSSRValue = (value) => getSSRRenderer().renderSSRValue(value);
3635
+ const renderSSRMap = (value, renderItem) => getSSRRenderer().renderSSRMap(value, renderItem);
3636
+ const renderStringArray = (values) => withActiveKeyedRangeScope(allocateKeyedRangeScope(), () => renderSSRValue(values));
3637
+ const renderSSRTemplateNode = (template) => renderSSRValue(template);
3276
3638
  const resolveRenderable = (value) => {
3277
3639
  let current = value;
3278
3640
  while (typeof current === "function" && !getLazyMeta(current) && !getComponentMeta(current) && !getContextProviderMeta(current)) current = current();
@@ -3314,8 +3676,28 @@ const renderProjectionSlotToString = (slot) => {
3314
3676
  if (frame?.component.id === slot.componentId && frame.projectionState.reuseExistingDom) return `<!--${start}--><!--${end}-->`;
3315
3677
  return `<!--${start}-->${renderStringNode(slot.source)}<!--${end}-->`;
3316
3678
  };
3317
- const wrapStringWithKeyedRange = (value, key) => {
3318
- return `<!--${createKeyedRangeMarker(key, "start")}-->${value}<!--${createKeyedRangeMarker(key, "end")}-->`;
3679
+ let unscopedKeyedRangeScopeCounter = 0;
3680
+ const allocateKeyedRangeScope = () => {
3681
+ const frame = getCurrentFrame();
3682
+ if (!frame) return `global:${unscopedKeyedRangeScopeCounter++}`;
3683
+ return `${frame.component.id}:k${frame.keyedRangeCursor++}`;
3684
+ };
3685
+ const withActiveKeyedRangeScope = (scope, render) => {
3686
+ const frame = getCurrentFrame();
3687
+ if (!frame) return render();
3688
+ frame.keyedRangeScopeStack.push(scope);
3689
+ try {
3690
+ return render();
3691
+ } finally {
3692
+ frame.keyedRangeScopeStack.pop();
3693
+ }
3694
+ };
3695
+ const resolveKeyedRangeScope = () => {
3696
+ const frame = getCurrentFrame();
3697
+ return (frame && frame.keyedRangeScopeStack.length > 0 ? frame.keyedRangeScopeStack[frame.keyedRangeScopeStack.length - 1] : null) ?? allocateKeyedRangeScope();
3698
+ };
3699
+ const wrapStringWithKeyedRange = (value, scope, key) => {
3700
+ return `<!--${createKeyedRangeMarker(scope, key, "start")}-->${value}<!--${createKeyedRangeMarker(scope, key, "end")}-->`;
3319
3701
  };
3320
3702
  const resolveForItemKey = (value, item, index) => value.key ? value.key(item, index) : typeof item === "string" || typeof item === "number" || typeof item === "symbol" ? item : index;
3321
3703
  const stripForChildRootKey = (value) => {
@@ -3332,10 +3714,11 @@ const resolveShowBranch = (value) => {
3332
3714
  };
3333
3715
  const renderForValueToString = (value) => {
3334
3716
  if (value.arr.length === 0) return renderStringNode(value.fallback ?? null);
3717
+ const scope = allocateKeyedRangeScope();
3335
3718
  let output = "";
3336
3719
  for (let index = 0; index < value.arr.length; index += 1) {
3337
3720
  const item = value.arr[index];
3338
- output += wrapStringWithKeyedRange(renderStringNode(stripForChildRootKey(value.fn(item, index))), resolveForItemKey(value, item, index));
3721
+ output += wrapStringWithKeyedRange(renderStringNode(stripForChildRootKey(value.fn(item, index))), scope, resolveForItemKey(value, item, index));
3339
3722
  }
3340
3723
  return output;
3341
3724
  };
@@ -3351,6 +3734,199 @@ const renderProjectionSlotToNodes = (slot, container) => {
3351
3734
  end
3352
3735
  ];
3353
3736
  };
3737
+ const createExternalRootHtml = (componentId, kind, body) => `<e-island-root ${EXTERNAL_ROOT_ATTR}="true" ${EXTERNAL_ROOT_COMPONENT_ATTR}="${escapeAttr(componentId)}" ${EXTERNAL_ROOT_KIND_ATTR}="${escapeAttr(kind)}">${body}</e-island-root>`;
3738
+ const createExternalRootNode = (container, componentId, kind, body) => {
3739
+ if (!container.doc) throw new Error("Client rendering requires a document.");
3740
+ const host = container.doc.createElement("e-island-root");
3741
+ host.setAttribute(EXTERNAL_ROOT_ATTR, "true");
3742
+ host.setAttribute(EXTERNAL_ROOT_COMPONENT_ATTR, componentId);
3743
+ host.setAttribute(EXTERNAL_ROOT_KIND_ATTR, kind);
3744
+ if (body) host.innerHTML = body;
3745
+ return host;
3746
+ };
3747
+ const getExternalRoot = (component) => {
3748
+ if (!component.start || !component.end) return null;
3749
+ let cursor = component.start.nextSibling;
3750
+ while (cursor && cursor !== component.end) {
3751
+ if (isElementNode(cursor) && cursor.getAttribute("data-e-external-root") === "true") return cursor;
3752
+ cursor = cursor.nextSibling;
3753
+ }
3754
+ return null;
3755
+ };
3756
+ const findExternalSlotHost = (host, kind, name) => {
3757
+ if (typeof host.querySelectorAll !== "function") return host.querySelector?.(`${getExternalSlotTag(kind)}[data-e-slot="${name}"]`) ?? null;
3758
+ const matches = [...host.querySelectorAll(`${getExternalSlotTag(kind)}[data-e-slot="${name}"]`)];
3759
+ if (matches.length === 0) return null;
3760
+ for (let index = matches.length - 1; index >= 0; index -= 1) {
3761
+ const candidate = matches[index];
3762
+ if (candidate.childNodes.length > 0 || (candidate.innerHTML ?? "") !== "") return candidate;
3763
+ }
3764
+ return matches[0];
3765
+ };
3766
+ const captureExternalSlotDom = (component) => {
3767
+ if (!component.external) return null;
3768
+ const host = getExternalRoot(component);
3769
+ if (!host || typeof host.querySelector !== "function") return null;
3770
+ const captured = /* @__PURE__ */ new Map();
3771
+ for (const name of component.external.slots) {
3772
+ const slotHost = findExternalSlotHost(host, component.external.kind, name);
3773
+ captured.set(name, slotHost ? [...slotHost.childNodes] : []);
3774
+ }
3775
+ return captured;
3776
+ };
3777
+ const captureExternalSlotHtml = (component) => {
3778
+ if (!component.external) return null;
3779
+ const host = getExternalRoot(component);
3780
+ if (!host || typeof host.querySelector !== "function") return null;
3781
+ const captured = /* @__PURE__ */ new Map();
3782
+ for (const name of component.external.slots) {
3783
+ const slotHost = findExternalSlotHost(host, component.external.kind, name);
3784
+ captured.set(name, slotHost?.innerHTML ?? "");
3785
+ }
3786
+ return captured;
3787
+ };
3788
+ const createExternalProjectionSlotOwnerId = (componentId, name, occurrence) => `${componentId}.$slot:${encodeURIComponent(name)}:${occurrence}`;
3789
+ const renderExternalProjectionSlotNodes = (container, component, name, occurrence, source) => {
3790
+ const ownerId = createExternalProjectionSlotOwnerId(component.id, name, occurrence);
3791
+ return {
3792
+ nodes: renderClientInsertableForOwner(source, container, {
3793
+ childIndex: 0,
3794
+ componentId: ownerId,
3795
+ keyedRangeCursor: 0,
3796
+ projectionCounters: []
3797
+ }),
3798
+ ownerId
3799
+ };
3800
+ };
3801
+ const syncExternalProjectionSlotDom = (container, component, props, host) => {
3802
+ if (!component.external || !component.projectionSlots) return false;
3803
+ const oldDescendants = collectDescendantIds(container, component.id);
3804
+ const slotRanges = collectProjectionSlotRanges([host]);
3805
+ const keptSlotOwners = /* @__PURE__ */ new Set();
3806
+ let changed = false;
3807
+ for (const [name, totalOccurrences] of Object.entries(component.projectionSlots)) for (let occurrence = 0; occurrence < totalOccurrences; occurrence += 1) {
3808
+ const rangeKey = createProjectionSlotRangeKey(component.id, name, occurrence);
3809
+ const range = slotRanges.get(rangeKey);
3810
+ if (!hasProjectionSlotValue(props, name)) {
3811
+ if (!range) continue;
3812
+ if (!tryPatchBoundaryContentsInPlace(range.start, range.end, [])) replaceProjectionSlotContents(range.start, range.end, []);
3813
+ changed = true;
3814
+ continue;
3815
+ }
3816
+ const slotHost = range || occurrence > 0 ? null : findExternalSlotHost(host, component.external.kind, name);
3817
+ if (!range && !slotHost) continue;
3818
+ const { nodes, ownerId } = renderExternalProjectionSlotNodes(container, component, name, occurrence, props[name]);
3819
+ keptSlotOwners.add(ownerId);
3820
+ if (range) {
3821
+ if (!tryPatchBoundaryContentsInPlace(range.start, range.end, nodes)) replaceProjectionSlotContents(range.start, range.end, nodes);
3822
+ changed = true;
3823
+ continue;
3824
+ }
3825
+ if (!slotHost) continue;
3826
+ while (slotHost.firstChild) slotHost.firstChild.remove();
3827
+ const start = container.doc.createComment(createProjectionSlotMarker(component.id, name, occurrence, "start"));
3828
+ const end = container.doc.createComment(createProjectionSlotMarker(component.id, name, occurrence, "end"));
3829
+ slotHost.appendChild(start);
3830
+ for (const node of nodes) slotHost.appendChild(node);
3831
+ slotHost.appendChild(end);
3832
+ rememberManagedAttributesForNodes([
3833
+ start,
3834
+ ...nodes,
3835
+ end
3836
+ ]);
3837
+ slotRanges.set(rangeKey, {
3838
+ end,
3839
+ start
3840
+ });
3841
+ changed = true;
3842
+ }
3843
+ if (!changed) return false;
3844
+ bindComponentBoundaries(container, host);
3845
+ restoreSignalRefs(container, host);
3846
+ bindRouterLinks(container, host);
3847
+ const keptDescendants = expandComponentIdsToDescendants(container, [...collectComponentBoundaryIds([host]), ...keptSlotOwners]);
3848
+ pruneRemovedComponents(container, component.id, keptDescendants);
3849
+ for (const descendantId of oldDescendants) {
3850
+ if (keptDescendants.has(descendantId)) continue;
3851
+ clearComponentSubscriptions(container, descendantId);
3852
+ }
3853
+ component.externalSlotDom = captureExternalSlotDom(component);
3854
+ component.externalSlotHtml = captureExternalSlotHtml(component);
3855
+ return true;
3856
+ };
3857
+ const restoreExternalSlotDom = (component, host) => {
3858
+ if (!component.external || !component.externalSlotDom || typeof host.querySelector !== "function") return;
3859
+ for (const [name, nodes] of component.externalSlotDom) {
3860
+ const slotHost = findExternalSlotHost(host, component.external.kind, name);
3861
+ if (!slotHost || slotHost.childNodes.length > 0 || nodes.length === 0) continue;
3862
+ for (const node of nodes) slotHost.appendChild(node);
3863
+ }
3864
+ };
3865
+ const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3866
+ const renderExternalSlotContentToString = (componentId, name, occurrence, source) => {
3867
+ if (source === null || source === void 0 || source === false) return "";
3868
+ return renderProjectionSlotToString(createProjectionSlot(componentId, name, occurrence, source));
3869
+ };
3870
+ const injectExternalSlotHtml = (componentId, kind, projectionSlots, props, html) => {
3871
+ if (!projectionSlots) return html;
3872
+ const slotTag = getExternalSlotTag(kind);
3873
+ let nextHtml = html;
3874
+ for (const [name, totalOccurrences] of Object.entries(projectionSlots)) {
3875
+ if (!hasProjectionSlotValue(props, name)) continue;
3876
+ const pattern = new RegExp(`<${slotTag}([^>]*?)data-e-slot=(["'])${escapeRegExp(name)}\\2([^>]*)>([\\s\\S]*?)</${slotTag}>`);
3877
+ for (let occurrence = 0; occurrence < totalOccurrences; occurrence += 1) {
3878
+ const slotHtml = renderExternalSlotContentToString(componentId, name, occurrence, props[name]);
3879
+ nextHtml = nextHtml.replace(pattern, `<${slotTag}$1data-e-slot="${name}"$3>${slotHtml}</${slotTag}>`);
3880
+ }
3881
+ }
3882
+ return nextHtml;
3883
+ };
3884
+ const renderExternalComponentHtml = (container, componentId, external, props, projectionSlots) => {
3885
+ const cacheKey = `${componentId}:${external.kind}`;
3886
+ const cached = container.externalRenderCache.get(cacheKey);
3887
+ if (cached?.status === "resolved") return injectExternalSlotHtml(componentId, external.kind, projectionSlots, props, cached.html ?? "");
3888
+ if (cached?.status === "rejected") throw cached.error;
3889
+ if (cached?.status === "pending") {
3890
+ if (cached.pending) container.pendingSuspensePromises.add(cached.pending);
3891
+ return "";
3892
+ }
3893
+ const result = external.renderToString(props);
3894
+ if (typeof result === "string") {
3895
+ container.externalRenderCache.set(cacheKey, {
3896
+ html: result,
3897
+ status: "resolved"
3898
+ });
3899
+ return injectExternalSlotHtml(componentId, external.kind, projectionSlots, props, result);
3900
+ }
3901
+ const pending = Promise.resolve(result).then((resolved) => {
3902
+ container.externalRenderCache.set(cacheKey, {
3903
+ html: resolved,
3904
+ status: "resolved"
3905
+ });
3906
+ return resolved;
3907
+ }, (error) => {
3908
+ container.externalRenderCache.set(cacheKey, {
3909
+ error,
3910
+ status: "rejected"
3911
+ });
3912
+ throw error;
3913
+ });
3914
+ container.externalRenderCache.set(cacheKey, {
3915
+ pending,
3916
+ status: "pending"
3917
+ });
3918
+ container.pendingSuspensePromises.add(pending);
3919
+ return "";
3920
+ };
3921
+ const syncExternalComponentInstance = async (component, external, props, host) => {
3922
+ if (component.externalInstance === void 0) {
3923
+ component.externalMeta = external;
3924
+ component.externalInstance = await external.hydrate(host, props);
3925
+ return;
3926
+ }
3927
+ component.externalMeta = external;
3928
+ component.externalInstance = await external.update(component.externalInstance, host, props);
3929
+ };
3354
3930
  const renderContextProviderToString = (token, props) => withRuntimeContextValue(token, props.value, () => renderStringNode(props.children ?? null));
3355
3931
  const renderContextProviderToNodes = (token, props, container) => withRuntimeContextValue(token, props.value, () => renderClientNodes(props.children ?? null, container));
3356
3932
  const renderStringNode = (inputElementLike) => {
@@ -3359,6 +3935,7 @@ const renderStringNode = (inputElementLike) => {
3359
3935
  if (resolved === false || resolved === null || resolved === void 0) return "";
3360
3936
  if (Array.isArray(resolved)) return renderStringNode(resolved);
3361
3937
  if (typeof resolved === "string" || typeof resolved === "number" || typeof resolved === "boolean") return escapeText(String(resolved));
3938
+ if (isSSRRawValue(resolved)) return resolved.value;
3362
3939
  if (isShowValue(resolved)) return renderStringNode(resolveShowBranch(resolved));
3363
3940
  if (isForValue(resolved)) return renderForValueToString(resolved);
3364
3941
  if (isSSRTemplate(resolved)) return renderSSRTemplateNode(resolved);
@@ -3370,7 +3947,7 @@ const renderStringNode = (inputElementLike) => {
3370
3947
  if (!isRenderObject(resolved)) return "";
3371
3948
  if (isSuspenseType(resolved.type)) {
3372
3949
  const rendered = renderSuspenseComponentToString(resolved.props);
3373
- return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolved.key);
3950
+ return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolveKeyedRangeScope(), resolved.key);
3374
3951
  }
3375
3952
  if (typeof resolved.type === "function") {
3376
3953
  const providerMeta = getContextProviderMeta(resolved.type);
@@ -3380,24 +3957,33 @@ const renderStringNode = (inputElementLike) => {
3380
3957
  const meta = getComponentMeta(componentFn);
3381
3958
  if (!meta || !container) {
3382
3959
  const rendered = renderStringNode(componentFn(resolved.props));
3383
- return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolved.key);
3960
+ return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolveKeyedRangeScope(), resolved.key);
3384
3961
  }
3385
3962
  const evaluatedProps = evaluateProps(resolved.props);
3386
3963
  const position = nextComponentPosition(container);
3387
3964
  const componentId = createComponentId(container, position.parentId, position.childIndex);
3388
3965
  const component = getOrCreateComponentState(container, componentId, meta.symbol, position.parentId);
3389
3966
  component.scopeId = registerScope(container, meta.captures());
3967
+ component.external = meta.external;
3390
3968
  component.optimizedRoot = meta.optimizedRoot === true;
3391
3969
  component.props = evaluatedProps;
3392
3970
  component.projectionSlots = meta.projectionSlots ?? null;
3971
+ component.rawProps = resolved.props;
3972
+ const externalMeta = getExternalComponentMeta(componentFn);
3973
+ if (externalMeta) {
3974
+ const externalBody = renderExternalComponentHtml(container, componentId, externalMeta, evaluatedProps, component.projectionSlots);
3975
+ const host = createExternalRootHtml(componentId, externalMeta.kind, externalBody);
3976
+ const rendered = `${createComponentBoundaryHtmlComment(componentId, "start")}${host}${createComponentBoundaryHtmlComment(componentId, "end")}`;
3977
+ return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolveKeyedRangeScope(), resolved.key);
3978
+ }
3393
3979
  const frame = createFrame(container, component, "ssr");
3394
3980
  clearComponentSubscriptions(container, component.id);
3395
3981
  const renderProps = createRenderProps(componentId, meta, resolved.props);
3396
3982
  const body = pushFrame(frame, () => renderStringNode(componentFn(renderProps)));
3397
3983
  pruneComponentVisibles(container, component, frame.visibleCursor);
3398
3984
  pruneComponentWatches(container, component, frame.watchCursor);
3399
- const rendered = `<!--ec:c:${componentId}:start-->${renderFrameScopedStylesToString(frame)}${body}<!--ec:c:${componentId}:end-->`;
3400
- return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolved.key);
3985
+ const rendered = `${createComponentBoundaryHtmlComment(componentId, "start")}${renderFrameScopedStylesToString(frame)}${body}${createComponentBoundaryHtmlComment(componentId, "end")}`;
3986
+ return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolveKeyedRangeScope(), resolved.key);
3401
3987
  }
3402
3988
  const attrParts = [];
3403
3989
  const container = getCurrentContainer();
@@ -3408,9 +3994,10 @@ const renderStringNode = (inputElementLike) => {
3408
3994
  for (const name in resolved.props) {
3409
3995
  if (!Object.hasOwn(resolved.props, name)) continue;
3410
3996
  if (name === "children") continue;
3997
+ if (name === "key") continue;
3411
3998
  const eventName = toEventName(name);
3412
3999
  const value = resolved.props[name];
3413
- if (name === BIND_VALUE_PROP) {
4000
+ if (name === "bind:value") {
3414
4001
  const signalId = getBindableSignalId(value);
3415
4002
  if (!signalId) continue;
3416
4003
  attrParts.push(`${BIND_VALUE_ATTR}="${escapeAttr(signalId)}"`);
@@ -3418,7 +4005,7 @@ const renderStringNode = (inputElementLike) => {
3418
4005
  if (currentValue !== void 0 && currentValue !== null) attrParts.push(`value="${escapeAttr(String(currentValue))}"`);
3419
4006
  continue;
3420
4007
  }
3421
- if (name === BIND_CHECKED_PROP) {
4008
+ if (name === "bind:checked") {
3422
4009
  const signalId = getBindableSignalId(value);
3423
4010
  if (!signalId) continue;
3424
4011
  attrParts.push(`${BIND_CHECKED_ATTR}="${escapeAttr(signalId)}"`);
@@ -3437,7 +4024,7 @@ const renderStringNode = (inputElementLike) => {
3437
4024
  if (signalId) attrParts.push(`${REF_SIGNAL_ATTR}="${escapeAttr(signalId)}"`);
3438
4025
  continue;
3439
4026
  }
3440
- if (name === DANGEROUSLY_SET_INNER_HTML_PROP) {
4027
+ if (isDangerouslySetInnerHTMLProp(name)) {
3441
4028
  hasInnerHTML = true;
3442
4029
  innerHTML = resolveDangerouslySetInnerHTML(value);
3443
4030
  continue;
@@ -3452,13 +4039,9 @@ const renderStringNode = (inputElementLike) => {
3452
4039
  }
3453
4040
  if (resolved.type === "body" && container) attrParts.push("data-e-resume=\"paused\"");
3454
4041
  let childrenText = innerHTML ?? "";
3455
- if (!hasInnerHTML) {
3456
- const children = resolved.props.children;
3457
- if (Array.isArray(children)) for (const child of children) childrenText += renderStringNode(child);
3458
- else childrenText += renderStringNode(children);
3459
- }
4042
+ if (!hasInnerHTML) childrenText += renderStringNode(resolved.props.children);
3460
4043
  const rendered = resolved.type === "__ECLIPSA_FRAGMENT" ? childrenText : `<${resolved.type}${attrParts.length > 0 ? ` ${attrParts.join(" ")}` : ""}>${childrenText}</${resolved.type}>`;
3461
- return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolved.key);
4044
+ return resolved.key === null || resolved.key === void 0 ? rendered : wrapStringWithKeyedRange(rendered, resolveKeyedRangeScope(), resolved.key);
3462
4045
  };
3463
4046
  const createElementNode = (doc, tagName) => doc.createElement(tagName);
3464
4047
  const renderComponentToNodes = (componentFn, props, container, mode, rawProps) => {
@@ -3474,23 +4057,54 @@ const renderComponentToNodes = (componentFn, props, container, mode, rawProps) =
3474
4057
  const previousRenderProps = component.rawProps ?? component.props ?? null;
3475
4058
  component.active = mode === "client";
3476
4059
  if (!existing || symbolChanged) resetComponentForSymbolChange(container, component, meta);
4060
+ component.external = meta.external;
3477
4061
  component.optimizedRoot = meta.optimizedRoot === true;
3478
4062
  component.props = props;
3479
4063
  component.rawProps = rawProps ?? null;
3480
4064
  component.projectionSlots = meta.projectionSlots ?? null;
4065
+ const externalMeta = getExternalComponentMeta(componentFn);
3481
4066
  const parentFrame = getCurrentFrame();
3482
4067
  const shouldReuseProjectionSlotDom = parentFrame?.projectionState.reuseProjectionSlotDom ?? false;
3483
4068
  const previousStart = component.start;
3484
4069
  const previousEnd = component.end;
3485
- const boundaryContentsChanged = symbolChanged || !areShallowEqualRenderProps(previousRenderProps, rawProps ?? props ?? null) || !wasActive && !!previousStart && !!previousEnd;
4070
+ const propsChanged = symbolChanged || !areShallowEqualRenderProps(previousRenderProps, rawProps ?? props ?? null);
4071
+ const boundaryContentsChanged = propsChanged || !wasActive && !!previousStart && !!previousEnd;
4072
+ if (mode === "client" && externalMeta && previousStart && previousEnd && !symbolChanged) {
4073
+ const { end, start } = createComponentBoundaryPair(container.doc, componentId);
4074
+ const host = getExternalRoot(component);
4075
+ if (wasActive && host && propsChanged) withClientContainer(container, async () => {
4076
+ syncExternalProjectionSlotDom(container, component, props, host);
4077
+ await syncExternalComponentInstance(component, externalMeta, props, host);
4078
+ syncExternalProjectionSlotDom(container, component, props, host);
4079
+ rebindExternalHost(container, host);
4080
+ scheduleExternalHostRebind(container, host);
4081
+ });
4082
+ if (parentFrame) for (const descendantId of expandComponentIdsToDescendants(container, [componentId])) parentFrame.visitedDescendants.add(descendantId);
4083
+ return [start, end];
4084
+ }
3486
4085
  if (mode === "client" && wasActive && previousStart && previousEnd && !boundaryContentsChanged) {
3487
- const start = container.doc.createComment(`ec:c:${componentId}:start`);
3488
- const end = container.doc.createComment(`ec:c:${componentId}:end`);
3489
- start[COMPONENT_BOUNDARY_PROPS_CHANGED] = false;
3490
- start[COMPONENT_BOUNDARY_SYMBOL_CHANGED] = false;
4086
+ const { end, start } = createComponentBoundaryPair(container.doc, componentId);
3491
4087
  if (parentFrame) for (const descendantId of expandComponentIdsToDescendants(container, [componentId])) parentFrame.visitedDescendants.add(descendantId);
3492
4088
  return [start, end];
3493
4089
  }
4090
+ if (externalMeta) {
4091
+ const { end, start } = createComponentBoundaryPair(container.doc, componentId, {
4092
+ propsChanged: true,
4093
+ symbolChanged
4094
+ });
4095
+ if (!previousStart || !previousEnd) {
4096
+ component.start = start;
4097
+ component.end = end;
4098
+ }
4099
+ const host = createExternalRootNode(container, componentId, externalMeta.kind);
4100
+ if (parentFrame) parentFrame.visitedDescendants.add(componentId);
4101
+ if (mode === "client") scheduleExternalComponentMount(container, component, externalMeta, props);
4102
+ return [
4103
+ start,
4104
+ host,
4105
+ end
4106
+ ];
4107
+ }
3494
4108
  const speculativeEffectCleanupSlot = !previousStart || !previousEnd ? null : boundaryContentsChanged ? null : createCleanupSlot();
3495
4109
  if (!speculativeEffectCleanupSlot) resetComponentRenderEffects(component);
3496
4110
  const frame = createFrame(container, component, mode, {
@@ -3500,10 +4114,10 @@ const renderComponentToNodes = (componentFn, props, container, mode, rawProps) =
3500
4114
  });
3501
4115
  clearComponentSubscriptions(container, componentId);
3502
4116
  const oldDescendants = collectDescendantIds(container, componentId);
3503
- const start = container.doc.createComment(`ec:c:${componentId}:start`);
3504
- const end = container.doc.createComment(`ec:c:${componentId}:end`);
3505
- start[COMPONENT_BOUNDARY_PROPS_CHANGED] = boundaryContentsChanged;
3506
- start[COMPONENT_BOUNDARY_SYMBOL_CHANGED] = symbolChanged;
4117
+ const { end, start } = createComponentBoundaryPair(container.doc, componentId, {
4118
+ propsChanged: boundaryContentsChanged,
4119
+ symbolChanged
4120
+ });
3507
4121
  if (!previousStart || !previousEnd) {
3508
4122
  component.start = start;
3509
4123
  component.end = end;
@@ -3548,28 +4162,29 @@ const renderComponentToNodes = (componentFn, props, container, mode, rawProps) =
3548
4162
  end
3549
4163
  ];
3550
4164
  };
3551
- const wrapNodesWithKeyedRange = (doc, nodes, key) => [
3552
- doc.createComment(createKeyedRangeMarker(key, "start")),
4165
+ const wrapNodesWithKeyedRange = (doc, nodes, scope, key) => [
4166
+ doc.createComment(createKeyedRangeMarker(scope, key, "start")),
3553
4167
  ...nodes,
3554
- doc.createComment(createKeyedRangeMarker(key, "end"))
4168
+ doc.createComment(createKeyedRangeMarker(scope, key, "end"))
3555
4169
  ];
3556
4170
  const renderForValueToNodes = (value, container) => {
3557
4171
  if (value.arr.length === 0) return renderClientNodes(value.fallback ?? null, container);
4172
+ const scope = allocateKeyedRangeScope();
3558
4173
  const nodes = [];
3559
4174
  for (let index = 0; index < value.arr.length; index += 1) {
3560
4175
  const item = value.arr[index];
3561
- nodes.push(...wrapNodesWithKeyedRange(container.doc, renderClientNodes(stripForChildRootKey(value.fn(item, index)), container), resolveForItemKey(value, item, index)));
4176
+ nodes.push(...wrapNodesWithKeyedRange(container.doc, renderClientNodes(stripForChildRootKey(value.fn(item, index)), container), scope, resolveForItemKey(value, item, index)));
3562
4177
  }
3563
4178
  return nodes;
3564
4179
  };
3565
4180
  const applyElementProp = (element, name, value, container) => {
3566
- if (name === BIND_VALUE_PROP) {
4181
+ if (name === "bind:value") {
3567
4182
  const signalId = getBindableSignalId(value);
3568
4183
  if (signalId) element.setAttribute(BIND_VALUE_ATTR, signalId);
3569
4184
  if ("value" in element) element.value = String(readBindableSignalValue(value) ?? "");
3570
4185
  return;
3571
4186
  }
3572
- if (name === BIND_CHECKED_PROP) {
4187
+ if (name === "bind:checked") {
3573
4188
  const signalId = getBindableSignalId(value);
3574
4189
  if (signalId) element.setAttribute(BIND_CHECKED_ATTR, signalId);
3575
4190
  if (isHTMLInputElementNode(element)) element.checked = Boolean(readBindableSignalValue(value));
@@ -3588,7 +4203,7 @@ const applyElementProp = (element, name, value, container) => {
3588
4203
  assignRuntimeRef(value, element, container);
3589
4204
  return;
3590
4205
  }
3591
- if (name === DANGEROUSLY_SET_INNER_HTML_PROP) {
4206
+ if (isDangerouslySetInnerHTMLProp(name)) {
3592
4207
  const html = resolveDangerouslySetInnerHTML(value);
3593
4208
  if (html !== null) element.innerHTML = html;
3594
4209
  return;
@@ -3612,7 +4227,7 @@ const applyElementProp = (element, name, value, container) => {
3612
4227
  };
3613
4228
  const renderClientNodes = (inputElementLike, container) => {
3614
4229
  if (!container.doc) throw new Error("Client rendering requires a document.");
3615
- if (Array.isArray(inputElementLike)) return inputElementLike.flatMap((entry) => renderClientNodes(entry, container));
4230
+ if (Array.isArray(inputElementLike)) return withActiveKeyedRangeScope(allocateKeyedRangeScope(), () => inputElementLike.flatMap((entry) => renderClientNodes(entry, container)));
3616
4231
  const resolved = resolveRenderable(inputElementLike);
3617
4232
  if (resolved === false || resolved === null || resolved === void 0) return [];
3618
4233
  if (Array.isArray(resolved)) return renderClientNodes(resolved, container);
@@ -3639,10 +4254,8 @@ const renderClientNodes = (inputElementLike, container) => {
3639
4254
  if (getComponentMeta(resolved.type)) nodes = withoutTrackedEffect(() => renderComponentToNodes(componentFn, evaluateProps(resolved.props), container, "client", resolved.props));
3640
4255
  else nodes = renderComponentToNodes(componentFn, resolved.props, container, "client", resolved.props);
3641
4256
  }
3642
- } else if (resolved.type === "__ECLIPSA_FRAGMENT") {
3643
- const children = resolved.props.children;
3644
- nodes = Array.isArray(children) ? children.flatMap((child) => renderClientNodes(child, container)) : renderClientNodes(children, container);
3645
- } else {
4257
+ } else if (resolved.type === "__ECLIPSA_FRAGMENT") nodes = renderClientNodes(resolved.props.children, container);
4258
+ else {
3646
4259
  const element = createElementNode(container.doc, resolved.type);
3647
4260
  const frame = getCurrentFrame();
3648
4261
  if (frame && hasScopedStyles(frame) && resolved.type !== "style") element.setAttribute(SCOPED_STYLE_ATTR, frame.component.scopeId);
@@ -3651,35 +4264,33 @@ const renderClientNodes = (inputElementLike, container) => {
3651
4264
  if (name === "children") continue;
3652
4265
  const value = descriptor.get ? descriptor.get.call(resolved.props) : descriptor.value;
3653
4266
  if (resolved.type === "body" && name === "data-e-resume") continue;
3654
- if (name === DANGEROUSLY_SET_INNER_HTML_PROP) hasInnerHTML = true;
4267
+ if (isDangerouslySetInnerHTMLProp(name)) hasInnerHTML = true;
3655
4268
  applyElementProp(element, name, value, container);
3656
4269
  }
3657
4270
  if (hasInnerHTML) {
3658
4271
  rememberManagedAttributesForNode(element);
3659
4272
  nodes = [element];
3660
4273
  } else {
3661
- const children = resolved.props.children;
3662
- const childNodes = Array.isArray(children) ? children.flatMap((child) => renderClientNodes(child, container)) : renderClientNodes(children, container);
4274
+ const childNodes = renderClientNodes(resolved.props.children, container);
3663
4275
  for (const child of childNodes) element.appendChild(child);
3664
4276
  rememberManagedAttributesForNode(element);
3665
4277
  nodes = [element];
3666
4278
  }
3667
4279
  }
3668
- return resolved.key === null || resolved.key === void 0 ? nodes : wrapNodesWithKeyedRange(container.doc, nodes, resolved.key);
4280
+ return resolved.key === null || resolved.key === void 0 ? nodes : wrapNodesWithKeyedRange(container.doc, nodes, resolveKeyedRangeScope(), resolved.key);
3669
4281
  };
3670
4282
  const scanComponentBoundaries = (root) => {
3671
- const walker = root.ownerDocument.createTreeWalker(root, DOM_SHOW_COMMENT);
4283
+ const walker = root.ownerDocument.createTreeWalker(root, 128);
3672
4284
  const boundaries = /* @__PURE__ */ new Map();
3673
4285
  while (walker.nextNode()) {
3674
4286
  const node = walker.currentNode;
3675
- if (!(node.nodeType === DOM_COMMENT_NODE || typeof Comment !== "undefined" && node instanceof Comment)) continue;
3676
- const matched = node.data.match(/^ec:c:(.+):(start|end)$/);
3677
- if (!matched) continue;
3678
- const [, id, edge] = matched;
3679
- const boundary = boundaries.get(id) ?? {};
3680
- if (edge === "start") boundary.start = node;
4287
+ if (!(node.nodeType === 8 || typeof Comment !== "undefined" && node instanceof Comment)) continue;
4288
+ const marker = parseComponentBoundaryMarker(node.data);
4289
+ if (!marker) continue;
4290
+ const boundary = boundaries.get(marker.id) ?? {};
4291
+ if (marker.kind === "start") boundary.start = node;
3681
4292
  else boundary.end = node;
3682
- boundaries.set(id, boundary);
4293
+ boundaries.set(marker.id, boundary);
3683
4294
  }
3684
4295
  return boundaries;
3685
4296
  };
@@ -3708,7 +4319,7 @@ const toMountedNodes = (value, container) => {
3708
4319
  if (!container.doc) throw new Error("Client rendering requires a document.");
3709
4320
  let resolved = value;
3710
4321
  while (typeof resolved === "function") resolved = resolved();
3711
- if (Array.isArray(resolved)) return resolved.flatMap((entry) => toMountedNodes(entry, container));
4322
+ if (Array.isArray(resolved)) return withActiveKeyedRangeScope(allocateKeyedRangeScope(), () => resolved.flatMap((entry) => toMountedNodes(entry, container)));
3712
4323
  if (resolved === null || resolved === void 0 || resolved === false) return [container.doc.createComment("eclipsa-empty")];
3713
4324
  if (typeof Node !== "undefined" && resolved instanceof Node) return [resolved];
3714
4325
  if (typeof resolved === "string" || typeof resolved === "number" || typeof resolved === "boolean") return [container.doc.createTextNode(String(resolved))];
@@ -3724,6 +4335,7 @@ const captureClientInsertOwner = (container, siteKey) => {
3724
4335
  return {
3725
4336
  childIndex: 0,
3726
4337
  componentId: ownerComponentId,
4338
+ keyedRangeCursor: frame.keyedRangeCursor,
3727
4339
  projectionCounters: [...frame.projectionState.counters.entries()]
3728
4340
  };
3729
4341
  };
@@ -3733,18 +4345,19 @@ const createDetachedClientInsertOwner = (container) => {
3733
4345
  return {
3734
4346
  childIndex: 0,
3735
4347
  componentId,
4348
+ keyedRangeCursor: 0,
3736
4349
  projectionCounters: []
3737
4350
  };
3738
4351
  };
3739
4352
  const inferClientInsertOwnerParentId = (componentId) => {
3740
- if (componentId.startsWith(CLIENT_INSERT_OWNER_ID_PREFIX)) return ROOT_COMPONENT_ID;
4353
+ if (componentId.startsWith("$insert:")) return ROOT_COMPONENT_ID;
3741
4354
  const lastDotIndex = componentId.lastIndexOf(".");
3742
4355
  if (lastDotIndex < 0) return ROOT_COMPONENT_ID;
3743
4356
  return componentId.slice(0, lastDotIndex);
3744
4357
  };
3745
4358
  const renderClientInsertableForOwner = (value, container, owner) => {
3746
4359
  if (!owner) return renderClientInsertable(value, container);
3747
- const component = container.components.get(owner.componentId) ?? getOrCreateComponentState(container, owner.componentId, CLIENT_INSERT_OWNER_SYMBOL, inferClientInsertOwnerParentId(owner.componentId));
4360
+ const component = container.components.get(owner.componentId) ?? getOrCreateComponentState(container, owner.componentId, "$client-insert-root", inferClientInsertOwnerParentId(owner.componentId));
3748
4361
  const parentFrame = getCurrentFrame();
3749
4362
  const oldDescendants = collectDescendantIds(container, owner.componentId);
3750
4363
  const frame = createFrame(container, component, "client", {
@@ -3752,6 +4365,7 @@ const renderClientInsertableForOwner = (value, container, owner) => {
3752
4365
  reuseProjectionSlotDom: false
3753
4366
  });
3754
4367
  frame.childCursor = owner.childIndex;
4368
+ frame.keyedRangeCursor = owner.keyedRangeCursor;
3755
4369
  frame.projectionState.counters = new Map(owner.projectionCounters);
3756
4370
  const nodes = pushContainer(container, () => pushFrame(frame, () => renderClientInsertable(value, container)));
3757
4371
  const keptDescendants = expandComponentIdsToDescendants(container, [...frame.visitedDescendants, ...collectComponentBoundaryIds(nodes)]);
@@ -3769,7 +4383,7 @@ const renderClientInsertableForOwner = (value, container, owner) => {
3769
4383
  const renderClientInsertable = (value, container = getCurrentContainer()) => {
3770
4384
  const doc = container?.doc ?? (typeof document !== "undefined" ? document : null);
3771
4385
  if (!doc) return [];
3772
- if (Array.isArray(value)) return value.flatMap((entry) => renderClientInsertable(entry, container));
4386
+ if (Array.isArray(value)) return withActiveKeyedRangeScope(allocateKeyedRangeScope(), () => value.flatMap((entry) => renderClientInsertable(entry, container)));
3773
4387
  let resolved = value;
3774
4388
  while (typeof resolved === "function") resolved = resolved();
3775
4389
  if (resolved === null || resolved === void 0 || resolved === false) return [doc.createComment("eclipsa-empty")];
@@ -3811,51 +4425,6 @@ const resetContainerForRouteRender = (container) => {
3811
4425
  if (!isRouterSignalId(id) && !isAtomSignalId(id)) container.signals.delete(id);
3812
4426
  }
3813
4427
  };
3814
- const isRouteSlot = (value) => isPlainObject(value) && value.__eclipsa_type === ROUTE_SLOT_TYPE;
3815
- const createRouteSlot = (route, startLayoutIndex) => {
3816
- const slot = {
3817
- __eclipsa_type: ROUTE_SLOT_TYPE,
3818
- pathname: route.pathname,
3819
- startLayoutIndex
3820
- };
3821
- Object.defineProperty(slot, ROUTE_SLOT_ROUTE_KEY, {
3822
- configurable: true,
3823
- enumerable: false,
3824
- value: route,
3825
- writable: true
3826
- });
3827
- return slot;
3828
- };
3829
- const resolveRouteSlot = (container, slot) => {
3830
- const route = slot[ROUTE_SLOT_ROUTE_KEY] ?? container?.router?.loadedRoutes.get(routeCacheKey(slot.pathname, "page"));
3831
- if (!route) return null;
3832
- return createRouteElement(route, slot.startLayoutIndex);
3833
- };
3834
- const createRouteElement = (route, startLayoutIndex = 0) => {
3835
- const createRouteProps = (props) => {
3836
- const nextProps = { ...props };
3837
- Object.defineProperty(nextProps, ROUTE_PARAMS_PROP, {
3838
- configurable: true,
3839
- enumerable: false,
3840
- value: route.params,
3841
- writable: true
3842
- });
3843
- Object.defineProperty(nextProps, ROUTE_ERROR_PROP, {
3844
- configurable: true,
3845
- enumerable: false,
3846
- value: route.error,
3847
- writable: true
3848
- });
3849
- return nextProps;
3850
- };
3851
- if (startLayoutIndex >= route.layouts.length) return jsxDEV(route.page.renderer, createRouteProps({}), null, false, {});
3852
- let children = null;
3853
- for (let index = route.layouts.length - 1; index >= startLayoutIndex; index -= 1) {
3854
- const layout = route.layouts[index];
3855
- children = jsxDEV(layout.renderer, createRouteProps({ children: createRouteSlot(route, index + 1) }), null, false, {});
3856
- }
3857
- return children;
3858
- };
3859
4428
  const trackSuspenseBoundaryPromise = (container, componentId, promise) => {
3860
4429
  const component = container.components.get(componentId);
3861
4430
  if (!component) return;
@@ -3874,13 +4443,12 @@ const renderSuspenseContentToString = (props, container, componentId) => {
3874
4443
  return renderStringNode(typeof props.children === "function" ? props.children() : props.children ?? null);
3875
4444
  } catch (error) {
3876
4445
  if (!isPendingSignalError(error)) throw error;
3877
- container.pendingSuspensePromises.add(error.promise);
3878
4446
  const component = container.components.get(componentId);
3879
4447
  if (component) component.suspensePromise = error.promise;
3880
4448
  return renderStringNode(props.fallback ?? null);
3881
4449
  }
3882
4450
  };
3883
- const collectPendingSuspenseBoundaryIds = (container) => [...container.components.values()].filter((component) => component.symbol === SUSPENSE_COMPONENT_SYMBOL && !!component.suspensePromise).map((component) => component.id).sort((left, right) => left.split(".").length - right.split(".").length);
4451
+ const collectPendingSuspenseBoundaryIds = (container) => [...container.components.values()].filter((component) => component.symbol === "$suspense" && !!component.suspensePromise).map((component) => component.id).sort((left, right) => left.split(".").length - right.split(".").length);
3884
4452
  const renderSuspenseContentToNodes = (props, container, componentId) => {
3885
4453
  try {
3886
4454
  return toMountedNodes(typeof props.children === "function" ? props.children() : props.children ?? null, container);
@@ -3907,7 +4475,7 @@ const renderSuspenseComponentToString = (props) => {
3907
4475
  const body = pushFrame(frame, () => renderSuspenseContentToString(component.props, container, componentId));
3908
4476
  pruneComponentVisibles(container, component, frame.visibleCursor);
3909
4477
  pruneComponentWatches(container, component, frame.watchCursor);
3910
- return `<!--ec:c:${componentId}:start-->${body}<!--ec:c:${componentId}:end-->`;
4478
+ return `${createComponentBoundaryHtmlComment(componentId, "start")}${body}${createComponentBoundaryHtmlComment(componentId, "end")}`;
3911
4479
  };
3912
4480
  const renderSuspenseComponentToNodes = (props, container, mode) => {
3913
4481
  const parentFrame = getCurrentFrame();
@@ -3933,8 +4501,7 @@ const renderSuspenseComponentToNodes = (props, container, mode) => {
3933
4501
  scheduleMountCallbacks(container, component, frame.mountCallbacks);
3934
4502
  scheduleVisibleCallbacksCheck(container);
3935
4503
  if (!container.doc) return bodyNodes;
3936
- const start = container.doc.createComment(`ec:c:${componentId}:start`);
3937
- const end = container.doc.createComment(`ec:c:${componentId}:end`);
4504
+ const { end, start } = createComponentBoundaryPair(container.doc, componentId);
3938
4505
  if (!component.start || !component.end) {
3939
4506
  component.start = start;
3940
4507
  component.end = end;
@@ -4020,7 +4587,7 @@ const loadResolvedRoute = async (container, matched, variant = "page") => {
4020
4587
  const cacheKey = routeCacheKey(normalizedPath, variant);
4021
4588
  const existing = router.loadedRoutes.get(cacheKey);
4022
4589
  if (existing) return existing;
4023
- const moduleUrl = variant === "page" ? matched.entry.page : variant === "loading" ? matched.entry.loading : variant === "error" ? matched.entry.error : matched.entry.notFound;
4590
+ const moduleUrl = getRouteModuleUrl(matched.entry, variant);
4024
4591
  if (!moduleUrl) return null;
4025
4592
  const [page, ...layouts] = await Promise.all([loadRouteModule(router, moduleUrl), ...matched.entry.layouts.map((layoutUrl) => loadRouteModule(router, layoutUrl))]);
4026
4593
  let route;
@@ -4037,13 +4604,14 @@ const loadResolvedRoute = async (container, matched, variant = "page") => {
4037
4604
  return route;
4038
4605
  };
4039
4606
  const loadResolvedRouteFromSpecial = async (container, pathname, kind) => {
4040
- const matched = findSpecialManifestEntry(ensureRouterState(container).manifest, pathname, kind);
4607
+ const manifest = ensureRouterState(container).manifest;
4608
+ const matched = kind === "notFound" ? resolveNotFoundRouteMatch(manifest, pathname) : findSpecialManifestEntry(manifest, pathname, kind);
4041
4609
  if (!matched) return null;
4042
4610
  return loadResolvedRoute(container, matched, kind === "error" ? "error" : "not-found");
4043
4611
  };
4044
4612
  const loadRouteComponent = async (container, pathname) => {
4045
- const matched = matchRouteManifest(ensureRouterState(container).manifest, pathname);
4046
- if (!matched || !matched.entry.page) return null;
4613
+ const matched = resolvePageRouteMatch(ensureRouterState(container).manifest, pathname);
4614
+ if (!matched) return null;
4047
4615
  return loadResolvedRoute(container, matched, "page");
4048
4616
  };
4049
4617
  const findRouteComponentChain = (container, symbols, parentId = null) => {
@@ -4092,7 +4660,7 @@ const resolveSharedLayoutRouteRoot = (container, boundaryId, slotRange) => {
4092
4660
  const component = container.components.get(candidateId);
4093
4661
  if (!component?.parentId) continue;
4094
4662
  const owner = container.components.get(component.parentId);
4095
- if (!owner || owner.symbol !== CLIENT_INSERT_OWNER_SYMBOL || owner.parentId !== boundaryId) continue;
4663
+ if (!owner || owner.symbol !== "$client-insert-root" || owner.parentId !== boundaryId) continue;
4096
4664
  return {
4097
4665
  kind: "owner",
4098
4666
  ownerId: owner.id,
@@ -4117,6 +4685,7 @@ const renderRouteSubtreeForProjectionSlotOwner = (container, ownerId, source) =>
4117
4685
  nodes: renderClientInsertableForOwner(source, container, {
4118
4686
  childIndex: 0,
4119
4687
  componentId: ownerId,
4688
+ keyedRangeCursor: 0,
4120
4689
  projectionCounters: []
4121
4690
  }),
4122
4691
  visitedDescendants: expandComponentIdsToDescendants(container, [ownerId])
@@ -4185,7 +4754,7 @@ const updateSharedLayoutBoundary = async (container, current, next, sharedLayout
4185
4754
  return true;
4186
4755
  };
4187
4756
  if ((boundary.projectionSlots?.children ?? 0) !== 1) return rerenderSharedLayoutBoundary();
4188
- const slotRange = collectProjectionSlotRanges(getBoundaryChildren(boundary.start, boundary.end)).get(`${boundaryId}:${encodeProjectionSlotName("children")}:0`);
4757
+ const slotRange = collectProjectionSlotRanges(getBoundaryChildren(boundary.start, boundary.end)).get(createProjectionSlotRangeKey(boundaryId, "children", 0));
4189
4758
  if (!slotRange) return rerenderSharedLayoutBoundary();
4190
4759
  const routeRoot = resolveSharedLayoutRouteRoot(container, boundaryId, slotRange);
4191
4760
  if (!routeRoot) return rerenderSharedLayoutBoundary();
@@ -4270,7 +4839,6 @@ const applyPrefetchedLoaders = (container, url) => {
4270
4839
  loaded: snapshot.loaded
4271
4840
  });
4272
4841
  };
4273
- const isRouteDataSuccess = (body) => body.ok === true && typeof body.finalHref === "string" && typeof body.finalPathname === "string" && (body.kind === "page" || body.kind === "not-found") && !!body.loaders && typeof body.loaders === "object";
4274
4842
  const extractScriptTextById = (html, id) => {
4275
4843
  const scriptPattern = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
4276
4844
  const idPattern = /\bid\s*=\s*(?:"([^"]*)"|'([^']*)')/i;
@@ -4288,31 +4856,20 @@ const parseRouteDataFromHtml = (container, requestUrl, response, html) => {
4288
4856
  ok: false
4289
4857
  };
4290
4858
  const payloadText = extractScriptTextById(html, "eclipsa-resume-final") ?? extractScriptTextById(html, "eclipsa-resume");
4291
- if (!payloadText) return {
4292
- document: true,
4293
- ok: false
4294
- };
4859
+ if (!payloadText) return ROUTE_DOCUMENT_FALLBACK;
4295
4860
  let payload;
4296
4861
  try {
4297
4862
  payload = JSON.parse(payloadText);
4298
4863
  } catch {
4299
- return {
4300
- document: true,
4301
- ok: false
4302
- };
4864
+ return ROUTE_DOCUMENT_FALLBACK;
4303
4865
  }
4304
4866
  const finalPathname = normalizeRoutePath(finalUrl.pathname);
4305
- const router = ensureRouterState(container);
4306
- const matched = matchRouteManifest(router.manifest, finalPathname);
4307
- const notFoundMatched = !matched ? findSpecialManifestEntry(router.manifest, finalPathname, "notFound") : null;
4308
- if (!matched?.entry.page && !notFoundMatched?.entry.notFound) return {
4309
- document: true,
4310
- ok: false
4311
- };
4867
+ const resolvedMatch = resolveRoutableMatch(ensureRouterState(container).manifest, finalPathname);
4868
+ if (!resolvedMatch) return ROUTE_DOCUMENT_FALLBACK;
4312
4869
  return {
4313
4870
  finalHref: finalUrl.href,
4314
4871
  finalPathname,
4315
- kind: matched?.entry.page ? "page" : "not-found",
4872
+ kind: resolvedMatch.kind,
4316
4873
  loaders: payload.loaders ?? {},
4317
4874
  ok: true
4318
4875
  };
@@ -4326,10 +4883,7 @@ const requestRouteData = async (container, href) => {
4326
4883
  const response = await fetch(endpointUrl.href);
4327
4884
  if (response.status >= 200 && response.status < 300) {
4328
4885
  const body = await response.json();
4329
- if (!body || typeof body !== "object" || typeof body.ok !== "boolean") return {
4330
- document: true,
4331
- ok: false
4332
- };
4886
+ if (!body || typeof body !== "object" || typeof body.ok !== "boolean") return ROUTE_DOCUMENT_FALLBACK;
4333
4887
  if (isRouteDataSuccess(body)) return body;
4334
4888
  if ("location" in body && typeof body.location === "string") return body;
4335
4889
  }
@@ -4338,10 +4892,7 @@ const requestRouteData = async (container, href) => {
4338
4892
  const response = await fetch(requestUrl.href);
4339
4893
  return parseRouteDataFromHtml(container, requestUrl, response, await response.text());
4340
4894
  } catch {}
4341
- return {
4342
- document: true,
4343
- ok: false
4344
- };
4895
+ return ROUTE_DOCUMENT_FALLBACK;
4345
4896
  };
4346
4897
  const resetRouteLoaderState = (container) => {
4347
4898
  container.loaders.clear();
@@ -4358,10 +4909,7 @@ const requestRoutePreflight = async (href) => {
4358
4909
  try {
4359
4910
  const requestUrl = new URL(href, typeof window === "undefined" ? "http://localhost" : window.location.href);
4360
4911
  const response = await fetch(requestUrl.href, { headers: { [ROUTE_PREFLIGHT_REQUEST_HEADER]: "1" } });
4361
- if (response.status < 200 || response.status >= 300) return {
4362
- document: true,
4363
- ok: false
4364
- };
4912
+ if (response.status < 200 || response.status >= 300) return ROUTE_DOCUMENT_FALLBACK;
4365
4913
  const finalUrl = new URL(response.url || requestUrl.href, requestUrl.href);
4366
4914
  if (finalUrl.origin !== requestUrl.origin || finalUrl.pathname !== requestUrl.pathname || finalUrl.search !== requestUrl.search) return {
4367
4915
  location: finalUrl.href,
@@ -4369,26 +4917,55 @@ const requestRoutePreflight = async (href) => {
4369
4917
  };
4370
4918
  return { ok: true };
4371
4919
  } catch {
4372
- return {
4373
- document: true,
4374
- ok: false
4375
- };
4920
+ return ROUTE_DOCUMENT_FALLBACK;
4376
4921
  }
4377
4922
  };
4378
4923
  const prefetchResolvedRouteModules = async (container, pathname, finalUrl) => {
4379
4924
  const router = ensureRouterState(container);
4380
- const matched = matchRouteManifest(router.manifest, pathname);
4381
- if (matched?.entry.page) {
4382
- await loadResolvedRoute(container, matched);
4383
- return;
4384
- }
4385
- const notFoundMatched = findSpecialManifestEntry(router.manifest, pathname, "notFound");
4386
- if (notFoundMatched?.entry.notFound) await loadResolvedRoute(container, notFoundMatched, "not-found");
4925
+ const resolvedMatch = resolveRoutableMatch(router.manifest, pathname);
4926
+ if (resolvedMatch) await loadResolvedRoute(container, resolvedMatch.matched, resolvedMatch.kind);
4387
4927
  if (finalUrl.pathname !== pathname) {
4388
4928
  const redirectedPath = normalizeRoutePath(finalUrl.pathname);
4389
- const redirectedMatched = matchRouteManifest(router.manifest, redirectedPath);
4390
- if (redirectedMatched?.entry.page) await loadResolvedRoute(container, redirectedMatched);
4929
+ const redirectedMatch = resolveRoutableMatch(router.manifest, redirectedPath);
4930
+ if (redirectedMatch) await loadResolvedRoute(container, redirectedMatch.matched, redirectedMatch.kind);
4931
+ }
4932
+ };
4933
+ const renderCurrentRoute = (container, route) => {
4934
+ renderRouteIntoRoot(container, route.render);
4935
+ ensureRouterState(container).currentRoute = route;
4936
+ };
4937
+ const applyCurrentRouteMetadata = (container, route, url) => {
4938
+ const doc = container.doc;
4939
+ if (!doc) return;
4940
+ applyRouteMetadata(doc, route, url, ensureRouterState(container).defaultTitle);
4941
+ };
4942
+ const commitRouteNavigation = (container, route, url, mode, options) => {
4943
+ const doc = container.doc;
4944
+ if (!doc) return;
4945
+ const router = ensureRouterState(container);
4946
+ applyCurrentRouteMetadata(container, route, url);
4947
+ commitBrowserNavigation(doc, url, mode);
4948
+ if (options?.writeLocation !== false) writeRouterLocation(router, url);
4949
+ };
4950
+ const renderAndCommitRouteNavigation = (container, route, url, mode, options) => {
4951
+ if (options?.resetLoaders) resetRouteLoaderState(container);
4952
+ renderCurrentRoute(container, route);
4953
+ commitRouteNavigation(container, route, url, mode);
4954
+ };
4955
+ const handleFailedRouteRequest = async (container, doc, url, mode, redirectDepth, result) => {
4956
+ if (!("location" in result)) {
4957
+ fallbackDocumentNavigation(doc, url, mode);
4958
+ return;
4959
+ }
4960
+ const redirectUrl = new URL(result.location, doc.location.href);
4961
+ if (redirectDepth >= 8 || redirectUrl.origin !== doc.location.origin) {
4962
+ fallbackDocumentNavigation(doc, redirectUrl, mode);
4963
+ return;
4391
4964
  }
4965
+ await navigateContainer(container, redirectUrl.href, {
4966
+ mode,
4967
+ redirectDepth: redirectDepth + 1
4968
+ });
4392
4969
  };
4393
4970
  const prefetchRoute = async (container, href) => {
4394
4971
  const doc = container.doc;
@@ -4403,26 +4980,18 @@ const prefetchRoute = async (container, href) => {
4403
4980
  return;
4404
4981
  }
4405
4982
  const pathname = normalizeRoutePath(requestUrl.pathname);
4406
- const matched = matchRouteManifest(router.manifest, pathname);
4407
- const specialRoute = !matched ? findSpecialManifestEntry(router.manifest, pathname, "notFound") : null;
4408
- if (!matched?.entry.page && !specialRoute?.entry.notFound) return;
4983
+ if (!resolveRoutableMatch(router.manifest, pathname)) return;
4409
4984
  const prefetchPromise = (async () => {
4410
4985
  try {
4411
4986
  const result = await requestRouteData(container, requestUrl.href);
4412
4987
  if (!result.ok) return result;
4413
4988
  const finalUrl = new URL(result.finalHref, requestUrl.href);
4414
- if (finalUrl.origin !== requestUrl.origin) return {
4415
- document: true,
4416
- ok: false
4417
- };
4989
+ if (finalUrl.origin !== requestUrl.origin) return ROUTE_DOCUMENT_FALLBACK;
4418
4990
  await prefetchResolvedRouteModules(container, result.finalPathname, finalUrl);
4419
4991
  cachePrefetchedLoaders(container, finalUrl, result.loaders);
4420
4992
  return result;
4421
4993
  } catch {
4422
- return {
4423
- document: true,
4424
- ok: false
4425
- };
4994
+ return ROUTE_DOCUMENT_FALLBACK;
4426
4995
  }
4427
4996
  })();
4428
4997
  router.routePrefetches.set(key, prefetchPromise);
@@ -4443,70 +5012,33 @@ const navigateContainer = async (container, href, options) => {
4443
5012
  const pathname = normalizeRoutePath(url.pathname);
4444
5013
  const router = ensureRouterState(container);
4445
5014
  const matched = matchRouteManifest(router.manifest, pathname);
4446
- const specialPreflightTarget = !matched ? findSpecialManifestEntry(router.manifest, pathname, "notFound") : null;
5015
+ const routeTarget = resolveRoutableMatch(router.manifest, pathname);
4447
5016
  const currentRouteUrl = new URL(router.currentUrl.value, doc.location.href);
4448
5017
  const currentHref = `${currentRouteUrl.pathname}${currentRouteUrl.search}${currentRouteUrl.hash}`;
4449
5018
  const nextHref = `${url.pathname}${url.search}${url.hash}`;
4450
5019
  if (!force && nextHref === currentHref) return;
4451
5020
  const prefetchKey = routePrefetchKey(url);
4452
5021
  let pendingPrefetch = router.routePrefetches.get(prefetchKey);
4453
- if (!pendingPrefetch && (matched?.entry.page || specialPreflightTarget?.entry.notFound)) {
5022
+ if (!pendingPrefetch && routeTarget) {
4454
5023
  await prefetchRoute(container, url.href);
4455
5024
  pendingPrefetch = router.routePrefetches.get(prefetchKey);
4456
5025
  }
4457
5026
  const prefetched = pendingPrefetch ? await pendingPrefetch : null;
4458
5027
  if (prefetched && !prefetched.ok) {
4459
- if ("location" in prefetched) {
4460
- if (redirectDepth >= 8) {
4461
- fallbackDocumentNavigation(doc, new URL(prefetched.location, doc.location.href), mode);
4462
- return;
4463
- }
4464
- const redirectUrl = new URL(prefetched.location, doc.location.href);
4465
- if (redirectUrl.origin !== doc.location.origin) {
4466
- fallbackDocumentNavigation(doc, redirectUrl, mode);
4467
- return;
4468
- }
4469
- await navigateContainer(container, redirectUrl.href, {
4470
- mode,
4471
- redirectDepth: redirectDepth + 1
4472
- });
4473
- return;
4474
- }
4475
- fallbackDocumentNavigation(doc, url, mode);
5028
+ await handleFailedRouteRequest(container, doc, url, mode, redirectDepth, prefetched);
4476
5029
  return;
4477
5030
  }
4478
- if ((matched?.entry.page && matched.entry.hasMiddleware || !!specialPreflightTarget?.entry.notFound && specialPreflightTarget.entry.hasMiddleware) && !prefetched) {
5031
+ if (!!routeTarget?.matched.entry.hasMiddleware && !prefetched) {
4479
5032
  const preflight = await requestRoutePreflight(url.href);
4480
5033
  if (!preflight.ok) {
4481
- if ("location" in preflight) {
4482
- if (redirectDepth >= 8) {
4483
- fallbackDocumentNavigation(doc, new URL(preflight.location, doc.location.href), mode);
4484
- return;
4485
- }
4486
- const redirectUrl = new URL(preflight.location, doc.location.href);
4487
- if (redirectUrl.origin !== doc.location.origin) {
4488
- fallbackDocumentNavigation(doc, redirectUrl, mode);
4489
- return;
4490
- }
4491
- await navigateContainer(container, redirectUrl.href, {
4492
- mode,
4493
- redirectDepth: redirectDepth + 1
4494
- });
4495
- return;
4496
- }
4497
- fallbackDocumentNavigation(doc, url, mode);
5034
+ await handleFailedRouteRequest(container, doc, url, mode, redirectDepth, preflight);
4498
5035
  return;
4499
5036
  }
4500
5037
  }
4501
5038
  if (!matched || !matched.entry.page) {
4502
5039
  const notFoundRoute = !matched ? await loadResolvedRouteFromSpecial(container, pathname, "notFound") : null;
4503
5040
  if (notFoundRoute) {
4504
- resetRouteLoaderState(container);
4505
- renderRouteIntoRoot(container, notFoundRoute.render);
4506
- router.currentRoute = notFoundRoute;
4507
- applyRouteMetadata(doc, notFoundRoute, url, router.defaultTitle);
4508
- commitBrowserNavigation(doc, url, mode);
4509
- writeRouterLocation(router, url);
5041
+ renderAndCommitRouteNavigation(container, notFoundRoute, url, mode, { resetLoaders: true });
4510
5042
  return;
4511
5043
  }
4512
5044
  fallbackDocumentNavigation(doc, url, mode);
@@ -4533,10 +5065,7 @@ const navigateContainer = async (container, href, options) => {
4533
5065
  await Promise.resolve();
4534
5066
  if (!settled) {
4535
5067
  const loadingRoute = await loadResolvedRoute(container, matched, "loading");
4536
- if (loadingRoute) {
4537
- renderRouteIntoRoot(container, loadingRoute.render);
4538
- router.currentRoute = loadingRoute;
4539
- }
5068
+ if (loadingRoute) renderCurrentRoute(container, loadingRoute);
4540
5069
  }
4541
5070
  }
4542
5071
  const [currentRoute, nextRoute] = await Promise.all([router.currentRoute ? Promise.resolve(router.currentRoute) : loadRouteComponent(container, router.currentPath.value), nextRoutePromise]);
@@ -4548,18 +5077,13 @@ const navigateContainer = async (container, href, options) => {
4548
5077
  router.currentRoute = nextRoute;
4549
5078
  writeRouterLocation(router, url);
4550
5079
  const sharedLayoutCount = countSharedLayouts(currentRoute, nextRoute);
4551
- if (!(currentRoute && sharedLayoutCount > 0 ? await updateSharedLayoutBoundary(container, currentRoute, nextRoute, sharedLayoutCount) : false)) renderRouteIntoRoot(container, nextRoute.render);
4552
- applyRouteMetadata(doc, nextRoute, url, router.defaultTitle);
4553
- commitBrowserNavigation(doc, url, mode);
5080
+ if (!(currentRoute && sharedLayoutCount > 0 ? await updateSharedLayoutBoundary(container, currentRoute, nextRoute, sharedLayoutCount) : false)) renderCurrentRoute(container, nextRoute);
5081
+ commitRouteNavigation(container, nextRoute, url, mode, { writeLocation: false });
4554
5082
  } catch (error) {
4555
5083
  if (sequence === router.sequence) {
4556
5084
  const fallbackRoute = isRouteNotFoundError(error) ? await loadResolvedRouteFromSpecial(container, pathname, "notFound") : await loadResolvedRoute(container, matched, "error");
4557
5085
  if (fallbackRoute) {
4558
- renderRouteIntoRoot(container, fallbackRoute.render);
4559
- router.currentRoute = fallbackRoute;
4560
- applyRouteMetadata(doc, fallbackRoute, url, router.defaultTitle);
4561
- commitBrowserNavigation(doc, url, mode);
4562
- writeRouterLocation(router, url);
5086
+ renderAndCommitRouteNavigation(container, fallbackRoute, url, mode);
4563
5087
  return;
4564
5088
  }
4565
5089
  fallbackDocumentNavigation(doc, url, mode);
@@ -4585,12 +5109,6 @@ const refreshRouteContainer = async (container) => {
4585
5109
  };
4586
5110
  const routeEntryReferencesModuleUrl = (entry, fileUrl) => entry.page === fileUrl || entry.loading === fileUrl || entry.error === fileUrl || entry.notFound === fileUrl || entry.layouts.includes(fileUrl);
4587
5111
  const routeReferencesModuleUrl = (route, fileUrl) => route.page.url === fileUrl || route.layouts.some((layout) => layout.url === fileUrl) || routeEntryReferencesModuleUrl(route.entry, fileUrl);
4588
- const resolveCurrentRouteManifestEntry = (router) => {
4589
- const currentPath = normalizeRoutePath(router.currentPath.value);
4590
- const matched = matchRouteManifest(router.manifest, currentPath);
4591
- if (matched?.entry.page) return matched.entry;
4592
- return findSpecialManifestEntry(router.manifest, currentPath, "notFound")?.entry ?? null;
4593
- };
4594
5112
  const invalidateRouteModulesForHmr = (container, fileUrl, bustToken = Date.now()) => {
4595
5113
  const router = container.router;
4596
5114
  if (!router) return false;
@@ -4618,17 +5136,15 @@ const invalidateRouteModulesForHmr = (container, fileUrl, bustToken = Date.now()
4618
5136
  const refreshRouteContainerForHmr = async (container, fileUrl, bustToken = Date.now()) => {
4619
5137
  const doc = container.doc;
4620
5138
  if (!doc || !invalidateRouteModulesForHmr(container, fileUrl, bustToken)) return false;
4621
- const router = ensureRouterState(container);
4622
- const pathname = normalizeRoutePath(router.currentPath.value);
5139
+ const pathname = normalizeRoutePath(ensureRouterState(container).currentPath.value);
4623
5140
  try {
4624
5141
  const nextRoute = await loadRouteComponent(container, pathname) ?? await loadResolvedRouteFromSpecial(container, pathname, "notFound");
4625
5142
  if (!nextRoute) {
4626
5143
  await refreshRouteContainer(container);
4627
5144
  return true;
4628
5145
  }
4629
- renderRouteIntoRoot(container, nextRoute.render);
4630
- router.currentRoute = nextRoute;
4631
- applyRouteMetadata(doc, nextRoute, new URL(doc.location.href), router.defaultTitle);
5146
+ renderCurrentRoute(container, nextRoute);
5147
+ applyCurrentRouteMetadata(container, nextRoute, new URL(doc.location.href));
4632
5148
  return true;
4633
5149
  } catch {
4634
5150
  await refreshRouteContainer(container);
@@ -4644,7 +5160,7 @@ const activateComponent = async (container, componentId) => {
4644
5160
  const activateSymbol = component.symbol;
4645
5161
  const activateMode = component.activateModeOnFlush ?? "replace";
4646
5162
  component.activateModeOnFlush = void 0;
4647
- if (component.symbol === SUSPENSE_COMPONENT_SYMBOL) {
5163
+ if (component.symbol === "$suspense") {
4648
5164
  clearComponentSubscriptions(container, componentId);
4649
5165
  const oldDescendants = collectDescendantIds(container, componentId);
4650
5166
  const suspenseSpeculativeEffectCleanupSlot = component.reuseProjectionSlotDomOnActivate ? createCleanupSlot() : null;
@@ -4696,6 +5212,36 @@ const activateComponent = async (container, componentId) => {
4696
5212
  const module = await loadSymbol(container, activateSymbol);
4697
5213
  const rawProps = component.rawProps && typeof component.rawProps === "object" ? component.rawProps : null;
4698
5214
  if (rawProps) component.props = evaluateProps(rawProps);
5215
+ const externalMeta = getExternalComponentMeta(module.default);
5216
+ if (externalMeta && component.props && typeof component.props === "object") {
5217
+ component.external = {
5218
+ kind: externalMeta.kind,
5219
+ slots: [...externalMeta.slots]
5220
+ };
5221
+ const focusSnapshot = captureBoundaryFocus(container.doc, component.start, component.end);
5222
+ let host = getExternalRoot(component);
5223
+ if (!host) {
5224
+ replaceBoundaryContents(component.start, component.end, [createExternalRootNode(container, component.id, externalMeta.kind)]);
5225
+ host = getExternalRoot(component);
5226
+ }
5227
+ if (!host) throw new Error(`Missing external root host for component ${component.id}.`);
5228
+ host.setAttribute("data-e-external-snapshot", component.id);
5229
+ globalThis.__eclipsaExternalSlotSnapshotMap ??= /* @__PURE__ */ new Map();
5230
+ globalThis.__eclipsaExternalSlotSnapshotMap.set(host, {
5231
+ dom: component.externalSlotDom,
5232
+ html: component.externalSlotHtml
5233
+ });
5234
+ restoreExternalSlotDom(component, host);
5235
+ await withClientContainer(container, async () => {
5236
+ await syncExternalComponentInstance(component, externalMeta, component.props, host);
5237
+ });
5238
+ rebindExternalHost(container, host);
5239
+ scheduleExternalHostRebind(container, host);
5240
+ restoreBoundaryFocus(container.doc, component.start, component.end, focusSnapshot);
5241
+ component.active = true;
5242
+ scheduleVisibleCallbacksCheck(container);
5243
+ return false;
5244
+ }
4699
5245
  await preloadComponentProps(container, {
4700
5246
  captures: () => [],
4701
5247
  projectionSlots: component.projectionSlots ?? void 0,
@@ -4777,7 +5323,7 @@ const resolveResumeHmrBoundarySymbols = (payload) => {
4777
5323
  };
4778
5324
  const findNearestMountedBoundary = (container, componentId) => {
4779
5325
  let currentId = componentId;
4780
- while (currentId && currentId !== ROOT_COMPONENT_ID) {
5326
+ while (currentId && currentId !== "$root") {
4781
5327
  const component = container.components.get(currentId);
4782
5328
  if (!component) return null;
4783
5329
  if (component.start && component.end) return component.id;
@@ -4937,7 +5483,7 @@ const beginSSRContainer = (symbols, render) => {
4937
5483
  };
4938
5484
  };
4939
5485
  const beginAsyncSSRContainer = async (symbols, render, prepare, options) => {
4940
- const container = createContainer(symbols, void 0, options?.asyncSignalSnapshotCache);
5486
+ const container = createContainer(symbols, void 0, options?.asyncSignalSnapshotCache, options?.externalRenderCache);
4941
5487
  const rootFrame = createFrame(container, {
4942
5488
  active: false,
4943
5489
  didMount: false,
@@ -4975,6 +5521,10 @@ const createResumePayload = (container, componentIds) => {
4975
5521
  result: serializeRuntimeValue(container, action.result)
4976
5522
  }])),
4977
5523
  components: Object.fromEntries(componentEntries.map(([id, component]) => [id, {
5524
+ ...component.external ? { external: {
5525
+ kind: component.external.kind,
5526
+ slots: [...component.external.slots]
5527
+ } } : {},
4978
5528
  ...component.optimizedRoot ? { optimizedRoot: true } : {},
4979
5529
  props: serializeRuntimeValue(container, component.props),
4980
5530
  ...component.projectionSlots ? { projectionSlots: { ...component.projectionSlots } } : {},
@@ -5039,6 +5589,12 @@ const mergeResumePayload = (container, payload) => {
5039
5589
  for (const [id, componentPayload] of Object.entries(payload.components)) container.components.set(id, {
5040
5590
  active: false,
5041
5591
  didMount: false,
5592
+ external: componentPayload.external ? {
5593
+ kind: componentPayload.external.kind,
5594
+ slots: [...componentPayload.external.slots]
5595
+ } : void 0,
5596
+ externalInstance: void 0,
5597
+ externalMeta: null,
5042
5598
  id,
5043
5599
  mountCleanupSlots: [],
5044
5600
  optimizedRoot: componentPayload.optimizedRoot === true,
@@ -5067,6 +5623,7 @@ const mergeResumePayload = (container, payload) => {
5067
5623
  watch.mode = watchPayload.mode;
5068
5624
  watch.scopeId = watchPayload.scope;
5069
5625
  watch.symbol = watchPayload.symbol;
5626
+ watch.resumed = true;
5070
5627
  watch.track = null;
5071
5628
  watch.run = null;
5072
5629
  clearEffectSignals(watch.effect);
@@ -5172,6 +5729,14 @@ const createResumeContainer = (source, payload, options) => {
5172
5729
  mergeResumePayload(container, payload);
5173
5730
  rememberManagedAttributesForNode(root);
5174
5731
  bindComponentBoundaries(container, root);
5732
+ for (const component of container.components.values()) {
5733
+ component.externalSlotHtml = captureExternalSlotHtml(component);
5734
+ component.externalSlotDom = captureExternalSlotDom(component);
5735
+ }
5736
+ globalThis.__eclipsaExternalSlotSnapshotStore = Object.fromEntries([...container.components.values()].filter((component) => !!component.external && (component.externalSlotDom || component.externalSlotHtml)).map((component) => [component.id, {
5737
+ dom: component.externalSlotDom,
5738
+ html: component.externalSlotHtml
5739
+ }]));
5175
5740
  restoreSignalRefs(container, root);
5176
5741
  restoreRegisteredRpcHandles(container);
5177
5742
  ensureRouterState(container);
@@ -5179,7 +5744,7 @@ const createResumeContainer = (source, payload, options) => {
5179
5744
  scheduleVisibleCallbacksCheck(container);
5180
5745
  return container;
5181
5746
  };
5182
- const canRestoreResumedLocalSignalEffects = (container, component) => !!component.start && !!component.end && !component.active && component.signalIds.length > 0 && (component.symbol === SUSPENSE_COMPONENT_SYMBOL || container.imports.has(component.symbol) || container.symbols.has(component.symbol));
5747
+ const canRestoreResumedLocalSignalEffects = (container, component) => !!component.start && !!component.end && !component.active && !component.external && component.signalIds.length > 0 && (component.symbol === "$suspense" || container.imports.has(component.symbol) || container.symbols.has(component.symbol));
5183
5748
  const restoreResumedLocalSignalEffects = async (container) => {
5184
5749
  let queued = false;
5185
5750
  const restoredIds = [];
@@ -5201,18 +5766,28 @@ const restoreResumedLocalSignalEffects = async (container) => {
5201
5766
  syncEffectOnlyLocalSignalPreference(component);
5202
5767
  }
5203
5768
  };
5769
+ const restoreResumedExternalComponents = async (container) => {
5770
+ const externalComponents = sortDirtyComponents([...container.components.values()].filter((component) => !!component.external && !!component.start && !!component.end && !component.active && !component.didMount && container.symbols.has(component.symbol)).map((component) => component.id));
5771
+ for (const componentId of externalComponents) await activateComponent(container, componentId);
5772
+ };
5204
5773
  const restoreRegisteredRpcHandles = (container) => {
5205
- withRuntimeContainer(container, () => {
5206
- for (const id of getRegisteredActionHookIds()) getRegisteredActionHook(id)?.();
5207
- for (const id of getRegisteredLoaderHookIds()) getRegisteredLoaderHook(id)?.();
5208
- });
5774
+ const injectedWindow = !("window" in globalThis && globalThis.window !== void 0) && container.doc?.defaultView ? container.doc.defaultView : null;
5775
+ if (injectedWindow) globalThis.window = injectedWindow;
5776
+ try {
5777
+ withRuntimeContainer(container, () => {
5778
+ for (const id of getRegisteredActionHookIds()) getRegisteredActionHook(id)?.();
5779
+ for (const id of getRegisteredLoaderHookIds()) getRegisteredLoaderHook(id)?.();
5780
+ });
5781
+ } finally {
5782
+ if (injectedWindow) delete globalThis.window;
5783
+ }
5209
5784
  };
5210
5785
  const primeRouteModules = async (container) => {
5211
5786
  const router = ensureRouterState(container);
5212
5787
  const currentRoute = await loadRouteComponent(container, router.currentPath.value);
5213
5788
  if (currentRoute) {
5214
5789
  router.currentRoute = currentRoute;
5215
- if (container.doc) applyRouteMetadata(container.doc, currentRoute, new URL(container.doc.location.href), router.defaultTitle);
5790
+ if (container.doc) applyCurrentRouteMetadata(container, currentRoute, new URL(container.doc.location.href));
5216
5791
  }
5217
5792
  };
5218
5793
  const getRouterEventState = (event) => {
@@ -5502,7 +6077,7 @@ const installResumeListeners = (container) => {
5502
6077
  const renderString = (inputElementLike) => renderStringNode(inputElementLike);
5503
6078
  const hasActiveRuntimeComponent = () => {
5504
6079
  const frame = getCurrentFrame();
5505
- return !!frame && frame.component.id !== ROOT_COMPONENT_ID;
6080
+ return !!frame && frame.component.id !== "$root";
5506
6081
  };
5507
6082
  const getRuntimeContextValue = (token) => {
5508
6083
  const stack = getContextValueStack();
@@ -5527,7 +6102,7 @@ const createStandaloneRuntimeSignal = (fallback) => {
5527
6102
  const useRuntimeSignal = (fallback) => {
5528
6103
  const container = getCurrentContainer();
5529
6104
  const frame = getCurrentFrame();
5530
- if (!container || !frame || frame.component.id === ROOT_COMPONENT_ID) throw new Error("useSignal() can only be used while rendering a component.");
6105
+ if (!container || !frame || frame.component.id === "$root") throw new Error("useSignal() can only be used while rendering a component.");
5531
6106
  const signalIndex = frame.signalCursor++;
5532
6107
  const existingId = frame.component.signalIds[signalIndex];
5533
6108
  const signalId = existingId ?? `s${container.nextSignalId++}`;
@@ -5590,7 +6165,7 @@ const createEffect = (fn, options) => {
5590
6165
  },
5591
6166
  signals: /* @__PURE__ */ new Set()
5592
6167
  };
5593
- if (frame && frame.mode === "client" && frame.component.id !== ROOT_COMPONENT_ID) frame.effectCleanupSlot.callbacks.push(() => {
6168
+ if (frame && frame.mode === "client" && frame.component.id !== "$root") frame.effectCleanupSlot.callbacks.push(() => {
5594
6169
  clearEffectSignals(effect);
5595
6170
  });
5596
6171
  effect.fn();
@@ -5601,14 +6176,14 @@ const createOnCleanup = (fn) => {
5601
6176
  };
5602
6177
  const createOnMount = (fn) => {
5603
6178
  const frame = getCurrentFrame();
5604
- if (!frame || frame.component.id === ROOT_COMPONENT_ID || frame.mode !== "client") return;
6179
+ if (!frame || frame.component.id === "$root" || frame.mode !== "client") return;
5605
6180
  frame.mountCallbacks.push(fn);
5606
6181
  };
5607
6182
  const createOnVisible = (fn) => {
5608
6183
  const container = getCurrentContainer();
5609
6184
  const frame = getCurrentFrame();
5610
6185
  const lazyMeta = getLazyMeta(fn);
5611
- if (!container || !frame || frame.component.id === ROOT_COMPONENT_ID) return;
6186
+ if (!container || !frame || frame.component.id === "$root") return;
5612
6187
  if (!lazyMeta && frame.mode === "ssr") return;
5613
6188
  const visibleIndex = frame.visibleCursor++;
5614
6189
  const visible = getOrCreateVisibleState(container, createVisibleId(frame.component.id, visibleIndex), frame.component.id);
@@ -5621,7 +6196,7 @@ const createWatch = (fn, dependencies) => {
5621
6196
  const container = getCurrentContainer();
5622
6197
  const frame = getCurrentFrame();
5623
6198
  const watchMeta = getWatchMeta(fn);
5624
- if (!container || !frame || frame.component.id === ROOT_COMPONENT_ID || !watchMeta) {
6199
+ if (!container || !frame || frame.component.id === "$root" || !watchMeta) {
5625
6200
  const cleanupSlot = createCleanupSlot();
5626
6201
  const effect = {
5627
6202
  fn() {
@@ -5639,6 +6214,14 @@ const createWatch = (fn, dependencies) => {
5639
6214
  watch.symbol = watchMeta.symbol;
5640
6215
  watch.track = dependencies ? () => trackWatchDependencies(dependencies) : null;
5641
6216
  watch.run = createLocalWatchRunner(watch.effect, watch.cleanupSlot, fn, dependencies);
6217
+ if (frame.mode === "client" && watch.resumed) {
6218
+ watch.resumed = false;
6219
+ if (dependencies) collectTrackedDependencies(watch.effect, () => {
6220
+ trackWatchDependencies(dependencies);
6221
+ });
6222
+ return;
6223
+ }
6224
+ watch.resumed = false;
5642
6225
  watch.effect.fn();
5643
6226
  };
5644
6227
  const getResumePayloadScriptContent = (payload) => escapeJSONScriptText(JSON.stringify(payload));
@@ -5886,10 +6469,15 @@ const toClientAsyncGenerator = async function* (response, container) {
5886
6469
  };
5887
6470
  const invokeAction = async (id, input, container) => {
5888
6471
  const isFormSubmission = isFormDataValue(input);
5889
- const response = await fetch(`/__eclipsa/action/${encodeURIComponent(id)}`, {
6472
+ const actionPath = `/__eclipsa/action/${encodeURIComponent(id)}`;
6473
+ const requestContext = typeof window === "undefined" ? getCurrentServerRequestContext() : null;
6474
+ const currentRouteUrl = typeof window !== "undefined" ? window.location.href : requestContext?.req.header("x-eclipsa-route-url") ?? requestContext?.req.raw.url ?? null;
6475
+ const requestUrl = requestContext ? new URL(actionPath, requestContext.req.raw.url).href : actionPath;
6476
+ const response = await (requestContext && typeof requestContext.var.fetch === "function" ? requestContext.var.fetch : fetch)(requestUrl, {
5890
6477
  body: isFormSubmission ? input : JSON.stringify({ input: serializeActionClientValue(container, input) }),
5891
6478
  headers: {
5892
6479
  accept: `${ACTION_STREAM_CONTENT_TYPE}, ${ACTION_CONTENT_TYPE}`,
6480
+ ...currentRouteUrl ? { [ROUTE_RPC_URL_HEADER]: currentRouteUrl } : {},
5893
6481
  ...isFormSubmission ? {} : { "content-type": ACTION_CONTENT_TYPE }
5894
6482
  },
5895
6483
  method: "POST"
@@ -6207,6 +6795,6 @@ const __eclipsaAction = (id, middlewares, handler) => {
6207
6795
  }, id));
6208
6796
  };
6209
6797
  //#endregion
6210
- export { restoreSignalRefs as $, loader as $t, createWatch as A, serializePublicValue as An, getLazyMeta as At, primeRouteModules as B, isNoSerialize as Bn, registerActionHook as Bt, createDetachedClientInsertOwner as C, getClientHooks as Cn, __eclipsaEvent as Ct, createOnVisible as D, resetClientHooks as Dn, getActionHookMeta as Dt, createOnMount as E, registerClientHooks as En, getActionHandleMeta as Et, getStreamingResumeBootstrapScriptContent as F, escapeInlineScriptText as Fn, getRegisteredActionHookIds as Ft, rememberInsertMarkerRange as G, setLoaderHookMeta as Gt, refreshRegisteredRouteContainers as H, setActionHandleMeta as Ht, installResumeListeners as I, escapeJSONScriptText as In, getRegisteredLoaderHook as It, renderClientInsertable as J, __eclipsaLoader as Jt, rememberManagedAttributesForNode as K, setNavigateMeta as Kt, notFound as L, parseSerializedJSON as Ln, getRegisteredLoaderHookIds as Lt, getRuntimeComponentId as M, transformCurrentPublicError as Mn, getLoaderHookMeta as Mt, getRuntimeContainer as N, withServerRequestContext as Nn, getNavigateMeta as Nt, createResumeContainer as O, resolveReroute as On, getComponentMeta as Ot, getRuntimeSignalId as P, deserializeValue as Pn, getRegisteredActionHook as Pt, restoreResumedLocalSignalEffects as Q, isPendingSsrLoaderError as Qt, preserveReusableContentInRoots as R, serializeJSONScriptContent as Rn, getSignalMeta as Rt, collectPendingSuspenseBoundaryIds as S, deserializePublicValue as Sn, __eclipsaComponent as St, createOnCleanup as T, markPublicError as Tn, __eclipsaWatch as Tt, registerResumeContainer as U, setActionHookMeta as Ut, readAsyncSignalSnapshot as V, noSerialize as Vn, registerLoaderHook as Vt, registerRuntimeScopedStyle as W, setLoaderHandleMeta as Wt, renderString as X, executeLoader as Xt, renderClientInsertableForOwner as Y, consumePendingSsrLoaderIds as Yt, restoreRegisteredRpcHandles as Z, hasLoader as Zt, assignRuntimeRef as _, isPendingSignalError as _n, ROUTE_MANIFEST_ELEMENT_ID as _t, action as a, ROUTE_METADATA_HEAD_ATTR as an, tryPatchElementShellInPlace as at, bindRuntimeEvent as b, attachRequestFetch as bn, ROUTE_PREFLIGHT_REQUEST_HEADER as bt, getActionFormSubmissionId as c, resolveRouteMetadata as cn, useRuntimeNavigate as ct, primeActionState as d, getRuntimeContextReference as dn, useRuntimeSignal as dt, loader_exports as en, shouldReconnectDetachedInsertMarkers as et, registerAction as f, materializeRuntimeContext as fn, withRuntimeContainer as ft, applyResumeHmrUpdateToRegisteredContainers as g, createPendingSignalError as gn, ROUTE_LINK_ATTR as gt, RESUME_STATE_ELEMENT_ID as h, Suspense as hn, ROUTE_DATA_REQUEST_HEADER as ht, __eclipsaAction as i, resolvePendingLoaders as in, toResumePayloadSubset as it, getResumePayloadScriptContent as j, toPublicError as jn, getLoaderHandleMeta as jt, createStandaloneRuntimeSignal as k, runHandleError as kn, getEventMeta as kt, getNormalizedActionInput as l, createContext as ln, useRuntimeRouteError as lt, RESUME_FINAL_STATE_ELEMENT_ID as m, useContext as mn, ROUTE_DATA_ENDPOINT as mt, ACTION_FORM_ATTR as n, primeLoaderState as nn, syncRuntimeRefMarker as nt, executeAction as o, composeRouteMetadata as on, tryPatchNodeSequenceInPlace as ot, validator as p, materializeRuntimeContextProvider as pn, writeAsyncSignalSnapshot as pt, rememberManagedAttributesForNodes as q, setSignalMeta as qt, ACTION_FORM_FIELD as r, registerLoader as rn, toResumePayload as rt, executeActionSubmission as s, renderRouteMetadataHead as sn, useRuntimeLocation as st, ACTION_CONTENT_TYPE as t, markPendingSsrLoader as tn, syncManagedAttributeSnapshot as tt, hasAction as u, getContextProviderMeta as un, useRuntimeRouteParams as ut, beginAsyncSSRContainer as v, isSuspenseType as vn, ROUTE_PREFETCH_ATTR as vt, createEffect as w, getCurrentServerRequestContext as wn, __eclipsaLazy as wt, captureClientInsertOwner as x, createRequestFetch as xn, ROUTE_REPLACE_ATTR as xt, beginSSRContainer as y, APP_HOOKS_ELEMENT_ID as yn, ROUTE_PREFLIGHT_ENDPOINT as yt, primeLocationState as z, serializeValue as zn, getWatchMeta as zt };
6798
+ export { shouldReconnectDetachedInsertMarkers as $, IS_BROWSER as $n, consumePendingSsrLoaderIds as $t, getRuntimeComponentId as A, isPendingSignalError as An, getComponentMeta as At, refreshRegisteredRouteContainers as B, resetClientHooks as Bn, getRegisteredLoaderHookIds as Bt, createOnCleanup as C, getContextProviderMeta as Cn, RESUME_STATE_ELEMENT_ID as Ct, createStandaloneRuntimeSignal as D, useContext as Dn, __eclipsaWatch as Dt, createResumeContainer as E, materializeRuntimeContextProvider as En, __eclipsaLazy as Et, notFound as F, deserializePublicValue as Fn, getLoaderHookMeta as Ft, renderSSRAttr as G, transformCurrentPublicError as Gn, setActionHandleMeta as Gt, registerRuntimeScopedStyle as H, runHandleError as Hn, getWatchMeta as Ht, preserveReusableContentInRoots as I, getClientHooks as In, getNavigateMeta as It, renderString as J, escapeInlineScriptText as Jn, setLoaderHandleMeta as Jt, renderSSRMap as K, withServerRequestContext as Kn, setActionHookMeta as Kt, primeLocationState as L, getCurrentServerRequestContext as Ln, getRegisteredActionHook as Lt, getRuntimeSignalId as M, APP_HOOKS_ELEMENT_ID as Mn, getExternalComponentMeta as Mt, getStreamingResumeBootstrapScriptContent as N, attachRequestFetch as Nn, getLazyMeta as Nt, createWatch as O, Suspense as On, getActionHandleMeta as Ot, installResumeListeners as P, createRequestFetch as Pn, getLoaderHandleMeta as Pt, restoreSignalRefs as Q, serializeValue as Qn, __eclipsaLoader as Qt, primeRouteModules as R, markPublicError as Rn, getRegisteredActionHookIds as Rt, createEffect as S, createContext as Sn, RESUME_FINAL_STATE_ELEMENT_ID as St, createOnVisible as T, materializeRuntimeContext as Tn, __eclipsaEvent as Tt, renderClientInsertable as U, serializePublicValue as Un, registerActionHook as Ut, registerResumeContainer as V, resolveReroute as Vn, getSignalMeta as Vt, renderClientInsertableForOwner as W, toPublicError as Wn, registerLoaderHook as Wt, restoreResumedExternalComponents as X, parseSerializedJSON as Xn, setNavigateMeta as Xt, restoreRegisteredRpcHandles as Y, escapeJSONScriptText as Yn, setLoaderHookMeta as Yt, restoreResumedLocalSignalEffects as Z, serializeJSONScriptContent as Zn, setSignalMeta as Zt, beginSSRContainer as _, ROUTE_RPC_URL_HEADER as _n, getRememberedInsertMarkerNodeCount as _t, action as a, markPendingSsrLoader as an, useRuntimeLocation as at, collectPendingSuspenseBoundaryIds as b, renderRouteMetadataHead as bn, rememberManagedAttributesForNodes as bt, getActionFormSubmissionId as c, resolvePendingLoaders as cn, useRuntimeRouteParams as ct, primeActionState as d, ROUTE_LINK_ATTR as dn, writeAsyncSignalSnapshot as dt, executeLoader as en, IS_SSR as er, syncRuntimeRefMarker as et, registerAction as f, ROUTE_MANIFEST_ELEMENT_ID as fn, INSERT_MARKER_PREFIX as ft, beginAsyncSSRContainer as g, ROUTE_REPLACE_ATTR as gn, parseInsertMarker as gt, assignRuntimeRef as h, ROUTE_PREFLIGHT_REQUEST_HEADER as hn, parseComponentBoundaryMarker as ht, __eclipsaAction as i, loader_exports as in, tryPatchNodeSequenceInPlace as it, getRuntimeContainer as j, isSuspenseType as jn, getEventMeta as jt, getResumePayloadScriptContent as k, createPendingSignalError as kn, getActionHookMeta as kt, getNormalizedActionInput as l, ROUTE_DATA_ENDPOINT as ln, useRuntimeSignal as lt, applyResumeHmrUpdateToRegisteredContainers as m, ROUTE_PREFLIGHT_ENDPOINT as mn, createInsertMarker as mt, ACTION_FORM_ATTR as n, isPendingSsrLoaderError as nn, noSerialize as nr, toResumePayloadSubset as nt, executeAction as o, primeLoaderState as on, useRuntimeNavigate as ot, validator as p, ROUTE_PREFETCH_ATTR as pn, createComponentBoundaryHtmlComment as pt, renderSSRValue as q, deserializeValue as qn, setExternalComponentMeta as qt, ACTION_FORM_FIELD as r, loader as rn, tryPatchElementShellInPlace as rt, executeActionSubmission as s, registerLoader as sn, useRuntimeRouteError as st, ACTION_CONTENT_TYPE as t, hasLoader as tn, isNoSerialize as tr, toResumePayload as tt, hasAction as u, ROUTE_DATA_REQUEST_HEADER as un, withRuntimeContainer as ut, bindRuntimeEvent as v, ROUTE_METADATA_HEAD_ATTR as vn, rememberInsertMarkerRange as vt, createOnMount as w, getRuntimeContextReference as wn, __eclipsaComponent as wt, createDetachedClientInsertOwner as x, resolveRouteMetadata as xn, syncManagedAttributeSnapshot as xt, captureClientInsertOwner as y, composeRouteMetadata as yn, rememberManagedAttributesForNode as yt, readAsyncSignalSnapshot as z, registerClientHooks as zn, getRegisteredLoaderHook as zt };
6211
6799
 
6212
- //# sourceMappingURL=action-CgM3EJUS.mjs.map
6800
+ //# sourceMappingURL=action-DqgkV3zb.mjs.map