@tanstack/router-core 1.171.14 → 1.171.16-pre.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.
Files changed (139) hide show
  1. package/dist/cjs/Matches.cjs.map +1 -1
  2. package/dist/cjs/Matches.d.cts +3 -12
  3. package/dist/cjs/await-signal.cjs +21 -0
  4. package/dist/cjs/await-signal.cjs.map +1 -0
  5. package/dist/cjs/await-signal.d.cts +1 -0
  6. package/dist/cjs/index.cjs +3 -1
  7. package/dist/cjs/index.d.cts +3 -2
  8. package/dist/cjs/isServer/client.cjs +2 -0
  9. package/dist/cjs/isServer/client.cjs.map +1 -1
  10. package/dist/cjs/isServer/client.d.cts +1 -0
  11. package/dist/cjs/isServer/development.cjs +2 -0
  12. package/dist/cjs/isServer/development.cjs.map +1 -1
  13. package/dist/cjs/isServer/development.d.cts +1 -0
  14. package/dist/cjs/isServer/server.cjs +2 -0
  15. package/dist/cjs/isServer/server.cjs.map +1 -1
  16. package/dist/cjs/isServer/server.d.cts +1 -0
  17. package/dist/cjs/load-client.cjs +1470 -0
  18. package/dist/cjs/load-client.cjs.map +1 -0
  19. package/dist/cjs/load-client.d.cts +147 -0
  20. package/dist/cjs/load-server.cjs +565 -0
  21. package/dist/cjs/load-server.cjs.map +1 -0
  22. package/dist/cjs/load-server.d.cts +16 -0
  23. package/dist/cjs/redirect.cjs.map +1 -1
  24. package/dist/cjs/redirect.d.cts +0 -1
  25. package/dist/cjs/route.cjs.map +1 -1
  26. package/dist/cjs/router.cjs +187 -445
  27. package/dist/cjs/router.cjs.map +1 -1
  28. package/dist/cjs/router.d.cts +62 -52
  29. package/dist/cjs/scroll-restoration.cjs +27 -34
  30. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  31. package/dist/cjs/ssr/client.cjs +2 -2
  32. package/dist/cjs/ssr/createRequestHandler.cjs +60 -9
  33. package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
  34. package/dist/cjs/ssr/createRequestHandler.d.cts +1 -0
  35. package/dist/cjs/ssr/handlerCallback.cjs +49 -4
  36. package/dist/cjs/ssr/handlerCallback.cjs.map +1 -1
  37. package/dist/cjs/ssr/handlerCallback.d.cts +3 -0
  38. package/dist/cjs/ssr/server.cjs +4 -0
  39. package/dist/cjs/ssr/server.d.cts +2 -2
  40. package/dist/cjs/ssr/ssr-client.d.cts +1 -10
  41. package/dist/cjs/ssr/ssr-match-id.cjs +2 -2
  42. package/dist/cjs/ssr/ssr-match-id.cjs.map +1 -1
  43. package/dist/cjs/ssr/ssr-server.cjs +6 -6
  44. package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
  45. package/dist/cjs/ssr/transformStreamWithRouter.cjs +27 -1
  46. package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
  47. package/dist/cjs/ssr/transformStreamWithRouter.d.cts +2 -0
  48. package/dist/cjs/ssr/types.d.cts +0 -1
  49. package/dist/cjs/stores.cjs +30 -104
  50. package/dist/cjs/stores.cjs.map +1 -1
  51. package/dist/cjs/stores.d.cts +7 -32
  52. package/dist/cjs/utils.cjs +0 -4
  53. package/dist/cjs/utils.cjs.map +1 -1
  54. package/dist/esm/Matches.d.ts +3 -12
  55. package/dist/esm/Matches.js.map +1 -1
  56. package/dist/esm/await-signal.d.ts +1 -0
  57. package/dist/esm/await-signal.js +21 -0
  58. package/dist/esm/await-signal.js.map +1 -0
  59. package/dist/esm/index.d.ts +3 -2
  60. package/dist/esm/index.js +3 -2
  61. package/dist/esm/isServer/client.d.ts +1 -0
  62. package/dist/esm/isServer/client.js +2 -1
  63. package/dist/esm/isServer/client.js.map +1 -1
  64. package/dist/esm/isServer/development.d.ts +1 -0
  65. package/dist/esm/isServer/development.js +2 -1
  66. package/dist/esm/isServer/development.js.map +1 -1
  67. package/dist/esm/isServer/server.d.ts +1 -0
  68. package/dist/esm/isServer/server.js +2 -1
  69. package/dist/esm/isServer/server.js.map +1 -1
  70. package/dist/esm/load-client.d.ts +147 -0
  71. package/dist/esm/load-client.js +1462 -0
  72. package/dist/esm/load-client.js.map +1 -0
  73. package/dist/esm/load-server.d.ts +16 -0
  74. package/dist/esm/load-server.js +565 -0
  75. package/dist/esm/load-server.js.map +1 -0
  76. package/dist/esm/redirect.d.ts +0 -1
  77. package/dist/esm/redirect.js.map +1 -1
  78. package/dist/esm/route.js.map +1 -1
  79. package/dist/esm/router.d.ts +62 -52
  80. package/dist/esm/router.js +188 -446
  81. package/dist/esm/router.js.map +1 -1
  82. package/dist/esm/scroll-restoration.js +27 -34
  83. package/dist/esm/scroll-restoration.js.map +1 -1
  84. package/dist/esm/ssr/client.js +1 -1
  85. package/dist/esm/ssr/createRequestHandler.d.ts +1 -0
  86. package/dist/esm/ssr/createRequestHandler.js +61 -11
  87. package/dist/esm/ssr/createRequestHandler.js.map +1 -1
  88. package/dist/esm/ssr/handlerCallback.d.ts +3 -0
  89. package/dist/esm/ssr/handlerCallback.js +47 -5
  90. package/dist/esm/ssr/handlerCallback.js.map +1 -1
  91. package/dist/esm/ssr/server.d.ts +2 -2
  92. package/dist/esm/ssr/server.js +3 -3
  93. package/dist/esm/ssr/ssr-client.d.ts +1 -10
  94. package/dist/esm/ssr/ssr-match-id.js +2 -2
  95. package/dist/esm/ssr/ssr-match-id.js.map +1 -1
  96. package/dist/esm/ssr/ssr-server.js +6 -6
  97. package/dist/esm/ssr/ssr-server.js.map +1 -1
  98. package/dist/esm/ssr/transformStreamWithRouter.d.ts +2 -0
  99. package/dist/esm/ssr/transformStreamWithRouter.js +27 -1
  100. package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
  101. package/dist/esm/ssr/types.d.ts +0 -1
  102. package/dist/esm/stores.d.ts +7 -32
  103. package/dist/esm/stores.js +30 -104
  104. package/dist/esm/stores.js.map +1 -1
  105. package/dist/esm/utils.js +1 -4
  106. package/dist/esm/utils.js.map +1 -1
  107. package/package.json +3 -3
  108. package/src/Matches.ts +6 -21
  109. package/src/await-signal.ts +27 -0
  110. package/src/index.ts +1 -3
  111. package/src/isServer/client.ts +1 -0
  112. package/src/isServer/development.ts +1 -0
  113. package/src/isServer/server.ts +1 -0
  114. package/src/load-client.ts +2701 -0
  115. package/src/load-server.ts +849 -0
  116. package/src/redirect.ts +0 -1
  117. package/src/route.ts +2 -11
  118. package/src/router.ts +380 -774
  119. package/src/scroll-restoration.ts +40 -56
  120. package/src/ssr/createRequestHandler.ts +109 -16
  121. package/src/ssr/handlerCallback.ts +76 -10
  122. package/src/ssr/server.ts +4 -1
  123. package/src/ssr/ssr-client.ts +1 -310
  124. package/src/ssr/ssr-match-id.ts +11 -2
  125. package/src/ssr/ssr-server.ts +9 -8
  126. package/src/ssr/transformStreamWithRouter.ts +37 -1
  127. package/src/ssr/types.ts +0 -1
  128. package/src/stores.ts +46 -208
  129. package/dist/cjs/load-matches.cjs +0 -658
  130. package/dist/cjs/load-matches.cjs.map +0 -1
  131. package/dist/cjs/load-matches.d.cts +0 -18
  132. package/dist/cjs/ssr/ssr-client.cjs +0 -183
  133. package/dist/cjs/ssr/ssr-client.cjs.map +0 -1
  134. package/dist/esm/load-matches.d.ts +0 -18
  135. package/dist/esm/load-matches.js +0 -656
  136. package/dist/esm/load-matches.js.map +0 -1
  137. package/dist/esm/ssr/ssr-client.js +0 -183
  138. package/dist/esm/ssr/ssr-client.js.map +0 -1
  139. package/src/load-matches.ts +0 -1278
