Skip to content

Commit

Permalink
Merged PR 37179: [internal/release/8.0] [Blazor] Fix interactive serv…
Browse files Browse the repository at this point in the history
…er component activation

Fixes an issue where interactive server components may sometimes fail to become interactive.
  • Loading branch information
Mackinnon Buck authored and wtgodbe committed Feb 13, 2024
1 parent 90035db commit 9cd97f4
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ public static IServerSideBlazorBuilder AddServerSideBlazor(this IServiceCollecti
// user's configuration. So even if the user has multiple independent server-side
// Components entrypoints, this lot is the same and repeated registrations are a no-op.
services.TryAddSingleton<ICircuitFactory, CircuitFactory>();
services.TryAddSingleton<IServerComponentDeserializer, ServerComponentDeserializer>();
services.TryAddSingleton<ICircuitHandleRegistry, CircuitHandleRegistry>();
services.TryAddSingleton<RootComponentTypeCache>();
services.TryAddSingleton<ComponentParameterDeserializer>();
services.TryAddSingleton<ComponentParametersTypeCache>();
services.TryAddSingleton<CircuitIdFactory>();
services.TryAddScoped<IServerComponentDeserializer, ServerComponentDeserializer>();
services.TryAddScoped<IErrorBoundaryLogger, RemoteErrorBoundaryLogger>();
services.TryAddScoped<AntiforgeryStateProvider, DefaultAntiforgeryStateProvider>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,55 @@ public void InteractiveServerRootComponent_CanAccessCircuitContext()
Browser.Equal("True", () => Browser.FindElement(By.Id("has-circuit-context")).Text);
}

[Fact]
public void InteractiveServerRootComponents_CanBecomeInteractive_WithoutInterferingWithOtherCircuits()
{
// Start by setting up 2 tabs with interactive server components.
SetUpPageWithOneInteractiveServerComponent();

var firstWindow = Browser.CurrentWindowHandle;
Browser.SwitchTo().NewWindow(WindowType.Tab);
var secondWindow = Browser.CurrentWindowHandle;

SetUpPageWithOneInteractiveServerComponent();

// Start streaming in the second tab.
Browser.Click(By.Id("start-streaming-link"));
Browser.Equal("Streaming", () => Browser.FindElement(By.Id("status")).Text);

// Add an interactive server component while streaming.
// This will update the existing component, but the new component
// won't become interactive until streaming ends.
Browser.Click(By.Id(AddServerPrerenderedId));
Browser.Equal("False", () => Browser.FindElement(By.Id($"is-interactive-1")).Text);

// Add an interactive server component in the first tab.
// This component will become interactive immediately because the response
// that rendered the component will have completed quickly.
Browser.SwitchTo().Window(firstWindow);
Browser.Click(By.Id(AddServerPrerenderedId));
Browser.Equal("True", () => Browser.FindElement(By.Id($"is-interactive-1")).Text);

// Stop streaming in the second tab.
// This will activate the pending component for interactivity.
// This check verifies that a circuit can activate components from its most
// recent response, even if that response isn't the most recent between all
// circuits.
Browser.SwitchTo().Window(secondWindow);
Browser.Click(By.Id("stop-streaming-link"));
Browser.Equal("True", () => Browser.FindElement(By.Id($"is-interactive-1")).Text);

void SetUpPageWithOneInteractiveServerComponent()
{
Navigate($"{ServerPathBase}/streaming-interactivity");

Browser.Equal("Not streaming", () => Browser.FindElement(By.Id("status")).Text);

Browser.Click(By.Id(AddServerPrerenderedId));
Browser.Equal("True", () => Browser.FindElement(By.Id($"is-interactive-0")).Text);
}
}

private void BlockWebAssemblyResourceLoad()
{
// Force a WebAssembly resource cache miss so that we can fall back to using server interactivity
Expand Down

0 comments on commit 9cd97f4

Please sign in to comment.