@reckona/mreact-router 0.0.210 → 0.0.211
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/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +17 -5
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +43 -3
- package/dist/build.js.map +1 -1
- package/dist/built-runtime.d.ts +1 -0
- package/dist/built-runtime.d.ts.map +1 -1
- package/dist/built-runtime.js +4 -0
- package/dist/built-runtime.js.map +1 -1
- package/dist/client-manifest-assets.d.ts +2 -0
- package/dist/client-manifest-assets.d.ts.map +1 -1
- package/dist/client-manifest-assets.js +2 -1
- package/dist/client-manifest-assets.js.map +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +365 -85
- package/dist/client.js.map +1 -1
- package/dist/module-preload-graph.d.ts +5 -0
- package/dist/module-preload-graph.d.ts.map +1 -0
- package/dist/module-preload-graph.js +48 -0
- package/dist/module-preload-graph.js.map +1 -0
- package/dist/render.d.ts +1 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +47 -10
- package/dist/render.js.map +1 -1
- package/dist/serve.js +1 -0
- package/dist/serve.js.map +1 -1
- package/package.json +11 -11
- package/src/adapters/cloudflare.ts +22 -5
- package/src/build.ts +50 -3
- package/src/built-runtime.ts +18 -6
- package/src/client-manifest-assets.ts +3 -1
- package/src/client.ts +365 -84
- package/src/module-preload-graph.ts +70 -0
- package/src/render.ts +74 -10
- package/src/serve.ts +1 -0
package/dist/client.js
CHANGED
|
@@ -1924,6 +1924,7 @@ export async function buildClientRouteEntrySource(options) {
|
|
|
1924
1924
|
const navigationStateDeclaration = inlineClientNavigation
|
|
1925
1925
|
? `const __mreactNavigationState = __mreactGlobal.__mreactNavigationState ??= {
|
|
1926
1926
|
cache: new Map(),
|
|
1927
|
+
cacheTokens: new Map(),
|
|
1927
1928
|
current: {
|
|
1928
1929
|
from: null,
|
|
1929
1930
|
pending: false,
|
|
@@ -1932,6 +1933,7 @@ export async function buildClientRouteEntrySource(options) {
|
|
|
1932
1933
|
},
|
|
1933
1934
|
fetchRevalidationInstalled: false,
|
|
1934
1935
|
installed: false,
|
|
1936
|
+
navigationFetchInits: new WeakSet(),
|
|
1935
1937
|
pendingHtmlFetches: new Map(),
|
|
1936
1938
|
prefetchedUrls: new Set(),
|
|
1937
1939
|
prefetchedScripts: new Set(),
|
|
@@ -1940,7 +1942,9 @@ export async function buildClientRouteEntrySource(options) {
|
|
|
1940
1942
|
routePrefetchManifestText: undefined,
|
|
1941
1943
|
viewportAnchors: new WeakSet(),
|
|
1942
1944
|
viewportObserver: undefined,
|
|
1943
|
-
}
|
|
1945
|
+
};
|
|
1946
|
+
__mreactNavigationState.cacheTokens ??= new Map();
|
|
1947
|
+
__mreactNavigationState.navigationFetchInits ??= new WeakSet();`
|
|
1944
1948
|
: "";
|
|
1945
1949
|
const deferredNavigationRuntime = deferredClientNavigation
|
|
1946
1950
|
? `
|
|
@@ -2103,10 +2107,10 @@ export async function __mreactNavigate(url, options = {}) {
|
|
|
2103
2107
|
: false;
|
|
2104
2108
|
}
|
|
2105
2109
|
|
|
2106
|
-
export async function __mreactPrefetch(url) {
|
|
2110
|
+
export async function __mreactPrefetch(url, options = {}) {
|
|
2107
2111
|
const runtime = await __mreactLoadNavigationRuntime();
|
|
2108
2112
|
return typeof runtime?.__mreactPrefetch === "function"
|
|
2109
|
-
? runtime.__mreactPrefetch(url)
|
|
2113
|
+
? runtime.__mreactPrefetch(url, options)
|
|
2110
2114
|
: false;
|
|
2111
2115
|
}
|
|
2112
2116
|
|
|
@@ -2152,13 +2156,16 @@ __mreactGlobal.__mreactRouteCell = (nativeCell, initial) => {
|
|
|
2152
2156
|
const stateCell = nativeCell(record.value);
|
|
2153
2157
|
const setStateCell = stateCell.set;
|
|
2154
2158
|
|
|
2155
|
-
|
|
2159
|
+
const setRouteStateCell = (next) => {
|
|
2156
2160
|
setStateCell((previous) => {
|
|
2157
2161
|
const resolved = typeof next === "function" ? next(previous) : next;
|
|
2158
2162
|
record.value = resolved;
|
|
2159
2163
|
return resolved;
|
|
2160
2164
|
});
|
|
2161
2165
|
};
|
|
2166
|
+
stateCell.set = setRouteStateCell;
|
|
2167
|
+
stateCell.setValue = (next) => stateCell.set(() => next);
|
|
2168
|
+
stateCell.update = (updater) => stateCell.set(updater);
|
|
2162
2169
|
|
|
2163
2170
|
__mreactActiveCellRecords.set(cellKey, record);
|
|
2164
2171
|
return stateCell;
|
|
@@ -2579,7 +2586,7 @@ function __mreactRouteAnnouncementElement() {
|
|
|
2579
2586
|
return announcement;
|
|
2580
2587
|
}
|
|
2581
2588
|
|
|
2582
|
-
export async function __mreactPrefetch(url) {
|
|
2589
|
+
export async function __mreactPrefetch(url, options = {}) {
|
|
2583
2590
|
if (!__mreactCanPrefetch()) {
|
|
2584
2591
|
return false;
|
|
2585
2592
|
}
|
|
@@ -2598,10 +2605,6 @@ export async function __mreactPrefetch(url) {
|
|
|
2598
2605
|
return false;
|
|
2599
2606
|
}
|
|
2600
2607
|
|
|
2601
|
-
if (__mreactNavigationState.prefetchedUrls.has(href)) {
|
|
2602
|
-
return true;
|
|
2603
|
-
}
|
|
2604
|
-
|
|
2605
2608
|
__mreactRememberPrefetchedUrl(href);
|
|
2606
2609
|
|
|
2607
2610
|
const script = __mreactRouteScriptForNavigationUrl(href);
|
|
@@ -2610,21 +2613,30 @@ export async function __mreactPrefetch(url) {
|
|
|
2610
2613
|
return __mreactPrefetchNavigationHtml(href);
|
|
2611
2614
|
}
|
|
2612
2615
|
|
|
2613
|
-
|
|
2616
|
+
const scriptPrefetched = __mreactPrefetchRouteScript(script);
|
|
2617
|
+
|
|
2618
|
+
if (options?.trigger === "viewport") {
|
|
2619
|
+
return scriptPrefetched;
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
return Promise.resolve(__mreactPrefetchNavigationHtml(href))
|
|
2623
|
+
.then(() => scriptPrefetched)
|
|
2624
|
+
.catch(() => scriptPrefetched);
|
|
2614
2625
|
}
|
|
2615
2626
|
|
|
2616
2627
|
function __mreactPrefetchNavigationHtml(href) {
|
|
2617
|
-
if (
|
|
2628
|
+
if (__mreactCachedNavigationHtml(href) !== undefined) {
|
|
2618
2629
|
return true;
|
|
2619
2630
|
}
|
|
2620
2631
|
|
|
2621
|
-
return __mreactFetchNavigationHtmlOnce(href)
|
|
2622
|
-
.then((
|
|
2632
|
+
return __mreactFetchNavigationHtmlOnce(href, { speculative: true })
|
|
2633
|
+
.then((result) => result.cacheable && typeof result.html === "string")
|
|
2623
2634
|
.catch(() => false);
|
|
2624
2635
|
}
|
|
2625
2636
|
|
|
2626
2637
|
const __mreactNavigationHtmlCacheMaxEntries = 64;
|
|
2627
2638
|
const __mreactNavigationPrefetchHistoryMaxEntries = 64;
|
|
2639
|
+
const __mreactNavigationHtmlCacheTtlMs = 30_000;
|
|
2628
2640
|
|
|
2629
2641
|
function __mreactRememberPrefetchedUrl(href) {
|
|
2630
2642
|
__mreactRememberPrefetchHistory(__mreactNavigationState.prefetchedUrls, href);
|
|
@@ -2653,23 +2665,49 @@ function __mreactRememberPrefetchHistory(history, href) {
|
|
|
2653
2665
|
}
|
|
2654
2666
|
|
|
2655
2667
|
function __mreactCachedNavigationHtml(href) {
|
|
2656
|
-
const
|
|
2668
|
+
const entry = __mreactNavigationState.cache.get(href);
|
|
2657
2669
|
|
|
2658
|
-
if (
|
|
2670
|
+
if (entry === undefined) {
|
|
2671
|
+
return undefined;
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
if (
|
|
2675
|
+
entry.token !== __mreactNavigationState.cacheTokens.get(href) ||
|
|
2676
|
+
entry.token.valid !== true ||
|
|
2677
|
+
entry.cacheContext !== __mreactNavigationCacheContext() ||
|
|
2678
|
+
Date.now() - entry.fetchedAt >= __mreactNavigationHtmlCacheTtlMs
|
|
2679
|
+
) {
|
|
2680
|
+
__mreactNavigationState.cache.delete(href);
|
|
2681
|
+
__mreactNavigationState.prefetchedUrls.delete(href);
|
|
2682
|
+
__mreactReleaseNavigationCacheToken(href, entry.token);
|
|
2659
2683
|
return undefined;
|
|
2660
2684
|
}
|
|
2661
2685
|
|
|
2662
2686
|
__mreactNavigationState.cache.delete(href);
|
|
2663
|
-
__mreactNavigationState.cache.set(href,
|
|
2664
|
-
return html;
|
|
2687
|
+
__mreactNavigationState.cache.set(href, entry);
|
|
2688
|
+
return entry.html;
|
|
2665
2689
|
}
|
|
2666
2690
|
|
|
2667
|
-
function __mreactRememberNavigationHtml(href, html) {
|
|
2691
|
+
function __mreactRememberNavigationHtml(href, html, token, cacheContext) {
|
|
2692
|
+
if (
|
|
2693
|
+
token === undefined ||
|
|
2694
|
+
token.valid !== true ||
|
|
2695
|
+
__mreactNavigationState.cacheTokens.get(href) !== token ||
|
|
2696
|
+
cacheContext !== __mreactNavigationCacheContext()
|
|
2697
|
+
) {
|
|
2698
|
+
return;
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2668
2701
|
if (__mreactNavigationState.cache.has(href)) {
|
|
2669
2702
|
__mreactNavigationState.cache.delete(href);
|
|
2670
2703
|
}
|
|
2671
2704
|
|
|
2672
|
-
__mreactNavigationState.cache.set(href,
|
|
2705
|
+
__mreactNavigationState.cache.set(href, {
|
|
2706
|
+
cacheContext,
|
|
2707
|
+
fetchedAt: Date.now(),
|
|
2708
|
+
html,
|
|
2709
|
+
token,
|
|
2710
|
+
});
|
|
2673
2711
|
|
|
2674
2712
|
while (__mreactNavigationState.cache.size > __mreactNavigationHtmlCacheMaxEntries) {
|
|
2675
2713
|
const oldestHref = __mreactNavigationState.cache.keys().next().value;
|
|
@@ -2680,37 +2718,100 @@ function __mreactRememberNavigationHtml(href, html) {
|
|
|
2680
2718
|
|
|
2681
2719
|
__mreactNavigationState.cache.delete(oldestHref);
|
|
2682
2720
|
__mreactNavigationState.prefetchedUrls.delete(oldestHref);
|
|
2721
|
+
__mreactReleaseNavigationCacheToken(oldestHref);
|
|
2683
2722
|
}
|
|
2684
2723
|
}
|
|
2685
2724
|
|
|
2686
|
-
function
|
|
2687
|
-
|
|
2688
|
-
|
|
2725
|
+
function __mreactNavigationCacheContext() {
|
|
2726
|
+
const authSession = typeof document === "undefined"
|
|
2727
|
+
? undefined
|
|
2728
|
+
: document.getElementById("__mreact_auth_session")?.textContent ?? undefined;
|
|
2729
|
+
const cookies = __mreactNavigationCookies();
|
|
2730
|
+
|
|
2731
|
+
return JSON.stringify([authSession, cookies]);
|
|
2732
|
+
}
|
|
2733
|
+
|
|
2734
|
+
function __mreactNavigationCookies() {
|
|
2735
|
+
return typeof document === "undefined" ? "" : document.cookie;
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
function __mreactNavigationResponseCacheContext(html, requestCookies) {
|
|
2739
|
+
let authSession;
|
|
2740
|
+
|
|
2741
|
+
if (typeof document !== "undefined") {
|
|
2742
|
+
const template = document.createElement("template");
|
|
2743
|
+
template.innerHTML = html;
|
|
2744
|
+
authSession = template.content.querySelector("#__mreact_auth_session")?.textContent ?? undefined;
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
return JSON.stringify([authSession, requestCookies]);
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
function __mreactReleaseNavigationCacheToken(href, token) {
|
|
2751
|
+
if (
|
|
2752
|
+
__mreactNavigationState.cache.get(href) === undefined &&
|
|
2753
|
+
__mreactNavigationState.pendingHtmlFetches.get(href) === undefined &&
|
|
2754
|
+
(token === undefined || __mreactNavigationState.cacheTokens.get(href) === token)
|
|
2755
|
+
) {
|
|
2756
|
+
__mreactNavigationState.cacheTokens.delete(href);
|
|
2689
2757
|
}
|
|
2758
|
+
}
|
|
2690
2759
|
|
|
2691
|
-
|
|
2760
|
+
function __mreactNavigationCacheToken(href) {
|
|
2761
|
+
const existing = __mreactNavigationState.cacheTokens.get(href);
|
|
2692
2762
|
|
|
2693
|
-
if (
|
|
2694
|
-
return
|
|
2763
|
+
if (existing !== undefined) {
|
|
2764
|
+
return existing;
|
|
2695
2765
|
}
|
|
2696
2766
|
|
|
2697
|
-
|
|
2698
|
-
|
|
2767
|
+
const token = { valid: true };
|
|
2768
|
+
__mreactNavigationState.cacheTokens.set(href, token);
|
|
2769
|
+
return token;
|
|
2770
|
+
}
|
|
2771
|
+
|
|
2772
|
+
function __mreactPrefetchRouteScript(route) {
|
|
2773
|
+
if (typeof document === "undefined") {
|
|
2774
|
+
return false;
|
|
2699
2775
|
}
|
|
2700
2776
|
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2777
|
+
const files = [route.script, ...(route.modulePreloads ?? [])];
|
|
2778
|
+
let valid = true;
|
|
2779
|
+
|
|
2780
|
+
for (const file of files) {
|
|
2781
|
+
const href = __mreactNormalizeAssetUrl(file);
|
|
2782
|
+
|
|
2783
|
+
if (
|
|
2784
|
+
href === undefined ||
|
|
2785
|
+
!__mreactIsSupportedModulePreloadUrl(file) ||
|
|
2786
|
+
!__mreactModulePreloadMatchesRouteScript(file, route.script)
|
|
2787
|
+
) {
|
|
2788
|
+
valid = false;
|
|
2789
|
+
continue;
|
|
2705
2790
|
}
|
|
2791
|
+
|
|
2792
|
+
if (__mreactNavigationState.prefetchedScripts.has(href)) {
|
|
2793
|
+
continue;
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2796
|
+
let found = false;
|
|
2797
|
+
for (const link of Array.from(document.querySelectorAll('link[rel="modulepreload"][href]'))) {
|
|
2798
|
+
if (link.href === href) {
|
|
2799
|
+
found = true;
|
|
2800
|
+
break;
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
|
|
2804
|
+
if (!found) {
|
|
2805
|
+
const link = document.createElement("link");
|
|
2806
|
+
link.rel = "modulepreload";
|
|
2807
|
+
link.href = href;
|
|
2808
|
+
document.head.appendChild(link);
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
__mreactRememberPrefetchedScript(href);
|
|
2706
2812
|
}
|
|
2707
2813
|
|
|
2708
|
-
|
|
2709
|
-
link.rel = "modulepreload";
|
|
2710
|
-
link.href = href;
|
|
2711
|
-
document.head.appendChild(link);
|
|
2712
|
-
__mreactRememberPrefetchedScript(href);
|
|
2713
|
-
return true;
|
|
2814
|
+
return valid;
|
|
2714
2815
|
}
|
|
2715
2816
|
|
|
2716
2817
|
export async function __mreactNavigate(url, options = {}) {
|
|
@@ -2723,19 +2824,46 @@ export async function __mreactNavigate(url, options = {}) {
|
|
|
2723
2824
|
__mreactSetNavigationState(__mreactPendingNavigationState(href, options.type ?? "push"));
|
|
2724
2825
|
|
|
2725
2826
|
try {
|
|
2726
|
-
|
|
2727
|
-
const script = __mreactRouteScriptForNavigationUrl(href);
|
|
2728
|
-
if (script !== undefined) {
|
|
2729
|
-
void __mreactPrefetchRouteScript(script);
|
|
2730
|
-
}
|
|
2731
|
-
const html = cachedHtml ?? await __mreactFetchNavigationHtmlOnce(href);
|
|
2827
|
+
let forceReload = __mreactNavigationState.reloadNextNavigationFetch === true;
|
|
2732
2828
|
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2829
|
+
for (;;) {
|
|
2830
|
+
const cachedHtml = forceReload ? undefined : __mreactCachedNavigationHtml(href);
|
|
2831
|
+
const script = __mreactRouteScriptForNavigationUrl(href);
|
|
2832
|
+
if (script !== undefined) {
|
|
2833
|
+
void __mreactPrefetchRouteScript(script);
|
|
2834
|
+
}
|
|
2835
|
+
const result = cachedHtml === undefined
|
|
2836
|
+
? await __mreactFetchNavigationHtmlOnce(href, { force: forceReload })
|
|
2837
|
+
: {
|
|
2838
|
+
cacheable: true,
|
|
2839
|
+
cacheContext: __mreactNavigationCacheContext(),
|
|
2840
|
+
cacheContextMatches: true,
|
|
2841
|
+
html: cachedHtml,
|
|
2842
|
+
reusable: true,
|
|
2843
|
+
speculative: false,
|
|
2844
|
+
token: undefined,
|
|
2845
|
+
};
|
|
2846
|
+
|
|
2847
|
+
if (result.token !== undefined && result.token.valid !== true) {
|
|
2848
|
+
forceReload = __mreactNavigationState.reloadNextNavigationFetch === true;
|
|
2849
|
+
continue;
|
|
2850
|
+
}
|
|
2736
2851
|
|
|
2737
|
-
|
|
2738
|
-
|
|
2852
|
+
if (result.speculative === true && result.cacheable !== true) {
|
|
2853
|
+
forceReload = true;
|
|
2854
|
+
continue;
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
if (result.reusable === true && result.cacheContextMatches !== true) {
|
|
2858
|
+
return false;
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
if (typeof result.html !== "string") {
|
|
2862
|
+
return false;
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
return await __mreactApplyNavigationHtmlWithOptionalTransition(result.html, href, options);
|
|
2866
|
+
}
|
|
2739
2867
|
} finally {
|
|
2740
2868
|
__mreactSetNavigationState(__mreactIdleNavigationState());
|
|
2741
2869
|
}
|
|
@@ -2870,7 +2998,7 @@ function __mreactViewTransitionsAllowed(transition) {
|
|
|
2870
2998
|
}
|
|
2871
2999
|
}
|
|
2872
3000
|
|
|
2873
|
-
export function __mreactInvalidateNavigationCache(path) {
|
|
3001
|
+
export function __mreactInvalidateNavigationCache(path, excludedRequest) {
|
|
2874
3002
|
const normalizedPath = __mreactNormalizeNavigationPath(path);
|
|
2875
3003
|
|
|
2876
3004
|
if (normalizedPath === undefined) {
|
|
@@ -2884,64 +3012,158 @@ export function __mreactInvalidateNavigationCache(path) {
|
|
|
2884
3012
|
|
|
2885
3013
|
for (const href of hrefs) {
|
|
2886
3014
|
if (__mreactNormalizeNavigationPath(href) === normalizedPath) {
|
|
3015
|
+
const token = __mreactNavigationState.cacheTokens.get(href);
|
|
3016
|
+
if (
|
|
3017
|
+
excludedRequest?.href === href &&
|
|
3018
|
+
excludedRequest.token === token &&
|
|
3019
|
+
token?.valid === true
|
|
3020
|
+
) {
|
|
3021
|
+
continue;
|
|
3022
|
+
}
|
|
3023
|
+
if (token !== undefined) {
|
|
3024
|
+
token.valid = false;
|
|
3025
|
+
}
|
|
2887
3026
|
__mreactNavigationState.cache.delete(href);
|
|
2888
3027
|
__mreactNavigationState.prefetchedUrls.delete(href);
|
|
2889
3028
|
__mreactNavigationState.pendingHtmlFetches.delete(href);
|
|
3029
|
+
__mreactNavigationState.cacheTokens.delete(href);
|
|
2890
3030
|
}
|
|
2891
3031
|
}
|
|
2892
3032
|
}
|
|
2893
3033
|
|
|
2894
3034
|
function __mreactInvalidateAllNavigationCache() {
|
|
3035
|
+
for (const entry of __mreactNavigationState.cache.values()) {
|
|
3036
|
+
entry.token.valid = false;
|
|
3037
|
+
}
|
|
3038
|
+
for (const request of __mreactNavigationState.pendingHtmlFetches.values()) {
|
|
3039
|
+
request.token.valid = false;
|
|
3040
|
+
}
|
|
2895
3041
|
__mreactNavigationState.cache.clear();
|
|
3042
|
+
__mreactNavigationState.cacheTokens.clear();
|
|
2896
3043
|
__mreactNavigationState.prefetchedUrls.clear();
|
|
2897
3044
|
__mreactNavigationState.pendingHtmlFetches.clear();
|
|
2898
3045
|
}
|
|
2899
3046
|
|
|
2900
|
-
function __mreactFetchNavigationHtmlOnce(href) {
|
|
3047
|
+
function __mreactFetchNavigationHtmlOnce(href, options = {}) {
|
|
2901
3048
|
const pending = __mreactNavigationState.pendingHtmlFetches.get(href);
|
|
2902
3049
|
|
|
3050
|
+
if (pending !== undefined && options.force !== true) {
|
|
3051
|
+
return pending.promise;
|
|
3052
|
+
}
|
|
3053
|
+
|
|
2903
3054
|
if (pending !== undefined) {
|
|
2904
|
-
|
|
3055
|
+
pending.token.valid = false;
|
|
3056
|
+
__mreactNavigationState.pendingHtmlFetches.delete(href);
|
|
3057
|
+
__mreactNavigationState.cacheTokens.delete(href);
|
|
2905
3058
|
}
|
|
2906
3059
|
|
|
2907
|
-
const
|
|
2908
|
-
|
|
3060
|
+
const token = __mreactNavigationCacheToken(href);
|
|
3061
|
+
const pendingRequest = {
|
|
3062
|
+
promise: undefined,
|
|
3063
|
+
token,
|
|
3064
|
+
};
|
|
3065
|
+
const request = __mreactFetchNavigationHtml(href, options, pendingRequest)
|
|
3066
|
+
.then((result) => {
|
|
3067
|
+
const enriched = {
|
|
3068
|
+
...result,
|
|
3069
|
+
speculative: options.speculative === true,
|
|
3070
|
+
token,
|
|
3071
|
+
};
|
|
2909
3072
|
if (
|
|
2910
|
-
|
|
2911
|
-
|
|
3073
|
+
enriched.cacheable === true &&
|
|
3074
|
+
typeof enriched.html === "string" &&
|
|
3075
|
+
__mreactNavigationState.pendingHtmlFetches.get(href) === pendingRequest &&
|
|
3076
|
+
token.valid === true &&
|
|
3077
|
+
__mreactNavigationState.cacheTokens.get(href) === token
|
|
2912
3078
|
) {
|
|
2913
|
-
__mreactRememberNavigationHtml(href, html);
|
|
3079
|
+
__mreactRememberNavigationHtml(href, enriched.html, token, enriched.cacheContext);
|
|
2914
3080
|
}
|
|
2915
3081
|
|
|
2916
|
-
return
|
|
3082
|
+
return enriched;
|
|
2917
3083
|
})
|
|
2918
3084
|
.finally(() => {
|
|
2919
|
-
if (__mreactNavigationState.pendingHtmlFetches.get(href) ===
|
|
3085
|
+
if (__mreactNavigationState.pendingHtmlFetches.get(href) === pendingRequest) {
|
|
2920
3086
|
__mreactNavigationState.pendingHtmlFetches.delete(href);
|
|
3087
|
+
__mreactReleaseNavigationCacheToken(href, token);
|
|
2921
3088
|
}
|
|
2922
3089
|
});
|
|
2923
3090
|
|
|
2924
|
-
|
|
3091
|
+
pendingRequest.promise = request;
|
|
3092
|
+
__mreactNavigationState.pendingHtmlFetches.set(href, pendingRequest);
|
|
2925
3093
|
return request;
|
|
2926
3094
|
}
|
|
2927
3095
|
|
|
2928
|
-
function __mreactFetchNavigationHtml(href) {
|
|
2929
|
-
const
|
|
2930
|
-
__mreactNavigationState.reloadNextNavigationFetch
|
|
3096
|
+
function __mreactFetchNavigationHtml(href, options = {}, pendingRequest) {
|
|
3097
|
+
const speculative = options.speculative === true;
|
|
3098
|
+
const reloadRouteCache = !speculative && __mreactNavigationState.reloadNextNavigationFetch === true;
|
|
3099
|
+
if (!speculative) {
|
|
3100
|
+
__mreactNavigationState.reloadNextNavigationFetch = false;
|
|
3101
|
+
}
|
|
2931
3102
|
const headers = reloadRouteCache
|
|
2932
3103
|
? { "x-mreact-navigation": "1", "x-mreact-navigation-cache": "reload" }
|
|
2933
3104
|
: { "x-mreact-navigation": "1" };
|
|
3105
|
+
const requestCacheContext = __mreactNavigationCacheContext();
|
|
3106
|
+
const requestCookies = __mreactNavigationCookies();
|
|
3107
|
+
const navigationRequestInit = { headers };
|
|
3108
|
+
__mreactNavigationState.navigationFetchInits.add(navigationRequestInit);
|
|
3109
|
+
|
|
3110
|
+
return fetch(__mreactStaticNavigationRequestHref(href), navigationRequestInit).then((response) => {
|
|
3111
|
+
const currentRequest =
|
|
3112
|
+
pendingRequest !== undefined &&
|
|
3113
|
+
__mreactNavigationState.pendingHtmlFetches.get(href) === pendingRequest &&
|
|
3114
|
+
__mreactNavigationState.cacheTokens.get(href) === pendingRequest.token &&
|
|
3115
|
+
pendingRequest.token.valid === true
|
|
3116
|
+
? { href, token: pendingRequest.token }
|
|
3117
|
+
: undefined;
|
|
3118
|
+
if (pendingRequest === undefined || currentRequest !== undefined) {
|
|
3119
|
+
__mreactApplyRevalidationHeader(response, currentRequest);
|
|
3120
|
+
}
|
|
3121
|
+
const requiresDocumentReload = __mreactNavigationResponseRequiresDocumentReload(response);
|
|
3122
|
+
const responseIsSuccessful =
|
|
3123
|
+
response.ok === true ||
|
|
3124
|
+
(response.ok === undefined && response.status >= 200 && response.status < 300);
|
|
3125
|
+
const responseIsRedirected = response.redirected === true;
|
|
3126
|
+
const cacheControl = (response.headers.get("cache-control") ?? "").toLowerCase();
|
|
3127
|
+
const responseDisallowsCache = /(?:^|,)\\s*(?:no-store|no-cache)(?:\\s*=|\\s*(?:,|$))/.test(
|
|
3128
|
+
cacheControl,
|
|
3129
|
+
);
|
|
3130
|
+
const reusable =
|
|
3131
|
+
!requiresDocumentReload &&
|
|
3132
|
+
responseIsSuccessful &&
|
|
3133
|
+
!responseIsRedirected &&
|
|
3134
|
+
!responseDisallowsCache;
|
|
3135
|
+
|
|
3136
|
+
if (requiresDocumentReload || responseIsRedirected || speculative && !reusable) {
|
|
3137
|
+
__mreactDiscardNavigationResponse(response);
|
|
3138
|
+
return { cacheable: false, html: undefined };
|
|
3139
|
+
}
|
|
3140
|
+
|
|
3141
|
+
return response.text().then((html) => {
|
|
3142
|
+
const cacheContext = __mreactNavigationResponseCacheContext(html, requestCookies);
|
|
3143
|
+
const currentCacheContext = __mreactNavigationCacheContext();
|
|
3144
|
+
const cacheContextMatches =
|
|
3145
|
+
cacheContext === currentCacheContext && requestCacheContext === currentCacheContext;
|
|
3146
|
+
|
|
3147
|
+
return {
|
|
3148
|
+
cacheContext,
|
|
3149
|
+
cacheContextMatches,
|
|
3150
|
+
cacheable: reusable && cacheContextMatches,
|
|
3151
|
+
html,
|
|
3152
|
+
reusable,
|
|
3153
|
+
};
|
|
3154
|
+
});
|
|
3155
|
+
});
|
|
3156
|
+
}
|
|
2934
3157
|
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
return undefined;
|
|
3158
|
+
function __mreactDiscardNavigationResponse(response) {
|
|
3159
|
+
try {
|
|
3160
|
+
const result = response?.body?.cancel?.();
|
|
3161
|
+
if (result !== undefined && typeof result.catch === "function") {
|
|
3162
|
+
void result.catch(() => {});
|
|
2941
3163
|
}
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
}
|
|
3164
|
+
} catch {
|
|
3165
|
+
// Ignore body cancellation failures while falling back to a document navigation.
|
|
3166
|
+
}
|
|
2945
3167
|
}
|
|
2946
3168
|
|
|
2947
3169
|
function __mreactStaticNavigationRequestHref(href) {
|
|
@@ -2979,7 +3201,7 @@ function __mreactNavigationResponseRequiresDocumentReload(response) {
|
|
|
2979
3201
|
return response.status === 204 || response.headers.get("x-mreact-navigation") === "reload";
|
|
2980
3202
|
}
|
|
2981
3203
|
|
|
2982
|
-
function __mreactApplyRevalidationHeader(response) {
|
|
3204
|
+
function __mreactApplyRevalidationHeader(response, currentRequest) {
|
|
2983
3205
|
const header = typeof response?.headers?.get === "function"
|
|
2984
3206
|
? response.headers.get("x-mreact-revalidate")
|
|
2985
3207
|
: null;
|
|
@@ -2988,18 +3210,34 @@ function __mreactApplyRevalidationHeader(response) {
|
|
|
2988
3210
|
return;
|
|
2989
3211
|
}
|
|
2990
3212
|
|
|
3213
|
+
const currentPath = __mreactNormalizeNavigationPath(currentRequest?.href);
|
|
3214
|
+
|
|
2991
3215
|
for (const path of header.split(",")) {
|
|
2992
|
-
|
|
3216
|
+
const trimmedPath = path.trim();
|
|
3217
|
+
const normalizedPath = __mreactNormalizeNavigationPath(trimmedPath);
|
|
3218
|
+
const excludedRequest =
|
|
3219
|
+
currentRequest !== undefined && normalizedPath === currentPath ? currentRequest : undefined;
|
|
3220
|
+
__mreactInvalidateNavigationCache(trimmedPath, excludedRequest);
|
|
2993
3221
|
}
|
|
2994
3222
|
}
|
|
2995
3223
|
|
|
3224
|
+
function __mreactIsNavigationFetchRequest(_input, init) {
|
|
3225
|
+
return init !== null && typeof init === "object" && __mreactNavigationState.navigationFetchInits.has(init);
|
|
3226
|
+
}
|
|
3227
|
+
|
|
2996
3228
|
function __mreactNormalizeNavigationPath(path) {
|
|
3229
|
+
if (typeof path !== "string" || path.trim() === "") {
|
|
3230
|
+
return undefined;
|
|
3231
|
+
}
|
|
3232
|
+
|
|
3233
|
+
const normalizedInput = path.trim();
|
|
3234
|
+
|
|
2997
3235
|
if (typeof location === "undefined") {
|
|
2998
|
-
return
|
|
3236
|
+
return normalizedInput;
|
|
2999
3237
|
}
|
|
3000
3238
|
|
|
3001
3239
|
try {
|
|
3002
|
-
const url = new URL(
|
|
3240
|
+
const url = new URL(normalizedInput, location.href);
|
|
3003
3241
|
const pathname = url.pathname.replace(/\\/+$/, "");
|
|
3004
3242
|
|
|
3005
3243
|
return pathname === "" ? "/" : pathname;
|
|
@@ -3015,7 +3253,7 @@ export function __mreactRestoreHistoryState(state) {
|
|
|
3015
3253
|
|
|
3016
3254
|
const html = typeof state.html === "string"
|
|
3017
3255
|
? state.html
|
|
3018
|
-
: typeof state.url === "string" ?
|
|
3256
|
+
: typeof state.url === "string" ? __mreactCachedNavigationHtml(state.url) : undefined;
|
|
3019
3257
|
|
|
3020
3258
|
if (typeof html !== "string") {
|
|
3021
3259
|
return false;
|
|
@@ -3391,7 +3629,7 @@ function __mreactRouteScriptForNavigationUrl(url) {
|
|
|
3391
3629
|
|
|
3392
3630
|
for (const route of __mreactClientRoutePrefetchManifest()) {
|
|
3393
3631
|
if (__mreactRoutePathMatches(route.path, nextUrl.pathname)) {
|
|
3394
|
-
return route
|
|
3632
|
+
return route;
|
|
3395
3633
|
}
|
|
3396
3634
|
}
|
|
3397
3635
|
|
|
@@ -3421,12 +3659,28 @@ function __mreactClientRoutePrefetchManifest() {
|
|
|
3421
3659
|
try {
|
|
3422
3660
|
const parsed = JSON.parse(text);
|
|
3423
3661
|
__mreactNavigationState.routePrefetchManifest = Array.isArray(parsed)
|
|
3424
|
-
? parsed.
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3662
|
+
? parsed.flatMap((route) => {
|
|
3663
|
+
if (
|
|
3664
|
+
route === null ||
|
|
3665
|
+
typeof route !== "object" ||
|
|
3666
|
+
typeof route.path !== "string" ||
|
|
3667
|
+
typeof route.script !== "string" ||
|
|
3668
|
+
!__mreactIsSupportedModulePreloadUrl(route.script)
|
|
3669
|
+
) {
|
|
3670
|
+
return [];
|
|
3671
|
+
}
|
|
3672
|
+
|
|
3673
|
+
const modulePreloads = Array.isArray(route.modulePreloads)
|
|
3674
|
+
? route.modulePreloads.filter(
|
|
3675
|
+
(file) =>
|
|
3676
|
+
typeof file === "string" &&
|
|
3677
|
+
__mreactIsSupportedModulePreloadUrl(file) &&
|
|
3678
|
+
__mreactModulePreloadMatchesRouteScript(file, route.script),
|
|
3679
|
+
)
|
|
3680
|
+
: [];
|
|
3681
|
+
|
|
3682
|
+
return [{ ...route, modulePreloads }];
|
|
3683
|
+
})
|
|
3430
3684
|
: [];
|
|
3431
3685
|
} catch {
|
|
3432
3686
|
__mreactNavigationState.routePrefetchManifest = [];
|
|
@@ -3435,6 +3689,29 @@ function __mreactClientRoutePrefetchManifest() {
|
|
|
3435
3689
|
return __mreactNavigationState.routePrefetchManifest;
|
|
3436
3690
|
}
|
|
3437
3691
|
|
|
3692
|
+
function __mreactIsSupportedModulePreloadUrl(value) {
|
|
3693
|
+
if (typeof value !== "string" || value === "" || value.startsWith("javascript:")) {
|
|
3694
|
+
return false;
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3697
|
+
try {
|
|
3698
|
+
const resolved = new URL(value, typeof location === "undefined" ? undefined : location.href);
|
|
3699
|
+
return resolved.protocol === "http:" || resolved.protocol === "https:";
|
|
3700
|
+
} catch {
|
|
3701
|
+
return false;
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
function __mreactModulePreloadMatchesRouteScript(value, script) {
|
|
3706
|
+
try {
|
|
3707
|
+
const scriptUrl = new URL(__mreactNormalizeAssetUrl(script), location.href);
|
|
3708
|
+
const dependencyUrl = new URL(__mreactNormalizeAssetUrl(value), location.href);
|
|
3709
|
+
return scriptUrl.origin === dependencyUrl.origin;
|
|
3710
|
+
} catch {
|
|
3711
|
+
return false;
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
|
|
3438
3715
|
function __mreactRoutePathMatches(routePath, pathname) {
|
|
3439
3716
|
const routeSegments = __mreactNormalizeRoutePath(routePath);
|
|
3440
3717
|
const pathSegments = __mreactNormalizeRoutePath(pathname);
|
|
@@ -3732,9 +4009,12 @@ function __mreactInstallNavigationFetchRevalidation() {
|
|
|
3732
4009
|
const fetchImpl = globalThis.fetch;
|
|
3733
4010
|
globalThis.fetch = function(input, init) {
|
|
3734
4011
|
const mutating = __mreactIsMutatingFetchRequest(input, init);
|
|
4012
|
+
const navigation = __mreactIsNavigationFetchRequest(input, init);
|
|
3735
4013
|
|
|
3736
4014
|
return Promise.resolve(fetchImpl.call(this, input, init)).then((response) => {
|
|
3737
|
-
|
|
4015
|
+
if (!navigation) {
|
|
4016
|
+
__mreactApplyRevalidationHeader(response);
|
|
4017
|
+
}
|
|
3738
4018
|
|
|
3739
4019
|
if (mutating) {
|
|
3740
4020
|
__mreactInvalidateAllNavigationCache();
|
|
@@ -3806,7 +4086,7 @@ function __mreactObserveViewportPrefetchAnchors(root) {
|
|
|
3806
4086
|
}
|
|
3807
4087
|
|
|
3808
4088
|
__mreactNavigationState.viewportObserver?.unobserve(entry.target);
|
|
3809
|
-
void __mreactPrefetch(entry.target.href);
|
|
4089
|
+
void __mreactPrefetch(entry.target.href, { trigger: "viewport" });
|
|
3810
4090
|
}
|
|
3811
4091
|
});
|
|
3812
4092
|
}
|