Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/Components/Web.JS/src/Boot.Web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,14 @@ function boot(options?: Partial<WebStartOptions>) : Promise<void> {
},
};

attachComponentDescriptorHandler(rootComponentManager);
attachStreamingRenderingListener(options?.ssr, navigationEnhancementCallbacks);

// Initialize enhanced navigation as early as possible to prevent timing issues
if (!options?.ssr?.disableDomPreservation) {
attachProgressivelyEnhancedNavigationListener(navigationEnhancementCallbacks);
}

attachComponentDescriptorHandler(rootComponentManager);
attachStreamingRenderingListener(options?.ssr, navigationEnhancementCallbacks);

enableFocusOnNavigate(jsEventRegistry);

// Wait until the initial page response completes before activating interactive components.
Expand Down
19 changes: 14 additions & 5 deletions src/Components/Web.JS/src/Services/NavigationEnhancement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,15 @@ different bundles that only contain minimal content.
const acceptHeader = 'text/html; blazor-enhanced-nav=on';

let currentEnhancedNavigationAbortController: AbortController | null;
let navigationEnhancementCallbacks: NavigationEnhancementCallbacks;
let navigationEnhancementCallbacks: Promise<NavigationEnhancementCallbacks>;
let navigationEnhancementCallbacksResolver: (callbacks: NavigationEnhancementCallbacks) => void;
let performingEnhancedPageLoad: boolean;

// Initialize the promise that will be resolved when callbacks are set
navigationEnhancementCallbacks = new Promise<NavigationEnhancementCallbacks>((resolve) => {
navigationEnhancementCallbacksResolver = resolve;
});

// This gets initialized to the current URL when we load.
// After that, it gets updated every time we successfully complete a navigation.
let currentContentUrl = location.href;
Expand All @@ -57,7 +63,7 @@ export function hasNeverStartedAnyEnhancedPageLoad() {
}

export function attachProgressivelyEnhancedNavigationListener(callbacks: NavigationEnhancementCallbacks) {
navigationEnhancementCallbacks = callbacks;
navigationEnhancementCallbacksResolver(callbacks);
document.addEventListener('click', onDocumentClick);
document.addEventListener('submit', onDocumentSubmit);
window.addEventListener('popstate', onPopState);
Expand Down Expand Up @@ -201,8 +207,11 @@ export async function performEnhancedPageLoad(internalDestinationHref: string, i
// Notify any interactive runtimes that an enhanced navigation is starting
notifyEnhancedNavigationListeners(internalDestinationHref, interceptedLink);

// Wait for navigation enhancement callbacks to be initialized before proceeding
const callbacks = await navigationEnhancementCallbacks;

// Notify handlers that enhanced navigation is starting
navigationEnhancementCallbacks.enhancedNavigationStarted();
callbacks.enhancedNavigationStarted();

// Now request the new page via fetch, and a special header that tells the server we want it to inject
// framing boundaries to distinguish the initial document and each subsequent streaming SSR update.
Expand Down Expand Up @@ -305,7 +314,7 @@ export async function performEnhancedPageLoad(internalDestinationHref: string, i
// For HTML responses, regardless of the status code, display it
const parsedHtml = new DOMParser().parseFromString(initialContent, 'text/html');
synchronizeDomContent(document, parsedHtml);
navigationEnhancementCallbacks.documentUpdated();
callbacks.documentUpdated();
} else if (responseContentType?.startsWith('text/') && initialContent) {
// For any other text-based content, we'll just display it, because that's what
// would happen if this was a non-enhanced request.
Expand Down Expand Up @@ -344,7 +353,7 @@ export async function performEnhancedPageLoad(internalDestinationHref: string, i
}

performingEnhancedPageLoad = false;
navigationEnhancementCallbacks.enhancedNavigationCompleted();
callbacks.enhancedNavigationCompleted();

// For non-GET requests, the destination has to be the same URL you're already on, or result in a redirection
// (post/redirect/get). You're not allowed to POST to a different URL without redirecting, because then back/forwards
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ private void AssertNotFoundRendered_ResponseStarted_Or_POST(bool hasReExecutionM
public void NotFoundSetOnFormSubmit_ResponseNotStarted_SSR(bool hasReExecutionMiddleware, bool hasCustomNotFoundPageSet)
{
string reexecution = hasReExecutionMiddleware ? "/reexecution" : "";
string testUrl = $"{ServerPathBase}{reexecution}/post-not-found-ssr-streaming?useCustomNotFoundPage={hasCustomNotFoundPageSet}";
string testUrl = $"{ServerPathBase}{reexecution}/post-not-found-ssr?useCustomNotFoundPage={hasCustomNotFoundPageSet}";
Navigate(testUrl);
Browser.FindElement(By.Id("not-found-form")).FindElement(By.TagName("button")).Click();

Expand Down
Loading