diff --git a/src/Components/Web.JS/src/Boot.Web.ts b/src/Components/Web.JS/src/Boot.Web.ts index 50e5bb94f793..df605ceebc52 100644 --- a/src/Components/Web.JS/src/Boot.Web.ts +++ b/src/Components/Web.JS/src/Boot.Web.ts @@ -26,6 +26,7 @@ import { LogLevel } from './Platform/Logging/Logger'; import { resolveOptions } from './Platform/Circuits/CircuitStartOptions'; import { JSInitializer } from './JSInitializers/JSInitializers'; import { enableFocusOnNavigate } from './Rendering/FocusOnNavigate'; +import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions'; let started = false; let rootComponentManager: WebRootComponentManager; @@ -91,10 +92,11 @@ function onInitialDomContentLoaded(options: Partial) { // so we do the same here. const initialCircuitOptions = resolveOptions(options?.circuit || {}); options.circuit = initialCircuitOptions; + options.webAssembly = options.webAssembly || ({} as WebAssemblyStartOptions); const logger = new ConsoleLogger(initialCircuitOptions.logLevel); const initializersPromise = fetchAndInvokeInitializers(options, logger); setCircuitOptions(resolveConfiguredOptions(initializersPromise, initialCircuitOptions)); - setWebAssemblyOptions(resolveConfiguredOptions(initializersPromise, options?.webAssembly || {})); + setWebAssemblyOptions(resolveConfiguredOptions(initializersPromise, options.webAssembly)); registerAllComponentDescriptors(document); rootComponentManager.onDocumentUpdated(); diff --git a/src/Components/test/E2ETest/ServerRenderingTests/BlazorWebJsInitializersTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/BlazorWebJsInitializersTest.cs index 513c477f795c..b6e0386d2739 100644 --- a/src/Components/test/E2ETest/ServerRenderingTests/BlazorWebJsInitializersTest.cs +++ b/src/Components/test/E2ETest/ServerRenderingTests/BlazorWebJsInitializersTest.cs @@ -33,6 +33,11 @@ public void InitializersRunsModernCallbacksByDefaultWhenPresent(bool streaming, var url = $"{ServerPathBase}/initializers?streaming={streaming}&wasm={webassembly}&server={server}"; Navigate(url); + if (webassembly) + { + ((IJavaScriptExecutor)Browser).ExecuteScript("sessionStorage.setItem('block-webassembly-settings', 'true')"); + } + foreach (var callback in expectedInvokedCallbacks) { Browser.Exists(By.Id(callback)); @@ -56,6 +61,11 @@ public void InitializersRunsClassicInitializersWhenEnabled(bool streaming, bool var url = $"{ServerPathBase}/initializers?streaming={streaming}&wasm={webassembly}&server={server}"; Navigate(url); + if (webassembly) + { + ((IJavaScriptExecutor)Browser).ExecuteScript("sessionStorage.setItem('block-webassembly-settings', 'true')"); + } + foreach (var callback in expectedCallbacks) { Browser.Exists(By.Id(callback)); @@ -82,12 +92,12 @@ public static TheoryData InitializerTestData() { { false, false, false, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started","modern-before-web-start", "modern-after-web-started"] }, { 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" ] }, - { 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"] }, - { 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"] }, + { 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"] }, + { 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"] }, { true, false, false, ["classic-and-modern-before-web-start", "classic-and-modern-after-web-started","modern-before-web-start", "modern-after-web-started"] }, { 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" ] }, - { 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"] }, - { 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"] }, + { 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"] }, + { 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"] }, }; return result; diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/JSInitializers/ClassicAndModern/BasicTestApp.lib.module.js b/src/Components/test/testassets/BasicTestApp/wwwroot/JSInitializers/ClassicAndModern/BasicTestApp.lib.module.js index 26c0b20b0185..7fc1b019bb84 100644 --- a/src/Components/test/testassets/BasicTestApp/wwwroot/JSInitializers/ClassicAndModern/BasicTestApp.lib.module.js +++ b/src/Components/test/testassets/BasicTestApp/wwwroot/JSInitializers/ClassicAndModern/BasicTestApp.lib.module.js @@ -36,6 +36,7 @@ export function afterServerStarted() { appendElement('classic-and-modern-after-server-started', 'Classic and modern "afterServerStarted"'); } +// Duplicated in Components.TestServer\wwwroot\Components.TestServer.lib.module.js function appendElement(id, text) { var content = document.getElementById('initializers-content'); if (!content) { diff --git a/src/Components/test/testassets/Components.TestServer/.gitignore b/src/Components/test/testassets/Components.TestServer/.gitignore deleted file mode 100644 index 5aa0a61168bd..000000000000 --- a/src/Components/test/testassets/Components.TestServer/.gitignore +++ /dev/null @@ -1 +0,0 @@ -wwwroot/**/* \ No newline at end of file diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor index e5e8afa59998..8c4a8f258b51 100644 --- a/src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor +++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/App.razor @@ -43,9 +43,11 @@ const enableClassicInitializers = sessionStorage.getItem('enable-classic-initializers') === 'true'; const suppressEnhancedNavigation = sessionStorage.getItem('suppress-enhanced-navigation') === 'true'; const blockLoadBootResource = sessionStorage.getItem('block-load-boot-resource') === 'true'; + const blockWebassemblySettings = sessionStorage.getItem('block-webassembly-settings') === 'true'; sessionStorage.removeItem('suppress-enhanced-navigation'); sessionStorage.removeItem('block-load-boot-resource'); sessionStorage.removeItem('enable-classic-initializers'); + sessionStorage.removeItem('block-webassembly-settings'); let loadBootResourceUnblocked = null; if (blockLoadBootResource) { @@ -66,6 +68,35 @@ let maxParallelResourceDownloadCount = 0; let currentParallelResourceDownloadCount = 0; + let webAssemblySettings = { + loadBootResource: function (type, name, defaultUri, integrity) { + switch (type) { + case 'manifest': + case 'dotnetjs': + case 'dotnetwasm': + // note this is resolved to absolute URL using document.baseURI + return `WasmMinimal/_framework/${name}`; + default: + // The following allows us to arbitrarily delay the loading of WebAssembly resources. + // This is useful for guaranteeing that auto mode components will fall back on + // using Blazor server. + currentParallelResourceDownloadCount++; + return fetch(`${document.baseURI}WasmMinimal/_framework/${name}?`, { + method: "GET", + }).then(async (response) => { + if (currentParallelResourceDownloadCount > maxParallelResourceDownloadCount) { + maxParallelResourceDownloadCount = currentParallelResourceDownloadCount; + window['__aspnetcore__testing__max__parallel__resource__download__count'] = maxParallelResourceDownloadCount; + } + currentParallelResourceDownloadCount--; + await loadBootResourceUnblocked; + return response; + }); + } + }, + }; + if (blockWebassemblySettings) + webAssemblySettings = null; Blazor.start({ ssr: { @@ -75,33 +106,7 @@ circuitInactivityTimeoutMs: 100, }, enableClassicInitializers: enableClassicInitializers, - webAssembly: { - loadBootResource: function (type, name, defaultUri, integrity) { - switch (type) { - case 'manifest': - case 'dotnetjs': - case 'dotnetwasm': - // note this is resolved to absolute URL using document.baseURI - return `WasmMinimal/_framework/${name}`; - default: - // The following allows us to arbitrarily delay the loading of WebAssembly resources. - // This is useful for guaranteeing that auto mode components will fall back on - // using Blazor server. - currentParallelResourceDownloadCount++; - return fetch(`${document.baseURI}WasmMinimal/_framework/${name}?`, { - method: "GET", - }).then(async (response) => { - if (currentParallelResourceDownloadCount > maxParallelResourceDownloadCount) { - maxParallelResourceDownloadCount = currentParallelResourceDownloadCount; - window['__aspnetcore__testing__max__parallel__resource__download__count'] = maxParallelResourceDownloadCount; - } - currentParallelResourceDownloadCount--; - await loadBootResourceUnblocked; - return response; - }); - } - }, - }, + webAssembly: webAssemblySettings, circuit: { reconnectionOptions: { // It's easier to test the reconnection logic if we wait a bit diff --git a/src/Components/test/testassets/Components.TestServer/wwwroot/Components.TestServer.lib.module.js b/src/Components/test/testassets/Components.TestServer/wwwroot/Components.TestServer.lib.module.js new file mode 100644 index 000000000000..4570b2c5d029 --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/wwwroot/Components.TestServer.lib.module.js @@ -0,0 +1,19 @@ +export function beforeWebAssemblyStart() { + appendElement('server--classic-and-modern-before-web-assembly-start', 'Server project Classic and modern "beforeWebAssemblyStart"'); +} + +export function afterWebAssemblyStarted() { + appendElement('server--classic-and-modern-after-web-assembly-started', 'Server project Classic and modern "afterWebAssemblyStarted"'); +} + +// Duplicated in BasicTestApp\wwwroot\JSInitializers\ClassicAndModern\BasicTestApp.lib.module.js +function appendElement(id, text) { + var content = document.getElementById('initializers-content'); + if (!content) { + return; + } + var element = document.createElement('p'); + element.id = id; + element.innerText = text; + content.appendChild(element); +}