Skip to content

Fix Blazor crash when interactive component is in layout with enhanced nav#66007

Open
maraf wants to merge 7 commits intomainfrom
maraf/fix-64722-enhanced-nav-layout-crash
Open

Fix Blazor crash when interactive component is in layout with enhanced nav#66007
maraf wants to merge 7 commits intomainfrom
maraf/fix-64722-enhanced-nav-layout-crash

Conversation

@maraf
Copy link
Copy Markdown
Member

@maraf maraf commented Mar 27, 2026

Fix Blazor crash when interactive component is in layout with enhanced navigation

Fixes #64722

Problem

When an InteractiveAuto or InteractiveWebAssembly component is placed in the layout (e.g. <Counter /> in MainLayout.razor), navigating between pages via enhanced navigation causes:

TypeError: Cannot read properties of null (reading 'insertBefore')

Root Cause

The <!--Blazor-WebAssembly:{...}--> metadata comment was removed from the physical DOM during discoverWebAssemblyOptions(), but remained in the parent element's logical children array as an orphaned node (parentNode === null). On subsequent enhanced navigations, insertLogicalChild() picked this orphaned comment as a reference node for insertBefore, crashing because parentNode was null.

Changes

  1. Reorder registerAllComponentDescriptors — Call discoverWebAssemblyOptions before upgradeComponentCommentsToLogicalRootComments, ensuring metadata comments are removed from the DOM before the logical tree is built.

  2. Strip metadata in preprocessAndSynchronizeDomContent — Remove metadata comments from new enhanced-nav content before building the logical tree, preventing orphaned nodes during navigation.

  3. Defensive null check in insertLogicalChild — Replace the non-null assertion parentNode!.insertBefore(...) with a null check, falling back to appendDomNode if the reference node is disconnected.

@github-actions github-actions bot added the area-blazor Includes: Blazor, Razor Components label Mar 27, 2026
@maraf maraf force-pushed the maraf/fix-64722-enhanced-nav-layout-crash branch from 22a336b to b530b67 Compare March 27, 2026 12:53
…d nav

When an InteractiveAuto/InteractiveWebAssembly component is placed in the
layout, navigating between pages via enhanced navigation causes:
TypeError: Cannot read properties of null (reading insertBefore)

Root cause: The Blazor-WebAssembly metadata comment was removed from the DOM
during discoverWebAssemblyOptions() but remained in the logical children
array as an orphaned node. On subsequent enhanced navigations, insertLogicalChild
would pick this orphaned comment as a reference node for insertBefore, crashing
because parentNode was null.

Fix:
1. Reorder registerAllComponentDescriptors to call discoverWebAssemblyOptions
   before upgradeComponentCommentsToLogicalRootComments, ensuring metadata
   comments are removed before the logical tree is built.
2. Strip metadata comments from new content in preprocessAndSynchronizeDomContent
   before building the logical tree during enhanced navigation.
3. Add defensive null check in insertLogicalChild for disconnected reference nodes.

Fixes #64722

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@maraf maraf force-pushed the maraf/fix-64722-enhanced-nav-layout-crash branch from b530b67 to 4f13842 Compare March 27, 2026 12:54
@maraf

This comment was marked as resolved.

…ced-nav-layout-crash

# Conflicts:
#	src/Components/Web.JS/src/Rendering/DomMerging/DomSync.ts

Co-authored-by: maraf <10020471+maraf@users.noreply.github.com>

This comment was marked as resolved.

@maraf maraf marked this pull request as ready for review April 15, 2026 11:14
@maraf maraf requested a review from a team as a code owner April 15, 2026 11:14
Copilot AI review requested due to automatic review settings April 15, 2026 11:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a crash in Blazor’s enhanced navigation DOM merging when an interactive component is rendered from a layout, by preventing WebAssembly metadata comments from becoming orphaned logical nodes and by making logical insertion more defensive. It also adds new test assets and an E2E regression test that navigates between pages using a layout containing an InteractiveAuto component.

Changes:

  • Adjust DOM merge preprocessing/registration ordering to remove WebAssembly options metadata comments before building logical element trees.
  • Add a defensive fallback in insertLogicalChild to avoid crashing when a reference node is disconnected.
  • Add new test pages/layout + an E2E regression test for navigating between enhanced-nav pages with an interactive component in the layout.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Components/Web.JS/src/Rendering/DomMerging/DomSync.ts Reorders descriptor registration steps and strips WASM options metadata from incoming enhanced-nav content before logical tree creation.
