From 04dbbc8e9f73aa59d1fb8cba09d6b1b749225bc5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 12:08:36 +0000 Subject: [PATCH 1/9] Initial plan From ab6ec409e9540806910f8e72c268d9dd7deffc06 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 12:25:12 +0000 Subject: [PATCH 2/9] Accept blazor.web.js startup options format in blazor.server.js and blazor.webassembly.js Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com> --- src/Components/Web.JS/src/Boot.Server.ts | 8 +- src/Components/Web.JS/src/Boot.WebAssembly.ts | 8 +- .../wwwroot/nestedWebAssemblyOptions.html | 81 +++++++++++++++++++ .../Pages/NestedCircuitOptions.cshtml | 75 +++++++++++++++++ 4 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html create mode 100644 src/Components/test/testassets/Components.TestServer/Pages/NestedCircuitOptions.cshtml diff --git a/src/Components/Web.JS/src/Boot.Server.ts b/src/Components/Web.JS/src/Boot.Server.ts index 824c12546963..307e8e9eed4c 100644 --- a/src/Components/Web.JS/src/Boot.Server.ts +++ b/src/Components/Web.JS/src/Boot.Server.ts @@ -10,15 +10,19 @@ import { DotNet } from '@microsoft/dotnet-js-interop'; import { InitialRootComponentsList } from './Services/InitialRootComponentsList'; import { JSEventRegistry } from './Services/JSEventRegistry'; +type BlazorServerStartOptions = Partial & { circuit?: Partial }; + let started = false; -function boot(userOptions?: Partial): Promise { +function boot(userOptions?: BlazorServerStartOptions): Promise { if (started) { throw new Error('Blazor has already started.'); } started = true; - const configuredOptions = resolveOptions(userOptions); + // Accept the `circuit` property from the blazor.web.js options format + const normalizedOptions = userOptions?.circuit ?? userOptions; + const configuredOptions = resolveOptions(normalizedOptions); setCircuitOptions(Promise.resolve(configuredOptions || {})); JSEventRegistry.create(Blazor); diff --git a/src/Components/Web.JS/src/Boot.WebAssembly.ts b/src/Components/Web.JS/src/Boot.WebAssembly.ts index a1b106b924c2..df014548cf08 100644 --- a/src/Components/Web.JS/src/Boot.WebAssembly.ts +++ b/src/Components/Web.JS/src/Boot.WebAssembly.ts @@ -12,15 +12,19 @@ import { InitialRootComponentsList } from './Services/InitialRootComponentsList' import { JSEventRegistry } from './Services/JSEventRegistry'; import { printErr } from './Platform/Mono/MonoPlatform'; +type BlazorWebAssemblyStartOptions = Partial & { webAssembly?: Partial }; + let started = false; -async function boot(options?: Partial): Promise { +async function boot(options?: BlazorWebAssemblyStartOptions): Promise { if (started) { throw new Error('Blazor has already started.'); } started = true; - setWebAssemblyOptions(Promise.resolve(options || {})); + // Accept the `webAssembly` property from the blazor.web.js options format + const normalizedOptions = options?.webAssembly ?? options ?? {}; + setWebAssemblyOptions(Promise.resolve(normalizedOptions)); JSEventRegistry.create(Blazor); const webAssemblyComponents = discoverComponents(document, 'webassembly') as WebAssemblyComponentDescriptor[]; diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html b/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html new file mode 100644 index 000000000000..fc237dded3ce --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html @@ -0,0 +1,81 @@ + + + + + + Basic test app - Nested WebAssembly Options + + + + + + + + + + + + + Loading... + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Components/test/testassets/Components.TestServer/Pages/NestedCircuitOptions.cshtml b/src/Components/test/testassets/Components.TestServer/Pages/NestedCircuitOptions.cshtml new file mode 100644 index 000000000000..a676ec7d15b6 --- /dev/null +++ b/src/Components/test/testassets/Components.TestServer/Pages/NestedCircuitOptions.cshtml @@ -0,0 +1,75 @@ +@page "/nestedCircuitOptions" +@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers" + + + + + Basic test app - Nested Circuit Options + + + + + + + + + + + + + + + + + + + + +
+ An unhandled error has occurred. + Reload + 🗙 +
+ + + + + + + + + + + + + + From ef361b3c9d68e496f9b3cb58ea9e9afb1fe1d40f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 12:40:04 +0000 Subject: [PATCH 3/9] Add E2E tests for nested blazor options format Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com> --- .../ServerNestedOptionsTest.cs | 47 +++++++++++++++++++ .../Tests/WebAssemblyNestedOptionsTest.cs | 44 +++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/Components/test/E2ETest/ServerExecutionTests/ServerNestedOptionsTest.cs create mode 100644 src/Components/test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs diff --git a/src/Components/test/E2ETest/ServerExecutionTests/ServerNestedOptionsTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/ServerNestedOptionsTest.cs new file mode 100644 index 000000000000..7bfa91f11831 --- /dev/null +++ b/src/Components/test/E2ETest/ServerExecutionTests/ServerNestedOptionsTest.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using BasicTestApp; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.E2ETesting; +using OpenQA.Selenium; +using TestServer; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests; + +/// +/// Tests that the blazor.web.js options format (with nested circuit: property) +/// is accepted by blazor.server.js. +/// +public class ServerNestedOptionsTest : ServerTestBase> +{ + public ServerNestedOptionsTest( + BrowserFixture browserFixture, + BasicTestAppServerSiteFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + } + + protected override void InitializeAsyncCore() + { + // Navigate to the page that uses the nested circuit options format + Navigate($"{ServerPathBase}/nestedCircuitOptions"); + } + + [Fact] + public void NestedCircuitOptionsAreAccepted() + { + // Verify the page loads and the counter component works, + // which confirms the circuit options were processed correctly + var appElement = Browser.MountTestComponent(); + var countDisplayElement = appElement.FindElement(By.TagName("p")); + Browser.Equal("Current count: 0", () => countDisplayElement.Text); + + // Clicking button increments count + appElement.FindElement(By.TagName("button")).Click(); + Browser.Equal("Current count: 1", () => countDisplayElement.Text); + } +} diff --git a/src/Components/test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs b/src/Components/test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs new file mode 100644 index 000000000000..5d036b17033c --- /dev/null +++ b/src/Components/test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using BasicTestApp; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.E2ETesting; +using OpenQA.Selenium; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETest.Tests; + +/// +/// Tests that the blazor.web.js options format (with nested webAssembly: property) +/// is accepted by blazor.webassembly.js. +/// +public class WebAssemblyNestedOptionsTest : ServerTestBase> +{ + public WebAssemblyNestedOptionsTest( + BrowserFixture browserFixture, + BlazorWasmTestAppFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + _serverFixture.PathBase = "/subdir"; + } + + protected override void InitializeAsyncCore() + { + base.InitializeAsyncCore(); + + // Navigate to the page that uses the nested webAssembly options format + Navigate($"{ServerPathBase}/nestedWebAssemblyOptions.html"); + Browser.MountTestComponent(); + } + + [Fact] + public void NestedWebAssemblyOptionsAreAccepted() + { + // Verify that the configureRuntime option inside the nested webAssembly property works + var element = Browser.Exists(By.Id("environment")); + Browser.Equal("true", () => element.Text); + } +} From 7a7d67712e4e6851268ea31b85a8c9e99aa181c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:31:17 +0000 Subject: [PATCH 4/9] Remove XML doc comments from test files per review feedback Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com> --- .../ServerExecutionTests/ServerNestedOptionsTest.cs | 8 -------- .../test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs | 6 ------ 2 files changed, 14 deletions(-) diff --git a/src/Components/test/E2ETest/ServerExecutionTests/ServerNestedOptionsTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/ServerNestedOptionsTest.cs index 7bfa91f11831..05d9416fdac1 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/ServerNestedOptionsTest.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/ServerNestedOptionsTest.cs @@ -11,10 +11,6 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests; -/// -/// Tests that the blazor.web.js options format (with nested circuit: property) -/// is accepted by blazor.server.js. -/// public class ServerNestedOptionsTest : ServerTestBase> { public ServerNestedOptionsTest( @@ -27,20 +23,16 @@ public ServerNestedOptionsTest( protected override void InitializeAsyncCore() { - // Navigate to the page that uses the nested circuit options format Navigate($"{ServerPathBase}/nestedCircuitOptions"); } [Fact] public void NestedCircuitOptionsAreAccepted() { - // Verify the page loads and the counter component works, - // which confirms the circuit options were processed correctly var appElement = Browser.MountTestComponent(); var countDisplayElement = appElement.FindElement(By.TagName("p")); Browser.Equal("Current count: 0", () => countDisplayElement.Text); - // Clicking button increments count appElement.FindElement(By.TagName("button")).Click(); Browser.Equal("Current count: 1", () => countDisplayElement.Text); } diff --git a/src/Components/test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs b/src/Components/test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs index 5d036b17033c..e6a2a8e63138 100644 --- a/src/Components/test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs +++ b/src/Components/test/E2ETest/Tests/WebAssemblyNestedOptionsTest.cs @@ -10,10 +10,6 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests; -/// -/// Tests that the blazor.web.js options format (with nested webAssembly: property) -/// is accepted by blazor.webassembly.js. -/// public class WebAssemblyNestedOptionsTest : ServerTestBase> { public WebAssemblyNestedOptionsTest( @@ -29,7 +25,6 @@ protected override void InitializeAsyncCore() { base.InitializeAsyncCore(); - // Navigate to the page that uses the nested webAssembly options format Navigate($"{ServerPathBase}/nestedWebAssemblyOptions.html"); Browser.MountTestComponent(); } @@ -37,7 +32,6 @@ protected override void InitializeAsyncCore() [Fact] public void NestedWebAssemblyOptionsAreAccepted() { - // Verify that the configureRuntime option inside the nested webAssembly property works var element = Browser.Exists(By.Id("environment")); Browser.Equal("true", () => element.Text); } From f3abc774c156c825406d4be709a9aa2857fd906e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Dec 2025 16:12:25 +0000 Subject: [PATCH 5/9] Simplify nested options test files by removing unnecessary code Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com> --- .../wwwroot/nestedWebAssemblyOptions.html | 60 ++----------------- .../Pages/NestedCircuitOptions.cshtml | 42 ------------- 2 files changed, 6 insertions(+), 96 deletions(-) diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html b/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html index fc237dded3ce..8d70c753a473 100644 --- a/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html +++ b/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html @@ -7,75 +7,27 @@ - - - - - - Loading... - - - - - - - - - - - - - - - diff --git a/src/Components/test/testassets/Components.TestServer/Pages/NestedCircuitOptions.cshtml b/src/Components/test/testassets/Components.TestServer/Pages/NestedCircuitOptions.cshtml index a676ec7d15b6..e05c2d7f889d 100644 --- a/src/Components/test/testassets/Components.TestServer/Pages/NestedCircuitOptions.cshtml +++ b/src/Components/test/testassets/Components.TestServer/Pages/NestedCircuitOptions.cshtml @@ -8,68 +8,26 @@ - - - - - - - - - - - -
An unhandled error has occurred. Reload 🗙
- - - - - - - - - From ec0f8432f18f92cf19b7b51508041e12b89e33e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:46:58 +0000 Subject: [PATCH 6/9] Fix nestedWebAssemblyOptions.html by adding required getRuntimeBuildConfiguration function Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com> --- .../BasicTestApp/wwwroot/nestedWebAssemblyOptions.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html b/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html index 8d70c753a473..87dd73a0cc76 100644 --- a/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html +++ b/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html @@ -18,6 +18,11 @@ 🗙 + diff --git a/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html b/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html deleted file mode 100644 index 0df1e619eb9e..000000000000 --- a/src/Components/test/testassets/BasicTestApp/wwwroot/nestedWebAssemblyOptions.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - Basic test app - Nested WebAssembly Options - - - - - - - Loading... - - - - - - - - - From f78b0c4d77240b51d4dafd64ad0578e10dee752e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 09:14:01 +0000 Subject: [PATCH 9/9] Revert unintended changes to package-lock.json Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com> --- package-lock.json | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index bdf1785cf3e2..d0c4ea772897 100644 --- a/package-lock.json +++ b/package-lock.json @@ -90,6 +90,7 @@ "integrity": "sha1-TIGzXlHhtzT1EMmbB9+8e7u0j34=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2608,6 +2609,7 @@ "integrity": "sha1-3y3Zw0bH13aLigZjmZRkDGQuKEw=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -4249,6 +4251,7 @@ "integrity": "sha1-G2PQgthJovyuilaSSPvi7huKVsc=", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -4849,6 +4852,7 @@ "integrity": "sha1-o2CJi8QV7arEbIJB9jg5dbkwuBY=", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5366,6 +5370,7 @@ "integrity": "sha1-9DaZGSJbaExWCFmYrGPb0FvgINU=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -5831,6 +5836,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -7363,7 +7369,8 @@ "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/devtools-protocol/-/devtools-protocol-0.0.1521046.tgz", "integrity": "sha1-kY5hdeqDEA/vyyt4d58Vp3qopBs=", "dev": true, - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/di": { "version": "0.0.1", @@ -7568,6 +7575,7 @@ "integrity": "sha1-VldK/deR9UqOmyeFwFgqLSYhD6k=", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "iconv-lite": "^0.6.2" } @@ -7899,6 +7907,7 @@ "integrity": "sha1-ffEJZUq6fju+XI6uUzxeRh08bKk=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -8864,7 +8873,8 @@ "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fp-ts/-/fp-ts-2.16.11.tgz", "integrity": "sha1-gxoQUUv04irfEgZXMvxaIMhdliM=", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/fs-constants": { "version": "1.0.0", @@ -9852,6 +9862,7 @@ "integrity": "sha1-WrDTY2/oSUonXwJmRhqwGdpLjQs=", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "fp-ts": "^2.5.0" } @@ -10334,6 +10345,7 @@ "integrity": "sha1-mUZ2/CQXfwiPHF43N/VpcgT/JhM=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -11662,6 +11674,7 @@ "integrity": "sha1-36WkJs9ai1O0PNVO8NDQl0I1FJI=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@colors/colors": "1.5.0", "body-parser": "^1.19.0", @@ -15476,6 +15489,7 @@ "integrity": "sha1-28jNh0OzhxABn7gpfo16duP6pAY=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -15707,6 +15721,7 @@ "integrity": "sha1-N9mlx3ava8ktf0+VEOukwKYNEaY=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -17463,6 +17478,7 @@ "integrity": "sha1-W09Z4VMQqxeiFvXWz1PuR27eZw8=", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -17947,6 +17963,7 @@ "integrity": "sha1-F6fFpQINWjo3wRjQAureXuLG89o=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -17996,6 +18013,7 @@ "integrity": "sha1-N8HWnI2FIUxaZeWJN49TrsZNqzE=", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.2.0", @@ -18649,6 +18667,7 @@ "integrity": "sha1-r4/PZv7uLtyGvF0c9F4zsGML81s=", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0",