@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/src/client.ts
CHANGED
|
@@ -61,6 +61,7 @@ export interface ClientRouteManifestEntry {
|
|
|
61
61
|
clientReferenceManifest?: readonly ClientReferenceMetadata[] | undefined;
|
|
62
62
|
devScript?: string;
|
|
63
63
|
imports?: readonly string[];
|
|
64
|
+
modulePreloads?: readonly string[];
|
|
64
65
|
navigation?: boolean;
|
|
65
66
|
navigationScript?: string;
|
|
66
67
|
routeId?: string;
|
|
@@ -3013,6 +3014,7 @@ export async function buildClientRouteEntrySource(
|
|
|
3013
3014
|
const navigationStateDeclaration = inlineClientNavigation
|
|
3014
3015
|
? `const __mreactNavigationState = __mreactGlobal.__mreactNavigationState ??= {
|
|
3015
3016
|
cache: new Map(),
|
|
3017
|
+
cacheTokens: new Map(),
|
|
3016
3018
|
current: {
|
|
3017
3019
|
from: null,
|
|
3018
3020
|
pending: false,
|
|
@@ -3021,6 +3023,7 @@ export async function buildClientRouteEntrySource(
|
|
|
3021
3023
|
},
|
|
3022
3024
|
fetchRevalidationInstalled: false,
|
|
3023
3025
|
installed: false,
|
|
3026
|
+
navigationFetchInits: new WeakSet(),
|
|
3024
3027
|
pendingHtmlFetches: new Map(),
|
|
3025
3028
|
prefetchedUrls: new Set(),
|
|
3026
3029
|
prefetchedScripts: new Set(),
|
|
@@ -3029,7 +3032,9 @@ export async function buildClientRouteEntrySource(
|
|
|
3029
3032
|
routePrefetchManifestText: undefined,
|
|
3030
3033
|
viewportAnchors: new WeakSet(),
|
|
3031
3034
|
viewportObserver: undefined,
|
|
3032
|
-
}
|
|
3035
|
+
};
|
|
3036
|
+
__mreactNavigationState.cacheTokens ??= new Map();
|
|
3037
|
+
__mreactNavigationState.navigationFetchInits ??= new WeakSet();`
|
|
3033
3038
|
: "";
|
|
3034
3039
|
const deferredNavigationRuntime = deferredClientNavigation
|
|
3035
3040
|
? `
|
|
@@ -3192,10 +3197,10 @@ export async function __mreactNavigate(url, options = {}) {
|
|
|
3192
3197
|
: false;
|
|
3193
3198
|
}
|
|
3194
3199
|
|
|
3195
|
-
export async function __mreactPrefetch(url) {
|
|
3200
|
+
export async function __mreactPrefetch(url, options = {}) {
|
|
3196
3201
|
const runtime = await __mreactLoadNavigationRuntime();
|
|
3197
3202
|
return typeof runtime?.__mreactPrefetch === "function"
|
|
3198
|
-
? runtime.__mreactPrefetch(url)
|
|
3203
|
+
? runtime.__mreactPrefetch(url, options)
|
|
3199
3204
|
: false;
|
|
3200
3205
|
}
|
|
3201
3206
|
|
|
@@ -3241,13 +3246,16 @@ __mreactGlobal.__mreactRouteCell = (nativeCell, initial) => {
|
|
|
3241
3246
|
const stateCell = nativeCell(record.value);
|
|
3242
3247
|
const setStateCell = stateCell.set;
|
|
3243
3248
|
|
|
3244
|
-
|
|
3249
|
+
const setRouteStateCell = (next) => {
|
|
3245
3250
|
setStateCell((previous) => {
|
|
3246
3251
|
const resolved = typeof next === "function" ? next(previous) : next;
|
|
3247
3252
|
record.value = resolved;
|
|
3248
3253
|
return resolved;
|
|
3249
3254
|
});
|
|
3250
3255
|
};
|
|
3256
|
+
stateCell.set = setRouteStateCell;
|
|
3257
|
+
stateCell.setValue = (next) => stateCell.set(() => next);
|
|
3258
|
+
stateCell.update = (updater) => stateCell.set(updater);
|
|
3251
3259
|
|
|
3252
3260
|
__mreactActiveCellRecords.set(cellKey, record);
|
|
3253
3261
|
return stateCell;
|
|
@@ -3674,7 +3682,7 @@ function __mreactRouteAnnouncementElement() {
|
|
|
3674
3682
|
return announcement;
|
|
3675
3683
|
}
|
|
3676
3684
|
|
|
3677
|
-
export async function __mreactPrefetch(url) {
|
|
3685
|
+
export async function __mreactPrefetch(url, options = {}) {
|
|
3678
3686
|
if (!__mreactCanPrefetch()) {
|
|
3679
3687
|
return false;
|
|
3680
3688
|
}
|
|
@@ -3693,10 +3701,6 @@ export async function __mreactPrefetch(url) {
|
|
|
3693
3701
|
return false;
|
|
3694
3702
|
}
|
|
3695
3703
|
|
|
3696
|
-
if (__mreactNavigationState.prefetchedUrls.has(href)) {
|
|
3697
|
-
return true;
|
|
3698
|
-
}
|
|
3699
|
-
|
|
3700
3704
|
__mreactRememberPrefetchedUrl(href);
|
|
3701
3705
|
|
|
3702
3706
|
const script = __mreactRouteScriptForNavigationUrl(href);
|
|
@@ -3705,21 +3709,30 @@ export async function __mreactPrefetch(url) {
|
|
|
3705
3709
|
return __mreactPrefetchNavigationHtml(href);
|
|
3706
3710
|
}
|
|
3707
3711
|
|
|
3708
|
-
|
|
3712
|
+
const scriptPrefetched = __mreactPrefetchRouteScript(script);
|
|
3713
|
+
|
|
3714
|
+
if (options?.trigger === "viewport") {
|
|
3715
|
+
return scriptPrefetched;
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3718
|
+
return Promise.resolve(__mreactPrefetchNavigationHtml(href))
|
|
3719
|
+
.then(() => scriptPrefetched)
|
|
3720
|
+
.catch(() => scriptPrefetched);
|
|
3709
3721
|
}
|
|
3710
3722
|
|
|
3711
3723
|
function __mreactPrefetchNavigationHtml(href) {
|
|
3712
|
-
if (
|
|
3724
|
+
if (__mreactCachedNavigationHtml(href) !== undefined) {
|
|
3713
3725
|
return true;
|
|
3714
3726
|
}
|
|
3715
3727
|
|
|
3716
|
-
return __mreactFetchNavigationHtmlOnce(href)
|
|
3717
|
-
.then((
|
|
3728
|
+
return __mreactFetchNavigationHtmlOnce(href, { speculative: true })
|
|
3729
|
+
.then((result) => result.cacheable && typeof result.html === "string")
|
|
3718
3730
|
.catch(() => false);
|
|
3719
3731
|
}
|
|
3720
3732
|
|
|
3721
3733
|
const __mreactNavigationHtmlCacheMaxEntries = 64;
|
|
3722
3734
|
const __mreactNavigationPrefetchHistoryMaxEntries = 64;
|
|
3735
|
+
const __mreactNavigationHtmlCacheTtlMs = 30_000;
|
|
3723
3736
|
|
|
3724
3737
|
function __mreactRememberPrefetchedUrl(href) {
|
|
3725
3738
|
__mreactRememberPrefetchHistory(__mreactNavigationState.prefetchedUrls, href);
|
|
@@ -3748,23 +3761,49 @@ function __mreactRememberPrefetchHistory(history, href) {
|
|
|
3748
3761
|
}
|
|
3749
3762
|
|
|
3750
3763
|
function __mreactCachedNavigationHtml(href) {
|
|
3751
|
-
const
|
|
3764
|
+
const entry = __mreactNavigationState.cache.get(href);
|
|
3752
3765
|
|
|
3753
|
-
if (
|
|
3766
|
+
if (entry === undefined) {
|
|
3767
|
+
return undefined;
|
|
3768
|
+
}
|
|
3769
|
+
|
|
3770
|
+
if (
|
|
3771
|
+
entry.token !== __mreactNavigationState.cacheTokens.get(href) ||
|
|
3772
|
+
entry.token.valid !== true ||
|
|
3773
|
+
entry.cacheContext !== __mreactNavigationCacheContext() ||
|
|
3774
|
+
Date.now() - entry.fetchedAt >= __mreactNavigationHtmlCacheTtlMs
|
|
3775
|
+
) {
|
|
3776
|
+
__mreactNavigationState.cache.delete(href);
|
|
3777
|
+
__mreactNavigationState.prefetchedUrls.delete(href);
|
|
3778
|
+
__mreactReleaseNavigationCacheToken(href, entry.token);
|
|
3754
3779
|
return undefined;
|
|
3755
3780
|
}
|
|
3756
3781
|
|
|
3757
3782
|
__mreactNavigationState.cache.delete(href);
|
|
3758
|
-
__mreactNavigationState.cache.set(href,
|
|
3759
|
-
return html;
|
|
3783
|
+
__mreactNavigationState.cache.set(href, entry);
|
|
3784
|
+
return entry.html;
|
|
3760
3785
|
}
|
|
3761
3786
|
|
|
3762
|
-
function __mreactRememberNavigationHtml(href, html) {
|
|
3787
|
+
function __mreactRememberNavigationHtml(href, html, token, cacheContext) {
|
|
3788
|
+
if (
|
|
3789
|
+
token === undefined ||
|
|
3790
|
+
token.valid !== true ||
|
|
3791
|
+
__mreactNavigationState.cacheTokens.get(href) !== token ||
|
|
3792
|
+
cacheContext !== __mreactNavigationCacheContext()
|
|
3793
|
+
) {
|
|
3794
|
+
return;
|
|
3795
|
+
}
|
|
3796
|
+
|
|
3763
3797
|
if (__mreactNavigationState.cache.has(href)) {
|
|
3764
3798
|
__mreactNavigationState.cache.delete(href);
|
|
3765
3799
|
}
|
|
3766
3800
|
|
|
3767
|
-
__mreactNavigationState.cache.set(href,
|
|
3801
|
+
__mreactNavigationState.cache.set(href, {
|
|
3802
|
+
cacheContext,
|
|
3803
|
+
fetchedAt: Date.now(),
|
|
3804
|
+
html,
|
|
3805
|
+
token,
|
|
3806
|
+
});
|
|
3768
3807
|
|
|
3769
3808
|
while (__mreactNavigationState.cache.size > __mreactNavigationHtmlCacheMaxEntries) {
|
|
3770
3809
|
const oldestHref = __mreactNavigationState.cache.keys().next().value;
|
|
@@ -3775,37 +3814,100 @@ function __mreactRememberNavigationHtml(href, html) {
|
|
|
3775
3814
|
|
|
3776
3815
|
__mreactNavigationState.cache.delete(oldestHref);
|
|
3777
3816
|
__mreactNavigationState.prefetchedUrls.delete(oldestHref);
|
|
3817
|
+
__mreactReleaseNavigationCacheToken(oldestHref);
|
|
3778
3818
|
}
|
|
3779
3819
|
}
|
|
3780
3820
|
|
|
3781
|
-
function
|
|
3782
|
-
|
|
3783
|
-
|
|
3821
|
+
function __mreactNavigationCacheContext() {
|
|
3822
|
+
const authSession = typeof document === "undefined"
|
|
3823
|
+
? undefined
|
|
3824
|
+
: document.getElementById("__mreact_auth_session")?.textContent ?? undefined;
|
|
3825
|
+
const cookies = __mreactNavigationCookies();
|
|
3826
|
+
|
|
3827
|
+
return JSON.stringify([authSession, cookies]);
|
|
3828
|
+
}
|
|
3829
|
+
|
|
3830
|
+
function __mreactNavigationCookies() {
|
|
3831
|
+
return typeof document === "undefined" ? "" : document.cookie;
|
|
3832
|
+
}
|
|
3833
|
+
|
|
3834
|
+
function __mreactNavigationResponseCacheContext(html, requestCookies) {
|
|
3835
|
+
let authSession;
|
|
3836
|
+
|
|
3837
|
+
if (typeof document !== "undefined") {
|
|
3838
|
+
const template = document.createElement("template");
|
|
3839
|
+
template.innerHTML = html;
|
|
3840
|
+
authSession = template.content.querySelector("#__mreact_auth_session")?.textContent ?? undefined;
|
|
3784
3841
|
}
|
|
3785
3842
|
|
|
3786
|
-
|
|
3843
|
+
return JSON.stringify([authSession, requestCookies]);
|
|
3844
|
+
}
|
|
3787
3845
|
|
|
3788
|
-
|
|
3789
|
-
|
|
3846
|
+
function __mreactReleaseNavigationCacheToken(href, token) {
|
|
3847
|
+
if (
|
|
3848
|
+
__mreactNavigationState.cache.get(href) === undefined &&
|
|
3849
|
+
__mreactNavigationState.pendingHtmlFetches.get(href) === undefined &&
|
|
3850
|
+
(token === undefined || __mreactNavigationState.cacheTokens.get(href) === token)
|
|
3851
|
+
) {
|
|
3852
|
+
__mreactNavigationState.cacheTokens.delete(href);
|
|
3790
3853
|
}
|
|
3854
|
+
}
|
|
3791
3855
|
|
|
3792
|
-
|
|
3793
|
-
|
|
3856
|
+
function __mreactNavigationCacheToken(href) {
|
|
3857
|
+
const existing = __mreactNavigationState.cacheTokens.get(href);
|
|
3858
|
+
|
|
3859
|
+
if (existing !== undefined) {
|
|
3860
|
+
return existing;
|
|
3794
3861
|
}
|
|
3795
3862
|
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3863
|
+
const token = { valid: true };
|
|
3864
|
+
__mreactNavigationState.cacheTokens.set(href, token);
|
|
3865
|
+
return token;
|
|
3866
|
+
}
|
|
3867
|
+
|
|
3868
|
+
function __mreactPrefetchRouteScript(route) {
|
|
3869
|
+
if (typeof document === "undefined") {
|
|
3870
|
+
return false;
|
|
3871
|
+
}
|
|
3872
|
+
|
|
3873
|
+
const files = [route.script, ...(route.modulePreloads ?? [])];
|
|
3874
|
+
let valid = true;
|
|
3875
|
+
|
|
3876
|
+
for (const file of files) {
|
|
3877
|
+
const href = __mreactNormalizeAssetUrl(file);
|
|
3878
|
+
|
|
3879
|
+
if (
|
|
3880
|
+
href === undefined ||
|
|
3881
|
+
!__mreactIsSupportedModulePreloadUrl(file) ||
|
|
3882
|
+
!__mreactModulePreloadMatchesRouteScript(file, route.script)
|
|
3883
|
+
) {
|
|
3884
|
+
valid = false;
|
|
3885
|
+
continue;
|
|
3886
|
+
}
|
|
3887
|
+
|
|
3888
|
+
if (__mreactNavigationState.prefetchedScripts.has(href)) {
|
|
3889
|
+
continue;
|
|
3890
|
+
}
|
|
3891
|
+
|
|
3892
|
+
let found = false;
|
|
3893
|
+
for (const link of Array.from(document.querySelectorAll('link[rel="modulepreload"][href]'))) {
|
|
3894
|
+
if (link.href === href) {
|
|
3895
|
+
found = true;
|
|
3896
|
+
break;
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
|
|
3900
|
+
if (!found) {
|
|
3901
|
+
const link = document.createElement("link");
|
|
3902
|
+
link.rel = "modulepreload";
|
|
3903
|
+
link.href = href;
|
|
3904
|
+
document.head.appendChild(link);
|
|
3800
3905
|
}
|
|
3906
|
+
|
|
3907
|
+
__mreactRememberPrefetchedScript(href);
|
|
3801
3908
|
}
|
|
3802
3909
|
|
|
3803
|
-
|
|
3804
|
-
link.rel = "modulepreload";
|
|
3805
|
-
link.href = href;
|
|
3806
|
-
document.head.appendChild(link);
|
|
3807
|
-
__mreactRememberPrefetchedScript(href);
|
|
3808
|
-
return true;
|
|
3910
|
+
return valid;
|
|
3809
3911
|
}
|
|
3810
3912
|
|
|
3811
3913
|
export async function __mreactNavigate(url, options = {}) {
|
|
@@ -3818,19 +3920,46 @@ export async function __mreactNavigate(url, options = {}) {
|
|
|
3818
3920
|
__mreactSetNavigationState(__mreactPendingNavigationState(href, options.type ?? "push"));
|
|
3819
3921
|
|
|
3820
3922
|
try {
|
|
3821
|
-
|
|
3822
|
-
const script = __mreactRouteScriptForNavigationUrl(href);
|
|
3823
|
-
if (script !== undefined) {
|
|
3824
|
-
void __mreactPrefetchRouteScript(script);
|
|
3825
|
-
}
|
|
3826
|
-
const html = cachedHtml ?? await __mreactFetchNavigationHtmlOnce(href);
|
|
3923
|
+
let forceReload = __mreactNavigationState.reloadNextNavigationFetch === true;
|
|
3827
3924
|
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3925
|
+
for (;;) {
|
|
3926
|
+
const cachedHtml = forceReload ? undefined : __mreactCachedNavigationHtml(href);
|
|
3927
|
+
const script = __mreactRouteScriptForNavigationUrl(href);
|
|
3928
|
+
if (script !== undefined) {
|
|
3929
|
+
void __mreactPrefetchRouteScript(script);
|
|
3930
|
+
}
|
|
3931
|
+
const result = cachedHtml === undefined
|
|
3932
|
+
? await __mreactFetchNavigationHtmlOnce(href, { force: forceReload })
|
|
3933
|
+
: {
|
|
3934
|
+
cacheable: true,
|
|
3935
|
+
cacheContext: __mreactNavigationCacheContext(),
|
|
3936
|
+
cacheContextMatches: true,
|
|
3937
|
+
html: cachedHtml,
|
|
3938
|
+
reusable: true,
|
|
3939
|
+
speculative: false,
|
|
3940
|
+
token: undefined,
|
|
3941
|
+
};
|
|
3942
|
+
|
|
3943
|
+
if (result.token !== undefined && result.token.valid !== true) {
|
|
3944
|
+
forceReload = __mreactNavigationState.reloadNextNavigationFetch === true;
|
|
3945
|
+
continue;
|
|
3946
|
+
}
|
|
3831
3947
|
|
|
3832
|
-
|
|
3833
|
-
|
|
3948
|
+
if (result.speculative === true && result.cacheable !== true) {
|
|
3949
|
+
forceReload = true;
|
|
3950
|
+
continue;
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3953
|
+
if (result.reusable === true && result.cacheContextMatches !== true) {
|
|
3954
|
+
return false;
|
|
3955
|
+
}
|
|
3956
|
+
|
|
3957
|
+
if (typeof result.html !== "string") {
|
|
3958
|
+
return false;
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3961
|
+
return await __mreactApplyNavigationHtmlWithOptionalTransition(result.html, href, options);
|
|
3962
|
+
}
|
|
3834
3963
|
} finally {
|
|
3835
3964
|
__mreactSetNavigationState(__mreactIdleNavigationState());
|
|
3836
3965
|
}
|
|
@@ -3965,7 +4094,7 @@ function __mreactViewTransitionsAllowed(transition) {
|
|
|
3965
4094
|
}
|
|
3966
4095
|
}
|
|
3967
4096
|
|
|
3968
|
-
export function __mreactInvalidateNavigationCache(path) {
|
|
4097
|
+
export function __mreactInvalidateNavigationCache(path, excludedRequest) {
|
|
3969
4098
|
const normalizedPath = __mreactNormalizeNavigationPath(path);
|
|
3970
4099
|
|
|
3971
4100
|
if (normalizedPath === undefined) {
|
|
@@ -3979,66 +4108,160 @@ export function __mreactInvalidateNavigationCache(path) {
|
|
|
3979
4108
|
|
|
3980
4109
|
for (const href of hrefs) {
|
|
3981
4110
|
if (__mreactNormalizeNavigationPath(href) === normalizedPath) {
|
|
4111
|
+
const token = __mreactNavigationState.cacheTokens.get(href);
|
|
4112
|
+
if (
|
|
4113
|
+
excludedRequest?.href === href &&
|
|
4114
|
+
excludedRequest.token === token &&
|
|
4115
|
+
token?.valid === true
|
|
4116
|
+
) {
|
|
4117
|
+
continue;
|
|
4118
|
+
}
|
|
4119
|
+
if (token !== undefined) {
|
|
4120
|
+
token.valid = false;
|
|
4121
|
+
}
|
|
3982
4122
|
__mreactNavigationState.cache.delete(href);
|
|
3983
4123
|
__mreactNavigationState.prefetchedUrls.delete(href);
|
|
3984
4124
|
__mreactNavigationState.pendingHtmlFetches.delete(href);
|
|
4125
|
+
__mreactNavigationState.cacheTokens.delete(href);
|
|
3985
4126
|
}
|
|
3986
4127
|
}
|
|
3987
4128
|
}
|
|
3988
4129
|
|
|
3989
4130
|
function __mreactInvalidateAllNavigationCache() {
|
|
4131
|
+
for (const entry of __mreactNavigationState.cache.values()) {
|
|
4132
|
+
entry.token.valid = false;
|
|
4133
|
+
}
|
|
4134
|
+
for (const request of __mreactNavigationState.pendingHtmlFetches.values()) {
|
|
4135
|
+
request.token.valid = false;
|
|
4136
|
+
}
|
|
3990
4137
|
__mreactNavigationState.cache.clear();
|
|
4138
|
+
__mreactNavigationState.cacheTokens.clear();
|
|
3991
4139
|
__mreactNavigationState.prefetchedUrls.clear();
|
|
3992
4140
|
__mreactNavigationState.pendingHtmlFetches.clear();
|
|
3993
4141
|
}
|
|
3994
4142
|
|
|
3995
|
-
function __mreactFetchNavigationHtmlOnce(href) {
|
|
4143
|
+
function __mreactFetchNavigationHtmlOnce(href, options = {}) {
|
|
3996
4144
|
const pending = __mreactNavigationState.pendingHtmlFetches.get(href);
|
|
3997
4145
|
|
|
4146
|
+
if (pending !== undefined && options.force !== true) {
|
|
4147
|
+
return pending.promise;
|
|
4148
|
+
}
|
|
4149
|
+
|
|
3998
4150
|
if (pending !== undefined) {
|
|
3999
|
-
|
|
4151
|
+
pending.token.valid = false;
|
|
4152
|
+
__mreactNavigationState.pendingHtmlFetches.delete(href);
|
|
4153
|
+
__mreactNavigationState.cacheTokens.delete(href);
|
|
4000
4154
|
}
|
|
4001
4155
|
|
|
4002
|
-
const
|
|
4003
|
-
|
|
4156
|
+
const token = __mreactNavigationCacheToken(href);
|
|
4157
|
+
const pendingRequest = {
|
|
4158
|
+
promise: undefined,
|
|
4159
|
+
token,
|
|
4160
|
+
};
|
|
4161
|
+
const request = __mreactFetchNavigationHtml(href, options, pendingRequest)
|
|
4162
|
+
.then((result) => {
|
|
4163
|
+
const enriched = {
|
|
4164
|
+
...result,
|
|
4165
|
+
speculative: options.speculative === true,
|
|
4166
|
+
token,
|
|
4167
|
+
};
|
|
4004
4168
|
if (
|
|
4005
|
-
|
|
4006
|
-
|
|
4169
|
+
enriched.cacheable === true &&
|
|
4170
|
+
typeof enriched.html === "string" &&
|
|
4171
|
+
__mreactNavigationState.pendingHtmlFetches.get(href) === pendingRequest &&
|
|
4172
|
+
token.valid === true &&
|
|
4173
|
+
__mreactNavigationState.cacheTokens.get(href) === token
|
|
4007
4174
|
) {
|
|
4008
|
-
__mreactRememberNavigationHtml(href, html);
|
|
4175
|
+
__mreactRememberNavigationHtml(href, enriched.html, token, enriched.cacheContext);
|
|
4009
4176
|
}
|
|
4010
4177
|
|
|
4011
|
-
return
|
|
4178
|
+
return enriched;
|
|
4012
4179
|
})
|
|
4013
4180
|
.finally(() => {
|
|
4014
|
-
if (__mreactNavigationState.pendingHtmlFetches.get(href) ===
|
|
4181
|
+
if (__mreactNavigationState.pendingHtmlFetches.get(href) === pendingRequest) {
|
|
4015
4182
|
__mreactNavigationState.pendingHtmlFetches.delete(href);
|
|
4183
|
+
__mreactReleaseNavigationCacheToken(href, token);
|
|
4016
4184
|
}
|
|
4017
4185
|
});
|
|
4018
4186
|
|
|
4019
|
-
|
|
4187
|
+
pendingRequest.promise = request;
|
|
4188
|
+
__mreactNavigationState.pendingHtmlFetches.set(href, pendingRequest);
|
|
4020
4189
|
return request;
|
|
4021
4190
|
}
|
|
4022
4191
|
|
|
4023
|
-
function __mreactFetchNavigationHtml(href) {
|
|
4024
|
-
const
|
|
4025
|
-
__mreactNavigationState.reloadNextNavigationFetch
|
|
4192
|
+
function __mreactFetchNavigationHtml(href, options = {}, pendingRequest) {
|
|
4193
|
+
const speculative = options.speculative === true;
|
|
4194
|
+
const reloadRouteCache = !speculative && __mreactNavigationState.reloadNextNavigationFetch === true;
|
|
4195
|
+
if (!speculative) {
|
|
4196
|
+
__mreactNavigationState.reloadNextNavigationFetch = false;
|
|
4197
|
+
}
|
|
4026
4198
|
const headers = reloadRouteCache
|
|
4027
4199
|
? { "x-mreact-navigation": "1", "x-mreact-navigation-cache": "reload" }
|
|
4028
4200
|
: { "x-mreact-navigation": "1" };
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4201
|
+
const requestCacheContext = __mreactNavigationCacheContext();
|
|
4202
|
+
const requestCookies = __mreactNavigationCookies();
|
|
4203
|
+
const navigationRequestInit = { headers };
|
|
4204
|
+
__mreactNavigationState.navigationFetchInits.add(navigationRequestInit);
|
|
4205
|
+
|
|
4206
|
+
return fetch(__mreactStaticNavigationRequestHref(href), navigationRequestInit).then((response) => {
|
|
4207
|
+
const currentRequest =
|
|
4208
|
+
pendingRequest !== undefined &&
|
|
4209
|
+
__mreactNavigationState.pendingHtmlFetches.get(href) === pendingRequest &&
|
|
4210
|
+
__mreactNavigationState.cacheTokens.get(href) === pendingRequest.token &&
|
|
4211
|
+
pendingRequest.token.valid === true
|
|
4212
|
+
? { href, token: pendingRequest.token }
|
|
4213
|
+
: undefined;
|
|
4214
|
+
if (pendingRequest === undefined || currentRequest !== undefined) {
|
|
4215
|
+
__mreactApplyRevalidationHeader(response, currentRequest);
|
|
4216
|
+
}
|
|
4217
|
+
const requiresDocumentReload = __mreactNavigationResponseRequiresDocumentReload(response);
|
|
4218
|
+
const responseIsSuccessful =
|
|
4219
|
+
response.ok === true ||
|
|
4220
|
+
(response.ok === undefined && response.status >= 200 && response.status < 300);
|
|
4221
|
+
const responseIsRedirected = response.redirected === true;
|
|
4222
|
+
const cacheControl = (response.headers.get("cache-control") ?? "").toLowerCase();
|
|
4223
|
+
const responseDisallowsCache = /(?:^|,)\\s*(?:no-store|no-cache)(?:\\s*=|\\s*(?:,|$))/.test(
|
|
4224
|
+
cacheControl,
|
|
4225
|
+
);
|
|
4226
|
+
const reusable =
|
|
4227
|
+
!requiresDocumentReload &&
|
|
4228
|
+
responseIsSuccessful &&
|
|
4229
|
+
!responseIsRedirected &&
|
|
4230
|
+
!responseDisallowsCache;
|
|
4231
|
+
|
|
4232
|
+
if (requiresDocumentReload || responseIsRedirected || speculative && !reusable) {
|
|
4233
|
+
__mreactDiscardNavigationResponse(response);
|
|
4234
|
+
return { cacheable: false, html: undefined };
|
|
4036
4235
|
}
|
|
4037
4236
|
|
|
4038
|
-
return response.text()
|
|
4237
|
+
return response.text().then((html) => {
|
|
4238
|
+
const cacheContext = __mreactNavigationResponseCacheContext(html, requestCookies);
|
|
4239
|
+
const currentCacheContext = __mreactNavigationCacheContext();
|
|
4240
|
+
const cacheContextMatches =
|
|
4241
|
+
cacheContext === currentCacheContext && requestCacheContext === currentCacheContext;
|
|
4242
|
+
|
|
4243
|
+
return {
|
|
4244
|
+
cacheContext,
|
|
4245
|
+
cacheContextMatches,
|
|
4246
|
+
cacheable: reusable && cacheContextMatches,
|
|
4247
|
+
html,
|
|
4248
|
+
reusable,
|
|
4249
|
+
};
|
|
4250
|
+
});
|
|
4039
4251
|
});
|
|
4040
4252
|
}
|
|
4041
4253
|
|
|
4254
|
+
function __mreactDiscardNavigationResponse(response) {
|
|
4255
|
+
try {
|
|
4256
|
+
const result = response?.body?.cancel?.();
|
|
4257
|
+
if (result !== undefined && typeof result.catch === "function") {
|
|
4258
|
+
void result.catch(() => {});
|
|
4259
|
+
}
|
|
4260
|
+
} catch {
|
|
4261
|
+
// Ignore body cancellation failures while falling back to a document navigation.
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
|
|
4042
4265
|
function __mreactStaticNavigationRequestHref(href) {
|
|
4043
4266
|
if (typeof document === "undefined" || typeof location === "undefined") {
|
|
4044
4267
|
return href;
|
|
@@ -4074,7 +4297,7 @@ function __mreactNavigationResponseRequiresDocumentReload(response) {
|
|
|
4074
4297
|
return response.status === 204 || response.headers.get("x-mreact-navigation") === "reload";
|
|
4075
4298
|
}
|
|
4076
4299
|
|
|
4077
|
-
function __mreactApplyRevalidationHeader(response) {
|
|
4300
|
+
function __mreactApplyRevalidationHeader(response, currentRequest) {
|
|
4078
4301
|
const header = typeof response?.headers?.get === "function"
|
|
4079
4302
|
? response.headers.get("x-mreact-revalidate")
|
|
4080
4303
|
: null;
|
|
@@ -4083,18 +4306,34 @@ function __mreactApplyRevalidationHeader(response) {
|
|
|
4083
4306
|
return;
|
|
4084
4307
|
}
|
|
4085
4308
|
|
|
4309
|
+
const currentPath = __mreactNormalizeNavigationPath(currentRequest?.href);
|
|
4310
|
+
|
|
4086
4311
|
for (const path of header.split(",")) {
|
|
4087
|
-
|
|
4312
|
+
const trimmedPath = path.trim();
|
|
4313
|
+
const normalizedPath = __mreactNormalizeNavigationPath(trimmedPath);
|
|
4314
|
+
const excludedRequest =
|
|
4315
|
+
currentRequest !== undefined && normalizedPath === currentPath ? currentRequest : undefined;
|
|
4316
|
+
__mreactInvalidateNavigationCache(trimmedPath, excludedRequest);
|
|
4088
4317
|
}
|
|
4089
4318
|
}
|
|
4090
4319
|
|
|
4320
|
+
function __mreactIsNavigationFetchRequest(_input, init) {
|
|
4321
|
+
return init !== null && typeof init === "object" && __mreactNavigationState.navigationFetchInits.has(init);
|
|
4322
|
+
}
|
|
4323
|
+
|
|
4091
4324
|
function __mreactNormalizeNavigationPath(path) {
|
|
4325
|
+
if (typeof path !== "string" || path.trim() === "") {
|
|
4326
|
+
return undefined;
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
const normalizedInput = path.trim();
|
|
4330
|
+
|
|
4092
4331
|
if (typeof location === "undefined") {
|
|
4093
|
-
return
|
|
4332
|
+
return normalizedInput;
|
|
4094
4333
|
}
|
|
4095
4334
|
|
|
4096
4335
|
try {
|
|
4097
|
-
const url = new URL(
|
|
4336
|
+
const url = new URL(normalizedInput, location.href);
|
|
4098
4337
|
const pathname = url.pathname.replace(/\\/+$/, "");
|
|
4099
4338
|
|
|
4100
4339
|
return pathname === "" ? "/" : pathname;
|
|
@@ -4110,7 +4349,7 @@ export function __mreactRestoreHistoryState(state) {
|
|
|
4110
4349
|
|
|
4111
4350
|
const html = typeof state.html === "string"
|
|
4112
4351
|
? state.html
|
|
4113
|
-
: typeof state.url === "string" ?
|
|
4352
|
+
: typeof state.url === "string" ? __mreactCachedNavigationHtml(state.url) : undefined;
|
|
4114
4353
|
|
|
4115
4354
|
if (typeof html !== "string") {
|
|
4116
4355
|
return false;
|
|
@@ -4486,7 +4725,7 @@ function __mreactRouteScriptForNavigationUrl(url) {
|
|
|
4486
4725
|
|
|
4487
4726
|
for (const route of __mreactClientRoutePrefetchManifest()) {
|
|
4488
4727
|
if (__mreactRoutePathMatches(route.path, nextUrl.pathname)) {
|
|
4489
|
-
return route
|
|
4728
|
+
return route;
|
|
4490
4729
|
}
|
|
4491
4730
|
}
|
|
4492
4731
|
|
|
@@ -4516,12 +4755,28 @@ function __mreactClientRoutePrefetchManifest() {
|
|
|
4516
4755
|
try {
|
|
4517
4756
|
const parsed = JSON.parse(text);
|
|
4518
4757
|
__mreactNavigationState.routePrefetchManifest = Array.isArray(parsed)
|
|
4519
|
-
? parsed.
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4758
|
+
? parsed.flatMap((route) => {
|
|
4759
|
+
if (
|
|
4760
|
+
route === null ||
|
|
4761
|
+
typeof route !== "object" ||
|
|
4762
|
+
typeof route.path !== "string" ||
|
|
4763
|
+
typeof route.script !== "string" ||
|
|
4764
|
+
!__mreactIsSupportedModulePreloadUrl(route.script)
|
|
4765
|
+
) {
|
|
4766
|
+
return [];
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4769
|
+
const modulePreloads = Array.isArray(route.modulePreloads)
|
|
4770
|
+
? route.modulePreloads.filter(
|
|
4771
|
+
(file) =>
|
|
4772
|
+
typeof file === "string" &&
|
|
4773
|
+
__mreactIsSupportedModulePreloadUrl(file) &&
|
|
4774
|
+
__mreactModulePreloadMatchesRouteScript(file, route.script),
|
|
4775
|
+
)
|
|
4776
|
+
: [];
|
|
4777
|
+
|
|
4778
|
+
return [{ ...route, modulePreloads }];
|
|
4779
|
+
})
|
|
4525
4780
|
: [];
|
|
4526
4781
|
} catch {
|
|
4527
4782
|
__mreactNavigationState.routePrefetchManifest = [];
|
|
@@ -4530,6 +4785,29 @@ function __mreactClientRoutePrefetchManifest() {
|
|
|
4530
4785
|
return __mreactNavigationState.routePrefetchManifest;
|
|
4531
4786
|
}
|
|
4532
4787
|
|
|
4788
|
+
function __mreactIsSupportedModulePreloadUrl(value) {
|
|
4789
|
+
if (typeof value !== "string" || value === "" || value.startsWith("javascript:")) {
|
|
4790
|
+
return false;
|
|
4791
|
+
}
|
|
4792
|
+
|
|
4793
|
+
try {
|
|
4794
|
+
const resolved = new URL(value, typeof location === "undefined" ? undefined : location.href);
|
|
4795
|
+
return resolved.protocol === "http:" || resolved.protocol === "https:";
|
|
4796
|
+
} catch {
|
|
4797
|
+
return false;
|
|
4798
|
+
}
|
|
4799
|
+
}
|
|
4800
|
+
|
|
4801
|
+
function __mreactModulePreloadMatchesRouteScript(value, script) {
|
|
4802
|
+
try {
|
|
4803
|
+
const scriptUrl = new URL(__mreactNormalizeAssetUrl(script), location.href);
|
|
4804
|
+
const dependencyUrl = new URL(__mreactNormalizeAssetUrl(value), location.href);
|
|
4805
|
+
return scriptUrl.origin === dependencyUrl.origin;
|
|
4806
|
+
} catch {
|
|
4807
|
+
return false;
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4810
|
+
|
|
4533
4811
|
function __mreactRoutePathMatches(routePath, pathname) {
|
|
4534
4812
|
const routeSegments = __mreactNormalizeRoutePath(routePath);
|
|
4535
4813
|
const pathSegments = __mreactNormalizeRoutePath(pathname);
|
|
@@ -4827,9 +5105,12 @@ function __mreactInstallNavigationFetchRevalidation() {
|
|
|
4827
5105
|
const fetchImpl = globalThis.fetch;
|
|
4828
5106
|
globalThis.fetch = function(input, init) {
|
|
4829
5107
|
const mutating = __mreactIsMutatingFetchRequest(input, init);
|
|
5108
|
+
const navigation = __mreactIsNavigationFetchRequest(input, init);
|
|
4830
5109
|
|
|
4831
5110
|
return Promise.resolve(fetchImpl.call(this, input, init)).then((response) => {
|
|
4832
|
-
|
|
5111
|
+
if (!navigation) {
|
|
5112
|
+
__mreactApplyRevalidationHeader(response);
|
|
5113
|
+
}
|
|
4833
5114
|
|
|
4834
5115
|
if (mutating) {
|
|
4835
5116
|
__mreactInvalidateAllNavigationCache();
|
|
@@ -4901,7 +5182,7 @@ function __mreactObserveViewportPrefetchAnchors(root) {
|
|
|
4901
5182
|
}
|
|
4902
5183
|
|
|
4903
5184
|
__mreactNavigationState.viewportObserver?.unobserve(entry.target);
|
|
4904
|
-
void __mreactPrefetch(entry.target.href);
|
|
5185
|
+
void __mreactPrefetch(entry.target.href, { trigger: "viewport" });
|
|
4905
5186
|
}
|
|
4906
5187
|
});
|
|
4907
5188
|
}
|