src/Components/Web.JS/src/Rendering/LogicalElements.ts Avoids insertBefore crash by handling disconnected reference nodes during logical insertions.
src/Components/test/E2ETest/ServerRenderingTests/EnhancedNavigationTest.cs Adds a new E2E regression test for enhanced navigation with an interactive component in the layout.
src/Components/test/testassets/TestContentPackage/InteractiveCounterInLayout.razor Adds an InteractiveAuto counter component intended to be rendered from a layout.
src/Components/test/testassets/Components.TestServer/RazorComponents/Shared/EnhancedNavWithInteractiveInLayout.razor Adds a layout that includes the interactive counter and enhanced-nav links.
src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/EnhancedNav/InteractiveInLayoutHome.razor Adds a home page using the new layout for the regression scenario.
src/Components/test/testassets/Components.TestServer/RazorComponents/Pages/EnhancedNav/InteractiveInLayoutOther.razor Adds a second page using the new layout to exercise back-and-forth enhanced navigation.

Comment thread src/Components/Web.JS/src/Rendering/DomMerging/DomSync.ts
Comment thread src/Components/test/E2ETest/ServerRenderingTests/EnhancedNavigationTest.cs Outdated
Comment thread src/Components/test/E2ETest/ServerRenderingTests/EnhancedNavigationTest.cs Outdated
Copy link
Copy Markdown
Member Author

maraf commented Apr 15, 2026

Addressing Copilot review feedback:

Comment on staleness assertion (line 938): Good catch. Applied — I now capture a layout element (#layout-counter) that persists across pages and assert it is not stale after each navigation to verify enhanced navigation was used.

Comment on error detection (line 949): Agreed. Replaced the unreliable blazor-error-ui check with Browser.GetBrowserLogs(LogLevel.Warning) + Assert.DoesNotContain(Error), matching the existing pattern in this file. Also added a click on the interactive counter button to prove the interactive layout component is still functional after navigation.

- Add staleness-based assertion using layout element to verify
  enhanced navigation was actually used (not full page reload)
- Replace unreliable blazor-error-ui check with browser console
  log assertion matching existing patterns in the file
- Click interactive counter button to prove the interactive layout
  component is still functional after navigation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member

@ilonatommy ilonatommy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks correct, one nit for discussion.

Comment thread src/Components/Web.JS/src/Rendering/LogicalElements.ts Outdated
maraf and others added 2 commits April 15, 2026 18:11
Replace the simple null-check fallback with a cleanup-first approach:
scan and remove all orphaned nodes (disconnected from DOM) from the
siblings array before the insert logic runs, adjusting the insertion
index as orphans are pruned. This ensures:

1. Correct DOM ordering is preserved - the reference sibling is always
   connected after cleanup, so insertBefore places nodes correctly.
2. Orphaned siblings are removed from the logical children array so
   subsequent operations don't encounter them.

Add unit tests for orphan cleanup in insertLogicalChild covering:
- Orphan at reference position
- Multiple orphans before insertion index (index adjustment)
- Orphans interspersed with connected nodes
- Append fallback after cleanup
- Normal insert (no regression)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use fresh Browser.Exists() queries inside WaitAssert lambdas instead
of a captured element reference. The InteractiveAuto component
re-renders client-side after clicking the button, replacing the DOM
node and making the captured reference stale.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member Author

maraf commented Apr 17, 2026

/azp run aspnetcore-components-e2e

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

… test

The test CanNavigateBetweenPagesWhenLayoutContainsInteractiveComponent was
racing against InteractiveAuto bootstrap: after enhanced navigation it
clicked the counter button before the component had finished transitioning
to interactive mode, so the click did nothing and the counter stayed at 0.

Add an 'Interactive' marker to InteractiveCounterInLayout (toggled from
OnAfterRender(firstRender)) and wait for it to read 'True' in the test
before clicking, mirroring the pattern used by TestContentPackage.Counter.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blazor Web App Crash in .NET 10 When Auto Component on the Homepage

4 participants