@@ -0,0 +1,1462 @@
1
+ import { deepEqual } from "./utils.js";
2
+ import { isNotFound } from "./not-found.js";
3
+ import { isRedirect } from "./redirect.js";
4
+ import { hydrateSsrMatchId } from "./ssr/ssr-match-id.js";
5
+ import { _getUserHistoryState, getLocationChangeInfo, runRouteLifecycle } from "./router.js";
6
+ //#region src/load-client.ts
7
+ function replaceRouteChunk(route, lazyFn) {
8
+ route.lazyFn = lazyFn ?? route.lazyFn;
9
+ route._lazy = void 0;
10
+ }
11
+ function preloadComponent(route, type) {
12
+ return route.options[type]?.preload?.();
13
+ }
14
+ function loadComponents(route) {
15
+ const component = preloadComponent(route, "component");
16
+ const pending = preloadComponent(route, "pendingComponent");
17
+ if (component && pending) return Promise.all([component, pending]).then(() => {});
18
+ return component ?? pending;
19
+ }
20
+ function loadRouteChunk(route, componentType) {
21
+ const afterLazy = () => componentType === false ? void 0 : componentType ? preloadComponent(route, componentType) : loadComponents(route);
22
+ const current = route._lazy;
23
+ if (current) return current === true ? afterLazy() : current.then(afterLazy);
24
+ if (!route.lazyFn) return afterLazy();
25
+ const promise = route.lazyFn().then((lazyRoute) => {
26
+ if (process.env.NODE_ENV === "production" || route._lazy === promise) {
27
+ const { id: _id, ...options } = lazyRoute.options;
28
+ Object.assign(route.options, options);
29
+ route._lazy = true;
30
+ }
31
+ }, (error) => {
32
+ if (process.env.NODE_ENV === "production" || route._lazy === promise) route._lazy = void 0;
33
+ throw error;
34
+ });
35
+ route._lazy = promise;
36
+ return promise.then(afterLazy);
37
+ }
38
+ /** Return the structural lane through the first terminal render boundary. */
39
+ function _getRenderedMatches(matches) {
40
+ const end = matches.findIndex((match) => match.status !== "success" || match._notFound) + 1;
41
+ return end && end < matches.length ? matches.slice(0, end) : matches;
42
+ }
43
+ /** Return the lane whose document assets belong to the current presentation. */
44
+ function _getAssetMatches(matches) {
45
+ let end = matches.length;
46
+ for (let index = 0; index < end; index++) {
47
+ const match = matches[index];
48
+ if (match._assetEnd !== void 0) {
49
+ end = Math.min(end, Math.max(index + 1, match._assetEnd));
50
+ continue;
51
+ }
52
+ if (match.status !== "success" || match._notFound) {
53
+ end = index + 1;
54
+ break;
55
+ }
56
+ }
57
+ return end < matches.length ? matches.slice(0, end) : matches;
58
+ }
59
+ const SUCCESS = 0;
60
+ const ERROR = 1;
61
+ const NOT_FOUND = 2;
62
+ const REDIRECTED = 3;
63
+ const CANCELED = 4;
64
+ function isControl(result) {
65
+ return typeof result[0] === "number";
66
+ }
67
+ function waitFor(value, signal) {
68
+ if (signal.aborted) return Promise.race([Promise.reject(signal), value]);
69
+ return new Promise((resolve, reject) => {
70
+ const abort = () => reject(signal);
71
+ signal.addEventListener("abort", abort, { once: true });
72
+ Promise.resolve(value).then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
73
+ });
74
+ }
75
+ function getRoute(router, match) {
76
+ return router.routesById[match.routeId];
77
+ }
78
+ function normalize(value, rejected, routeId) {
79
+ if (isRedirect(value)) return [REDIRECTED, value];
80
+ if (isNotFound(value)) {
81
+ value.routeId ||= routeId;
82
+ return [NOT_FOUND, value];
83
+ }
84
+ if (rejected && typeof value?.then === "function") value = new Error("A Promise was thrown", { cause: value });
85
+ return rejected ? [ERROR, value] : [SUCCESS, value];
86
+ }
87
+ function normalizeError(route, cause) {
88
+ let outcome = normalize(cause, true, route.id);
89
+ if (outcome[0] !== ERROR) return outcome;
90
+ try {
91
+ route.options.onError?.(outcome[1]);
92
+ } catch (onErrorCause) {
93
+ outcome = normalize(onErrorCause, true, route.id);
94
+ }
95
+ return outcome;
96
+ }
97
+ function normalizeLaneError(route, cause, options) {
98
+ if (options[0].signal.aborted || !options[2]()) {
99
+ options[0].abort();
100
+ return [CANCELED];
101
+ }
102
+ return normalizeError(route, cause);
103
+ }
104
+ function navigateFrom(router, location) {
105
+ return (opts) => router.navigate({
106
+ ...opts,
107
+ _fromLocation: location
108
+ });
109
+ }
110
+ async function contextualize(router, lane, options, end) {
111
+ const [location, matches] = lane;
112
+ const signal = options[0].signal;
113
+ const preload = !!options[4];
114
+ for (let index = options[7] ?? 0; index < end; index++) {
115
+ const match = matches[index];
116
+ const route = getRoute(router, match);
117
+ match.abortController = options[0];
118
+ const parentContext = matches[index - 1]?.context ?? router.options.context ?? {};
119
+ const common = {
120
+ params: match.params,
121
+ location,
122
+ navigate: navigateFrom(router, location),
123
+ buildLocation: router.buildLocation,
124
+ cause: preload ? "preload" : match.cause,
125
+ abortController: options[0],
126
+ preload,
127
+ matches,
128
+ routeId: route.id
129
+ };
130
+ let context = parentContext;
131
+ try {
132
+ let routeContext = match._ctx;
133
+ if (!routeContext && route.options.context) routeContext = match._ctx = route.options.context({
134
+ ...common,
135
+ deps: match.loaderDeps,
136
+ context: parentContext
137
+ }) || {};
138
+ context = {
139
+ ...parentContext,
140
+ ...routeContext
141
+ };
142
+ match.context = context;
143
+ } catch (cause) {
144
+ releaseFlight(router, match);
145
+ return [index, normalizeLaneError(route, cause, options)];
146
+ }
147
+ if (signal.aborted || !options[2]()) {
148
+ options[0].abort();
149
+ return [index, [CANCELED]];
150
+ }
151
+ const validationError = match.paramsError ?? match.searchError;
152
+ if (validationError !== void 0) {
153
+ releaseFlight(router, match);
154
+ return [index, normalizeLaneError(route, validationError, options)];
155
+ }
156
+ const beforeLoad = route.options.beforeLoad;
157
+ if (!beforeLoad) continue;
158
+ const beforeLoadContext = {
159
+ ...common,
160
+ search: match.search,
161
+ context,
162
+ ...router.options.additionalContext
163
+ };
164
+ const previousStatus = match.status;
165
+ if (previousStatus === "success") match.status = "pending";
166
+ options[8]?.();
167
+ try {
168
+ setFetching(router, match, "beforeLoad", options[0]);
169
+ const result = await waitFor(beforeLoad(beforeLoadContext), signal);
170
+ if (!options[2]()) {
171
+ options[0].abort();
172
+ return [index, [CANCELED]];
173
+ }
174
+ const outcome = normalize(result, false, route.id);
175
+ if (outcome[0] !== SUCCESS) {
176
+ releaseFlight(router, match);
177
+ return [index, outcome];
178
+ }
179
+ match.context = {
180
+ ...context,
181
+ ...result
182
+ };
183
+ } catch (cause) {
184
+ releaseFlight(router, match);
185
+ return [index, normalizeLaneError(route, cause, options)];
186
+ } finally {
187
+ if (previousStatus === "success" && match.status === "pending") match.status = "success";
188
+ setFetching(router, match, false, options[0]);
189
+ }
190
+ }
191
+ }
192
+ function releaseOwnedFlight(router, id, flight) {
193
+ if (!flight || --flight[2]) return;
194
+ if (router._flights?.get(id) === flight) router._flights.delete(id);
195
+ return flight[1];
196
+ }
197
+ function releaseFlight(router, match) {
198
+ const flight = match._flight;
199
+ match._flight = void 0;
200
+ releaseOwnedFlight(router, match.id, flight)?.abort();
201
+ }
202
+ function laneInputs(router, location) {
203
+ const masked = location.maskedLocation;
204
+ return [
205
+ router.routeTree,
206
+ router.options.context ?? {},
207
+ router.options.additionalContext,
208
+ _getUserHistoryState(location.state),
209
+ location.search,
210
+ masked && [
211
+ masked.href,
212
+ _getUserHistoryState(masked.state),
213
+ masked.search,
214
+ masked.unmaskOnReload
215
+ ]
216
+ ];
217
+ }
218
+ function samePreloadLane(preload, router, location, redirects) {
219
+ return preload[3] === router._committed && preload[5] === redirects && deepEqual(preload[4], laneInputs(router, location)) && !preload[0].some((match) => getRoute(router, match).options.preload === false);
220
+ }
221
+ /**
222
+ * Not passing in a `next` ownership recipient
223
+ * is equivalent to discarding the match resources
224
+ */
225
+ function transferMatchResources(router, previous, next) {
226
+ const abort = [];
227
+ for (const match of previous) if (!next?.includes(match)) {
228
+ const flight = match._flight;
229
+ match._flight = void 0;
230
+ const controller = releaseOwnedFlight(router, match.id, flight);
231
+ if (controller) abort.push(controller);
232
+ }
233
+ for (const controller of abort) controller.abort();
234
+ }
235
+ function discardPreload(router, preload) {
236
+ preload[1].abort();
237
+ transferMatchResources(router, preload[0]);
238
+ }
239
+ function acquireMatchResources(matches) {
240
+ for (const match of matches) {
241
+ const flight = match._flight;
242
+ if (flight) flight[2]++;
243
+ }
244
+ }
245
+ function setFetching(router, match, value, owner) {
246
+ match.isFetching = value;
247
+ if (owner && router._tx?.[0] !== owner) return;
248
+ const store = router.stores.byRoute.get(match.routeId);
249
+ const presented = store?.get();
250
+ if (presented?.id === match.id) store.set({
251
+ ...presented,
252
+ isFetching: value
253
+ });
254
+ }
255
+ function getLoaderContext(router, lane, match, route, controller, parentMatchPromise, preload) {
256
+ const location = lane[0];
257
+ return {
258
+ params: match.params,
259
+ location,
260
+ navigate: navigateFrom(router, location),
261
+ cause: preload ? "preload" : match.cause,
262
+ abortController: controller,
263
+ preload,
264
+ deps: match.loaderDeps,
265
+ parentMatchPromise,
266
+ context: match.context,
267
+ route,
268
+ ...router.options.additionalContext
269
+ };
270
+ }
271
+ async function loadResource(router, lane, match, route, loader, parentMatchPromise, preload, owner) {
272
+ const signal = owner.signal;
273
+ if (signal.aborted) return [CANCELED];
274
+ if (!loader) return [SUCCESS, void 0];
275
+ let flight = match._flight;
276
+ let joined = !!flight;
277
+ setFetching(router, match, "loader", owner);
278
+ try {
279
+ for (;;) {
280
+ if (!flight) {
281
+ const controller = new AbortController();
282
+ flight = [
283
+ Promise.resolve().then(() => loader(getLoaderContext(router, lane, match, route, controller, parentMatchPromise, preload))).then((value) => normalize(value, false, route.id), (cause) => normalize(cause, true, route.id)).then((result) => {
284
+ return result[0] === ERROR && match._flight === flight ? normalizeError(route, result[1]) : result;
285
+ }),
286
+ controller,
287
+ 1
288
+ ];
289
+ (router._flights ??= /* @__PURE__ */ new Map()).set(match.id, flight);
290
+ }
291
+ match._flight = flight;
292
+ match.abortController = flight[1];
293
+ try {
294
+ const outcome = await waitFor(flight[0], signal);
295
+ if (!joined || outcome[0] === SUCCESS || outcome[0] === REDIRECTED) return outcome;
296
+ } catch (cause) {
297
+ if (cause === signal) {
298
+ releaseFlight(router, match);
299
+ return [CANCELED];
300
+ }
301
+ throw cause;
302
+ }
303
+ releaseFlight(router, match);
304
+ if (signal.aborted) return [CANCELED];
305
+ flight = void 0;
306
+ joined = false;
307
+ }
308
+ } finally {
309
+ setFetching(router, match, false, owner);
310
+ }
311
+ }
312
+ function settleInto(match, result, preload) {
313
+ if (result[0] === SUCCESS) {
314
+ match.loaderData = result[1];
315
+ match.error = void 0;
316
+ match.status = "success";
317
+ match.invalid = false;
318
+ match.updatedAt = Date.now();
319
+ match.preload = preload;
320
+ } else if (result[0] !== REDIRECTED) {
321
+ match.status = "success";
322
+ match.error = void 0;
323
+ match.invalid = true;
324
+ }
325
+ }
326
+ function cacheLoaderMatch(router, match, planned) {
327
+ const current = router._cache.get(match.id);
328
+ if (current !== planned || router._committed.some((candidate) => candidate.id === match.id && candidate._flight === match._flight)) return;
329
+ const cached = {
330
+ ...match,
331
+ _notFound: void 0,
332
+ context: {}
333
+ };
334
+ if (cached._flight) cached._flight[2]++;
335
+ router._cache.set(match.id, cached);
336
+ if (current) releaseFlight(router, current);
337
+ }
338
+ function getParentSnapshot(match, outcome) {
339
+ if (outcome[0] === ERROR || outcome[0] === NOT_FOUND) return {
340
+ ...match,
341
+ status: outcome[0] === ERROR ? "error" : "notFound",
342
+ error: outcome[1],
343
+ _flight: void 0
344
+ };
345
+ return match;
346
+ }
347
+ function createLoaderTask(router, lane, index, tasks, semanticParent, options) {
348
+ const match = lane[1][index];
349
+ const route = getRoute(router, match);
350
+ const preload = !!options[4];
351
+ const plannedCacheMatch = preload ? router._cache.get(match.id) : void 0;
352
+ let reload = false;
353
+ let reloadFailure;
354
+ try {
355
+ let configured;
356
+ if (match.status === "success") {
357
+ configured = route.options.shouldReload;
358
+ if (typeof configured === "function") configured = configured(getLoaderContext(router, lane, match, route, options[0], semanticParent, preload));
359
+ if (!options[2]()) {
360
+ options[0].abort();
361
+ reloadFailure = [CANCELED];
362
+ }
363
+ }
364
+ if (!reloadFailure) if (match.status !== "success") reload = true;
365
+ else {
366
+ const staleAge = options[4] || match.preload ? route.options.preloadStaleTime ?? router.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? router.options.defaultStaleTime ?? 0;
367
+ reload = !!(match.invalid || configured || configured === void 0 && Date.now() - match.updatedAt >= staleAge && (options[6] || match.cause === "enter" || options[3].some((candidate) => candidate.routeId === match.routeId && candidate.id !== match.id)));
368
+ }
369
+ } catch (cause) {
370
+ match.invalid = true;
371
+ releaseFlight(router, match);
372
+ reloadFailure = normalizeLaneError(route, cause, options);
373
+ }
374
+ const routeLoader = route.options.loader;
375
+ const loader = typeof routeLoader === "function" ? routeLoader : routeLoader?.handler;
376
+ const background = !!(routeLoader && reload && match.status === "success" && !preload && !options[5] && ((typeof routeLoader === "function" ? void 0 : routeLoader?.staleReloadMode) ?? router.options.defaultStaleReloadMode) !== "blocking");
377
+ const loaded = reload && (!preload || route.options.preload !== false);
378
+ const blocking = loaded && !background && (match.status !== "success" || !!routeLoader);
379
+ if (loaded && !routeLoader) {
380
+ match.invalid = false;
381
+ match.updatedAt = Date.now();
382
+ }
383
+ let donor = loaded && routeLoader ? router._flights?.get(match.id) : void 0;
384
+ if (donor === match._flight) donor = void 0;
385
+ else if (donor) donor[2]++;
386
+ if (blocking) {
387
+ const acceptedFlight = match._flight;
388
+ match._flight = donor;
389
+ releaseOwnedFlight(router, match.id, acceptedFlight)?.abort();
390
+ if (match.status === "success") match.status = "pending";
391
+ options[8]?.();
392
+ }
393
+ if (!loaded) match.isFetching = false;
394
+ const outcome = (reloadFailure ? Promise.resolve(reloadFailure) : !blocking ? Promise.resolve([SUCCESS, match.loaderData]) : loadResource(router, lane, match, route, loader, semanticParent, preload, options[0])).then((result) => {
395
+ if (blocking) {
396
+ settleInto(match, result, preload);
397
+ if (result[0] === SUCCESS) {
398
+ if (preload && routeLoader) cacheLoaderMatch(router, match, plannedCacheMatch);
399
+ match.status = "pending";
400
+ }
401
+ }
402
+ return result;
403
+ });
404
+ const chunkFailure = waitFor(Promise.resolve().then(() => loadRouteChunk(route)), options[0].signal).then(() => {
405
+ options[8]?.();
406
+ }, (cause) => [index, normalizeLaneError(route, cause, options)]).then((failure) => outcome.then((result) => {
407
+ if (blocking && !failure && result[0] === SUCCESS && match.status === "pending" && options[2]()) {
408
+ match.status = "success";
409
+ options[8]?.();
410
+ }
411
+ return failure;
412
+ }));
413
+ tasks.push([
414
+ index,
415
+ outcome,
416
+ chunkFailure
417
+ ]);
418
+ if (!background) return outcome.then((result) => getParentSnapshot(match, result));
419
+ const candidate = {
420
+ ...match,
421
+ status: "pending",
422
+ preload: false,
423
+ _flight: donor
424
+ };
425
+ match.invalid = false;
426
+ match.isFetching = "loader";
427
+ const backgroundOutcome = loadResource(router, lane, candidate, route, loader, semanticParent, false, options[0]).then((result) => {
428
+ match.isFetching = false;
429
+ settleInto(candidate, result, false);
430
+ return result;
431
+ });
432
+ (lane[2] ??= []).push([
433
+ index,
434
+ backgroundOutcome,
435
+ chunkFailure,
436
+ candidate
437
+ ]);
438
+ return backgroundOutcome.then((result) => getParentSnapshot(candidate, result));
439
+ }
440
+ async function getNotFoundBoundary(router, matches, indexed, signal, fallback = 0) {
441
+ const cause = indexed?.[1][1];
442
+ let index = cause?.routeId ? matches.findIndex((match) => match.routeId === cause.routeId) : indexed?.[0] ?? matches.length - 1;
443
+ if (index < 0) index = 0;
444
+ for (let i = index; i >= 0; i--) {
445
+ const route = getRoute(router, matches[i]);
446
+ const loading = loadRouteChunk(route, false);
447
+ if (loading) try {
448
+ await waitFor(loading, signal);
449
+ } catch (cause) {
450
+ if (cause === signal) throw cause;
451
+ }
452
+ if (route.options.notFoundComponent) return i;
453
+ }
454
+ return cause?.routeId ? index : fallback;
455
+ }
456
+ function discardBackground(router, lane) {
457
+ if (lane[2]) {
458
+ transferMatchResources(router, lane[2].map((task) => task[3]));
459
+ lane[2] = void 0;
460
+ }
461
+ }
462
+ async function settleTasks(tasks, serialFailure, redirectTasks, gate) {
463
+ let loaderFailure;
464
+ try {
465
+ await Promise.all(tasks.map((task) => task[1].then(async (outcome) => {
466
+ const taskIndex = task[0];
467
+ if (gate && taskIndex >= await gate) return;
468
+ if (outcome[0] >= REDIRECTED) throw [taskIndex, outcome];
469
+ if (!loaderFailure && outcome[0] !== SUCCESS) {
470
+ loaderFailure = [taskIndex, outcome];
471
+ await Promise.all((redirectTasks ?? []).map((nextTask) => {
472
+ if (nextTask[0] <= taskIndex) return;
473
+ return nextTask[1].then((nextOutcome) => {
474
+ if (nextOutcome[0] === REDIRECTED) throw [nextTask[0], nextOutcome];
475
+ });
476
+ }));
477
+ }
478
+ })));
479
+ } catch (cause) {
480
+ return cause;
481
+ }
482
+ return serialFailure ?? loaderFailure;
483
+ }
484
+ async function reduceLane(router, lane, tasks, controller, redirects, settlement, onReady) {
485
+ const matches = lane[1];
486
+ let failure = await settlement;
487
+ let redirectLimitExceeded = false;
488
+ const plannedBoundary = matches.findIndex((match) => match._notFound);
489
+ const boundaryOf = (found) => found[1][0] === NOT_FOUND ? getNotFoundBoundary(router, matches, found, controller.signal) : found[0];
490
+ let readinessEnd = plannedBoundary < 0 ? matches.length : plannedBoundary;
491
+ if ((failure?.[1][0] ?? 0) >= REDIRECTED) readinessEnd = 0;
492
+ else if (failure) {
493
+ readinessEnd = failure[2] ??= await boundaryOf(failure);
494
+ for (const task of tasks) {
495
+ if (task[0] >= readinessEnd) break;
496
+ const outcome = await task[1];
497
+ if (outcome[0] !== SUCCESS && outcome[0] < REDIRECTED && !("loaderData" in matches[task[0]])) {
498
+ failure = [task[0], outcome];
499
+ readinessEnd = failure[2] = await boundaryOf(failure);
500
+ break;
501
+ }
502
+ }
503
+ }
504
+ for (const task of tasks) {
505
+ if (task[0] >= readinessEnd) break;
506
+ const chunkFailure = await task[2];
507
+ if (!chunkFailure) continue;
508
+ failure = chunkFailure;
509
+ break;
510
+ }
511
+ if ((failure?.[1][0] ?? 0) >= REDIRECTED) {
512
+ const outcome = failure[1];
513
+ if (outcome[0] !== REDIRECTED || outcome[1].options.reloadDocument || redirects < 20) {
514
+ discardBackground(router, lane);
515
+ return outcome;
516
+ }
517
+ redirectLimitExceeded = true;
518
+ failure = [0, [ERROR, /* @__PURE__ */ new Error("Too many redirects")]];
519
+ }
520
+ const boundary = failure ? failure[2] ?? await boundaryOf(failure) : plannedBoundary;
521
+ if (boundary >= 0) {
522
+ const outcome = failure?.[1];
523
+ const kind = outcome?.[0];
524
+ const match = matches[boundary];
525
+ const cause = outcome?.[1];
526
+ const install = () => {
527
+ if (outcome) {
528
+ match._notFound = void 0;
529
+ if (kind === ERROR) match.status = "error";
530
+ else {
531
+ cause.routeId = match.routeId;
532
+ if (match.routeId === router.routeTree.id) {
533
+ match.status = "success";
534
+ match._notFound = true;
535
+ } else match.status = "notFound";
536
+ }
537
+ match.error = cause;
538
+ match.isFetching = false;
539
+ }
540
+ };
541
+ install();
542
+ try {
543
+ await waitFor(outcome ? Promise.resolve().then(() => loadRouteChunk(getRoute(router, match), kind === ERROR ? "errorComponent" : "notFoundComponent")) : Promise.all([loadRouteChunk(getRoute(router, match)), loadRouteChunk(getRoute(router, match), "notFoundComponent")]), controller.signal);
544
+ } catch (cause) {
545
+ if (cause === controller.signal) {
546
+ discardBackground(router, lane);
547
+ return [CANCELED];
548
+ }
549
+ }
550
+ if (!outcome) {
551
+ match.status = "success";
552
+ onReady?.();
553
+ } else if (redirectLimitExceeded) {
554
+ controller.abort();
555
+ await Promise.all([
556
+ ...tasks.map((task) => task[1]),
557
+ ...tasks.map((task) => task[2]),
558
+ ...(lane[2] ?? []).map((task) => task[1])
559
+ ]);
560
+ discardBackground(router, lane);
561
+ transferMatchResources(router, matches);
562
+ install();
563
+ }
564
+ }
565
+ return lane;
566
+ }
567
+ async function projectLane(router, lane, signal, start = 0, end = lane[1].length) {
568
+ const matches = lane[1];
569
+ for (let index = start; index < end; index++) {
570
+ const match = matches[index];
571
+ const routeOptions = getRoute(router, match).options;
572
+ if (routeOptions.head || routeOptions.scripts) try {
573
+ const context = {
574
+ ssr: router.options.ssr,
575
+ matches,
576
+ match,
577
+ params: match.params,
578
+ loaderData: match.loaderData
579
+ };
580
+ const [head, scripts] = await waitFor(Promise.all([routeOptions.head?.(context), routeOptions.scripts?.(context)]), signal);
581
+ match.meta = head?.meta;
582
+ match.links = head?.links;
583
+ match.headScripts = head?.scripts;
584
+ match.styles = head?.styles;
585
+ match.scripts = scripts;
586
+ } catch (cause) {
587
+ if (cause === signal) break;
588
+ console.error(cause);
589
+ }
590
+ if (match.status !== "success" || match._notFound) break;
591
+ }
592
+ return lane;
593
+ }
594
+ async function executeClientLane(router, location, matches, options) {
595
+ const matched = [location, matches];
596
+ let plannedBoundary = matches.findIndex((match) => match._notFound);
597
+ if (router.options.notFoundMode !== "root" && plannedBoundary >= 0) {
598
+ const boundary = await getNotFoundBoundary(router, matched[1], void 0, options[0].signal, plannedBoundary);
599
+ if (boundary !== plannedBoundary) {
600
+ matches[plannedBoundary]._notFound = void 0;
601
+ matches[boundary]._notFound = true;
602
+ }
603
+ plannedBoundary = boundary;
604
+ }
605
+ let end = plannedBoundary < 0 ? matches.length : plannedBoundary + 1;
606
+ const failure = await contextualize(router, matched, options, end);
607
+ if (failure) options[5] = true;
608
+ const tasks = [];
609
+ const start = options[7] ?? 0;
610
+ let semanticParent = start ? Promise.resolve(matched[1][start - 1]) : void 0;
611
+ end = failure?.[0] ?? end;
612
+ if (failure?.[1][0] === NOT_FOUND) {
613
+ failure[2] = await getNotFoundBoundary(router, matched[1], failure, options[0].signal);
614
+ end = Math.min(end, failure[2] + 1);
615
+ } else if ((failure?.[1][0] ?? 0) >= REDIRECTED) end = 0;
616
+ for (let index = start; index < end; index++) {
617
+ if (options[0].signal.aborted) break;
618
+ semanticParent = createLoaderTask(router, matched, index, tasks, semanticParent, options);
619
+ }
620
+ let reduced;
621
+ try {
622
+ const reduction = reduceLane(router, matched, tasks, options[0], options[1], settleTasks(tasks, failure, matched[2]), options[8]);
623
+ if (matched[2]?.length) matched[3] = settleTasks(matched[2], void 0, void 0, reduction.then((foreground) => isControl(foreground) ? 0 : _getRenderedMatches(foreground[1]).length, () => 0));
624
+ reduced = await reduction;
625
+ } catch (cause) {
626
+ discardBackground(router, matched);
627
+ throw cause;
628
+ }
629
+ if (isControl(reduced)) return reduced;
630
+ return projectLane(router, reduced, options[0].signal, options[7] === reduced[1].length ? options[7] : 0);
631
+ }
632
+ /**
633
+ * Finds the first route that should show pending UI and its two timing values.
634
+ * A fallback already on screen remains selected after its route loads, so we
635
+ * do not jump to a child fallback. Matches put back into pending by invalidation
636
+ * skip pendingMs, and a route without a usable fallback blocks pending UI for deeper routes.
637
+ */
638
+ function pendingConfig(router, matches) {
639
+ const presented = router.stores.matches.get();
640
+ for (let index = 0; index < matches.length; index++) {
641
+ const match = matches[index];
642
+ const success = match.status === "success";
643
+ const visible = success && presented[index]?.id === match.id && presented[index]?.status === "pending";
644
+ if (success && !visible) continue;
645
+ const route = getRoute(router, match);
646
+ const delay = visible || match.invalid ? 0 : route.options.pendingMs ?? router.options.defaultPendingMs;
647
+ const component = route.options.pendingComponent ?? router.options.defaultPendingComponent;
648
+ return component && typeof delay === "number" && delay !== Infinity ? [
649
+ delay,
650
+ index,
651
+ route.options.pendingMinMs ?? router.options.defaultPendingMinMs ?? 0,
652
+ component
653
+ ] : void 0;
654
+ }
655
+ }
656
+ /**
657
+ * Waits for `pendingMs`, then presents the complete lane. Rendering applies the
658
+ * selected boundary cutoff while retaining every match's structural state.
659
+ * A replacement load for the same match keeps the timer; choosing a different
660
+ * match resets it. `pendingMinMs` starts after the fallback renders.
661
+ */
662
+ function offerPending(router, tx) {
663
+ if (router._tx !== tx) return;
664
+ let session = router._pending;
665
+ let tookOver = false;
666
+ const sessionMatchId = session?.[0][3][session[1]]?.id;
667
+ if (session?.[0] !== tx) if (session && tx[3][session[1]]?.id === sessionMatchId) {
668
+ session[0] = tx;
669
+ tookOver = true;
670
+ } else {
671
+ clearTimeout(session?.[3]);
672
+ router._pending = session = void 0;
673
+ }
674
+ const config = pendingConfig(router, tx[3]);
675
+ if (!config) return;
676
+ const [delay, boundary, min, component] = config;
677
+ const matchId = tx[3][boundary].id;
678
+ if (!session || session[1] !== boundary || sessionMatchId !== matchId) {
679
+ clearTimeout(session?.[3]);
680
+ const presented = router.stores.matches.get()[boundary];
681
+ const visible = presented?.id === matchId && presented.status === "pending";
682
+ router._pending = session = [
683
+ tx,
684
+ boundary,
685
+ visible ? Date.now() + min : tx[4] + delay,
686
+ void 0,
687
+ visible ? Promise.resolve(true) : void 0,
688
+ component
689
+ ];
690
+ }
691
+ if (session[4] && !tookOver && session[5] === component) return;
692
+ session[5] = component;
693
+ if (!session[4]) {
694
+ clearTimeout(session[3]);
695
+ const remaining = session[2] - Date.now();
696
+ if (remaining > 0) {
697
+ session[3] = setTimeout(() => {
698
+ offerPending(router, tx);
699
+ }, remaining);
700
+ return;
701
+ }
702
+ session[2] = 0;
703
+ }
704
+ const offered = tx[3].map((match) => ({
705
+ ...match,
706
+ _flight: void 0
707
+ }));
708
+ offered[boundary].status = "pending";
709
+ const ack = router.startTransition(() => router.stores.setMatches(offered), offered, true).then((rendered) => {
710
+ if (rendered && router._pending === session && session[4] === ack && !session[2]) session[2] = Date.now() + min;
711
+ return rendered;
712
+ });
713
+ session[4] = ack;
714
+ }
715
+ /**
716
+ * Cancels pending UI timing when its load ends. The ownership check prevents
717
+ * an older, superseded load from clearing pending UI that a newer load took over.
718
+ */
719
+ function finishPending(router, tx) {
720
+ const session = router._pending;
721
+ if (session?.[0] === tx) {
722
+ clearTimeout(session[3]);
723
+ router._pending = void 0;
724
+ }
725
+ }
726
+ function publishMatches(router, matches) {
727
+ router._committed = matches;
728
+ router.stores.setMatches(matches);
729
+ }
730
+ function discardLane(router, lane) {
731
+ transferMatchResources(router, lane[1]);
732
+ discardBackground(router, lane);
733
+ }
734
+ function commitMatches(router, tx, matches, resolvedPrefix) {
735
+ const previous = router._committed;
736
+ const previousCached = router._cache;
737
+ for (const match of matches) {
738
+ match.preload = false;
739
+ if (resolvedPrefix) match._assetEnd = void 0;
740
+ }
741
+ const cut = _getRenderedMatches(matches).length;
742
+ const cached = /* @__PURE__ */ new Map();
743
+ const now = Date.now();
744
+ for (const match of [...previous, ...previousCached.values()]) {
745
+ if (match.status !== "success" || matches.some((candidate, index) => candidate.id === match.id && (index < cut || candidate.status === "success"))) continue;
746
+ const route = getRoute(router, match);
747
+ if (!route.options.loader || now - match.updatedAt >= (match.preload ? route.options.preloadGcTime ?? router.options.defaultPreloadGcTime ?? 3e5 : route.options.gcTime ?? router.options.defaultGcTime ?? 3e5)) continue;
748
+ cached.set(match.id, previousCached.get(match.id) === match ? match : {
749
+ ...match,
750
+ _flight: void 0,
751
+ isFetching: false,
752
+ context: {}
753
+ });
754
+ }
755
+ tx[3] = [];
756
+ router._cache = cached;
757
+ publishMatches(router, matches);
758
+ transferMatchResources(router, [...previousCached.values(), ...previous], [...matches, ...cached.values()]);
759
+ runRouteLifecycle(router, previous, matches, () => router._tx === tx);
760
+ }
761
+ function commitRefreshMatches(router, tx, matches, checkpoint) {
762
+ const previous = router._committed;
763
+ const previousCached = router._cache;
764
+ for (const match of matches) match.preload = false;
765
+ const cached = /* @__PURE__ */ new Map();
766
+ tx[3] = [];
767
+ router._cache = cached;
768
+ checkpoint.previousMatches = previous;
769
+ checkpoint.previousCache = previousCached;
770
+ checkpoint.published = true;
771
+ publishMatches(router, matches);
772
+ if (!checkpoint.published || router._tx !== tx) return;
773
+ runRouteLifecycle(router, previous, matches, () => router._tx === tx);
774
+ }
775
+ function settlePublication(router, checkpoint) {
776
+ if (!checkpoint.published) return;
777
+ checkpoint.published = false;
778
+ transferMatchResources(router, [...checkpoint.previousCache.values(), ...checkpoint.previousMatches], [...router._cache.values(), ...router._committed]);
779
+ }
780
+ function rollbackPublication(router, tx, lane, checkpoint) {
781
+ if (!checkpoint.published || router._tx !== tx || router._committed !== lane[1]) {
782
+ settlePublication(router, checkpoint);
783
+ return false;
784
+ }
785
+ const discarded = [...router._cache.values(), ...router._committed];
786
+ const restored = [...checkpoint.previousCache.values(), ...checkpoint.previousMatches];
787
+ router._cache = checkpoint.previousCache;
788
+ router._committed = checkpoint.previousMatches;
789
+ checkpoint.published = false;
790
+ for (const match of discarded) if (!restored.includes(match) && match._flight && router._flights?.get(match.id) === match._flight) router._flights.delete(match.id);
791
+ finishPending(router, tx);
792
+ router.batch(() => {
793
+ router.stores.status.set("idle");
794
+ router.stores.setMatches(checkpoint.previousPresentation);
795
+ });
796
+ tx[0].abort();
797
+ transferMatchResources(router, discarded, restored);
798
+ discardBackground(router, lane);
799
+ if (router._tx === tx && router._commitPromise === checkpoint.commitPromise) {
800
+ router._commitPromise?.resolve();
801
+ router._commitPromise = void 0;
802
+ }
803
+ return true;
804
+ }
805
+ async function transitionRefresh(router, tx, lane, changeInfo) {
806
+ const checkpoint = {
807
+ previousMatches: router._committed,
808
+ previousPresentation: tx[6]?.[0] ?? router.stores.matches.get(),
809
+ previousCache: router._cache,
810
+ commitPromise: router._commitPromise,
811
+ published: false
812
+ };
813
+ const commit = () => {
814
+ finishPending(router, tx);
815
+ router._rollbackRefresh = rollback;
816
+ commitRefreshMatches(router, tx, lane[1], checkpoint);
817
+ if (!checkpoint.published || router._tx !== tx) return;
818
+ router.emit({
819
+ type: "onLoad",
820
+ ...changeInfo
821
+ });
822
+ if (router._tx === tx) router.emit({
823
+ type: "onBeforeRouteMount",
824
+ ...changeInfo
825
+ });
826
+ };
827
+ const rollback = () => {
828
+ if (router._rollbackRefresh === rollback) router._rollbackRefresh = void 0;
829
+ const restored = rollbackPublication(router, tx, lane, checkpoint);
830
+ router._cancelTransition?.();
831
+ return restored;
832
+ };
833
+ try {
834
+ const rendered = await router.startTransition(commit, lane[1]);
835
+ if (router._rollbackRefresh === rollback) router._rollbackRefresh = void 0;
836
+ if (checkpoint.published) {
837
+ const handoff = tx[6]?.[1];
838
+ if (handoff && router._handoff === handoff) handoff[1]();
839
+ if (router._tx === tx) tx[6] = void 0;
840
+ }
841
+ settlePublication(router, checkpoint);
842
+ return rendered;
843
+ } catch (cause) {
844
+ if (rollback()) return;
845
+ throw cause;
846
+ }
847
+ }
848
+ async function awaitCurrent(router, owner) {
849
+ let current = router._tx;
850
+ while (current && current !== owner) {
851
+ await current[5];
852
+ if (router._tx === current) return;
853
+ current = router._tx;
854
+ }
855
+ }
856
+ async function followRedirect(router, tx, redirect) {
857
+ await router.navigate({
858
+ ...redirect.options,
859
+ replace: true,
860
+ ignoreBlocker: true,
861
+ _redirects: tx[1] + 1
862
+ });
863
+ }
864
+ function restoreCommitted(router, tx) {
865
+ finishPending(router, tx);
866
+ tx[0].abort();
867
+ transferMatchResources(router, tx[3]);
868
+ tx[3] = [];
869
+ if (router._tx !== tx) return;
870
+ router.batch(() => {
871
+ router.stores.status.set("idle");
872
+ router.stores.setMatches(router._committed);
873
+ });
874
+ if (router._tx === tx) {
875
+ router._commitPromise?.resolve();
876
+ router._commitPromise = void 0;
877
+ }
878
+ }
879
+ async function runBackground(router, tx, base, tasks, settlement) {
880
+ const next = base.map((match) => ({ ...match }));
881
+ acquireMatchResources(next);
882
+ for (const task of tasks) {
883
+ releaseFlight(router, next[task[0]]);
884
+ next[task[0]] = task[3];
885
+ }
886
+ const lane = [tx[2], next];
887
+ let reduced;
888
+ try {
889
+ reduced = await reduceLane(router, lane, tasks, tx[0], tx[1], settlement);
890
+ } catch (cause) {
891
+ transferMatchResources(router, next);
892
+ throw cause;
893
+ }
894
+ if (isControl(reduced)) {
895
+ transferMatchResources(router, next);
896
+ if (reduced[0] === REDIRECTED && router._tx === tx && router._committed === base) await followRedirect(router, tx, reduced[1]);
897
+ return;
898
+ }
899
+ const projected = await projectLane(router, reduced, tx[0].signal);
900
+ if (router._tx !== tx || router._committed !== base) {
901
+ transferMatchResources(router, projected[1]);
902
+ return;
903
+ }
904
+ for (const match of projected[1]) {
905
+ const cached = router._cache.get(match.id);
906
+ if (cached?._flight && cached._flight === match._flight) {
907
+ router._cache.delete(match.id);
908
+ releaseFlight(router, cached);
909
+ }
910
+ }
911
+ publishMatches(router, projected[1]);
912
+ transferMatchResources(router, base, projected[1]);
913
+ }
914
+ async function runClientTransaction(router, tx, forceStaleReload, onReady, sync, resolvedPrefix, adopted, retained) {
915
+ const options = [
916
+ tx[0],
917
+ tx[1],
918
+ () => router._tx === tx && !!tx[3].length,
919
+ router._committed,
920
+ void 0,
921
+ sync,
922
+ forceStaleReload,
923
+ resolvedPrefix,
924
+ onReady
925
+ ];
926
+ let result;
927
+ try {
928
+ result = adopted ? await adopted[2] : await executeClientLane(router, tx[2], tx[3], options);
929
+ } finally {
930
+ if (retained) discardPreload(router, retained);
931
+ }
932
+ if (adopted && router._tx === tx && (isControl(result) && result[0] === CANCELED || !isControl(result) && result[1].some((match) => match.status !== "success" || match._notFound))) {
933
+ const donors = tx[3];
934
+ tx[3] = [];
935
+ transferMatchResources(router, donors);
936
+ tx[0].abort();
937
+ if (router._tx !== tx) return;
938
+ const controller = new AbortController();
939
+ tx[0] = options[0] = controller;
940
+ tx[3] = router.matchRoutes(tx[2], { _controller: controller });
941
+ acquireMatchResources(tx[3]);
942
+ result = await executeClientLane(router, tx[2], tx[3], options);
943
+ }
944
+ if (isControl(result)) {
945
+ if (result[0] === REDIRECTED && router._tx === tx) {
946
+ finishPending(router, tx);
947
+ transferMatchResources(router, tx[3]);
948
+ tx[3] = [];
949
+ if (router._tx === tx) {
950
+ if (process.env.NODE_ENV !== "production" && tx[6]) router._refreshNextLoad = true;
951
+ await followRedirect(router, tx, result[1]);
952
+ }
953
+ } else restoreCommitted(router, tx);
954
+ return;
955
+ }
956
+ const pending = router._pending;
957
+ if (pending?.[0] === tx) {
958
+ /**
959
+ * Loading finished, so cancel any pending reveal. If the fallback rendered,
960
+ * wait out the rest of `pendingMinMs` before replacing it. If it never
961
+ * rendered, there is no minimum wait; if another load took it over, that
962
+ * load owns the deadline.
963
+ */
964
+ clearTimeout(pending[3]);
965
+ if (pending[4]) {
966
+ const signal = tx[0].signal;
967
+ let rendered = false;
968
+ try {
969
+ rendered = await waitFor(pending[4], signal);
970
+ } catch (cause) {
971
+ if (cause !== signal) throw cause;
972
+ }
973
+ if (rendered && router._pending === pending && pending[0] === tx) {
974
+ const remaining = pending[2] - Date.now();
975
+ if (remaining > 0) {
976
+ try {
977
+ await waitFor(new Promise((resolve) => {
978
+ pending[3] = setTimeout(resolve, remaining);
979
+ }), signal);
980
+ } catch {}
981
+ clearTimeout(pending[3]);
982
+ }
983
+ }
984
+ }
985
+ }
986
+ if (router._tx !== tx) {
987
+ finishPending(router, tx);
988
+ discardLane(router, result);
989
+ return;
990
+ }
991
+ const toLocation = tx[2];
992
+ const changeInfo = getLocationChangeInfo(toLocation, router.stores.resolvedLocation.get());
993
+ const background = result[2];
994
+ await router.startViewTransition(async () => {
995
+ if (router._tx !== tx) {
996
+ discardLane(router, result);
997
+ return;
998
+ }
999
+ const commit = () => {
1000
+ finishPending(router, tx);
1001
+ commitMatches(router, tx, result[1], resolvedPrefix);
1002
+ if (router._tx !== tx) return;
1003
+ router.emit({
1004
+ type: "onLoad",
1005
+ ...changeInfo
1006
+ });
1007
+ if (router._tx === tx) router.emit({
1008
+ type: "onBeforeRouteMount",
1009
+ ...changeInfo
1010
+ });
1011
+ };
1012
+ const rendered = process.env.NODE_ENV !== "production" && tx[6] ? await transitionRefresh(router, tx, result, changeInfo) : await router.startTransition(commit, result[1]);
1013
+ if (process.env.NODE_ENV !== "production" && tx[6] && rendered === void 0) return;
1014
+ if (router._tx !== tx) {
1015
+ discardBackground(router, result);
1016
+ return;
1017
+ }
1018
+ if (background?.length) runBackground(router, tx, result[1], background, result[3]).catch(console.error);
1019
+ router.batch(() => {
1020
+ router.stores.resolvedLocation.set(toLocation);
1021
+ router.stores.status.set("idle");
1022
+ if (router._tx === tx) router.emit({
1023
+ type: "onResolved",
1024
+ ...changeInfo
1025
+ });
1026
+ if (rendered && router._tx === tx) router.emit({
1027
+ type: "onRendered",
1028
+ ...changeInfo
1029
+ });
1030
+ });
1031
+ if (router._tx !== tx) return;
1032
+ router._commitPromise?.resolve();
1033
+ router._commitPromise = void 0;
1034
+ });
1035
+ }
1036
+ async function loadClientRoute(router, opts) {
1037
+ let rematerialize = false;
1038
+ if (process.env.NODE_ENV !== "production") {
1039
+ router._rollbackRefresh?.();
1040
+ rematerialize = !!router._refreshNextLoad || !!router._tx?.[6];
1041
+ }
1042
+ const refreshPresentation = rematerialize ? router.stores.matches.get() : void 0;
1043
+ const previousOwner = router._tx;
1044
+ const resolvedLocation = router.stores.resolvedLocation.get();
1045
+ const previousLocation = resolvedLocation ?? router.stores.location.get();
1046
+ const location = router.latestLocation;
1047
+ const pendingLocation = router._pendingLocation;
1048
+ const redirects = pendingLocation?.href === location.href ? pendingLocation._redirects ?? 0 : 0;
1049
+ if (opts?._dedupe && !redirects && previousOwner && !rematerialize && previousOwner[2].href === location.href && router.stores.status.get() === "pending") {
1050
+ await awaitCurrent(router);
1051
+ return;
1052
+ }
1053
+ const handoff = router._handoff;
1054
+ const hydrationController = rematerialize ? void 0 : handoff?.[0]();
1055
+ const preflight = new AbortController();
1056
+ const previousPreflight = router._preflight;
1057
+ router._preflight = preflight;
1058
+ if (!rematerialize && !hydrationController) handoff?.[1]();
1059
+ previousPreflight?.abort();
1060
+ if (preflight.signal.aborted || router._tx !== previousOwner) {
1061
+ await awaitCurrent(router, previousOwner);
1062
+ return;
1063
+ }
1064
+ const changeInfo = getLocationChangeInfo(location, resolvedLocation);
1065
+ router.emit({
1066
+ type: "onBeforeNavigate",
1067
+ ...changeInfo
1068
+ });
1069
+ if (!preflight.signal.aborted && router._tx === previousOwner) router.emit({
1070
+ type: "onBeforeLoad",
1071
+ ...changeInfo
1072
+ });
1073
+ if (preflight.signal.aborted || router._tx !== previousOwner) {
1074
+ preflight.abort();
1075
+ await awaitCurrent(router, previousOwner);
1076
+ return;
1077
+ }
1078
+ const sameHref = previousLocation.href === location.href;
1079
+ let adopted = router._preloads?.get(location.href);
1080
+ let retained;
1081
+ if (rematerialize && adopted) {
1082
+ router._preloads.delete(location.href);
1083
+ discardPreload(router, adopted);
1084
+ adopted = void 0;
1085
+ if (preflight.signal.aborted || router._tx !== previousOwner) {
1086
+ preflight.abort();
1087
+ await awaitCurrent(router, previousOwner);
1088
+ return;
1089
+ }
1090
+ }
1091
+ if (adopted && (hydrationController || !samePreloadLane(adopted, router, pendingLocation?.href === location.href ? pendingLocation : location, redirects))) {
1092
+ router._preloads.delete(location.href);
1093
+ retained = adopted;
1094
+ adopted = void 0;
1095
+ }
1096
+ let matches;
1097
+ let controller = preflight;
1098
+ let resolvedPrefix;
1099
+ if (adopted) {
1100
+ controller = adopted[1];
1101
+ matches = adopted[0];
1102
+ router._preloads.delete(location.href);
1103
+ } else {
1104
+ try {
1105
+ matches = process.env.NODE_ENV !== "production" && rematerialize ? router.matchRoutes(location, {
1106
+ _controller: preflight,
1107
+ _rematerialize: true
1108
+ }) : router.matchRoutes(location, { _controller: preflight });
1109
+ acquireMatchResources(matches);
1110
+ } catch (cause) {
1111
+ preflight.abort();
1112
+ if (retained) discardPreload(router, retained);
1113
+ if (!isRedirect(cause)) {
1114
+ if (process.env.NODE_ENV !== "production" && rematerialize) router._refreshNextLoad = void 0;
1115
+ await awaitCurrent(router);
1116
+ router._commitPromise?.resolve();
1117
+ router._commitPromise = void 0;
1118
+ return;
1119
+ }
1120
+ await router.navigate({
1121
+ ...cause.options,
1122
+ replace: true,
1123
+ ignoreBlocker: true
1124
+ });
1125
+ await awaitCurrent(router, previousOwner);
1126
+ return;
1127
+ }
1128
+ resolvedPrefix = hydrationController ? handoff[1](matches) : void 0;
1129
+ if (resolvedPrefix) controller = hydrationController;
1130
+ else hydrationController?.abort();
1131
+ }
1132
+ if (router._preflight !== preflight || router._tx !== previousOwner) {
1133
+ preflight.abort();
1134
+ transferMatchResources(router, matches);
1135
+ await awaitCurrent(router, previousOwner);
1136
+ return;
1137
+ }
1138
+ router._preflight = void 0;
1139
+ const tx = [
1140
+ controller,
1141
+ redirects,
1142
+ location,
1143
+ matches,
1144
+ Date.now(),
1145
+ Promise.resolve().then(() => runClientTransaction(router, tx, sameHref, () => offerPending(router, tx), opts?.sync, resolvedPrefix, adopted, retained)).catch(() => {
1146
+ if (router._tx === tx) restoreCommitted(router, tx);
1147
+ })
1148
+ ];
1149
+ if (process.env.NODE_ENV !== "production" && rematerialize) {
1150
+ tx[6] = [refreshPresentation, handoff];
1151
+ router._refreshNextLoad = void 0;
1152
+ }
1153
+ router._tx = tx;
1154
+ if (!rematerialize && router._handoff === handoff) router._handoff = void 0;
1155
+ if (previousOwner) {
1156
+ for (const match of router.stores.matches.get()) {
1157
+ if (router._tx !== tx) break;
1158
+ if (match.isFetching) setFetching(router, match, false);
1159
+ }
1160
+ previousOwner[0].abort();
1161
+ transferMatchResources(router, previousOwner[3]);
1162
+ }
1163
+ if (router._tx !== tx) {
1164
+ transferMatchResources(router, tx[3]);
1165
+ tx[3] = [];
1166
+ await awaitCurrent(router, tx);
1167
+ return;
1168
+ }
1169
+ router.batch(() => {
1170
+ router.stores.status.set("pending");
1171
+ router.stores.location.set(location);
1172
+ });
1173
+ offerPending(router, tx);
1174
+ try {
1175
+ await tx[5];
1176
+ } finally {
1177
+ await awaitCurrent(router, tx);
1178
+ }
1179
+ }
1180
+ async function refreshClientRoute(router) {
1181
+ router._rollbackRefresh?.();
1182
+ const pending = router._tx;
1183
+ if (pending && !pending[6] && router.stores.status.get() === "pending") {
1184
+ await pending[5];
1185
+ if (router._tx !== pending) await awaitCurrent(router, pending);
1186
+ }
1187
+ router._flights?.clear();
1188
+ router.clearCache();
1189
+ router._refreshNextLoad = true;
1190
+ await loadClientRoute(router, { sync: true });
1191
+ }
1192
+ function followPreloadRedirect(router, result, location, owner, redirects) {
1193
+ if (result[0] === REDIRECTED && !result[1].options.reloadDocument && router._tx === owner) return preloadClientRoute(router, {
1194
+ ...result[1].options,
1195
+ _fromLocation: location
1196
+ }, redirects + 1);
1197
+ }
1198
+ async function preloadClientRoute(router, opts, redirects = 0) {
1199
+ if (redirects > 20) return;
1200
+ const owner = router._tx;
1201
+ if (process.env.NODE_ENV !== "production" && (router._refreshNextLoad || owner?.[6])) return;
1202
+ const location = opts._builtLocation ?? router.buildLocation(opts);
1203
+ const base = router._committed;
1204
+ const controller = new AbortController();
1205
+ let matches;
1206
+ let preload;
1207
+ let replaced;
1208
+ try {
1209
+ const pending = router._preloads?.get(location.href);
1210
+ if (pending) {
1211
+ if (samePreloadLane(pending, router, location, redirects)) {
1212
+ const result = await pending[2];
1213
+ return isControl(result) ? followPreloadRedirect(router, result, location, owner, redirects) : result[1];
1214
+ }
1215
+ router._preloads.delete(location.href);
1216
+ replaced = pending;
1217
+ }
1218
+ matches = router.matchRoutes(location, { _controller: controller });
1219
+ acquireMatchResources(matches);
1220
+ const promise = Promise.resolve().then(() => executeClientLane(router, location, matches, [
1221
+ controller,
1222
+ redirects,
1223
+ () => true,
1224
+ base,
1225
+ true
1226
+ ])).finally(() => {
1227
+ if (replaced) discardPreload(router, replaced);
1228
+ });
1229
+ preload = [
1230
+ matches,
1231
+ controller,
1232
+ promise,
1233
+ base,
1234
+ laneInputs(router, location),
1235
+ redirects
1236
+ ];
1237
+ (router._preloads ??= /* @__PURE__ */ new Map()).set(location.href, preload);
1238
+ const result = await promise;
1239
+ if (router._preloads?.get(location.href) !== preload) return isControl(result) ? void 0 : result[1];
1240
+ router._preloads.delete(location.href);
1241
+ if (isControl(result)) {
1242
+ controller.abort();
1243
+ transferMatchResources(router, matches);
1244
+ return followPreloadRedirect(router, result, location, owner, redirects);
1245
+ }
1246
+ transferMatchResources(router, result[1]);
1247
+ controller.abort();
1248
+ return result[1];
1249
+ } catch (cause) {
1250
+ if (!preload || router._preloads?.get(location.href) === preload) {
1251
+ if (preload) router._preloads.delete(location.href);
1252
+ controller.abort();
1253
+ if (matches) transferMatchResources(router, matches);
1254
+ }
1255
+ if (router._tx !== owner) return;
1256
+ if (!isNotFound(cause)) console.error(cause);
1257
+ return;
1258
+ }
1259
+ }
1260
+ async function hydrate(router) {
1261
+ if (process.env.NODE_ENV !== "production" && !window.$_TSR) throw new Error("Invariant failed: Expected to find bootstrap data on window.$_TSR, but we did not. Please file an issue!");
1262
+ const tsr = window.$_TSR;
1263
+ const adapters = router.options.serializationAdapters;
1264
+ if (adapters?.length) {
1265
+ tsr.t = new Map(adapters.map((adapter) => [adapter.key, adapter.fromSerializable]));
1266
+ tsr.buffer.forEach((script) => script());
1267
+ }
1268
+ tsr.initialized = true;
1269
+ const dehydratedRouter = tsr.router;
1270
+ if (process.env.NODE_ENV !== "production" && !dehydratedRouter) throw new Error("Invariant failed: Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!");
1271
+ router.ssr = { manifest: dehydratedRouter.manifest };
1272
+ const nonce = document.querySelector("meta[property=\"csp-nonce\"]")?.content;
1273
+ router.options.ssr = { nonce };
1274
+ const dehydratedMatches = dehydratedRouter.matches;
1275
+ const controller = new AbortController();
1276
+ const previousPreflight = router._preflight;
1277
+ router._preflight = controller;
1278
+ previousPreflight?.abort();
1279
+ const retire = (cause) => {
1280
+ if (router._preflight === controller) router._preflight = void 0;
1281
+ controller.abort(cause);
1282
+ return false;
1283
+ };
1284
+ const isCurrent = () => !router._tx && router._preflight === controller && !controller.signal.aborted || retire();
1285
+ let location;
1286
+ let candidates;
1287
+ let handoffInputs;
1288
+ try {
1289
+ await waitFor(router.options.hydrate?.(dehydratedRouter.dehydratedData), controller.signal);
1290
+ if (!isCurrent()) return;
1291
+ router.updateLatestLocation();
1292
+ location = router.latestLocation;
1293
+ router.stores.location.set(location);
1294
+ handoffInputs = laneInputs(router, location);
1295
+ candidates = router.matchRoutes(location, { _controller: controller });
1296
+ } catch (cause) {
1297
+ retire(cause);
1298
+ if (cause !== controller.signal) throw cause;
1299
+ }
1300
+ if (!isCurrent()) return;
1301
+ const committed = [];
1302
+ let pendingBoundary;
1303
+ let verifiedAssetEnd = 0;
1304
+ const retryFrom = (index) => {
1305
+ verifiedAssetEnd = Math.min(verifiedAssetEnd, index + 1);
1306
+ const removed = committed.splice(index);
1307
+ for (const match of removed) if (getRoute(router, match).options.loader && (match.status === "success" || !match.invalid && "loaderData" in match)) cacheLoaderMatch(router, {
1308
+ ...match,
1309
+ status: "success",
1310
+ error: void 0,
1311
+ preload: true
1312
+ }, router._cache.get(match.id));
1313
+ transferMatchResources(router, removed);
1314
+ };
1315
+ const shared = dehydratedMatches.length > candidates.length ? candidates.findIndex((match) => match._notFound) + 1 : dehydratedMatches.length;
1316
+ let isTerminal = false;
1317
+ for (let index = 0; index < shared; index++) {
1318
+ const candidate = candidates[index];
1319
+ const dehydrated = dehydratedMatches[index];
1320
+ if (typeof dehydrated.i !== "string" || hydrateSsrMatchId(dehydrated.i) !== candidate.id) {
1321
+ pendingBoundary ??= index;
1322
+ break;
1323
+ }
1324
+ verifiedAssetEnd = index + 1;
1325
+ const route = getRoute(router, candidate);
1326
+ if ("l" in dehydrated || dehydrated.s === "success" && dehydrated.e === void 0 && route.options.loader) candidate.loaderData = dehydrated.l;
1327
+ candidate.status = dehydrated.s;
1328
+ candidate.ssr = dehydrated.ssr;
1329
+ route.options.ssr = candidate.ssr;
1330
+ candidate.updatedAt = dehydrated.u;
1331
+ candidate.error = dehydrated.e;
1332
+ candidate._notFound ||= dehydrated.g;
1333
+ if (candidate.status === "error" || candidate.status === "notFound" || candidate._notFound) {
1334
+ isTerminal = true;
1335
+ committed.push(candidate);
1336
+ if (candidate.ssr === false || candidate.ssr === "data-only") pendingBoundary ??= index;
1337
+ break;
1338
+ }
1339
+ if (candidate.status === "pending") {
1340
+ pendingBoundary ??= index;
1341
+ break;
1342
+ }
1343
+ committed.push(candidate);
1344
+ if (candidate.ssr === "data-only") pendingBoundary ??= index;
1345
+ }
1346
+ let verifiedContextEnd = verifiedAssetEnd;
1347
+ if (!isTerminal && committed.length === shared && shared < candidates.length) pendingBoundary = shared;
1348
+ const chunks = committed.map(async (match) => {
1349
+ try {
1350
+ const route = getRoute(router, match);
1351
+ if (match._notFound) await Promise.all([loadRouteChunk(route), loadRouteChunk(route, "notFoundComponent")]);
1352
+ else await loadRouteChunk(route, match.status === "error" ? "errorComponent" : match.status === "notFound" ? "notFoundComponent" : void 0);
1353
+ return true;
1354
+ } catch {
1355
+ return false;
1356
+ }
1357
+ });
1358
+ let chunkFailure = 0;
1359
+ try {
1360
+ while (chunkFailure < chunks.length && await waitFor(chunks[chunkFailure], controller.signal)) chunkFailure++;
1361
+ } catch {
1362
+ isCurrent();
1363
+ return;
1364
+ }
1365
+ if (!isCurrent()) return;
1366
+ if (chunkFailure < committed.length) {
1367
+ verifiedContextEnd = Math.min(verifiedContextEnd, chunkFailure);
1368
+ retryFrom(chunkFailure);
1369
+ }
1370
+ const contextEnd = Math.max(pendingBoundary === committed.length ? committed.length + 1 : committed.length, verifiedContextEnd);
1371
+ for (let index = 0; index < contextEnd; index++) {
1372
+ const match = candidates[index];
1373
+ const route = getRoute(router, match);
1374
+ const parentContext = candidates[index - 1]?.context ?? router.options.context ?? {};
1375
+ let routeContext;
1376
+ if (route.options.context) {
1377
+ try {
1378
+ routeContext = match._ctx = route.options.context({
1379
+ deps: match.loaderDeps,
1380
+ params: match.params,
1381
+ context: parentContext,
1382
+ location,
1383
+ navigate: navigateFrom(router, location),
1384
+ buildLocation: router.buildLocation,
1385
+ cause: match.cause,
1386
+ abortController: controller,
1387
+ preload: false,
1388
+ matches: candidates,
1389
+ routeId: route.id
1390
+ }) || {};
1391
+ } catch {
1392
+ if (!isCurrent()) return;
1393
+ if (match.status !== "error" && match.status !== "notFound" && !match._notFound) {
1394
+ retryFrom(index);
1395
+ break;
1396
+ }
1397
+ }
1398
+ if (!isCurrent()) return;
1399
+ }
1400
+ match.context = {
1401
+ ...parentContext,
1402
+ ...routeContext,
1403
+ ...committed[index] && dehydratedMatches[index].b
1404
+ };
1405
+ }
1406
+ await projectLane(router, [location, candidates], controller.signal, 0, verifiedAssetEnd);
1407
+ if (!isCurrent()) return;
1408
+ const needsClientLoad = pendingBoundary !== void 0 || committed.length < shared;
1409
+ const committedMatches = isTerminal && committed.length === shared ? candidates : committed;
1410
+ let presented = needsClientLoad ? candidates : committedMatches;
1411
+ let dataOnlyAssetEnd;
1412
+ if (needsClientLoad && pendingBoundary !== void 0) {
1413
+ const boundary = presented[pendingBoundary];
1414
+ dataOnlyAssetEnd = boundary.status === "success" && boundary.ssr === "data-only" && boundary.error === void 0 && !boundary._notFound && verifiedAssetEnd > pendingBoundary + 1 ? verifiedAssetEnd : void 0;
1415
+ presented = presented.slice();
1416
+ presented[pendingBoundary] = {
1417
+ ...boundary,
1418
+ status: "pending",
1419
+ ssr: boundary.ssr === "data-only" ? "data-only" : false,
1420
+ _assetEnd: dataOnlyAssetEnd
1421
+ };
1422
+ }
1423
+ const claim = () => needsClientLoad && !router._tx && router.latestLocation.state === location.state && deepEqual(handoffInputs, laneInputs(router, router.latestLocation)) && router._committed === committedMatches && committedMatches.length && !controller.signal.aborted ? controller : void 0;
1424
+ const handoff = [claim, (matches) => {
1425
+ if (router._handoff !== handoff) return;
1426
+ const prefix = committedMatches.length;
1427
+ if (!matches || !claim() || committedMatches.some((match, index) => match.id !== matches[index]?.id)) {
1428
+ router._handoff = void 0;
1429
+ controller.abort();
1430
+ return;
1431
+ }
1432
+ let handoffAssetEnd = dataOnlyAssetEnd;
1433
+ if (handoffAssetEnd !== void 0) {
1434
+ for (let index = prefix; index < handoffAssetEnd; index++) if (candidates[index]?.id !== matches[index]?.id) {
1435
+ handoffAssetEnd = index > (pendingBoundary ?? -1) + 1 ? index : void 0;
1436
+ break;
1437
+ }
1438
+ }
1439
+ const clones = committedMatches.map((match) => ({ ...match }));
1440
+ if (handoffAssetEnd !== void 0) clones[pendingBoundary]._assetEnd = handoffAssetEnd;
1441
+ transferMatchResources(router, matches.splice(0, prefix, ...clones));
1442
+ for (let index = prefix; index < matches.length; index++) {
1443
+ const match = matches[index];
1444
+ const hydrated = candidates[index];
1445
+ if (hydrated?.id === match.id && hydrated._ctx) match._ctx = hydrated._ctx;
1446
+ match.abortController = controller;
1447
+ }
1448
+ return prefix;
1449
+ }];
1450
+ router._committed = committedMatches;
1451
+ router._handoff = handoff;
1452
+ router._preflight = void 0;
1453
+ router.batch(() => {
1454
+ router.stores.setMatches(presented);
1455
+ router.stores.status.set("idle");
1456
+ if (!needsClientLoad) router.stores.resolvedLocation.set(router.stores.location.get());
1457
+ });
1458
+ }
1459
+ //#endregion
1460
+ export { _getAssetMatches, _getRenderedMatches, hydrate, loadClientRoute, loadRouteChunk, preloadClientRoute, refreshClientRoute, replaceRouteChunk, transferMatchResources };
1461
+
1462
+ //# sourceMappingURL=load-client.js.map