Skip to content

Commit e42a2b0

Browse files
authored
[Blazor] Ensure WebAssembly startup options are initialized just once (#59905)
1 parent 95bc200 commit e42a2b0

File tree

6 files changed

+69
-33
lines changed

6 files changed

+69
-33
lines changed

src/Components/Web.JS/src/Boot.Web.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { LogLevel } from './Platform/Logging/Logger';
2626
import { resolveOptions } from './Platform/Circuits/CircuitStartOptions';
2727
import { JSInitializer } from './JSInitializers/JSInitializers';
2828
import { enableFocusOnNavigate } from './Rendering/FocusOnNavigate';
29+
import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions';
2930

3031
let started = false;
3132
let rootComponentManager: WebRootComponentManager;
@@ -91,10 +92,11 @@ function onInitialDomContentLoaded(options: Partial<WebStartOptions>) {
9192
// so we do the same here.
9293
const initialCircuitOptions = resolveOptions(options?.circuit || {});
9394
options.circuit = initialCircuitOptions;
95+
options.webAssembly = options.webAssembly || ({} as WebAssemblyStartOptions);
9496
const logger = new ConsoleLogger(initialCircuitOptions.logLevel);
9597
const initializersPromise = fetchAndInvokeInitializers(options, logger);
9698
setCircuitOptions(resolveConfiguredOptions(initializersPromise, initialCircuitOptions));
97-
setWebAssemblyOptions(resolveConfiguredOptions(initializersPromise, options?.webAssembly || {}));
99+
setWebAssemblyOptions(resolveConfiguredOptions(initializersPromise, options.webAssembly));
98100

99101
registerAllComponentDescriptors(document);
100102
rootComponentManager.onDocumentUpdated();

src/Components/test/E2ETest/ServerRenderingTests/BlazorWebJsInitializersTest.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public void InitializersRunsModernCallbacksByDefaultWhenPresent(bool streaming,
3333
var url = $"{ServerPathBase}/initializers?streaming={streaming}&wasm={webassembly}&server={server}";
3434
Navigate(url);
3535

36+
if (webassembly)
37+
{
38+
((IJavaScriptExecutor)Browser).ExecuteScript("sessionStorage.setItem('block-webassembly-settings', 'true')");
39+
}
40+
3641
foreach (var callback in expectedInvokedCallbacks)
3742
{
3843
Browser.Exists(By.Id(callback));
@@ -56,6 +61,11 @@ public void InitializersRunsClassicInitializersWhenEnabled(bool streaming, bool
5661
var url = $"{ServerPathBase}/initializers?streaming={streaming}&wasm={webassembly}&server={server}";
5762
Navigate(url);
5863

64+
if (webassembly)
65+
{
66+
((IJavaScriptExecutor)Browser).ExecuteScript("sessionStorage.setItem('block-webassembly-settings', 'true')");
67+
}
68+
5969
foreach (var callback in expectedCallbacks)
6070
{
6171
Browser.Exists(By.Id(callback));
@@ -82,12 +92,12 @@ public static TheoryData<bool, bool, bool, string[]> InitializerTestData()
8292
{
8393
{ false, false, false, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started","modern-before-web-start", "modern-after-web-started"] },
8494
{ false, false, true, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-server-start", "classic-and-modern-after-server-started", "classic-and-modern-circuit-opened", "modern-before-web-start", "modern-after-web-started", "modern-before-server-start", "modern-after-server-started", "modern-circuit-opened" ] },
85-
{ false, true, false, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-web-assembly-start", "classic-and-modern-after-web-assembly-started", "modern-before-web-start", "modern-after-web-started", "modern-before-web-assembly-start", "modern-after-web-assembly-started"] },
86-
{ false, true, true, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-server-start", "classic-and-modern-circuit-opened", "classic-and-modern-after-server-started", "classic-and-modern-before-web-assembly-start", "classic-and-modern-after-web-assembly-started", "modern-before-web-start", "modern-after-web-started", "modern-before-server-start", "modern-circuit-opened", "modern-after-server-started", "modern-before-web-assembly-start", "modern-after-web-assembly-started"] },
95+
{ false, true, false, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-web-assembly-start", "classic-and-modern-after-web-assembly-started", "server--classic-and-modern-before-web-assembly-start", "server--classic-and-modern-after-web-assembly-started", "modern-before-web-start", "modern-after-web-started", "modern-before-web-assembly-start", "modern-after-web-assembly-started"] },
96+
{ false, true, true, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-server-start", "classic-and-modern-circuit-opened", "classic-and-modern-after-server-started", "classic-and-modern-before-web-assembly-start", "classic-and-modern-after-web-assembly-started", "server--classic-and-modern-before-web-assembly-start", "server--classic-and-modern-after-web-assembly-started", "modern-before-web-start", "modern-after-web-started", "modern-before-server-start", "modern-circuit-opened", "modern-after-server-started", "modern-before-web-assembly-start", "modern-after-web-assembly-started"] },
8797
{ true, false, false, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started","modern-before-web-start", "modern-after-web-started"] },
8898
{ true, false, true, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-server-start", "classic-and-modern-after-server-started", "classic-and-modern-circuit-opened", "modern-before-web-start", "modern-after-web-started", "modern-before-server-start", "modern-after-server-started", "modern-circuit-opened" ] },
89-
{ true, true, false, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-web-assembly-start", "classic-and-modern-after-web-assembly-started", "modern-before-web-start", "modern-after-web-started", "modern-before-web-assembly-start", "modern-after-web-assembly-started"] },
90-
{ true, true, true, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-server-start", "classic-and-modern-circuit-opened", "classic-and-modern-after-server-started", "classic-and-modern-before-web-assembly-start", "classic-and-modern-after-web-assembly-started", "modern-before-web-start", "modern-after-web-started", "modern-before-server-start", "modern-circuit-opened", "modern-after-server-started", "modern-before-web-assembly-start", "modern-after-web-assembly-started"] },
99+
{ true, true, false, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-web-assembly-start", "classic-and-modern-after-web-assembly-started", "server--classic-and-modern-before-web-assembly-start", "server--classic-and-modern-after-web-assembly-started", "modern-before-web-start", "modern-after-web-started", "modern-before-web-assembly-start", "modern-after-web-assembly-started"] },
100+
{ true, true, true, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started", "classic-and-modern-before-server-start", "classic-and-modern-circuit-opened", "classic-and-modern-after-server-started", "classic-and-modern-before-web-assembly-start", "classic-and-modern-after-web-assembly-started", "server--classic-and-modern-before-web-assembly-start", "server--classic-and-modern-after-web-assembly-started", "modern-before-web-start", "modern-after-web-started", "modern-before-server-start", "modern-circuit-opened", "modern-after-server-started", "modern-before-web-assembly-start", "modern-after-web-assembly-started"] },
91101
};
92102

93103
return result;

src/Components/test/testassets/BasicTestApp/wwwroot/JSInitializers/ClassicAndModern/BasicTestApp.lib.module.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export function afterServerStarted() {
3636
appendElement('classic-and-modern-after-server-started', 'Classic and modern "afterServerStarted"');
3737
}
3838

39+
// Duplicated in Components.TestServer\wwwroot\Components.TestServer.lib.module.js
3940
function appendElement(id, text) {
4041
var content = document.getElementById('initializers-content');
4142
if (!content) {

src/Components/test/testassets/Components.TestServer/.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@
4343
const enableClassicInitializers = sessionStorage.getItem('enable-classic-initializers') === 'true';
4444
const suppressEnhancedNavigation = sessionStorage.getItem('suppress-enhanced-navigation') === 'true';
4545
const blockLoadBootResource = sessionStorage.getItem('block-load-boot-resource') === 'true';
46+
const blockWebassemblySettings = sessionStorage.getItem('block-webassembly-settings') === 'true';
4647
sessionStorage.removeItem('suppress-enhanced-navigation');
4748
sessionStorage.removeItem('block-load-boot-resource');
4849
sessionStorage.removeItem('enable-classic-initializers');
50+
sessionStorage.removeItem('block-webassembly-settings');
4951
5052
let loadBootResourceUnblocked = null;
5153
if (blockLoadBootResource) {
@@ -66,6 +68,35 @@
6668
6769
let maxParallelResourceDownloadCount = 0;
6870
let currentParallelResourceDownloadCount = 0;
71+
let webAssemblySettings = {
72+
loadBootResource: function (type, name, defaultUri, integrity) {
73+
switch (type) {
74+
case 'manifest':
75+
case 'dotnetjs':
76+
case 'dotnetwasm':
77+
// note this is resolved to absolute URL using document.baseURI
78+
return `WasmMinimal/_framework/${name}`;
79+
default:
80+
// The following allows us to arbitrarily delay the loading of WebAssembly resources.
81+
// This is useful for guaranteeing that auto mode components will fall back on
82+
// using Blazor server.
83+
currentParallelResourceDownloadCount++;
84+
return fetch(`${document.baseURI}WasmMinimal/_framework/${name}?`, {
85+
method: "GET",
86+
}).then(async (response) => {
87+
if (currentParallelResourceDownloadCount > maxParallelResourceDownloadCount) {
88+
maxParallelResourceDownloadCount = currentParallelResourceDownloadCount;
89+
window['__aspnetcore__testing__max__parallel__resource__download__count'] = maxParallelResourceDownloadCount;
90+
}
91+
currentParallelResourceDownloadCount--;
92+
await loadBootResourceUnblocked;
93+
return response;
94+
});
95+
}
96+
},
97+
};
98+
if (blockWebassemblySettings)
99+
webAssemblySettings = null;
69100
70101
Blazor.start({
71102
ssr: {
@@ -75,33 +106,7 @@
75106
circuitInactivityTimeoutMs: 100,
76107
},
77108
enableClassicInitializers: enableClassicInitializers,
78-
webAssembly: {
79-
loadBootResource: function (type, name, defaultUri, integrity) {
80-
switch (type) {
81-
case 'manifest':
82-
case 'dotnetjs':
83-
case 'dotnetwasm':
84-
// note this is resolved to absolute URL using document.baseURI
85-
return `WasmMinimal/_framework/${name}`;
86-
default:
87-
// The following allows us to arbitrarily delay the loading of WebAssembly resources.
88-
// This is useful for guaranteeing that auto mode components will fall back on
89-
// using Blazor server.
90-
currentParallelResourceDownloadCount++;
91-
return fetch(`${document.baseURI}WasmMinimal/_framework/${name}?`, {
92-
method: "GET",
93-
}).then(async (response) => {
94-
if (currentParallelResourceDownloadCount > maxParallelResourceDownloadCount) {
95-
maxParallelResourceDownloadCount = currentParallelResourceDownloadCount;
96-
window['__aspnetcore__testing__max__parallel__resource__download__count'] = maxParallelResourceDownloadCount;
97-
}
98-
currentParallelResourceDownloadCount--;
99-
await loadBootResourceUnblocked;
100-
return response;
101-
});
102-
}
103-
},
104-
},
109+
webAssembly: webAssemblySettings,
105110
circuit: {
106111
reconnectionOptions: {
107112
// It's easier to test the reconnection logic if we wait a bit
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export function beforeWebAssemblyStart() {
2+
appendElement('server--classic-and-modern-before-web-assembly-start', 'Server project Classic and modern "beforeWebAssemblyStart"');
3+
}
4+
5+
export function afterWebAssemblyStarted() {
6+
appendElement('server--classic-and-modern-after-web-assembly-started', 'Server project Classic and modern "afterWebAssemblyStarted"');
7+
}
8+
9+
// Duplicated in BasicTestApp\wwwroot\JSInitializers\ClassicAndModern\BasicTestApp.lib.module.js
10+
function appendElement(id, text) {
11+
var content = document.getElementById('initializers-content');
12+
if (!content) {
13+
return;
14+
}
15+
var element = document.createElement('p');
16+
element.id = id;
17+
element.innerText = text;
18+
content.appendChild(element);
19+
}

0 commit comments

Comments
 (0)