@askrjs/askr 0.2.3 → 0.3.0
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/CHANGELOG.md +11 -0
- package/dist/access-CEA2pOry.js +1046 -0
- package/dist/actions/index.d.ts +16 -2
- package/dist/actions/index.js +5 -5
- package/dist/{activity-ZxJXI9hF.js → activity-oy2YFTFF.js} +22 -16
- package/dist/benchmark.js +8 -9
- package/dist/boot/index.d.ts +21 -9
- package/dist/boot/index.js +1 -1
- package/dist/{boot-D4GaLA0d.js → boot-BMBMWUGI.js} +680 -440
- package/dist/capabilities-Bbf0mlp9.js +42 -0
- package/dist/components/index.d.ts +11 -8
- package/dist/components/index.js +1 -1
- package/dist/{compose-ref-Bfaf4kUC.js → compose-ref-v0qGlHoN.js} +7 -1
- package/dist/control/index.d.ts +20 -2
- package/dist/control/index.js +1 -1
- package/dist/{control-57x3wa4J.js → control-BR_mrX__.js} +4 -4
- package/dist/core.d.ts +163 -0
- package/dist/csp-nonce-BfFWcd0w.js +173 -0
- package/dist/data/index.d.ts +74 -2
- package/dist/data/index.js +3 -3
- package/dist/{data-B7XCDeC8.js → data-2edW0jhF.js} +133 -138
- package/dist/{data-runtime-7t_Y0iv3.js → data-runtime-CxoY98lX.js} +22 -15
- package/dist/{deferred-BELyvMsC.js → deferred-CbgNhf67.js} +5 -5
- package/dist/dom-renderer.d.ts +77 -0
- package/dist/domains/actions.d.ts +70 -0
- package/dist/domains/component.d.ts +119 -0
- package/dist/domains/context.d.ts +73 -0
- package/dist/domains/control.d.ts +328 -0
- package/dist/domains/data.d.ts +461 -0
- package/dist/domains/diagnostics.d.ts +21 -0
- package/dist/domains/lifecycle.d.ts +112 -0
- package/dist/domains/refs.d.ts +18 -0
- package/dist/domains/renderer.d.ts +127 -0
- package/dist/domains/routing.d.ts +501 -0
- package/dist/domains/scheduler.d.ts +79 -0
- package/dist/domains/server.d.ts +112 -0
- package/dist/domains/state.d.ts +129 -0
- package/dist/domains/telemetry.d.ts +29 -0
- package/dist/eager-control.d.ts +8 -0
- package/dist/{effect-4LwBwV58.js → effect-C3Zsc1k6.js} +14 -41
- package/dist/{types-DkVJhVs9.d.ts → elements.d.ts} +84 -42
- package/dist/{for-internal-DeoSg_AV.js → for-state-BDykeOJL.js} +623 -511
- package/dist/foundations/icon/index.d.ts +67 -16
- package/dist/foundations/icon/index.js +1 -1
- package/dist/foundations/index.d.ts +26 -3
- package/dist/foundations/index.js +1 -1
- package/dist/foundations/interactions/index.d.ts +73 -34
- package/dist/foundations/interactions/index.js +1 -1
- package/dist/foundations/state/index.d.ts +12 -5
- package/dist/foundations/state/index.js +1 -1
- package/dist/foundations/structures/index.d.ts +44 -3
- package/dist/foundations/structures/index.js +1 -1
- package/dist/foundations/utilities/index.d.ts +34 -3
- package/dist/foundations/utilities/index.js +1 -1
- package/dist/fx/index.d.ts +72 -25
- package/dist/fx/index.js +8 -8
- package/dist/index.d.ts +121 -4
- package/dist/index.js +316 -47
- package/dist/{component-internal-Dl02WQKS.js → instance-VAFYVJOa.js} +495 -283
- package/dist/{interactions-D102JxBR.js → interactions-CTeACdT_.js} +1 -1
- package/dist/jsx-dev-runtime.d.ts +51 -11
- package/dist/jsx-globals.d.ts +2 -0
- package/dist/jsx-runtime-CPJXAOBF.js +43 -0
- package/dist/jsx-runtime.d.ts +17 -3
- package/dist/jsx-runtime.js +2 -42
- package/dist/jsx.d.ts +108 -0
- package/dist/{manifest-D6rfj_jC.js → manifest-D1P3UNWV.js} +4 -9
- package/dist/{navigate-C46GtScG.js → navigate-prC5V8XV.js} +204 -476
- package/dist/{navigate-wel1e6cU.d.ts → navigation.d.ts} +10 -8
- package/dist/{readable-CEcteIDE.js → notify-DxxuDPeY.js} +96 -34
- package/dist/{query-registry-Bua3cDyb.js → query-registry-LrYpQsDJ.js} +1 -1
- package/dist/{compose-ref-DOJHoW5X.d.ts → refs.d.ts} +11 -7
- package/dist/{ssr-BaC5qHEw.js → render-resolved-BC0W7_5b.js} +165 -558
- package/dist/{renderer-BhXofszH.js → renderer-CT0HeY58.js} +6866 -5715
- package/dist/{resolution-t8J0yNaU.js → resolution-3DskUkjG.js} +189 -180
- package/dist/{resource-operation-B8q-QRUx.js → resource-18-sFRl9.js} +98 -58
- package/dist/resources/index.d.ts +64 -46
- package/dist/resources/index.js +215 -9
- package/dist/route-activity.d.ts +21 -0
- package/dist/{route-matching-Bo6UqG-5.js → route-matching-CUzZ31gT.js} +68 -82
- package/dist/router/index.d.ts +378 -79
- package/dist/router/index.js +9 -9
- package/dist/router-internal-7nuNEHfG.js +36 -0
- package/dist/scope-Cq_iYbTR.js +403 -0
- package/dist/{selector-C7rIpOnN.js → selector-BSPVkjKP.js} +41 -41
- package/dist/{shared-CGrx2AOL.js → shared-kU8yvryp.js} +3 -6
- package/dist/{snapshot-source-BB42xgwb.js → snapshot-source-An4iKajG.js} +1 -1
- package/dist/ssg/index.d.ts +51 -15
- package/dist/ssg/index.js +269 -209
- package/dist/ssr/index.d.ts +121 -68
- package/dist/ssr/index.js +2 -1
- package/dist/ssr-CiNm6Vzl.js +393 -0
- package/dist/{ssr-DSHd_Q9K.js → ssr-EPjwJH5R.js} +5 -1
- package/dist/{state-BzhOW2TX.js → state-BXJfudq1.js} +10 -15
- package/dist/{structures-BwfeO4Iz.js → structures-CjEzfj4h.js} +37 -57
- package/dist/{index-r5THqzPN.d.ts → structures.d.ts} +57 -36
- package/dist/testing/index.d.ts +125 -24
- package/dist/testing/index.js +26 -62
- package/dist/timer-C7uqnJVt.js +85 -0
- package/dist/{index-B1gu0_m0.d.ts → utilities.d.ts} +24 -13
- package/dist/{verify-hydration-_Q6avFp0.js → verify-hydration-ikaxotf7.js} +8 -5
- package/package.json +13 -15
- package/dist/access-Rr7CMa06.js +0 -507
- package/dist/activity-CAJ5eho-.d.ts +0 -14
- package/dist/benchmark.d.ts +0 -26
- package/dist/cleanup-DsrbV-rr.js +0 -535
- package/dist/component-cleanup-DjpwO9WX.js +0 -143
- package/dist/component-scope-4I3yEMkb.js +0 -195
- package/dist/control-DdFw-Caz.d.ts +0 -8
- package/dist/csp-nonce-C9OuML0U.js +0 -72
- package/dist/css-BuPaTOfe.js +0 -70
- package/dist/fastlane-Buz1Rvlr.js +0 -166
- package/dist/index-DSqXWc77.d.ts +0 -1402
- package/dist/jsx-runtime-BTzDdBJ_.d.ts +0 -2
- package/dist/jsx-runtime-Cdd6Gkb0.d.ts +0 -38
- package/dist/lifecycle-batch-Be-CLDjV.js +0 -253
- package/dist/lifecycle-operations-C5m03NQc.js +0 -195
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { r as
|
|
4
|
-
import {
|
|
5
|
-
import { n as
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { T as isProductionEnvironment, r as flushRuntimeScheduler, u as isRuntimeSchedulerExecuting, v as logger, w as isDevelopmentEnvironment } from "./access-CEA2pOry.js";
|
|
2
|
+
import { P as isPromiseLike } from "./instance-VAFYVJOa.js";
|
|
3
|
+
import { i as commitTransaction, l as registerCommitParticipant, o as discardTransaction, r as beginCommitTransaction } from "./notify-DxxuDPeY.js";
|
|
4
|
+
import { i as syncCurrentRouteSnapshot } from "./activity-oy2YFTFF.js";
|
|
5
|
+
import { a as resolveRouteRequest, i as hasRouteRenderData, n as getRouteRenderContext, r as getRouteRenderData } from "./resolution-3DskUkjG.js";
|
|
6
|
+
import { L as lockRouteRegistration, b as getActiveRouteBasePath, o as addRouteBasePath, r as computeRouteActivityMatches } from "./route-matching-CUzZ31gT.js";
|
|
7
|
+
//#region src/common/root-update.ts
|
|
8
|
+
let rootUpdateHost;
|
|
9
|
+
function configureRootUpdateHost(host) {
|
|
10
|
+
rootUpdateHost = host;
|
|
11
|
+
}
|
|
12
|
+
function prepareRootUpdate(root, input) {
|
|
13
|
+
if (!rootUpdateHost) throw new Error("[Askr] Root update host is not configured.");
|
|
14
|
+
return rootUpdateHost.prepare(root, input);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
13
17
|
//#region src/router/navigation-registry.ts
|
|
14
18
|
let currentInstance = null;
|
|
15
19
|
let currentPathname = "/";
|
|
@@ -112,6 +116,58 @@ const DEFAULT_SCROLL_RESTORATION = {
|
|
|
112
116
|
};
|
|
113
117
|
let scrollRestorationOptions = { ...DEFAULT_SCROLL_RESTORATION };
|
|
114
118
|
const scrollPositions = /* @__PURE__ */ new Map();
|
|
119
|
+
let capturedActivationFocus;
|
|
120
|
+
let pendingNavigationFocus;
|
|
121
|
+
let focusAtHistoryNavigationStart = null;
|
|
122
|
+
function readFocusDescriptor() {
|
|
123
|
+
if (typeof document === "undefined" || !(document.activeElement instanceof HTMLElement)) return;
|
|
124
|
+
const active = document.activeElement;
|
|
125
|
+
for (const attribute of [
|
|
126
|
+
"data-askr-focus-key",
|
|
127
|
+
"id",
|
|
128
|
+
"name",
|
|
129
|
+
"aria-label"
|
|
130
|
+
]) {
|
|
131
|
+
const value = active.getAttribute(attribute);
|
|
132
|
+
if (value) return {
|
|
133
|
+
attribute,
|
|
134
|
+
value
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if ("labels" in active) {
|
|
138
|
+
const label = Array.from(active.labels ?? []).map((element) => element.textContent?.trim()).find(Boolean);
|
|
139
|
+
if (label) return {
|
|
140
|
+
attribute: "label",
|
|
141
|
+
value: label
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function clearCapturedNavigationFocus() {
|
|
146
|
+
capturedActivationFocus = void 0;
|
|
147
|
+
}
|
|
148
|
+
function isPrimaryPointerActivation(event) {
|
|
149
|
+
if (event instanceof MouseEvent && (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) return false;
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
/** Stage entry-owned focus for the duration of one primary pointer activation. */
|
|
153
|
+
function captureNavigationFocus(event) {
|
|
154
|
+
clearCapturedNavigationFocus();
|
|
155
|
+
if (!isPrimaryPointerActivation(event)) return;
|
|
156
|
+
capturedActivationFocus = readFocusDescriptor();
|
|
157
|
+
}
|
|
158
|
+
/** Release pointer activation state after its click has finished dispatching. */
|
|
159
|
+
function releaseNavigationFocusCapture() {
|
|
160
|
+
clearCapturedNavigationFocus();
|
|
161
|
+
}
|
|
162
|
+
/** Preserve the active control before route content can be replaced. */
|
|
163
|
+
function prepareNavigationFocus() {
|
|
164
|
+
pendingNavigationFocus = capturedActivationFocus ?? readFocusDescriptor();
|
|
165
|
+
clearCapturedNavigationFocus();
|
|
166
|
+
}
|
|
167
|
+
/** Mark the active element so restoration can avoid overwriting focus moved during route commit. */
|
|
168
|
+
function beginHistoryFocusRestoration() {
|
|
169
|
+
focusAtHistoryNavigationStart = typeof document === "undefined" ? null : document.activeElement;
|
|
170
|
+
}
|
|
115
171
|
function getWindowHref() {
|
|
116
172
|
if (typeof window === "undefined") return "/";
|
|
117
173
|
return `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
@@ -146,8 +202,10 @@ function writeHistoryScrollPosition(href, position) {
|
|
|
146
202
|
window.history.replaceState({
|
|
147
203
|
...state,
|
|
148
204
|
path: href,
|
|
149
|
-
scroll: position
|
|
205
|
+
scroll: position,
|
|
206
|
+
focus: pendingNavigationFocus ?? readFocusDescriptor()
|
|
150
207
|
}, "", href);
|
|
208
|
+
pendingNavigationFocus = void 0;
|
|
151
209
|
}
|
|
152
210
|
function saveScrollPosition(href) {
|
|
153
211
|
if (!scrollRestorationOptions.enabled || typeof window === "undefined") return;
|
|
@@ -194,6 +252,12 @@ function applyHistoryScroll(href, state) {
|
|
|
194
252
|
x: 0,
|
|
195
253
|
y: 0
|
|
196
254
|
});
|
|
255
|
+
const focus = state && typeof state === "object" && state.focus && typeof state.focus === "object" ? state.focus : void 0;
|
|
256
|
+
if (focus && (focus.attribute === "data-askr-focus-key" || focus.attribute === "id" || focus.attribute === "name" || focus.attribute === "aria-label" || focus.attribute === "label") && typeof focus.value === "string" && typeof document !== "undefined" && (document.activeElement === document.body || document.activeElement === document.documentElement || document.activeElement === focusAtHistoryNavigationStart)) {
|
|
257
|
+
const target = focus.attribute === "label" ? Array.from(document.querySelectorAll("input,select,textarea,button")).find((element) => "labels" in element && Array.from(element.labels ?? []).some((label) => label.textContent?.trim() === focus.value)) : Array.from(document.querySelectorAll(`[${focus.attribute}]`)).find((element) => element.getAttribute(focus.attribute) === focus.value);
|
|
258
|
+
if (target?.isConnected && !target.hasAttribute("disabled") && target.getAttribute("aria-hidden") !== "true" && target.getClientRects().length > 0) target.focus({ preventScroll: true });
|
|
259
|
+
}
|
|
260
|
+
focusAtHistoryNavigationStart = null;
|
|
197
261
|
}
|
|
198
262
|
function configureScrollRestoration(options) {
|
|
199
263
|
scrollRestorationOptions = normalizeScrollRestorationOptions(options);
|
|
@@ -362,6 +426,11 @@ function beginRouteRequest() {
|
|
|
362
426
|
function isStaleRouteRequest(requestId) {
|
|
363
427
|
return requestId !== activeRouteRequestId;
|
|
364
428
|
}
|
|
429
|
+
/**
|
|
430
|
+
* @internal Teardown-only cancellation. Prefer aborting through the signal
|
|
431
|
+
* returned by `beginRouteRequest()`; this exists for registry teardown, where
|
|
432
|
+
* no request owns the abort.
|
|
433
|
+
*/
|
|
365
434
|
function cancelRouteRequests() {
|
|
366
435
|
activeRouteRequestId += 1;
|
|
367
436
|
activeRouteRequestController?.abort();
|
|
@@ -419,29 +488,6 @@ function createDeniedResolvedRoute(status) {
|
|
|
419
488
|
function bindResolvedRouteHandler(resolved) {
|
|
420
489
|
return () => resolved.handler(resolved.params);
|
|
421
490
|
}
|
|
422
|
-
function wrapRootRouteHandler(componentFn, cspNonce) {
|
|
423
|
-
const wrappedFn = (props, ctx) => {
|
|
424
|
-
const out = componentFn(props, ctx);
|
|
425
|
-
if (isPromiseLike(out)) throw new Error("Async components are not supported. Components must return synchronously.");
|
|
426
|
-
const portalVNode = {
|
|
427
|
-
$$typeof: ELEMENT_TYPE,
|
|
428
|
-
type: getDefaultPortalHost(),
|
|
429
|
-
props: { __askrAutoDefaultPortal: true },
|
|
430
|
-
key: "__default_portal"
|
|
431
|
-
};
|
|
432
|
-
const root = {
|
|
433
|
-
$$typeof: ELEMENT_TYPE,
|
|
434
|
-
type: Fragment,
|
|
435
|
-
props: { children: out === void 0 || out === null ? [portalVNode] : [out, portalVNode] }
|
|
436
|
-
};
|
|
437
|
-
return cspNonce === void 0 ? root : CspNonceScope({
|
|
438
|
-
value: cspNonce,
|
|
439
|
-
children: root
|
|
440
|
-
});
|
|
441
|
-
};
|
|
442
|
-
Object.defineProperty(wrappedFn, "name", { value: componentFn.name || "Component" });
|
|
443
|
-
return wrappedFn;
|
|
444
|
-
}
|
|
445
491
|
function flattenLifecycleErrors(error, result) {
|
|
446
492
|
if (error instanceof AggregateError) {
|
|
447
493
|
for (const nested of error.errors) flattenLifecycleErrors(nested, result);
|
|
@@ -456,255 +502,6 @@ function reportRouteCleanupErrors(errors) {
|
|
|
456
502
|
for (const cleanupError of flattened.length > 0 ? flattened : [error]) logger.error("[Askr] route cleanup failed:", cleanupError);
|
|
457
503
|
}
|
|
458
504
|
}
|
|
459
|
-
function captureRouteDom(root) {
|
|
460
|
-
if (!root) return null;
|
|
461
|
-
const nodes = [];
|
|
462
|
-
const visit = (node) => {
|
|
463
|
-
nodes.push({
|
|
464
|
-
node,
|
|
465
|
-
children: Array.from(node.childNodes),
|
|
466
|
-
attributes: node instanceof Element ? Array.from(node.attributes).map((attribute) => [attribute.name, attribute.value]) : null,
|
|
467
|
-
nodeValue: node.nodeValue
|
|
468
|
-
});
|
|
469
|
-
for (const child of Array.from(node.childNodes)) visit(child);
|
|
470
|
-
};
|
|
471
|
-
visit(root);
|
|
472
|
-
return {
|
|
473
|
-
root,
|
|
474
|
-
nodes
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
function collectProvisionalRouteNodes(snapshot) {
|
|
478
|
-
const originalNodes = new Set(snapshot.nodes.map((entry) => entry.node));
|
|
479
|
-
const provisional = [];
|
|
480
|
-
const visit = (node) => {
|
|
481
|
-
if (!originalNodes.has(node)) {
|
|
482
|
-
provisional.push(node);
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
for (const child of Array.from(node.childNodes)) visit(child);
|
|
486
|
-
};
|
|
487
|
-
for (const child of Array.from(snapshot.root.childNodes)) visit(child);
|
|
488
|
-
return provisional;
|
|
489
|
-
}
|
|
490
|
-
function restoreRouteDom(snapshot) {
|
|
491
|
-
if (!snapshot) return [];
|
|
492
|
-
const errors = [];
|
|
493
|
-
for (const node of collectProvisionalRouteNodes(snapshot)) try {
|
|
494
|
-
teardownNodeSubtree(node, { strict: true });
|
|
495
|
-
} catch (error) {
|
|
496
|
-
errors.push(error);
|
|
497
|
-
}
|
|
498
|
-
for (const entry of snapshot.nodes) {
|
|
499
|
-
const { node, attributes } = entry;
|
|
500
|
-
try {
|
|
501
|
-
if (attributes && node instanceof Element) {
|
|
502
|
-
const expected = new Map(attributes);
|
|
503
|
-
for (const attribute of Array.from(node.attributes)) if (!expected.has(attribute.name)) node.removeAttribute(attribute.name);
|
|
504
|
-
for (const [name, value] of attributes) if (node.getAttribute(name) !== value) node.setAttribute(name, value);
|
|
505
|
-
} else if (!(node instanceof Element)) node.nodeValue = entry.nodeValue;
|
|
506
|
-
if (node instanceof Element || node instanceof DocumentFragment) node.replaceChildren(...entry.children);
|
|
507
|
-
} catch (error) {
|
|
508
|
-
errors.push(error);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
return errors;
|
|
512
|
-
}
|
|
513
|
-
function collectHostInstances(root) {
|
|
514
|
-
const instances = [];
|
|
515
|
-
const seen = /* @__PURE__ */ new Set();
|
|
516
|
-
const pending = [root];
|
|
517
|
-
while (pending.length > 0) {
|
|
518
|
-
const node = pending.pop();
|
|
519
|
-
const host = node;
|
|
520
|
-
for (const instance of host.__ASKR_INSTANCES ?? []) if (!seen.has(instance)) {
|
|
521
|
-
seen.add(instance);
|
|
522
|
-
instances.push(instance);
|
|
523
|
-
}
|
|
524
|
-
if (host.__ASKR_INSTANCE && !seen.has(host.__ASKR_INSTANCE)) {
|
|
525
|
-
seen.add(host.__ASKR_INSTANCE);
|
|
526
|
-
instances.push(host.__ASKR_INSTANCE);
|
|
527
|
-
}
|
|
528
|
-
for (let child = node.lastChild; child; child = child.previousSibling) pending.push(child);
|
|
529
|
-
}
|
|
530
|
-
return instances;
|
|
531
|
-
}
|
|
532
|
-
function captureDeferredRouteCleanup(instance) {
|
|
533
|
-
return {
|
|
534
|
-
instance,
|
|
535
|
-
previousOwnershipGeneration: instance._ownershipGeneration,
|
|
536
|
-
previousFn: instance.fn,
|
|
537
|
-
previousProps: instance.props,
|
|
538
|
-
previousExpectedStateIndices: instance.expectedStateIndices,
|
|
539
|
-
previousFirstRenderComplete: instance.firstRenderComplete,
|
|
540
|
-
previousStateIndexCheck: instance.stateIndexCheck,
|
|
541
|
-
previousErrorBoundaryState: instance.errorBoundaryState,
|
|
542
|
-
previousTarget: instance.target,
|
|
543
|
-
previousDom: captureRouteDom(instance.target),
|
|
544
|
-
previousStateValues: instance.stateValues,
|
|
545
|
-
previousCleanupFns: instance.cleanupFns,
|
|
546
|
-
previousOwnedChildScopes: instance._ownedChildScopes,
|
|
547
|
-
previousAbortController: instance.abortController,
|
|
548
|
-
previousMountOperations: instance.mountOperations,
|
|
549
|
-
previousCommitOperations: instance.commitOperations,
|
|
550
|
-
previousLifecycleSlots: instance.lifecycleSlots,
|
|
551
|
-
previousLifecycleGeneration: instance.lifecycleGeneration,
|
|
552
|
-
previousEvaluationGeneration: instance.evaluationGeneration,
|
|
553
|
-
previousHasPendingUpdate: instance.hasPendingUpdate,
|
|
554
|
-
previousNotifyUpdate: instance.notifyUpdate,
|
|
555
|
-
previousPlaceholder: instance._placeholder,
|
|
556
|
-
previousMounted: instance.mounted,
|
|
557
|
-
previousCurrentRenderToken: instance._currentRenderToken,
|
|
558
|
-
previousLastRenderToken: instance.lastRenderToken,
|
|
559
|
-
previousPendingReadSources: instance._pendingReadSources,
|
|
560
|
-
previousPendingReadSourceVersions: instance._pendingReadSourceVersions,
|
|
561
|
-
previousLastReadSources: instance._lastReadSources,
|
|
562
|
-
previousReaderEntries: Array.from(instance._lastReadSources ?? []).map((source) => ({
|
|
563
|
-
source,
|
|
564
|
-
reader: source._readers?.get(instance)
|
|
565
|
-
})),
|
|
566
|
-
previousAppRenderRuntime: instance._appRenderRuntime,
|
|
567
|
-
previousInstances: instance.target ? collectHostInstances(instance.target) : [],
|
|
568
|
-
previousDisposed: false
|
|
569
|
-
};
|
|
570
|
-
}
|
|
571
|
-
function restoreDeferredRouteInstance(deferred) {
|
|
572
|
-
const instance = deferred.instance;
|
|
573
|
-
const errors = [];
|
|
574
|
-
const activeGeneration = instance._ownershipGeneration;
|
|
575
|
-
const activeReadSources = instance._lastReadSources;
|
|
576
|
-
if (activeGeneration !== deferred.previousOwnershipGeneration) {
|
|
577
|
-
try {
|
|
578
|
-
cleanupReadableSubscriptionSources(instance, activeReadSources, activeGeneration);
|
|
579
|
-
} catch (error) {
|
|
580
|
-
errors.push(error);
|
|
581
|
-
}
|
|
582
|
-
instance._lastReadSources = void 0;
|
|
583
|
-
try {
|
|
584
|
-
cleanupComponent(instance);
|
|
585
|
-
} catch (error) {
|
|
586
|
-
errors.push(error);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
errors.push(...restoreRouteDom(deferred.previousDom));
|
|
590
|
-
instance.fn = deferred.previousFn;
|
|
591
|
-
instance._ownershipGeneration = deferred.previousOwnershipGeneration;
|
|
592
|
-
instance.props = deferred.previousProps;
|
|
593
|
-
instance.expectedStateIndices = deferred.previousExpectedStateIndices;
|
|
594
|
-
instance.firstRenderComplete = deferred.previousFirstRenderComplete;
|
|
595
|
-
instance.stateIndexCheck = deferred.previousStateIndexCheck;
|
|
596
|
-
instance.errorBoundaryState = deferred.previousErrorBoundaryState;
|
|
597
|
-
instance.target = deferred.previousTarget;
|
|
598
|
-
instance.stateValues = deferred.previousStateValues;
|
|
599
|
-
instance.cleanupFns = deferred.previousCleanupFns;
|
|
600
|
-
instance._ownedChildScopes = deferred.previousOwnedChildScopes;
|
|
601
|
-
instance.abortController = deferred.previousAbortController;
|
|
602
|
-
instance.mountOperations = deferred.previousMountOperations;
|
|
603
|
-
instance.commitOperations = deferred.previousCommitOperations;
|
|
604
|
-
instance.lifecycleSlots = deferred.previousLifecycleSlots;
|
|
605
|
-
instance.lifecycleGeneration = deferred.previousLifecycleGeneration;
|
|
606
|
-
instance.evaluationGeneration = deferred.previousEvaluationGeneration;
|
|
607
|
-
instance.hasPendingUpdate = deferred.previousHasPendingUpdate;
|
|
608
|
-
instance.notifyUpdate = deferred.previousNotifyUpdate;
|
|
609
|
-
instance._placeholder = deferred.previousPlaceholder;
|
|
610
|
-
instance.mounted = deferred.previousMounted;
|
|
611
|
-
instance._currentRenderToken = deferred.previousCurrentRenderToken;
|
|
612
|
-
instance.lastRenderToken = deferred.previousLastRenderToken;
|
|
613
|
-
instance._pendingReadSources = deferred.previousPendingReadSources;
|
|
614
|
-
instance._pendingReadSourceVersions = deferred.previousPendingReadSourceVersions;
|
|
615
|
-
instance._lastReadSources = deferred.previousLastReadSources;
|
|
616
|
-
instance._appRenderRuntime = deferred.previousAppRenderRuntime;
|
|
617
|
-
const previousSources = new Set(deferred.previousReaderEntries.map(({ source }) => source));
|
|
618
|
-
for (const source of activeReadSources ?? []) {
|
|
619
|
-
if (previousSources.has(source)) continue;
|
|
620
|
-
if ((source._readers?.get(instance))?.generation === activeGeneration) {
|
|
621
|
-
if (source._readers?.delete(instance) && false);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
for (const { source, reader } of deferred.previousReaderEntries) {
|
|
625
|
-
if (!reader) {
|
|
626
|
-
if (source._readers?.delete(instance) && false);
|
|
627
|
-
continue;
|
|
628
|
-
}
|
|
629
|
-
let readers = source._readers;
|
|
630
|
-
if (!readers) {
|
|
631
|
-
readers = /* @__PURE__ */ new Map();
|
|
632
|
-
source._readers = readers;
|
|
633
|
-
}
|
|
634
|
-
readers.has(instance);
|
|
635
|
-
readers.set(instance, reader);
|
|
636
|
-
}
|
|
637
|
-
return errors;
|
|
638
|
-
}
|
|
639
|
-
function restoreDeferredRouteInstances(deferredCleanups) {
|
|
640
|
-
const errors = [];
|
|
641
|
-
for (let index = deferredCleanups.length - 1; index >= 0; index -= 1) errors.push(...restoreDeferredRouteInstance(deferredCleanups[index]));
|
|
642
|
-
if (errors.length > 0) reportRouteCleanupErrors(errors);
|
|
643
|
-
}
|
|
644
|
-
function cleanupDeferredRouteInstance(deferred) {
|
|
645
|
-
const errors = [];
|
|
646
|
-
const instance = deferred.instance;
|
|
647
|
-
if (!deferred.previousDisposed) {
|
|
648
|
-
deferred.previousDisposed = true;
|
|
649
|
-
try {
|
|
650
|
-
cleanupComponentGeneration(instance, {
|
|
651
|
-
ownershipGeneration: deferred.previousOwnershipGeneration,
|
|
652
|
-
cleanupFns: deferred.previousCleanupFns,
|
|
653
|
-
ownedChildScopes: deferred.previousOwnedChildScopes,
|
|
654
|
-
abortController: deferred.previousAbortController,
|
|
655
|
-
readSources: deferred.previousLastReadSources
|
|
656
|
-
});
|
|
657
|
-
} catch (error) {
|
|
658
|
-
errors.push(error);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
const root = instance.target;
|
|
662
|
-
const liveInstances = root ? new Set(collectHostInstances(root)) : /* @__PURE__ */ new Set();
|
|
663
|
-
for (let index = deferred.previousInstances.length - 1; index >= 0; index--) {
|
|
664
|
-
const previous = deferred.previousInstances[index];
|
|
665
|
-
if (previous === instance || liveInstances.has(previous)) continue;
|
|
666
|
-
try {
|
|
667
|
-
cleanupComponent(previous);
|
|
668
|
-
} catch (error) {
|
|
669
|
-
errors.push(error);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
return errors;
|
|
673
|
-
}
|
|
674
|
-
function remountResolvedRoute(instance, resolved, pathname, href, existingSnapshot) {
|
|
675
|
-
const deferredCleanup = existingSnapshot ?? captureDeferredRouteCleanup(instance);
|
|
676
|
-
clearRegisteredDefaultPortalForInstance(instance);
|
|
677
|
-
instance.fn = wrapRootRouteHandler(bindResolvedRouteHandler(resolved), instance._cspNonce);
|
|
678
|
-
instance.props = {};
|
|
679
|
-
instance._ownershipGeneration = {};
|
|
680
|
-
instance.stateValues = [];
|
|
681
|
-
instance.expectedStateIndices = [];
|
|
682
|
-
instance.firstRenderComplete = false;
|
|
683
|
-
instance.stateIndexCheck = -1;
|
|
684
|
-
instance.evaluationGeneration++;
|
|
685
|
-
instance.lifecycleGeneration++;
|
|
686
|
-
instance.notifyUpdate = null;
|
|
687
|
-
instance.mountOperations = [];
|
|
688
|
-
instance.commitOperations = [];
|
|
689
|
-
instance.lifecycleSlots = [];
|
|
690
|
-
instance.cleanupFns = [];
|
|
691
|
-
instance._ownedChildScopes = /* @__PURE__ */ new Set();
|
|
692
|
-
instance._placeholder = void 0;
|
|
693
|
-
instance.hasPendingUpdate = false;
|
|
694
|
-
instance._currentRenderToken = void 0;
|
|
695
|
-
instance.lastRenderToken = 0;
|
|
696
|
-
instance._pendingReadSources = void 0;
|
|
697
|
-
instance._lastReadSources = void 0;
|
|
698
|
-
instance.abortController = null;
|
|
699
|
-
executeComponent(instance);
|
|
700
|
-
setCurrentRouteLocation(pathname, href);
|
|
701
|
-
return deferredCleanup;
|
|
702
|
-
}
|
|
703
|
-
function rerenderResolvedRoute(instance, pathname, href) {
|
|
704
|
-
setCurrentRouteLocation(pathname, href);
|
|
705
|
-
instance._enqueueRun?.();
|
|
706
|
-
return true;
|
|
707
|
-
}
|
|
708
505
|
function resolveAppRouteRequest(app, pathname, href, signal) {
|
|
709
506
|
return resolveRouteRequest(href, {
|
|
710
507
|
registry: app.registry,
|
|
@@ -721,21 +518,15 @@ function getResolvedRouteHandler(resolved) {
|
|
|
721
518
|
params: resolved.params
|
|
722
519
|
};
|
|
723
520
|
}
|
|
724
|
-
function
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
hasRoute: resolved?.kind === "render" && hasRouteRenderData(resolved)
|
|
521
|
+
function prepareNavigationRoot(target, href, replaceLifetime) {
|
|
522
|
+
const resolved = target.resolved;
|
|
523
|
+
return prepareRootUpdate(target.app.instance, {
|
|
524
|
+
handler: bindResolvedRouteHandler(getResolvedRouteHandler(resolved)),
|
|
525
|
+
href,
|
|
526
|
+
routeData: isRenderResult(resolved) ? getRouteRenderData(resolved) : void 0,
|
|
527
|
+
hasRouteData: isRenderResult(resolved) && hasRouteRenderData(resolved),
|
|
528
|
+
replaceLifetime
|
|
733
529
|
});
|
|
734
|
-
stageAppRenderRouteLocation(runtime, href);
|
|
735
|
-
instance._appRenderRuntime = runtime;
|
|
736
|
-
}
|
|
737
|
-
function clearStagedRouteLocations(targets) {
|
|
738
|
-
for (const target of targets) clearStagedAppRenderRouteLocation(target.app.instance._appRenderRuntime);
|
|
739
530
|
}
|
|
740
531
|
function resolveNavigationTargetsForApps(pathname, href, signal) {
|
|
741
532
|
const apps = getRegisteredAppsSnapshot();
|
|
@@ -790,94 +581,17 @@ function applyNavigationTargets(requestId, path, options, redirectState, pathnam
|
|
|
790
581
|
return;
|
|
791
582
|
}
|
|
792
583
|
if (isStaleRouteRequest(requestId)) return;
|
|
793
|
-
|
|
794
|
-
const rootsToPrepare = [];
|
|
795
|
-
for (const target of matchedTargets) {
|
|
796
|
-
const resolved = target.resolved;
|
|
797
|
-
if (resolved.kind === "redirect") continue;
|
|
798
|
-
if (pathname === target.app.pathname && isRenderResult(resolved)) {
|
|
799
|
-
samePathTargets.push(target);
|
|
800
|
-
continue;
|
|
801
|
-
}
|
|
802
|
-
rootsToPrepare.push(target);
|
|
803
|
-
}
|
|
804
|
-
const rollbackSnapshots = matchedTargets.map((target) => captureDeferredRouteCleanup(target.app.instance));
|
|
805
|
-
const rollbackSnapshotByInstance = new Map(rollbackSnapshots.map((snapshot) => [snapshot.instance, snapshot]));
|
|
806
|
-
const deferredCleanups = [];
|
|
807
|
-
const cleanupErrors = [];
|
|
808
|
-
const previousAppLocations = matchedTargets.map((target) => ({
|
|
809
|
-
app: target.app,
|
|
810
|
-
pathname: target.app.pathname,
|
|
811
|
-
href: target.app.href
|
|
812
|
-
}));
|
|
813
|
-
const restoreOnExit = () => {
|
|
814
|
-
if (!navigationBatchClosed) {
|
|
815
|
-
discardLifecycleCommitBatch(navigationBatch);
|
|
816
|
-
navigationBatchClosed = true;
|
|
817
|
-
}
|
|
818
|
-
restoreDeferredRouteInstances(rollbackSnapshots);
|
|
819
|
-
for (const previous of previousAppLocations) {
|
|
820
|
-
previous.app.pathname = previous.pathname;
|
|
821
|
-
previous.app.href = previous.href;
|
|
822
|
-
}
|
|
823
|
-
setCurrentRouteLocation(previousPathname, previousHref);
|
|
824
|
-
};
|
|
825
|
-
const navigationBatch = beginLifecycleCommitBatch();
|
|
826
|
-
let navigationBatchClosed = false;
|
|
827
|
-
try {
|
|
828
|
-
for (const target of rootsToPrepare) {
|
|
829
|
-
if (isStaleRouteRequest(requestId)) {
|
|
830
|
-
restoreOnExit();
|
|
831
|
-
return;
|
|
832
|
-
}
|
|
833
|
-
updateRouteRuntime(target.app.instance, target.resolved, href);
|
|
834
|
-
const deferredCleanup = remountResolvedRoute(target.app.instance, getResolvedRouteHandler(target.resolved), pathname, href, rollbackSnapshotByInstance.get(target.app.instance));
|
|
835
|
-
deferredCleanups.push(deferredCleanup);
|
|
836
|
-
}
|
|
837
|
-
if (isStaleRouteRequest(requestId)) {
|
|
838
|
-
restoreOnExit();
|
|
839
|
-
return;
|
|
840
|
-
}
|
|
841
|
-
flushRuntimeScheduler();
|
|
842
|
-
cleanupErrors.push(...drainLifecycleCommitErrors());
|
|
843
|
-
if (isStaleRouteRequest(requestId)) {
|
|
844
|
-
restoreOnExit();
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
for (const target of samePathTargets) {
|
|
848
|
-
if (isStaleRouteRequest(requestId)) {
|
|
849
|
-
restoreOnExit();
|
|
850
|
-
return;
|
|
851
|
-
}
|
|
852
|
-
updateRouteRuntime(target.app.instance, target.resolved, href);
|
|
853
|
-
rerenderResolvedRoute(target.app.instance, pathname, href);
|
|
854
|
-
}
|
|
855
|
-
flushRuntimeScheduler();
|
|
856
|
-
cleanupErrors.push(...drainLifecycleCommitErrors());
|
|
857
|
-
if (isStaleRouteRequest(requestId)) {
|
|
858
|
-
restoreOnExit();
|
|
859
|
-
return;
|
|
860
|
-
}
|
|
861
|
-
flushLifecycleCommitBatch(navigationBatch);
|
|
862
|
-
navigationBatchClosed = true;
|
|
863
|
-
cleanupErrors.push(...drainLifecycleCommitErrors());
|
|
864
|
-
for (const target of matchedTargets) if (target.resolved && target.resolved.kind !== "redirect") syncAppRegistrationLocation(target.app, pathname, href);
|
|
865
|
-
if (isStaleRouteRequest(requestId)) return;
|
|
584
|
+
commitNavigationRoots(requestId, pathname, href, matchedTargets, () => {
|
|
866
585
|
saveScrollPosition(previousHref);
|
|
867
586
|
const historyMethod = getNavigationHistoryMode(options) === "replace" ? "replaceState" : "pushState";
|
|
868
|
-
window.history[historyMethod]({
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
587
|
+
window.history[historyMethod]({
|
|
588
|
+
path: href,
|
|
589
|
+
askrHasState: Object.prototype.hasOwnProperty.call(options, "state"),
|
|
590
|
+
askrState: options.state
|
|
591
|
+
}, "", href);
|
|
592
|
+
}, () => {
|
|
873
593
|
if (pathname !== previousPathname || parseTargetUrl(href).hash) applyNavigationScroll(options.scroll);
|
|
874
|
-
|
|
875
|
-
for (const error of cleanupErrors) reportRouteCleanupErrors([error]);
|
|
876
|
-
} catch (error) {
|
|
877
|
-
restoreOnExit();
|
|
878
|
-
logger.error("[Askr] navigation failed:", error);
|
|
879
|
-
throw error;
|
|
880
|
-
}
|
|
594
|
+
});
|
|
881
595
|
}
|
|
882
596
|
function applyPopStateNavigationTargets(requestId, previousHref, previousState, pathname, href, state, targets, navigate) {
|
|
883
597
|
if (isStaleRouteRequest(requestId)) return;
|
|
@@ -892,100 +606,86 @@ function applyPopStateNavigationTargets(requestId, previousHref, previousState,
|
|
|
892
606
|
navigate(resolved.to, { history: getRedirectHistoryMode(resolved.replace) });
|
|
893
607
|
return;
|
|
894
608
|
}
|
|
895
|
-
const samePathTargets = [];
|
|
896
|
-
const rootsToPrepare = [];
|
|
897
|
-
for (const target of matchedTargets) {
|
|
898
|
-
const resolved = target.resolved;
|
|
899
|
-
if (pathname === target.app.pathname && isRenderResult(resolved)) {
|
|
900
|
-
samePathTargets.push(target);
|
|
901
|
-
continue;
|
|
902
|
-
}
|
|
903
|
-
if (resolved.kind === "redirect") continue;
|
|
904
|
-
rootsToPrepare.push(target);
|
|
905
|
-
}
|
|
906
|
-
const previousPathname = getCurrentPathname();
|
|
907
609
|
saveScrollPosition(previousHref);
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
const
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
610
|
+
commitNavigationRoots(requestId, pathname, href, matchedTargets, () => {}, () => applyHistoryScroll(href, state), () => {
|
|
611
|
+
window.history.replaceState(previousState, "", previousHref);
|
|
612
|
+
syncRegisteredRouteSnapshot();
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
/** Every root joins one transaction. History remains after lifecycle work,
|
|
616
|
+
* so a navigation started by that work can supersede this destination. */
|
|
617
|
+
function commitNavigationRoots(requestId, pathname, href, targets, updateHistory, updateScroll, restoreHistory) {
|
|
618
|
+
const previousPathname = getCurrentPathname();
|
|
619
|
+
const previousHref = getCurrentHref();
|
|
620
|
+
const roots = targets.map((target) => {
|
|
621
|
+
const replaceLifetime = pathname !== target.app.pathname || !isRenderResult(target.resolved);
|
|
622
|
+
return {
|
|
623
|
+
target,
|
|
624
|
+
replaceLifetime,
|
|
625
|
+
previousPathname: target.app.pathname,
|
|
626
|
+
previousHref: target.app.href,
|
|
627
|
+
prepared: prepareNavigationRoot(target, href, replaceLifetime)
|
|
628
|
+
};
|
|
629
|
+
});
|
|
630
|
+
const transaction = beginCommitTransaction();
|
|
631
|
+
let completionFailure;
|
|
632
|
+
registerCommitParticipant({
|
|
633
|
+
rollback() {
|
|
634
|
+
const errors = [];
|
|
635
|
+
for (let index = roots.length - 1; index >= 0; index--) errors.push(...roots[index].prepared.rollback());
|
|
636
|
+
for (const root of roots) {
|
|
637
|
+
root.target.app.pathname = root.previousPathname;
|
|
638
|
+
root.target.app.href = root.previousHref;
|
|
936
639
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
640
|
+
setCurrentRouteLocation(previousPathname, previousHref);
|
|
641
|
+
try {
|
|
642
|
+
restoreHistory?.();
|
|
643
|
+
} catch (error) {
|
|
644
|
+
errors.push(error);
|
|
645
|
+
}
|
|
646
|
+
reportRouteCleanupErrors(errors);
|
|
647
|
+
},
|
|
648
|
+
settle() {
|
|
649
|
+
const errors = [];
|
|
650
|
+
for (const root of roots) errors.push(...root.prepared.retire());
|
|
651
|
+
reportRouteCleanupErrors(errors);
|
|
652
|
+
},
|
|
653
|
+
complete() {
|
|
654
|
+
if (isStaleRouteRequest(requestId)) return;
|
|
655
|
+
try {
|
|
656
|
+
updateHistory();
|
|
657
|
+
setCurrentRouteLocation(pathname, href);
|
|
658
|
+
syncRegisteredRouteSnapshot();
|
|
659
|
+
reconcileNavigationMetadata(targets);
|
|
660
|
+
updateScroll();
|
|
661
|
+
} catch (error) {
|
|
662
|
+
completionFailure = { error };
|
|
663
|
+
throw error;
|
|
664
|
+
} finally {
|
|
665
|
+
for (const root of roots) root.prepared.publish();
|
|
955
666
|
}
|
|
956
|
-
updateRouteRuntime(target.app.instance, target.resolved, href);
|
|
957
|
-
rerenderResolvedRoute(target.app.instance, pathname, href);
|
|
958
|
-
}
|
|
959
|
-
flushRuntimeScheduler();
|
|
960
|
-
cleanupErrors.push(...drainLifecycleCommitErrors());
|
|
961
|
-
if (isStaleRouteRequest(requestId)) {
|
|
962
|
-
restoreOnExit();
|
|
963
|
-
return;
|
|
964
|
-
}
|
|
965
|
-
flushLifecycleCommitBatch(navigationBatch);
|
|
966
|
-
navigationBatchClosed = true;
|
|
967
|
-
cleanupErrors.push(...drainLifecycleCommitErrors());
|
|
968
|
-
for (const target of matchedTargets) if (target.resolved && target.resolved.kind !== "redirect") syncAppRegistrationLocation(target.app, pathname, href);
|
|
969
|
-
if (isStaleRouteRequest(requestId)) {
|
|
970
|
-
restoreOnExit();
|
|
971
|
-
return;
|
|
972
667
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
668
|
+
});
|
|
669
|
+
try {
|
|
670
|
+
for (const replaceLifetime of [true, false]) {
|
|
671
|
+
for (const root of roots) {
|
|
672
|
+
if (isStaleRouteRequest(requestId)) return;
|
|
673
|
+
if (root.replaceLifetime === replaceLifetime) root.prepared.apply();
|
|
674
|
+
}
|
|
675
|
+
if (isStaleRouteRequest(requestId)) return;
|
|
676
|
+
flushRuntimeScheduler();
|
|
677
|
+
if (isStaleRouteRequest(requestId)) return;
|
|
678
|
+
}
|
|
679
|
+
registerCommitParticipant({ publish() {
|
|
680
|
+
for (const root of roots) syncAppRegistrationLocation(root.target.app, pathname, href);
|
|
681
|
+
} });
|
|
682
|
+
commitTransaction(transaction);
|
|
683
|
+
if (completionFailure) throw completionFailure.error;
|
|
980
684
|
} catch (error) {
|
|
981
|
-
|
|
982
|
-
try {
|
|
983
|
-
window.history.replaceState(previousState, "", previousHref);
|
|
984
|
-
syncRegisteredRouteSnapshot();
|
|
985
|
-
} catch (rollbackError) {
|
|
986
|
-
logger.error("[Askr] failed to restore URL after popstate failure:", rollbackError);
|
|
987
|
-
}
|
|
685
|
+
logger.error("[Askr] navigation failed:", error);
|
|
988
686
|
throw error;
|
|
687
|
+
} finally {
|
|
688
|
+
discardTransaction(transaction);
|
|
989
689
|
}
|
|
990
690
|
}
|
|
991
691
|
//#endregion
|
|
@@ -994,16 +694,38 @@ function applyPopStateNavigationTargets(requestId, previousHref, previousState,
|
|
|
994
694
|
* Client-side navigation with History API
|
|
995
695
|
*/
|
|
996
696
|
let navigationInitialized = false;
|
|
997
|
-
|
|
697
|
+
let navigationRegistryHosted = false;
|
|
698
|
+
/**
|
|
699
|
+
* Publish request cancellation to the navigation registry.
|
|
700
|
+
*
|
|
701
|
+
* The registry cannot import this module (it is imported *by* it), so the
|
|
702
|
+
* capability is injected. Doing that at module scope meant whether an app
|
|
703
|
+
* could cancel its in-flight route requests depended on whether anything had
|
|
704
|
+
* imported this module yet; every entry point that can navigate composes it.
|
|
705
|
+
*/
|
|
706
|
+
function ensureNavigationRegistryHost() {
|
|
707
|
+
if (navigationRegistryHosted) return;
|
|
708
|
+
navigationRegistryHosted = true;
|
|
709
|
+
configureNavigationRegistryHost({ cancelRouteRequests });
|
|
710
|
+
}
|
|
998
711
|
/** Navigate the client-side router to `path` using the History API. */
|
|
999
712
|
function navigate(path, options = {}) {
|
|
713
|
+
ensureNavigationRegistryHost();
|
|
1000
714
|
if (typeof window === "undefined") return;
|
|
715
|
+
prepareNavigationFocus();
|
|
1001
716
|
const targetPath = addRouteBasePath(path, getActiveRouteBasePath());
|
|
1002
717
|
const initialTarget = parseTargetUrl(targetPath);
|
|
1003
|
-
|
|
718
|
+
const redirectState = {
|
|
1004
719
|
redirects: 0,
|
|
1005
720
|
visited: /* @__PURE__ */ new Set([`${initialTarget.pathname}${initialTarget.search}${initialTarget.hash}`])
|
|
1006
|
-
}
|
|
721
|
+
};
|
|
722
|
+
if (isRuntimeSchedulerExecuting()) {
|
|
723
|
+
queueMicrotask(() => {
|
|
724
|
+
navigateWithRedirectState(targetPath, options, redirectState);
|
|
725
|
+
});
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
navigateWithRedirectState(targetPath, options, redirectState);
|
|
1007
729
|
}
|
|
1008
730
|
function navigateWithRedirectState(path, options, redirectState) {
|
|
1009
731
|
if (typeof window === "undefined") return;
|
|
@@ -1021,6 +743,7 @@ function navigateWithRedirectState(path, options, redirectState) {
|
|
|
1021
743
|
logger.error("[Askr] navigation failed:", error);
|
|
1022
744
|
}
|
|
1023
745
|
}, (error) => {
|
|
746
|
+
if (isStaleRouteRequest(request.id)) return;
|
|
1024
747
|
logger.error("[Askr] navigation failed:", error);
|
|
1025
748
|
});
|
|
1026
749
|
return;
|
|
@@ -1028,6 +751,7 @@ function navigateWithRedirectState(path, options, redirectState) {
|
|
|
1028
751
|
applyNavigationTargets(request.id, path, options, redirectState, pathname, href, resolvedTargets, navigateWithRedirectState);
|
|
1029
752
|
}
|
|
1030
753
|
function handlePopState(event) {
|
|
754
|
+
beginHistoryFocusRestoration();
|
|
1031
755
|
const request = beginRouteRequest();
|
|
1032
756
|
const previousHref = getCurrentHref();
|
|
1033
757
|
const pathname = window.location.pathname;
|
|
@@ -1045,6 +769,7 @@ function handlePopState(event) {
|
|
|
1045
769
|
Promise.resolve(resolvedTargets).then((next) => {
|
|
1046
770
|
applyResolved(next);
|
|
1047
771
|
}, (error) => {
|
|
772
|
+
if (isStaleRouteRequest(request.id)) return;
|
|
1048
773
|
logger.error("[Askr] popstate navigation failed:", error);
|
|
1049
774
|
});
|
|
1050
775
|
return;
|
|
@@ -1052,9 +777,12 @@ function handlePopState(event) {
|
|
|
1052
777
|
applyResolved(resolvedTargets);
|
|
1053
778
|
}
|
|
1054
779
|
function initializeNavigation() {
|
|
780
|
+
ensureNavigationRegistryHost();
|
|
1055
781
|
if (typeof window === "undefined" || navigationInitialized) return;
|
|
1056
782
|
navigationInitialized = true;
|
|
1057
783
|
window.addEventListener("popstate", handlePopState);
|
|
784
|
+
document.addEventListener("pointerdown", captureNavigationFocus, true);
|
|
785
|
+
document.addEventListener("click", releaseNavigationFocusCapture);
|
|
1058
786
|
}
|
|
1059
787
|
//#endregion
|
|
1060
|
-
export { serializeRouteMeta as a, getCurrentHref as c, parseTargetUrl as d, registerAppInstance as f, unregisterAppInstance as g, syncRegisteredRouteSnapshot as h, resolveRouteMeta as i, getRegisteredAppsSnapshot as l, syncAppRegistrationLocation as m, navigate as n, configureScrollRestoration as o, setCurrentRouteLocation as p, reconcileRouteMeta as r, saveScrollPosition as s, initializeNavigation as t, getWindowHref$1 as u };
|
|
788
|
+
export { configureRootUpdateHost as _, serializeRouteMeta as a, getCurrentHref as c, parseTargetUrl as d, registerAppInstance as f, unregisterAppInstance as g, syncRegisteredRouteSnapshot as h, resolveRouteMeta as i, getRegisteredAppsSnapshot as l, syncAppRegistrationLocation as m, navigate as n, configureScrollRestoration as o, setCurrentRouteLocation as p, reconcileRouteMeta as r, saveScrollPosition as s, initializeNavigation as t, getWindowHref$1 as u };
|