eclipsa 0.1.3 → 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.
- package/{action-CgM3EJUS.mjs → action-DqgkV3zb.mjs} +1584 -996
- package/action-DqgkV3zb.mjs.map +1 -0
- package/{client-COjBNTyt.mjs → client-DKPmN-wJ.mjs} +126 -40
- package/client-DKPmN-wJ.mjs.map +1 -0
- package/{component-D_nEtZ69.d.mts → component-yvTtnI00.d.mts} +2 -2
- package/core/client/mod.d.mts +2 -2
- package/core/client/mod.mjs +3 -3
- package/core/dev-client/mod.d.mts +1 -1
- package/core/dev-client/mod.mjs +10 -5
- package/core/dev-client/mod.mjs.map +1 -1
- package/core/internal.d.mts +2 -2
- package/core/internal.mjs +2 -2
- package/core/prod-client/mod.d.mts +3 -3
- package/core/prod-client/mod.mjs +4 -4
- package/{internal-Csbm0Qnv.d.mts → internal-CHYAJznU.d.mts} +116 -72
- package/jsx/jsx-dev-runtime.d.mts +8 -2
- package/jsx/jsx-dev-runtime.mjs +2 -2
- package/jsx/jsx-runtime.d.mts +1 -1
- package/jsx/mod.d.mts +1 -1
- package/jsx/mod.mjs +1 -1
- package/{jsx-dev-runtime-CY60yQJY.mjs → jsx-dev-runtime-DpbWQ4Q0.mjs} +8 -3
- package/jsx-dev-runtime-DpbWQ4Q0.mjs.map +1 -0
- package/{mod-DLb8ple9.d.mts → mod-aLmFvMYF.d.mts} +4 -4
- package/mod.d.mts +20 -38
- package/mod.mjs +19 -145
- package/mod.mjs.map +1 -1
- package/package.json +6 -2
- package/{signal-B7AfIKrr.d.mts → signal-CosyYdtA.d.mts} +1 -1
- package/{signal-CJtquEfo.mjs → signal-DBzloBrN.mjs} +2 -2
- package/{signal-CJtquEfo.mjs.map → signal-DBzloBrN.mjs.map} +1 -1
- package/ssr-CRg57Wn2.mjs +157 -0
- package/ssr-CRg57Wn2.mjs.map +1 -0
- package/ssr-D8F-DtCv.d.mts +37 -0
- package/{types-BCEY9lGp.d.mts → types-Cu9gFlEY.d.mts} +6 -2
- package/{types-DKpefD_u.d.mts → types-DDeNM8UH.d.mts} +1 -1
- package/vite/build/runtime.d.mts +4 -0
- package/vite/build/runtime.mjs +4 -0
- package/vite/mod.mjs +257 -38
- package/vite/mod.mjs.map +1 -1
- package/web-utils/mod.d.mts +1 -1
- package/web-utils/mod.mjs +2 -2
- package/action-CgM3EJUS.mjs.map +0 -1
- package/client-COjBNTyt.mjs.map +0 -1
- package/jsx-dev-runtime-CY60yQJY.mjs.map +0 -1
- /package/{jsx-runtime-BFDPoxFn.d.mts → jsx-runtime-QIK6ADiK.d.mts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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 (
|
|
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
|
|
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: {
|
|
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/
|
|
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
|
|
1057
|
-
const
|
|
1058
|
-
const
|
|
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
|
|
1191
|
-
|
|
1192
|
-
|
|
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
|
|
1196
|
-
const
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
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
|
|
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
|
|
1249
|
-
const writeAsyncSignalSnapshot = (id, value, container
|
|
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
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
|
|
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
|
|
1451
|
+
const pathSegments = splitRoutePath(pathname);
|
|
1381
1452
|
let score = 0;
|
|
1382
|
-
for (let index = 0; index < entry.segments.length && index <
|
|
1453
|
+
for (let index = 0; index < entry.segments.length && index < pathSegments.length; index += 1) {
|
|
1383
1454
|
const segment = entry.segments[index];
|
|
1384
|
-
const pathnameSegment =
|
|
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
|
|
1415
|
-
const
|
|
1416
|
-
|
|
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
|
|
1429
|
-
const
|
|
1430
|
-
|
|
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
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
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
|
|
1457
|
-
|
|
1458
|
-
|
|
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
|
|
1461
|
-
|
|
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
|
|
1464
|
-
|
|
1465
|
-
|
|
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
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
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
|
|
1477
|
-
const
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
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
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
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
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
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" ? """ : null;
|
|
1578
|
+
break;
|
|
1579
|
+
case 38:
|
|
1580
|
+
escaped = "&";
|
|
1581
|
+
break;
|
|
1582
|
+
case 39:
|
|
1583
|
+
escaped = mode === "attr" ? "'" : null;
|
|
1584
|
+
break;
|
|
1585
|
+
case 60:
|
|
1586
|
+
escaped = "<";
|
|
1587
|
+
break;
|
|
1588
|
+
case 62:
|
|
1589
|
+
escaped = ">";
|
|
1590
|
+
break;
|
|
1591
|
+
}
|
|
1592
|
+
if (!escaped) continue;
|
|
1593
|
+
output += value.slice(lastIndex, index);
|
|
1594
|
+
output += escaped;
|
|
1595
|
+
lastIndex = index + 1;
|
|
1502
1596
|
}
|
|
1503
|
-
|
|
1504
|
-
trackWatchDependencies(dependencies);
|
|
1505
|
-
});
|
|
1506
|
-
withCleanupSlot(cleanupSlot, fn);
|
|
1597
|
+
return output + value.slice(lastIndex);
|
|
1507
1598
|
};
|
|
1508
|
-
const
|
|
1509
|
-
|
|
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
|
|
1512
|
-
|
|
1513
|
-
const
|
|
1514
|
-
|
|
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
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
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
|
|
1535
|
-
const
|
|
1536
|
-
const
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
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
|
-
|
|
1564
|
-
|
|
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
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
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
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
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
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
props,
|
|
1658
|
-
type: createMaterializedRenderComponentType(container, typeValue, scopeValue)
|
|
2041
|
+
deserializeRuntimeValue,
|
|
2042
|
+
preloadResumableValue,
|
|
2043
|
+
serializeRuntimeValue
|
|
1659
2044
|
};
|
|
1660
2045
|
};
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
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
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
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
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
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
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
const
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
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
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
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
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
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
|
-
|
|
2180
|
+
} finally {
|
|
2181
|
+
currentCleanupSlot = previous;
|
|
1821
2182
|
}
|
|
1822
|
-
if (
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
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
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
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
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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 ===
|
|
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 ===
|
|
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
|
|
2612
|
-
if (
|
|
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)
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
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 (
|
|
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
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
const
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
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
|
-
|
|
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 ===
|
|
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 =
|
|
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
|
-
|
|
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))
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 (
|
|
3005
|
-
if (
|
|
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 ===
|
|
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 ===
|
|
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
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
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
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
return
|
|
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" ? """ : null;
|
|
3222
|
-
break;
|
|
3223
|
-
case 38:
|
|
3224
|
-
escaped = "&";
|
|
3225
|
-
break;
|
|
3226
|
-
case 39:
|
|
3227
|
-
escaped = mode === "attr" ? "'" : null;
|
|
3228
|
-
break;
|
|
3229
|
-
case 60:
|
|
3230
|
-
escaped = "<";
|
|
3231
|
-
break;
|
|
3232
|
-
case 62:
|
|
3233
|
-
escaped = ">";
|
|
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
|
-
|
|
3318
|
-
|
|
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 =
|
|
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 ===
|
|
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 ===
|
|
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
|
|
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
|
|
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
|
|
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
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
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 ===
|
|
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 ===
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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 ===
|
|
3676
|
-
const
|
|
3677
|
-
if (!
|
|
3678
|
-
const
|
|
3679
|
-
|
|
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(
|
|
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,
|
|
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 ===
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
4046
|
-
if (!matched
|
|
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 !==
|
|
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(
|
|
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
|
|
4306
|
-
|
|
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:
|
|
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
|
|
4381
|
-
if (matched
|
|
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
|
|
4390
|
-
if (
|
|
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
|
-
|
|
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
|
|
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 &&
|
|
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
|
-
|
|
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 (
|
|
5031
|
+
if (!!routeTarget?.matched.entry.hasMiddleware && !prefetched) {
|
|
4479
5032
|
const preflight = await requestRoutePreflight(url.href);
|
|
4480
5033
|
if (!preflight.ok) {
|
|
4481
|
-
|
|
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
|
-
|
|
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))
|
|
4552
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
4630
|
-
|
|
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 ===
|
|
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 !==
|
|
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 ===
|
|
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
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
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)
|
|
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 !==
|
|
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 ===
|
|
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 !==
|
|
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 ===
|
|
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 ===
|
|
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 ===
|
|
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
|
|
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 {
|
|
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-
|
|
6800
|
+
//# sourceMappingURL=action-DqgkV3zb.mjs.map
|