@tanstack/router-core 1.171.24 → 1.171.26
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/dist/cjs/load-client.cjs +299 -389
- package/dist/cjs/load-client.cjs.map +1 -1
- package/dist/cjs/load-client.d.cts +18 -18
- package/dist/cjs/load-server.cjs +45 -32
- package/dist/cjs/load-server.cjs.map +1 -1
- package/dist/cjs/new-process-route-tree.cjs +1 -1
- package/dist/cjs/new-process-route-tree.cjs.map +1 -1
- package/dist/cjs/path.cjs +10 -4
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/redirect.cjs +1 -1
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/redirect.d.cts +1 -1
- package/dist/cjs/router.cjs +34 -30
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -5
- package/dist/esm/load-client.d.ts +18 -18
- package/dist/esm/load-client.js +299 -389
- package/dist/esm/load-client.js.map +1 -1
- package/dist/esm/load-server.js +45 -32
- package/dist/esm/load-server.js.map +1 -1
- package/dist/esm/new-process-route-tree.js +1 -1
- package/dist/esm/new-process-route-tree.js.map +1 -1
- package/dist/esm/path.js +10 -4
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/redirect.d.ts +1 -1
- package/dist/esm/redirect.js +1 -1
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/router.d.ts +3 -5
- package/dist/esm/router.js +35 -31
- package/dist/esm/router.js.map +1 -1
- package/package.json +8 -2
- package/src/load-client.ts +535 -659
- package/src/load-server.ts +97 -35
- package/src/new-process-route-tree.ts +1 -1
- package/src/path.ts +20 -6
- package/src/redirect.ts +2 -18
- package/src/router.ts +54 -78
package/dist/cjs/load-client.cjs
CHANGED
|
@@ -61,7 +61,7 @@ const SUCCESS = 0;
|
|
|
61
61
|
const ERROR = 1;
|
|
62
62
|
const NOT_FOUND = 2;
|
|
63
63
|
const REDIRECTED = 3;
|
|
64
|
-
const
|
|
64
|
+
const CANCELED_OUTCOME = [4];
|
|
65
65
|
function isControl(result) {
|
|
66
66
|
return typeof result[0] === "number";
|
|
67
67
|
}
|
|
@@ -95,24 +95,15 @@ function normalizeError(route, cause) {
|
|
|
95
95
|
}
|
|
96
96
|
return outcome;
|
|
97
97
|
}
|
|
98
|
-
function normalizeLaneError(route, cause, options) {
|
|
99
|
-
if (options[0].signal.aborted
|
|
100
|
-
|
|
101
|
-
return [CANCELED];
|
|
102
|
-
}
|
|
103
|
-
return normalizeError(route, cause);
|
|
104
|
-
}
|
|
105
|
-
function navigateFrom(router, location) {
|
|
106
|
-
return (opts) => router.navigate({
|
|
107
|
-
...opts,
|
|
108
|
-
_fromLocation: location
|
|
109
|
-
});
|
|
98
|
+
function normalizeLaneError(router, lane, route, cause, options) {
|
|
99
|
+
if (options[0].signal.aborted) return CANCELED_OUTCOME;
|
|
100
|
+
return materializeRedirect(router, lane, route, normalizeError(route, cause), options);
|
|
110
101
|
}
|
|
111
102
|
async function contextualize(router, lane, options, end, planSuccessfulLane, retainedEnd) {
|
|
112
103
|
const [location, matches] = lane;
|
|
113
104
|
const signal = options[0].signal;
|
|
114
|
-
const preload = !!options[
|
|
115
|
-
for (let index = options[
|
|
105
|
+
const preload = !!options[3];
|
|
106
|
+
for (let index = options[6] ?? 0; index < end; index++) {
|
|
116
107
|
const match = matches[index];
|
|
117
108
|
const route = getRoute(router, match);
|
|
118
109
|
match.abortController = options[0];
|
|
@@ -120,7 +111,10 @@ async function contextualize(router, lane, options, end, planSuccessfulLane, ret
|
|
|
120
111
|
const common = {
|
|
121
112
|
params: match.params,
|
|
122
113
|
location,
|
|
123
|
-
navigate:
|
|
114
|
+
navigate: (opts) => router.navigate({
|
|
115
|
+
...opts,
|
|
116
|
+
_fromLocation: location
|
|
117
|
+
}),
|
|
124
118
|
buildLocation: router.buildLocation,
|
|
125
119
|
cause: preload ? "preload" : match.cause,
|
|
126
120
|
abortController: options[0],
|
|
@@ -143,16 +137,13 @@ async function contextualize(router, lane, options, end, planSuccessfulLane, ret
|
|
|
143
137
|
match.context = context;
|
|
144
138
|
} catch (cause) {
|
|
145
139
|
releaseFlight(router, match);
|
|
146
|
-
return [index, normalizeLaneError(route, cause, options)];
|
|
147
|
-
}
|
|
148
|
-
if (signal.aborted || !options[2]()) {
|
|
149
|
-
options[0].abort();
|
|
150
|
-
return [index, [CANCELED]];
|
|
140
|
+
return [index, normalizeLaneError(router, lane, route, cause, options)];
|
|
151
141
|
}
|
|
142
|
+
if (signal.aborted) return [index, CANCELED_OUTCOME];
|
|
152
143
|
const validationError = match.paramsError ?? match.searchError;
|
|
153
144
|
if (validationError !== void 0) {
|
|
154
145
|
releaseFlight(router, match);
|
|
155
|
-
return [index, normalizeLaneError(route, validationError, options)];
|
|
146
|
+
return [index, normalizeLaneError(router, lane, route, validationError, options)];
|
|
156
147
|
}
|
|
157
148
|
const beforeLoad = route.options.beforeLoad;
|
|
158
149
|
if (!beforeLoad) continue;
|
|
@@ -163,16 +154,15 @@ async function contextualize(router, lane, options, end, planSuccessfulLane, ret
|
|
|
163
154
|
...router.options.additionalContext
|
|
164
155
|
};
|
|
165
156
|
const previousStatus = match.status;
|
|
166
|
-
if (
|
|
167
|
-
|
|
157
|
+
if (index >= retainedEnd) {
|
|
158
|
+
match.status = "pending";
|
|
159
|
+
options[7]?.();
|
|
160
|
+
}
|
|
168
161
|
try {
|
|
169
162
|
setFetching(router, match, "beforeLoad", options[0]);
|
|
170
163
|
const result = await waitFor(beforeLoad(beforeLoadContext), signal);
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
return [index, [CANCELED]];
|
|
174
|
-
}
|
|
175
|
-
const outcome = normalize(result, false, route.id);
|
|
164
|
+
if (signal.aborted) return [index, CANCELED_OUTCOME];
|
|
165
|
+
const outcome = materializeRedirect(router, lane, route, normalize(result, false, route.id), options);
|
|
176
166
|
if (outcome[0] !== SUCCESS) {
|
|
177
167
|
releaseFlight(router, match);
|
|
178
168
|
return [index, outcome];
|
|
@@ -183,9 +173,9 @@ async function contextualize(router, lane, options, end, planSuccessfulLane, ret
|
|
|
183
173
|
};
|
|
184
174
|
} catch (cause) {
|
|
185
175
|
releaseFlight(router, match);
|
|
186
|
-
return [index, normalizeLaneError(route, cause, options)];
|
|
176
|
+
return [index, normalizeLaneError(router, lane, route, cause, options)];
|
|
187
177
|
} finally {
|
|
188
|
-
if (
|
|
178
|
+
if (match.status === "pending") match.status = previousStatus;
|
|
189
179
|
setFetching(router, match, false, options[0]);
|
|
190
180
|
}
|
|
191
181
|
}
|
|
@@ -195,7 +185,7 @@ function releaseOwnedFlight(router, match, flight) {
|
|
|
195
185
|
if (!flight || --flight[2]) return;
|
|
196
186
|
if (router._flights?.get(match.id) === flight) {
|
|
197
187
|
const current = router._tx;
|
|
198
|
-
if (current && !current[0].signal.aborted && !
|
|
188
|
+
if (current && !current[0].signal.aborted && !current[3].includes(match) && current[3].some((candidate) => candidate.id === match.id) && current[3].some((candidate) => candidate.isFetching === "beforeLoad")) return;
|
|
199
189
|
router._flights.delete(match.id);
|
|
200
190
|
}
|
|
201
191
|
return flight[1];
|
|
@@ -214,7 +204,7 @@ function transferMatchResources(router, previous, next, deferSameIdFlight) {
|
|
|
214
204
|
for (const match of previous) if (!next?.includes(match)) {
|
|
215
205
|
const flight = match._flight;
|
|
216
206
|
match._flight = void 0;
|
|
217
|
-
if (deferSameIdFlight && flight?.[2] === 1 && router._flights?.get(match.id) === flight &&
|
|
207
|
+
if (deferSameIdFlight && flight?.[2] === 1 && router._flights?.get(match.id) === flight && next?.some((candidate) => candidate.id === match.id)) flight[2] = 0;
|
|
218
208
|
else {
|
|
219
209
|
const controller = releaseOwnedFlight(router, match, flight);
|
|
220
210
|
if (controller) abort.push(controller);
|
|
@@ -243,7 +233,10 @@ function getLoaderContext(router, lane, match, route, controller, parentMatchPro
|
|
|
243
233
|
return {
|
|
244
234
|
params: match.params,
|
|
245
235
|
location,
|
|
246
|
-
navigate:
|
|
236
|
+
navigate: (opts) => router.navigate({
|
|
237
|
+
...opts,
|
|
238
|
+
_fromLocation: location
|
|
239
|
+
}),
|
|
247
240
|
cause: preload ? "preload" : match.cause,
|
|
248
241
|
abortController: controller,
|
|
249
242
|
preload,
|
|
@@ -254,9 +247,10 @@ function getLoaderContext(router, lane, match, route, controller, parentMatchPro
|
|
|
254
247
|
...router.options.additionalContext
|
|
255
248
|
};
|
|
256
249
|
}
|
|
257
|
-
async function loadResource(router, lane, match, route, loader, parentMatchPromise,
|
|
250
|
+
async function loadResource(router, lane, match, route, loader, parentMatchPromise, options) {
|
|
251
|
+
const owner = options[0];
|
|
258
252
|
const signal = owner.signal;
|
|
259
|
-
if (signal.aborted) return
|
|
253
|
+
if (signal.aborted) return CANCELED_OUTCOME;
|
|
260
254
|
if (!loader) return [SUCCESS, void 0];
|
|
261
255
|
let flight = match._flight;
|
|
262
256
|
setFetching(router, match, "loader", owner);
|
|
@@ -264,7 +258,7 @@ async function loadResource(router, lane, match, route, loader, parentMatchPromi
|
|
|
264
258
|
if (!flight) {
|
|
265
259
|
const controller = new AbortController();
|
|
266
260
|
flight = [
|
|
267
|
-
Promise.resolve().then(() => loader(getLoaderContext(router, lane, match, route, controller, parentMatchPromise,
|
|
261
|
+
Promise.resolve().then(() => loader(getLoaderContext(router, lane, match, route, controller, parentMatchPromise, !!options[3]))).then((value) => normalize(value, false, route.id), (cause) => normalize(cause, true, route.id)).then((result) => {
|
|
268
262
|
if (result[0] !== SUCCESS && router._flights?.get(match.id) === flight) {
|
|
269
263
|
router._flights.delete(match.id);
|
|
270
264
|
if (!flight[2]) controller.abort();
|
|
@@ -278,11 +272,11 @@ async function loadResource(router, lane, match, route, loader, parentMatchPromi
|
|
|
278
272
|
}
|
|
279
273
|
match._flight = flight;
|
|
280
274
|
match.abortController = flight[1];
|
|
281
|
-
return await waitFor(flight[0], signal);
|
|
275
|
+
return materializeRedirect(router, lane, route, await waitFor(flight[0], signal), options);
|
|
282
276
|
} catch (cause) {
|
|
283
|
-
if (cause !== signal) throw cause;
|
|
277
|
+
if (cause !== signal || !signal.aborted) throw cause;
|
|
284
278
|
releaseFlight(router, match);
|
|
285
|
-
return
|
|
279
|
+
return CANCELED_OUTCOME;
|
|
286
280
|
} finally {
|
|
287
281
|
setFetching(router, match, false, owner);
|
|
288
282
|
}
|
|
@@ -325,7 +319,7 @@ function getParentSnapshot(match, outcome) {
|
|
|
325
319
|
function createLoaderTask(router, lane, index, tasks, semanticParent, options, retainedEnd) {
|
|
326
320
|
const match = lane[1][index];
|
|
327
321
|
const route = getRoute(router, match);
|
|
328
|
-
const preload = !!options[
|
|
322
|
+
const preload = !!options[3];
|
|
329
323
|
const plannedCacheMatch = router._cache.get(match.id);
|
|
330
324
|
let configured;
|
|
331
325
|
let reload = false;
|
|
@@ -334,20 +328,17 @@ function createLoaderTask(router, lane, index, tasks, semanticParent, options, r
|
|
|
334
328
|
if (match.status === "success") {
|
|
335
329
|
configured = route.options.shouldReload;
|
|
336
330
|
if (typeof configured === "function") configured = configured(getLoaderContext(router, lane, match, route, options[0], semanticParent, preload));
|
|
337
|
-
if (
|
|
338
|
-
options[0].abort();
|
|
339
|
-
reloadFailure = [CANCELED];
|
|
340
|
-
}
|
|
331
|
+
if (options[0].signal.aborted) reloadFailure = CANCELED_OUTCOME;
|
|
341
332
|
}
|
|
342
333
|
if (!reloadFailure) if (match.status !== "success") reload = true;
|
|
343
334
|
else {
|
|
344
|
-
const staleAge = options[
|
|
345
|
-
reload = !!(match.invalid || configured || configured === void 0 && Date.now() - match.updatedAt >= staleAge && (options[
|
|
335
|
+
const staleAge = options[3] || match.preload ? route.options.preloadStaleTime ?? router.options.defaultPreloadStaleTime ?? 3e4 : route.options.staleTime ?? router.options.defaultStaleTime ?? 0;
|
|
336
|
+
reload = !!(match.invalid || configured || configured === void 0 && Date.now() - match.updatedAt >= staleAge && (options[5] || match.cause === "enter" || options[2].some((candidate) => candidate.routeId === match.routeId && candidate.id !== match.id)));
|
|
346
337
|
}
|
|
347
338
|
} catch (cause) {
|
|
348
339
|
match.invalid = true;
|
|
349
340
|
releaseFlight(router, match);
|
|
350
|
-
reloadFailure = normalizeLaneError(route, cause, options);
|
|
341
|
+
reloadFailure = normalizeLaneError(router, lane, route, cause, options);
|
|
351
342
|
}
|
|
352
343
|
const routeLoader = route.options.loader;
|
|
353
344
|
const loader = typeof routeLoader === "function" ? routeLoader : routeLoader?.handler;
|
|
@@ -355,10 +346,11 @@ function createLoaderTask(router, lane, index, tasks, semanticParent, options, r
|
|
|
355
346
|
if (donor === match._flight || reloadFailure) donor = void 0;
|
|
356
347
|
else if (donor && !reload && !preload && configured === void 0) reload = true;
|
|
357
348
|
else if (!reload) donor = void 0;
|
|
358
|
-
const background = !!(routeLoader && reload && match.status === "success" && !preload && !options[
|
|
349
|
+
const background = !!(routeLoader && reload && match.status === "success" && !preload && !options[4] && ((typeof routeLoader === "function" ? void 0 : routeLoader?.staleReloadMode) ?? router.options.defaultStaleReloadMode) !== "blocking");
|
|
359
350
|
const loaded = reload && (!preload || route.options.preload !== false);
|
|
360
351
|
const blocking = loaded && !background && (match.status !== "success" || !!routeLoader);
|
|
361
|
-
const
|
|
352
|
+
const onReady = index >= retainedEnd ? options[7] : void 0;
|
|
353
|
+
const onLazyReady = route.lazyFn && route._lazy !== true ? onReady : void 0;
|
|
362
354
|
if (loaded && !routeLoader) {
|
|
363
355
|
match.invalid = false;
|
|
364
356
|
match.updatedAt = Date.now();
|
|
@@ -368,24 +360,24 @@ function createLoaderTask(router, lane, index, tasks, semanticParent, options, r
|
|
|
368
360
|
const acceptedFlight = match._flight;
|
|
369
361
|
match._flight = donor;
|
|
370
362
|
releaseOwnedFlight(router, match, acceptedFlight)?.abort();
|
|
371
|
-
if (
|
|
372
|
-
|
|
363
|
+
if (index >= retainedEnd) match.status = "pending";
|
|
364
|
+
onReady?.();
|
|
373
365
|
}
|
|
374
366
|
if (!loaded) match.isFetching = false;
|
|
375
|
-
const outcome = (reloadFailure ? Promise.resolve(reloadFailure) : !blocking ? Promise.resolve([SUCCESS, match.loaderData]) : loadResource(router, lane, match, route, loader, semanticParent,
|
|
367
|
+
const outcome = (reloadFailure ? Promise.resolve(reloadFailure) : !blocking ? Promise.resolve([SUCCESS, match.loaderData]) : loadResource(router, lane, match, route, loader, semanticParent, options)).then((result) => {
|
|
376
368
|
if (blocking) {
|
|
377
369
|
settleInto(match, result, preload);
|
|
378
370
|
if (result[0] === SUCCESS) {
|
|
379
|
-
if (routeLoader && !options[0].signal.aborted
|
|
380
|
-
match.status = "pending";
|
|
371
|
+
if (routeLoader && !options[0].signal.aborted) cacheLoaderMatch(router, match, plannedCacheMatch);
|
|
372
|
+
if (index >= retainedEnd) match.status = "pending";
|
|
381
373
|
}
|
|
382
374
|
}
|
|
383
375
|
return result;
|
|
384
376
|
});
|
|
385
|
-
const chunkFailure = waitFor(Promise.resolve().then(() => loadRouteChunk(route, void 0, onLazyReady)), options[0].signal).then(() => void 0, (cause) => [index, normalizeLaneError(route, cause, options)]).then((failure) => outcome.then((result) => {
|
|
386
|
-
if (blocking && !failure && result[0] === SUCCESS && match.status === "pending" && options[
|
|
377
|
+
const chunkFailure = waitFor(Promise.resolve().then(() => loadRouteChunk(route, void 0, onLazyReady)), options[0].signal).then(() => void 0, (cause) => lane[1].some((candidate, candidateIndex) => candidateIndex <= index && (candidate.status === "error" || candidate.status === "notFound" || candidate._notFound)) ? void 0 : [index, normalizeLaneError(router, lane, route, cause, options)]).then((failure) => outcome.then((result) => {
|
|
378
|
+
if (blocking && !failure && result[0] === SUCCESS && match.status === "pending" && !options[0].signal.aborted) {
|
|
387
379
|
match.status = "success";
|
|
388
|
-
|
|
380
|
+
onReady?.();
|
|
389
381
|
}
|
|
390
382
|
return failure;
|
|
391
383
|
}));
|
|
@@ -403,7 +395,7 @@ function createLoaderTask(router, lane, index, tasks, semanticParent, options, r
|
|
|
403
395
|
};
|
|
404
396
|
match.invalid = false;
|
|
405
397
|
match.isFetching = "loader";
|
|
406
|
-
const backgroundOutcome = loadResource(router, lane, candidate, route, loader, semanticParent,
|
|
398
|
+
const backgroundOutcome = loadResource(router, lane, candidate, route, loader, semanticParent, options).then((result) => {
|
|
407
399
|
match.isFetching = false;
|
|
408
400
|
settleInto(candidate, result, false);
|
|
409
401
|
return result;
|
|
@@ -422,11 +414,11 @@ async function getNotFoundBoundary(router, matches, indexed, signal, fallback =
|
|
|
422
414
|
if (index < 0) index = 0;
|
|
423
415
|
for (let i = index; i >= 0; i--) {
|
|
424
416
|
const route = getRoute(router, matches[i]);
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
await waitFor(loading, signal);
|
|
417
|
+
try {
|
|
418
|
+
const loading = loadRouteChunk(route, false);
|
|
419
|
+
if (loading) await waitFor(loading, signal);
|
|
428
420
|
} catch (cause) {
|
|
429
|
-
if (cause === signal) throw cause;
|
|
421
|
+
if (cause === signal && signal.aborted) throw cause;
|
|
430
422
|
}
|
|
431
423
|
if (route.options.notFoundComponent) return i;
|
|
432
424
|
}
|
|
@@ -460,7 +452,32 @@ async function settleTasks(tasks, serialFailure, redirectTasks, gate) {
|
|
|
460
452
|
}
|
|
461
453
|
return serialFailure ?? loaderFailure;
|
|
462
454
|
}
|
|
463
|
-
|
|
455
|
+
function materializeRedirect(router, lane, route, outcome, options, failed) {
|
|
456
|
+
while (outcome[0] === REDIRECTED) {
|
|
457
|
+
const redirect = outcome[1];
|
|
458
|
+
if (redirect.options.reloadDocument ? options[3] : options[1] >= 20) return outcome;
|
|
459
|
+
try {
|
|
460
|
+
if (redirect.options.href && redirect.options.reloadDocument) {
|
|
461
|
+
router.resolveRedirect(redirect);
|
|
462
|
+
return outcome;
|
|
463
|
+
}
|
|
464
|
+
return [
|
|
465
|
+
REDIRECTED,
|
|
466
|
+
redirect,
|
|
467
|
+
router.buildLocation({
|
|
468
|
+
...redirect.options,
|
|
469
|
+
_fromLocation: lane[0],
|
|
470
|
+
_includeValidateSearch: true
|
|
471
|
+
})
|
|
472
|
+
];
|
|
473
|
+
} catch (cause) {
|
|
474
|
+
outcome = failed ? [ERROR, cause] : normalizeError(route, cause);
|
|
475
|
+
failed = true;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return outcome;
|
|
479
|
+
}
|
|
480
|
+
async function reduceLane(router, lane, tasks, controller, settlement, onReady) {
|
|
464
481
|
const matches = lane[1];
|
|
465
482
|
let failure = await settlement;
|
|
466
483
|
let redirectLimitExceeded = false;
|
|
@@ -489,7 +506,7 @@ async function reduceLane(router, lane, tasks, controller, redirects, settlement
|
|
|
489
506
|
}
|
|
490
507
|
if ((failure?.[1][0] ?? 0) >= REDIRECTED) {
|
|
491
508
|
const outcome = failure[1];
|
|
492
|
-
if (outcome[0] !== REDIRECTED || outcome[1].options.reloadDocument ||
|
|
509
|
+
if (outcome[0] !== REDIRECTED || outcome[1].options.reloadDocument || outcome[2]) {
|
|
493
510
|
discardBackground(router, lane);
|
|
494
511
|
return outcome;
|
|
495
512
|
}
|
|
@@ -518,19 +535,18 @@ async function reduceLane(router, lane, tasks, controller, redirects, settlement
|
|
|
518
535
|
}
|
|
519
536
|
};
|
|
520
537
|
install();
|
|
538
|
+
if (!outcome) onReady?.();
|
|
521
539
|
const route = getRoute(router, match);
|
|
522
540
|
try {
|
|
523
541
|
await waitFor(outcome ? Promise.resolve().then(() => loadRouteChunk(route, kind === ERROR ? "errorComponent" : "notFoundComponent")) : Promise.all([loadRouteChunk(route), loadRouteChunk(route, "notFoundComponent")]), controller.signal);
|
|
524
542
|
} catch (cause) {
|
|
525
|
-
if (cause === controller.signal) {
|
|
543
|
+
if (cause === controller.signal && controller.signal.aborted) {
|
|
526
544
|
discardBackground(router, lane);
|
|
527
|
-
return
|
|
545
|
+
return CANCELED_OUTCOME;
|
|
528
546
|
}
|
|
529
547
|
}
|
|
530
|
-
if (!outcome)
|
|
531
|
-
|
|
532
|
-
onReady?.();
|
|
533
|
-
} else if (redirectLimitExceeded) {
|
|
548
|
+
if (!outcome) match.status = "success";
|
|
549
|
+
else if (redirectLimitExceeded) {
|
|
534
550
|
controller.abort();
|
|
535
551
|
await Promise.all([
|
|
536
552
|
...tasks.map((task) => task[1]),
|
|
@@ -564,7 +580,7 @@ async function projectLane(router, lane, signal, start = 0, end = lane[1].length
|
|
|
564
580
|
match.styles = head?.styles;
|
|
565
581
|
match.scripts = scripts;
|
|
566
582
|
} catch (cause) {
|
|
567
|
-
if (cause === signal) break;
|
|
583
|
+
if (cause === signal && signal.aborted) break;
|
|
568
584
|
console.error(cause);
|
|
569
585
|
}
|
|
570
586
|
if (match.status !== "success" || match._notFound) break;
|
|
@@ -573,63 +589,66 @@ async function projectLane(router, lane, signal, start = 0, end = lane[1].length
|
|
|
573
589
|
}
|
|
574
590
|
async function executeClientLane(router, location, matches, options) {
|
|
575
591
|
const matched = [location, matches];
|
|
576
|
-
const
|
|
577
|
-
let
|
|
578
|
-
|
|
579
|
-
const
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
592
|
+
const signal = options[0].signal;
|
|
593
|
+
let reduced;
|
|
594
|
+
try {
|
|
595
|
+
const presented = router.stores.matches.get();
|
|
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, signal, plannedBoundary);
|
|
599
|
+
if (boundary !== plannedBoundary) {
|
|
600
|
+
matches[plannedBoundary]._notFound = void 0;
|
|
601
|
+
matches[boundary]._notFound = true;
|
|
602
|
+
}
|
|
603
|
+
plannedBoundary = boundary;
|
|
583
604
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
if (committed?.id !== match.id || committed.status !== "success" || committed._notFound || match.preload || visible?.id !== match.id || visible.status !== "success" || visible._notFound) break;
|
|
593
|
-
retainedEnd++;
|
|
594
|
-
}
|
|
595
|
-
const tasks = [];
|
|
596
|
-
const start = options[7] ?? 0;
|
|
597
|
-
let semanticParent = start ? Promise.resolve(matched[1][start - 1]) : void 0;
|
|
598
|
-
const planSuccessfulLane = () => {
|
|
599
|
-
for (let index = start; index < end; index++) {
|
|
600
|
-
if (options[0].signal.aborted) break;
|
|
601
|
-
semanticParent = createLoaderTask(router, matched, index, tasks, semanticParent, options, retainedEnd);
|
|
605
|
+
let end = plannedBoundary < 0 ? matches.length : plannedBoundary + 1;
|
|
606
|
+
let retainedEnd = 0;
|
|
607
|
+
while (retainedEnd < end && retainedEnd !== plannedBoundary) {
|
|
608
|
+
const match = matches[retainedEnd];
|
|
609
|
+
const committed = options[2][retainedEnd];
|
|
610
|
+
const visible = presented[retainedEnd];
|
|
611
|
+
if (committed?.id !== match.id || committed.status !== "success" || committed._notFound || match.preload || visible?.id !== match.id || visible.status !== "success" || visible._notFound) break;
|
|
612
|
+
retainedEnd++;
|
|
602
613
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
612
|
-
planSuccessfulLane
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
614
|
+
const tasks = [];
|
|
615
|
+
const start = options[6] ?? 0;
|
|
616
|
+
let semanticParent = start ? Promise.resolve(matched[1][start - 1]) : void 0;
|
|
617
|
+
const planSuccessfulLane = () => {
|
|
618
|
+
for (let index = start; index < end; index++) {
|
|
619
|
+
if (signal.aborted) break;
|
|
620
|
+
semanticParent = createLoaderTask(router, matched, index, tasks, semanticParent, options, retainedEnd);
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
const failure = await contextualize(router, matched, options, end, planSuccessfulLane, retainedEnd);
|
|
624
|
+
if (failure) {
|
|
625
|
+
options[4] = true;
|
|
626
|
+
end = failure[0];
|
|
627
|
+
if (failure[1][0] === NOT_FOUND) {
|
|
628
|
+
const boundary = await getNotFoundBoundary(router, matched[1], failure, signal);
|
|
629
|
+
failure[2] = boundary;
|
|
630
|
+
end = Math.min(end, boundary + 1);
|
|
631
|
+
} else if (failure[1][0] >= REDIRECTED) end = 0;
|
|
632
|
+
planSuccessfulLane();
|
|
619
633
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
634
|
+
if (!signal.aborted && !options[3]) {
|
|
635
|
+
const abort = [];
|
|
636
|
+
for (const [id, flight] of router._flights ?? []) if (!flight[2]) {
|
|
637
|
+
router._flights.delete(id);
|
|
638
|
+
abort.push(flight[1]);
|
|
639
|
+
}
|
|
640
|
+
for (const controller of abort) controller.abort();
|
|
641
|
+
}
|
|
642
|
+
const reduction = reduceLane(router, matched, tasks, options[0], settleTasks(tasks, failure, matched[2]), options[7]);
|
|
625
643
|
if (matched[2]?.length) matched[3] = settleTasks(matched[2], void 0, void 0, reduction.then((foreground) => isControl(foreground) ? 0 : _getRenderedMatches(foreground[1]).length, () => 0));
|
|
626
644
|
reduced = await reduction;
|
|
627
645
|
} catch (cause) {
|
|
628
646
|
discardBackground(router, matched);
|
|
647
|
+
if (cause === signal && signal.aborted) return CANCELED_OUTCOME;
|
|
629
648
|
throw cause;
|
|
630
649
|
}
|
|
631
650
|
if (isControl(reduced)) return reduced;
|
|
632
|
-
return projectLane(router, reduced,
|
|
651
|
+
return projectLane(router, reduced, signal, options[6] === reduced[1].length ? options[6] : 0);
|
|
633
652
|
}
|
|
634
653
|
/**
|
|
635
654
|
* Waits for `pendingMs`, then presents the complete lane. Rendering applies the
|
|
@@ -639,90 +658,94 @@ async function executeClientLane(router, location, matches, options) {
|
|
|
639
658
|
*/
|
|
640
659
|
function offerPending(router, tx) {
|
|
641
660
|
if (router._tx !== tx) return;
|
|
642
|
-
let session = router._pending;
|
|
643
|
-
let tookOver = false;
|
|
644
|
-
const sessionMatchId = session?.[0][3][session[1]]?.id;
|
|
645
|
-
if (session?.[0] !== tx) if (session && tx[3][session[1]]?.id === sessionMatchId) {
|
|
646
|
-
session[0] = tx;
|
|
647
|
-
tookOver = true;
|
|
648
|
-
} else {
|
|
649
|
-
clearTimeout(session?.[3]);
|
|
650
|
-
router._pending = session = void 0;
|
|
651
|
-
}
|
|
652
661
|
const matches = tx[3];
|
|
653
662
|
const presented = router.stores.matches.get();
|
|
654
|
-
let
|
|
655
|
-
let delay;
|
|
656
|
-
let min;
|
|
657
|
-
let component;
|
|
658
|
-
let presentedPending = false;
|
|
663
|
+
let session = router._pending;
|
|
659
664
|
for (let index = 0; index < matches.length; index++) {
|
|
660
665
|
const match = matches[index];
|
|
661
|
-
const success = match.status === "success";
|
|
662
|
-
presentedPending = presented[index]?.id === match.id && presented[index]?.status === "pending";
|
|
666
|
+
const success = match.status === "success" && !match._notFound;
|
|
667
|
+
const presentedPending = presented[index]?.id === match.id && presented[index]?.status === "pending";
|
|
663
668
|
if (success && !presentedPending) continue;
|
|
664
669
|
const route = getRoute(router, match);
|
|
665
|
-
delay = success && presentedPending || match.invalid ? 0 : route.options.pendingMs ?? router.options.defaultPendingMs;
|
|
666
|
-
component = route.options.pendingComponent ?? router.options.defaultPendingComponent;
|
|
667
|
-
if (!component || typeof delay !== "number" || delay === Infinity)
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
670
|
+
const delay = success && presentedPending || match.invalid ? 0 : route.options.pendingMs ?? router.options.defaultPendingMs;
|
|
671
|
+
const component = route.options.pendingComponent ?? router.options.defaultPendingComponent;
|
|
672
|
+
if (!component || typeof delay !== "number" || delay === Infinity) {
|
|
673
|
+
if (session) {
|
|
674
|
+
session[0] = tx;
|
|
675
|
+
session[2] = 0;
|
|
676
|
+
session[4] = true;
|
|
677
|
+
}
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const min = route.options.pendingMinMs ?? router.options.defaultPendingMinMs ?? 0;
|
|
681
|
+
let tookOver = false;
|
|
682
|
+
if (session?.[1] === match.id) {
|
|
683
|
+
tookOver = session[0] !== tx;
|
|
684
|
+
session[0] = tx;
|
|
685
|
+
} else {
|
|
686
|
+
clearTimeout(session?.[3]);
|
|
687
|
+
router._pending = session = void 0;
|
|
688
|
+
}
|
|
689
|
+
if (!session) router._pending = session = [
|
|
677
690
|
tx,
|
|
678
|
-
|
|
691
|
+
match.id,
|
|
679
692
|
presentedPending ? Date.now() + min : tx[4] + delay,
|
|
680
693
|
void 0,
|
|
681
|
-
presentedPending
|
|
694
|
+
presentedPending || void 0,
|
|
682
695
|
component
|
|
683
696
|
];
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
697
|
+
if (session[4] && !tookOver && session[5] === component) return;
|
|
698
|
+
session[5] = component;
|
|
699
|
+
if (!session[4]) {
|
|
700
|
+
clearTimeout(session[3]);
|
|
701
|
+
const remaining = session[2] - Date.now();
|
|
702
|
+
if (remaining > 0) {
|
|
703
|
+
session[3] = setTimeout(() => offerPending(router, tx), remaining);
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
session[2] = 0;
|
|
693
707
|
}
|
|
694
|
-
|
|
708
|
+
const offered = matches.map((match) => ({
|
|
709
|
+
...match,
|
|
710
|
+
_flight: void 0
|
|
711
|
+
}));
|
|
712
|
+
offered[index].status = "pending";
|
|
713
|
+
const ack = session[4] = router.startTransition(() => router.stores.setMatches(offered), offered).then((rendered) => {
|
|
714
|
+
if (rendered && router._pending === session && session[4] === ack && !session[2]) session[2] = Date.now() + min;
|
|
715
|
+
return rendered;
|
|
716
|
+
});
|
|
717
|
+
return;
|
|
695
718
|
}
|
|
696
|
-
const offered = matches.map((match) => ({
|
|
697
|
-
...match,
|
|
698
|
-
_flight: void 0
|
|
699
|
-
}));
|
|
700
|
-
offered[boundary].status = "pending";
|
|
701
|
-
const ack = router.startTransition(() => router.stores.setMatches(offered), offered).then((rendered) => {
|
|
702
|
-
if (rendered && router._pending === session && session[4] === ack && !session[2]) session[2] = Date.now() + min;
|
|
703
|
-
return rendered;
|
|
704
|
-
});
|
|
705
|
-
session[4] = ack;
|
|
706
719
|
}
|
|
707
720
|
/**
|
|
708
|
-
* Cancels pending UI timing
|
|
709
|
-
*
|
|
721
|
+
* Cancels pending UI timing unless the current successor can take over the
|
|
722
|
+
* same boundary that remains painted.
|
|
710
723
|
*/
|
|
711
724
|
function finishPending(router, tx) {
|
|
712
725
|
const session = router._pending;
|
|
713
|
-
if (
|
|
714
|
-
clearTimeout(session[3]);
|
|
726
|
+
if (router._tx === tx || !router._tx?.[3].some((match) => match.id === session?.[1])) {
|
|
727
|
+
clearTimeout(session?.[3]);
|
|
715
728
|
router._pending = void 0;
|
|
716
729
|
}
|
|
717
730
|
}
|
|
731
|
+
async function awaitPendingMinimum(router, tx) {
|
|
732
|
+
const session = router._pending;
|
|
733
|
+
if (!session) return;
|
|
734
|
+
clearTimeout(session[3]);
|
|
735
|
+
const remaining = session[2] - Date.now();
|
|
736
|
+
if (!session[4] || remaining <= 0 || !_getRenderedMatches(tx[3]).some((match) => match.id === session[1])) return;
|
|
737
|
+
let timer;
|
|
738
|
+
try {
|
|
739
|
+
await waitFor(new Promise((resolve) => {
|
|
740
|
+
timer = setTimeout(resolve, remaining);
|
|
741
|
+
}), tx[0].signal);
|
|
742
|
+
} catch {}
|
|
743
|
+
clearTimeout(timer);
|
|
744
|
+
}
|
|
718
745
|
function publishMatches(router, matches) {
|
|
719
746
|
router._committed = matches;
|
|
720
747
|
router.stores.setMatches(matches);
|
|
721
748
|
}
|
|
722
|
-
function discardLane(router, lane) {
|
|
723
|
-
transferMatchResources(router, lane[1]);
|
|
724
|
-
discardBackground(router, lane);
|
|
725
|
-
}
|
|
726
749
|
function commitMatches(router, tx, matches, resolvedPrefix) {
|
|
727
750
|
const previous = router._committed;
|
|
728
751
|
const previousCached = router._cache;
|
|
@@ -732,111 +755,29 @@ function commitMatches(router, tx, matches, resolvedPrefix) {
|
|
|
732
755
|
}
|
|
733
756
|
const cut = _getRenderedMatches(matches).length;
|
|
734
757
|
const cached = /* @__PURE__ */ new Map();
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
758
|
+
if (process.env.NODE_ENV === "production" || !tx[6]) {
|
|
759
|
+
const now = Date.now();
|
|
760
|
+
for (const match of [...previous, ...previousCached.values()]) {
|
|
761
|
+
if (match.status !== "success" || matches.some((candidate, index) => candidate.id === match.id && (index < cut || candidate.status === "success"))) continue;
|
|
762
|
+
const route = getRoute(router, match);
|
|
763
|
+
if (!route.options.loader || now - match.updatedAt >= (match.preload ? route.options.preloadGcTime ?? router.options.defaultPreloadGcTime ?? 3e5 : route.options.gcTime ?? router.options.defaultGcTime ?? 3e5)) continue;
|
|
764
|
+
cached.set(match.id, previousCached.get(match.id) === match ? match : {
|
|
765
|
+
...match,
|
|
766
|
+
_flight: void 0,
|
|
767
|
+
isFetching: false,
|
|
768
|
+
context: {}
|
|
769
|
+
});
|
|
770
|
+
}
|
|
746
771
|
}
|
|
747
772
|
tx[3] = [];
|
|
748
773
|
router._cache = cached;
|
|
749
774
|
publishMatches(router, matches);
|
|
750
775
|
transferMatchResources(router, [...previousCached.values(), ...previous], [...matches, ...cached.values()]);
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
const previous = router._committed;
|
|
755
|
-
const previousCached = router._cache;
|
|
756
|
-
for (const match of matches) match.preload = false;
|
|
757
|
-
const cached = /* @__PURE__ */ new Map();
|
|
758
|
-
tx[3] = [];
|
|
759
|
-
router._cache = cached;
|
|
760
|
-
checkpoint.previousMatches = previous;
|
|
761
|
-
checkpoint.previousCache = previousCached;
|
|
762
|
-
checkpoint.published = true;
|
|
763
|
-
publishMatches(router, matches);
|
|
764
|
-
if (!checkpoint.published || router._tx !== tx) return;
|
|
765
|
-
require_router.runRouteLifecycle(router, previous, matches, () => router._tx === tx);
|
|
766
|
-
}
|
|
767
|
-
function settlePublication(router, checkpoint) {
|
|
768
|
-
if (!checkpoint.published) return;
|
|
769
|
-
checkpoint.published = false;
|
|
770
|
-
transferMatchResources(router, [...checkpoint.previousCache.values(), ...checkpoint.previousMatches], [...router._cache.values(), ...router._committed]);
|
|
771
|
-
}
|
|
772
|
-
function rollbackPublication(router, tx, lane, checkpoint) {
|
|
773
|
-
if (!checkpoint.published || router._tx !== tx || router._committed !== lane[1]) {
|
|
774
|
-
settlePublication(router, checkpoint);
|
|
775
|
-
return false;
|
|
776
|
-
}
|
|
777
|
-
const discarded = [...router._cache.values(), ...router._committed];
|
|
778
|
-
const restored = [...checkpoint.previousCache.values(), ...checkpoint.previousMatches];
|
|
779
|
-
router._cache = checkpoint.previousCache;
|
|
780
|
-
router._committed = checkpoint.previousMatches;
|
|
781
|
-
checkpoint.published = false;
|
|
782
|
-
for (const match of discarded) if (!restored.includes(match) && match._flight && router._flights?.get(match.id) === match._flight) router._flights.delete(match.id);
|
|
783
|
-
finishPending(router, tx);
|
|
784
|
-
router.batch(() => {
|
|
785
|
-
router.stores.status.set("idle");
|
|
786
|
-
router.stores.setMatches(checkpoint.previousPresentation);
|
|
787
|
-
});
|
|
788
|
-
tx[0].abort();
|
|
789
|
-
transferMatchResources(router, discarded, restored);
|
|
790
|
-
discardBackground(router, lane);
|
|
791
|
-
if (router._tx === tx && router._commitPromise === checkpoint.commitPromise) {
|
|
792
|
-
router._commitPromise?.resolve();
|
|
793
|
-
router._commitPromise = void 0;
|
|
794
|
-
}
|
|
795
|
-
return true;
|
|
796
|
-
}
|
|
797
|
-
async function transitionRefresh(router, tx, lane, changeInfo) {
|
|
798
|
-
const refresh = tx[6];
|
|
799
|
-
const checkpoint = {
|
|
800
|
-
previousMatches: router._committed,
|
|
801
|
-
previousPresentation: refresh[0],
|
|
802
|
-
previousCache: router._cache,
|
|
803
|
-
commitPromise: router._commitPromise,
|
|
804
|
-
published: false
|
|
805
|
-
};
|
|
806
|
-
const commit = () => {
|
|
807
|
-
finishPending(router, tx);
|
|
808
|
-
refresh[2] = rollback;
|
|
809
|
-
commitRefreshMatches(router, tx, lane[1], checkpoint);
|
|
810
|
-
if (!checkpoint.published || router._tx !== tx) return;
|
|
811
|
-
router.emit({
|
|
812
|
-
type: "onLoad",
|
|
813
|
-
...changeInfo
|
|
814
|
-
});
|
|
815
|
-
if (router._tx === tx) router.emit({
|
|
816
|
-
type: "onBeforeRouteMount",
|
|
817
|
-
...changeInfo
|
|
818
|
-
});
|
|
819
|
-
};
|
|
820
|
-
const rollback = () => {
|
|
821
|
-
if (refresh[2] === rollback) refresh[2] = void 0;
|
|
822
|
-
const restored = rollbackPublication(router, tx, lane, checkpoint);
|
|
823
|
-
router._cancelTransition?.();
|
|
824
|
-
return restored;
|
|
825
|
-
};
|
|
826
|
-
try {
|
|
827
|
-
const rendered = await router.startTransition(commit, lane[1]);
|
|
828
|
-
if (refresh[2] === rollback) refresh[2] = void 0;
|
|
829
|
-
if (checkpoint.published) {
|
|
830
|
-
const handoff = refresh[1];
|
|
831
|
-
if (handoff && router._handoff === handoff) handoff[1]();
|
|
832
|
-
if (router._tx === tx) tx[6] = void 0;
|
|
833
|
-
}
|
|
834
|
-
settlePublication(router, checkpoint);
|
|
835
|
-
return rendered;
|
|
836
|
-
} catch (cause) {
|
|
837
|
-
if (rollback()) return;
|
|
838
|
-
throw cause;
|
|
776
|
+
if (process.env.NODE_ENV !== "production") {
|
|
777
|
+
const handoff = tx[6]?.[0];
|
|
778
|
+
if (handoff && router._handoff === handoff) handoff[1]();
|
|
839
779
|
}
|
|
780
|
+
require_router.runRouteLifecycle(router, previous, matches, tx);
|
|
840
781
|
}
|
|
841
782
|
async function awaitCurrent(router, owner) {
|
|
842
783
|
let current = router._tx;
|
|
@@ -846,28 +787,40 @@ async function awaitCurrent(router, owner) {
|
|
|
846
787
|
current = router._tx;
|
|
847
788
|
}
|
|
848
789
|
}
|
|
849
|
-
async function followRedirect(router, tx,
|
|
850
|
-
|
|
851
|
-
|
|
790
|
+
async function followRedirect(router, tx, outcome) {
|
|
791
|
+
const redirect = outcome[1];
|
|
792
|
+
const location = outcome[2];
|
|
793
|
+
if (!location) {
|
|
794
|
+
await router.navigate({
|
|
795
|
+
...redirect.options,
|
|
796
|
+
replace: true,
|
|
797
|
+
ignoreBlocker: true
|
|
798
|
+
});
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
if (redirect.options.reloadDocument) {
|
|
802
|
+
await router.navigate({
|
|
803
|
+
href: location.publicHref,
|
|
804
|
+
reloadDocument: true,
|
|
805
|
+
replace: true,
|
|
806
|
+
ignoreBlocker: true
|
|
807
|
+
});
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
location._redirects = tx[1] + 1;
|
|
811
|
+
router._pendingLocation = location;
|
|
812
|
+
const committed = router.commitLocation({
|
|
813
|
+
...location,
|
|
814
|
+
viewTransition: redirect.options.viewTransition,
|
|
852
815
|
replace: true,
|
|
853
|
-
|
|
854
|
-
|
|
816
|
+
resetScroll: redirect.options.resetScroll,
|
|
817
|
+
hashScrollIntoView: redirect.options.hashScrollIntoView,
|
|
818
|
+
ignoreBlocker: true
|
|
855
819
|
});
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
finishPending(router, tx);
|
|
859
|
-
tx[0].abort();
|
|
860
|
-
transferMatchResources(router, tx[3]);
|
|
861
|
-
tx[3] = [];
|
|
862
|
-
if (router._tx !== tx) return;
|
|
863
|
-
router.batch(() => {
|
|
864
|
-
router.stores.status.set("idle");
|
|
865
|
-
router.stores.setMatches(router._committed);
|
|
820
|
+
queueMicrotask(() => {
|
|
821
|
+
if (router._pendingLocation === location) router._pendingLocation = void 0;
|
|
866
822
|
});
|
|
867
|
-
|
|
868
|
-
router._commitPromise?.resolve();
|
|
869
|
-
router._commitPromise = void 0;
|
|
870
|
-
}
|
|
823
|
+
await committed;
|
|
871
824
|
}
|
|
872
825
|
async function runBackground(router, tx, base, tasks, settlement) {
|
|
873
826
|
const next = base.map((match) => ({ ...match }));
|
|
@@ -879,14 +832,14 @@ async function runBackground(router, tx, base, tasks, settlement) {
|
|
|
879
832
|
const lane = [tx[2], next];
|
|
880
833
|
let reduced;
|
|
881
834
|
try {
|
|
882
|
-
reduced = await reduceLane(router, lane, tasks, tx[0],
|
|
835
|
+
reduced = await reduceLane(router, lane, tasks, tx[0], settlement);
|
|
883
836
|
} catch (cause) {
|
|
884
837
|
transferMatchResources(router, next);
|
|
885
838
|
throw cause;
|
|
886
839
|
}
|
|
887
840
|
if (isControl(reduced)) {
|
|
888
841
|
transferMatchResources(router, next);
|
|
889
|
-
if (reduced[0] === REDIRECTED && router._tx === tx && router._committed === base) await followRedirect(router, tx, reduced
|
|
842
|
+
if (reduced[0] === REDIRECTED && router._tx === tx && router._committed === base) await followRedirect(router, tx, reduced);
|
|
890
843
|
return;
|
|
891
844
|
}
|
|
892
845
|
const projected = await projectLane(router, reduced, tx[0].signal);
|
|
@@ -908,7 +861,6 @@ async function runClientTransaction(router, tx, forceStaleReload, onReady, sync,
|
|
|
908
861
|
const options = [
|
|
909
862
|
tx[0],
|
|
910
863
|
tx[1],
|
|
911
|
-
() => router._tx === tx && !!tx[3].length,
|
|
912
864
|
router._committed,
|
|
913
865
|
void 0,
|
|
914
866
|
sync,
|
|
@@ -918,50 +870,30 @@ async function runClientTransaction(router, tx, forceStaleReload, onReady, sync,
|
|
|
918
870
|
];
|
|
919
871
|
const result = await executeClientLane(router, tx[2], tx[3], options);
|
|
920
872
|
if (isControl(result)) {
|
|
921
|
-
|
|
873
|
+
const follow = result[0] === REDIRECTED && router._tx === tx;
|
|
874
|
+
if (!follow || result[1].options.reloadDocument) finishPending(router, tx);
|
|
875
|
+
transferMatchResources(router, tx[3]);
|
|
876
|
+
tx[3] = [];
|
|
877
|
+
if (!follow) return;
|
|
878
|
+
if (router._tx !== tx) {
|
|
922
879
|
finishPending(router, tx);
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
await followRedirect(router, tx, result[1]);
|
|
928
|
-
}
|
|
929
|
-
} else restoreCommitted(router, tx);
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
if (process.env.NODE_ENV !== "production" && tx[6]) router._refreshNextLoad = true;
|
|
883
|
+
await followRedirect(router, tx, result);
|
|
930
884
|
return;
|
|
931
885
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
* rendered, there is no minimum wait; if another load took it over, that
|
|
938
|
-
* load owns the deadline.
|
|
939
|
-
*/
|
|
940
|
-
clearTimeout(pending[3]);
|
|
941
|
-
if (pending[4]) {
|
|
942
|
-
const signal = tx[0].signal;
|
|
943
|
-
let rendered = false;
|
|
944
|
-
try {
|
|
945
|
-
rendered = await waitFor(pending[4], signal);
|
|
946
|
-
} catch (cause) {
|
|
947
|
-
if (cause !== signal) throw cause;
|
|
948
|
-
}
|
|
949
|
-
if (rendered && router._pending === pending && pending[0] === tx) {
|
|
950
|
-
const remaining = pending[2] - Date.now();
|
|
951
|
-
if (remaining > 0) {
|
|
952
|
-
try {
|
|
953
|
-
await waitFor(new Promise((resolve) => {
|
|
954
|
-
pending[3] = setTimeout(resolve, remaining);
|
|
955
|
-
}), signal);
|
|
956
|
-
} catch {}
|
|
957
|
-
clearTimeout(pending[3]);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
}
|
|
886
|
+
if (router._tx !== tx) {
|
|
887
|
+
finishPending(router, tx);
|
|
888
|
+
transferMatchResources(router, result[1]);
|
|
889
|
+
discardBackground(router, result);
|
|
890
|
+
return;
|
|
961
891
|
}
|
|
892
|
+
await awaitPendingMinimum(router, tx);
|
|
962
893
|
if (router._tx !== tx) {
|
|
963
894
|
finishPending(router, tx);
|
|
964
|
-
|
|
895
|
+
transferMatchResources(router, result[1]);
|
|
896
|
+
discardBackground(router, result);
|
|
965
897
|
return;
|
|
966
898
|
}
|
|
967
899
|
const toLocation = tx[2];
|
|
@@ -969,7 +901,16 @@ async function runClientTransaction(router, tx, forceStaleReload, onReady, sync,
|
|
|
969
901
|
const background = result[2];
|
|
970
902
|
await router.startViewTransition(async () => {
|
|
971
903
|
if (router._tx !== tx) {
|
|
972
|
-
|
|
904
|
+
finishPending(router, tx);
|
|
905
|
+
transferMatchResources(router, result[1]);
|
|
906
|
+
discardBackground(router, result);
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
await awaitPendingMinimum(router, tx);
|
|
910
|
+
if (router._tx !== tx) {
|
|
911
|
+
finishPending(router, tx);
|
|
912
|
+
transferMatchResources(router, result[1]);
|
|
913
|
+
discardBackground(router, result);
|
|
973
914
|
return;
|
|
974
915
|
}
|
|
975
916
|
const commit = () => {
|
|
@@ -985,8 +926,8 @@ async function runClientTransaction(router, tx, forceStaleReload, onReady, sync,
|
|
|
985
926
|
...changeInfo
|
|
986
927
|
});
|
|
987
928
|
};
|
|
988
|
-
const rendered =
|
|
989
|
-
if (process.env.NODE_ENV !== "production" && tx[6]
|
|
929
|
+
const rendered = await router.startTransition(commit, result[1]);
|
|
930
|
+
if (process.env.NODE_ENV !== "production" && tx[6]) tx[6] = void 0;
|
|
990
931
|
if (router._tx !== tx) {
|
|
991
932
|
discardBackground(router, result);
|
|
992
933
|
return;
|
|
@@ -1011,11 +952,7 @@ async function runClientTransaction(router, tx, forceStaleReload, onReady, sync,
|
|
|
1011
952
|
}
|
|
1012
953
|
async function loadClientRoute(router, opts) {
|
|
1013
954
|
let rematerialize = false;
|
|
1014
|
-
if (process.env.NODE_ENV !== "production")
|
|
1015
|
-
router._tx?.[6]?.[2]?.();
|
|
1016
|
-
rematerialize = !!router._refreshNextLoad || !!router._tx?.[6];
|
|
1017
|
-
}
|
|
1018
|
-
const refreshPresentation = rematerialize ? router.stores.matches.get() : void 0;
|
|
955
|
+
if (process.env.NODE_ENV !== "production") rematerialize = !!router._refreshNextLoad || !!router._tx?.[6];
|
|
1019
956
|
const previousOwner = router._tx;
|
|
1020
957
|
const resolvedLocation = router.stores.resolvedLocation.get();
|
|
1021
958
|
const previousLocation = resolvedLocation ?? router.stores.location.get();
|
|
@@ -1047,31 +984,12 @@ async function loadClientRoute(router, opts) {
|
|
|
1047
984
|
return;
|
|
1048
985
|
}
|
|
1049
986
|
const sameHref = previousLocation.href === location.href;
|
|
1050
|
-
let matches;
|
|
1051
987
|
let controller = preflight;
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
acquireMatchResources(matches);
|
|
1058
|
-
} catch (cause) {
|
|
1059
|
-
preflight.abort();
|
|
1060
|
-
if (!require_redirect.isRedirect(cause)) {
|
|
1061
|
-
if (process.env.NODE_ENV !== "production" && rematerialize) router._refreshNextLoad = void 0;
|
|
1062
|
-
await awaitCurrent(router);
|
|
1063
|
-
router._commitPromise?.resolve();
|
|
1064
|
-
router._commitPromise = void 0;
|
|
1065
|
-
return;
|
|
1066
|
-
}
|
|
1067
|
-
await router.navigate({
|
|
1068
|
-
...cause.options,
|
|
1069
|
-
replace: true,
|
|
1070
|
-
ignoreBlocker: true
|
|
1071
|
-
});
|
|
1072
|
-
await awaitCurrent(router, previousOwner);
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
988
|
+
const matches = process.env.NODE_ENV !== "production" && rematerialize ? router.matchRoutes(location, {
|
|
989
|
+
_controller: preflight,
|
|
990
|
+
_rematerialize: true
|
|
991
|
+
}) : router.matchRoutes(location, { _controller: preflight });
|
|
992
|
+
acquireMatchResources(matches);
|
|
1075
993
|
const resolvedPrefix = hydrationController ? handoff[1](matches) : void 0;
|
|
1076
994
|
if (resolvedPrefix) controller = hydrationController;
|
|
1077
995
|
else hydrationController?.abort();
|
|
@@ -1087,12 +1005,10 @@ async function loadClientRoute(router, opts) {
|
|
|
1087
1005
|
location,
|
|
1088
1006
|
matches,
|
|
1089
1007
|
Date.now(),
|
|
1090
|
-
Promise.resolve().then(() => runClientTransaction(router, tx, sameHref, () => offerPending(router, tx), opts?.sync, resolvedPrefix)).
|
|
1091
|
-
if (router._tx === tx) restoreCommitted(router, tx);
|
|
1092
|
-
})
|
|
1008
|
+
Promise.resolve().then(() => runClientTransaction(router, tx, sameHref, () => offerPending(router, tx), opts?.sync, resolvedPrefix)).then()
|
|
1093
1009
|
];
|
|
1094
1010
|
if (process.env.NODE_ENV !== "production" && rematerialize) {
|
|
1095
|
-
tx[6] = [
|
|
1011
|
+
tx[6] = [handoff];
|
|
1096
1012
|
router._refreshNextLoad = void 0;
|
|
1097
1013
|
}
|
|
1098
1014
|
router._tx = tx;
|
|
@@ -1114,15 +1030,11 @@ async function loadClientRoute(router, opts) {
|
|
|
1114
1030
|
router.stores.status.set("pending");
|
|
1115
1031
|
router.stores.location.set(location);
|
|
1116
1032
|
});
|
|
1117
|
-
if (!
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
} finally {
|
|
1121
|
-
await awaitCurrent(router, tx);
|
|
1122
|
-
}
|
|
1033
|
+
if (resolvedPrefix || !router._committed.length && !matches.some((match) => match._notFound)) offerPending(router, tx);
|
|
1034
|
+
await tx[5];
|
|
1035
|
+
await awaitCurrent(router, tx);
|
|
1123
1036
|
}
|
|
1124
1037
|
async function refreshClientRoute(router) {
|
|
1125
|
-
router._tx?.[6]?.[2]?.();
|
|
1126
1038
|
const pending = router._tx;
|
|
1127
1039
|
if (pending && !pending[6] && router.stores.status.get() === "pending") {
|
|
1128
1040
|
await pending[5];
|
|
@@ -1133,10 +1045,9 @@ async function refreshClientRoute(router) {
|
|
|
1133
1045
|
router._refreshNextLoad = true;
|
|
1134
1046
|
await loadClientRoute(router, { sync: true });
|
|
1135
1047
|
}
|
|
1136
|
-
async function preloadClientRoute(router, opts, redirects = 0) {
|
|
1137
|
-
if (redirects > 20) return;
|
|
1048
|
+
async function preloadClientRoute(router, opts, redirects = 0, builtLocation) {
|
|
1138
1049
|
if (process.env.NODE_ENV !== "production" && (router._refreshNextLoad || router._tx?.[6])) return;
|
|
1139
|
-
const location =
|
|
1050
|
+
const location = builtLocation ?? router.buildLocation(opts);
|
|
1140
1051
|
const base = router._committed;
|
|
1141
1052
|
const controller = new AbortController();
|
|
1142
1053
|
let matches;
|
|
@@ -1156,7 +1067,6 @@ async function preloadClientRoute(router, opts, redirects = 0) {
|
|
|
1156
1067
|
result = await executeClientLane(router, location, matches, [
|
|
1157
1068
|
controller,
|
|
1158
1069
|
redirects,
|
|
1159
|
-
() => true,
|
|
1160
1070
|
base,
|
|
1161
1071
|
true
|
|
1162
1072
|
]);
|
|
@@ -1166,10 +1076,7 @@ async function preloadClientRoute(router, opts, redirects = 0) {
|
|
|
1166
1076
|
controller.abort();
|
|
1167
1077
|
}
|
|
1168
1078
|
if (!isControl(result)) return result[1];
|
|
1169
|
-
if (active && result[0] === REDIRECTED && !result[1].options.reloadDocument) return preloadClientRoute(router,
|
|
1170
|
-
...result[1].options,
|
|
1171
|
-
_fromLocation: location
|
|
1172
|
-
}, redirects + 1);
|
|
1079
|
+
if (active && result[0] === REDIRECTED && !result[1].options.reloadDocument) return preloadClientRoute(router, result[1].options, redirects + 1, result[2]);
|
|
1173
1080
|
} catch (cause) {
|
|
1174
1081
|
if (!require_not_found.isNotFound(cause)) console.error(cause);
|
|
1175
1082
|
}
|
|
@@ -1290,7 +1197,10 @@ async function hydrate(router) {
|
|
|
1290
1197
|
params: match.params,
|
|
1291
1198
|
context: parentContext,
|
|
1292
1199
|
location,
|
|
1293
|
-
navigate:
|
|
1200
|
+
navigate: (opts) => router.navigate({
|
|
1201
|
+
...opts,
|
|
1202
|
+
_fromLocation: location
|
|
1203
|
+
}),
|
|
1294
1204
|
buildLocation: router.buildLocation,
|
|
1295
1205
|
cause: match.cause,
|
|
1296
1206
|
abortController: controller,
|