diff --git a/src/Components/Components/src/ComponentBase.cs b/src/Components/Components/src/ComponentBase.cs index 51483977d68d..196fb84f064c 100644 --- a/src/Components/Components/src/ComponentBase.cs +++ b/src/Components/Components/src/ComponentBase.cs @@ -102,7 +102,7 @@ protected void StateHasChanged() return; } - if (_hasNeverRendered || ShouldRender() || _renderHandle.IsHotReloading) + if (_hasNeverRendered || ShouldRender() || _renderHandle.IsRenderingOnMetadataUpdate) { _hasPendingQueuedRender = true; diff --git a/src/Components/Components/src/HotReload/HotReloadManager.cs b/src/Components/Components/src/HotReload/HotReloadManager.cs index 7c5c193f0140..ca785633527e 100644 --- a/src/Components/Components/src/HotReload/HotReloadManager.cs +++ b/src/Components/Components/src/HotReload/HotReloadManager.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Components.HotReload { internal static class HotReloadManager { - internal static event Action? OnDeltaApplied; + internal static event Action? OnDeltaApplied; public static void DeltaApplied() { diff --git a/src/Components/Components/src/HotReload/TestableMetadataUpdate.cs b/src/Components/Components/src/HotReload/TestableMetadataUpdate.cs new file mode 100644 index 000000000000..b58fb566112f --- /dev/null +++ b/src/Components/Components/src/HotReload/TestableMetadataUpdate.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection.Metadata; + +namespace Microsoft.AspNetCore.Components.HotReload +{ + internal sealed class TestableMetadataUpdate + { + public static bool TestIsSupported { private get; set; } + + /// + /// A proxy for that is testable. + /// + public static bool IsSupported => MetadataUpdater.IsSupported || TestIsSupported; + } +} diff --git a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj index 7518710f7f6b..f68c4e4bfcf1 100644 --- a/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj +++ b/src/Components/Components/src/Microsoft.AspNetCore.Components.csproj @@ -13,7 +13,6 @@ - diff --git a/src/Components/Components/src/Properties/AssemblyInfo.cs b/src/Components/Components/src/Properties/AssemblyInfo.cs index 66e087922b0d..d8172297fb5b 100644 --- a/src/Components/Components/src/Properties/AssemblyInfo.cs +++ b/src/Components/Components/src/Properties/AssemblyInfo.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Blazor.Build.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Components/Components/src/Properties/ILLink.Substitutions.xml b/src/Components/Components/src/Properties/ILLink.Substitutions.xml index 3c0e49fe451c..9f780bc2f8b2 100644 --- a/src/Components/Components/src/Properties/ILLink.Substitutions.xml +++ b/src/Components/Components/src/Properties/ILLink.Substitutions.xml @@ -1,6 +1,6 @@ - + diff --git a/src/Components/Components/src/PublicAPI.Unshipped.txt b/src/Components/Components/src/PublicAPI.Unshipped.txt index bb22b4def547..cfb5294d5d43 100644 --- a/src/Components/Components/src/PublicAPI.Unshipped.txt +++ b/src/Components/Components/src/PublicAPI.Unshipped.txt @@ -40,7 +40,7 @@ Microsoft.AspNetCore.Components.NavigationOptions.ForceLoad.init -> void Microsoft.AspNetCore.Components.NavigationOptions.NavigationOptions() -> void Microsoft.AspNetCore.Components.NavigationOptions.ReplaceHistoryEntry.get -> bool Microsoft.AspNetCore.Components.NavigationOptions.ReplaceHistoryEntry.init -> void -Microsoft.AspNetCore.Components.RenderHandle.IsHotReloading.get -> bool +Microsoft.AspNetCore.Components.RenderHandle.IsRenderingOnMetadataUpdate.get -> bool Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder.Dispose() -> void Microsoft.AspNetCore.Components.Routing.Router.PreferExactMatches.get -> bool Microsoft.AspNetCore.Components.Routing.Router.PreferExactMatches.set -> void diff --git a/src/Components/Components/src/RenderHandle.cs b/src/Components/Components/src/RenderHandle.cs index d7789e18cec8..e94b8a151e22 100644 --- a/src/Components/Components/src/RenderHandle.cs +++ b/src/Components/Components/src/RenderHandle.cs @@ -45,9 +45,9 @@ public Dispatcher Dispatcher public bool IsInitialized => _renderer is not null; /// - /// Gets a value that determines if the is triggering a render in response to a hot-reload change. + /// Gets a value that determines if the is triggering a render in response to a metadata update (hot-reload) change. /// - public bool IsHotReloading => HotReloadFeature.IsSupported && (_renderer?.IsHotReloading ?? false); + public bool IsRenderingOnMetadataUpdate => TestableMetadataUpdate.IsSupported && (_renderer?.IsRenderingOnMetadataUpdate ?? false); /// /// Notifies the renderer that the component should be rendered. diff --git a/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs b/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs index 6ba718884410..efaa52f4b43a 100644 --- a/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs +++ b/src/Components/Components/src/RenderTree/RenderTreeDiffBuilder.cs @@ -542,7 +542,7 @@ private static void UpdateRetainedChildComponent( var oldParameters = new ParameterView(ParameterViewLifetime.Unbound, oldTree, oldComponentIndex); var newParametersLifetime = new ParameterViewLifetime(diffContext.BatchBuilder); var newParameters = new ParameterView(newParametersLifetime, newTree, newComponentIndex); - if (!newParameters.DefinitelyEquals(oldParameters) || (HotReloadFeature.IsSupported && diffContext.Renderer.IsHotReloading)) + if (!newParameters.DefinitelyEquals(oldParameters) || (TestableMetadataUpdate.IsSupported && diffContext.Renderer.IsRenderingOnMetadataUpdate)) { componentState.SetDirectParameters(newParameters); } diff --git a/src/Components/Components/src/RenderTree/Renderer.cs b/src/Components/Components/src/RenderTree/Renderer.cs index 9217df4d41dd..50f98618f33f 100644 --- a/src/Components/Components/src/RenderTree/Renderer.cs +++ b/src/Components/Components/src/RenderTree/Renderer.cs @@ -97,7 +97,7 @@ public Renderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, _logger = loggerFactory.CreateLogger(); _componentFactory = new ComponentFactory(componentActivator); - if (HotReloadFeature.IsSupported) + if (TestableMetadataUpdate.IsSupported) { HotReloadManager.OnDeltaApplied += RenderRootComponentsOnHotReload; } @@ -121,9 +121,9 @@ private static IComponentActivator GetComponentActivatorOrDefault(IServiceProvid protected internal ElementReferenceContext? ElementReferenceContext { get; protected set; } /// - /// Gets a value that determines if the is triggering a render in response to a hot-reload change. + /// Gets a value that determines if the is triggering a render in response to a (metadata update) hot-reload change. /// - internal bool IsHotReloading { get; private set; } + internal bool IsRenderingOnMetadataUpdate { get; private set; } private async void RenderRootComponentsOnHotReload() { @@ -139,7 +139,7 @@ await Dispatcher.InvokeAsync(() => return; } - IsHotReloading = true; + IsRenderingOnMetadataUpdate = true; try { foreach (var (componentState, initialParameters) in _rootComponents) @@ -149,7 +149,7 @@ await Dispatcher.InvokeAsync(() => } finally { - IsHotReloading = false; + IsRenderingOnMetadataUpdate = false; } }); } @@ -227,7 +227,7 @@ protected async Task RenderRootComponentAsync(int componentId, ParameterView ini // During the asynchronous rendering process we want to wait up until all components have // finished rendering so that we can produce the complete output. var componentState = GetRequiredComponentState(componentId); - if (HotReloadFeature.IsSupported) + if (TestableMetadataUpdate.IsSupported) { // when we're doing hot-reload, stash away the parameters used while rendering root components. // We'll use this to trigger re-renders on hot reload updates. @@ -998,7 +998,7 @@ public void Dispose() /// public async ValueTask DisposeAsync() { - if (HotReloadFeature.IsSupported) + if (TestableMetadataUpdate.IsSupported) { HotReloadManager.OnDeltaApplied -= RenderRootComponentsOnHotReload; } diff --git a/src/Components/Components/src/Routing/Router.cs b/src/Components/Components/src/Routing/Router.cs index 3a05e7589bea..832f697a363b 100644 --- a/src/Components/Components/src/Routing/Router.cs +++ b/src/Components/Components/src/Routing/Router.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Reflection.Metadata; using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; @@ -99,7 +100,7 @@ public void Attach(RenderHandle renderHandle) _locationAbsolute = NavigationManager.Uri; NavigationManager.LocationChanged += OnLocationChanged; - if (HotReloadFeature.IsSupported) + if (TestableMetadataUpdate.IsSupported) { HotReloadManager.OnDeltaApplied += ClearRouteCaches; } @@ -143,7 +144,7 @@ public async Task SetParametersAsync(ParameterView parameters) public void Dispose() { NavigationManager.LocationChanged -= OnLocationChanged; - if (HotReloadFeature.IsSupported) + if (TestableMetadataUpdate.IsSupported) { HotReloadManager.OnDeltaApplied -= ClearRouteCaches; } diff --git a/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs b/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs index ff0632370c92..29ca2c94ab78 100644 --- a/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs +++ b/src/Components/Forms/src/EditContextDataAnnotationsExtensions.cs @@ -63,7 +63,7 @@ public DataAnnotationsEventSubscriptions(EditContext editContext) _editContext.OnFieldChanged += OnFieldChanged; _editContext.OnValidationRequested += OnValidationRequested; - if (HotReloadFeature.IsSupported) + if (MetadataUpdater.IsSupported) { OnClearCache += ClearCache; } @@ -132,7 +132,7 @@ public void Dispose() _editContext.OnValidationRequested -= OnValidationRequested; _editContext.NotifyValidationStateChanged(); - if (HotReloadFeature.IsSupported) + if (MetadataUpdater.IsSupported) { OnClearCache -= ClearCache; } diff --git a/src/Components/Forms/src/Microsoft.AspNetCore.Components.Forms.csproj b/src/Components/Forms/src/Microsoft.AspNetCore.Components.Forms.csproj index 12b071a02268..7ac8a9203e0f 100644 --- a/src/Components/Forms/src/Microsoft.AspNetCore.Components.Forms.csproj +++ b/src/Components/Forms/src/Microsoft.AspNetCore.Components.Forms.csproj @@ -9,19 +9,8 @@ true - - - - - - - - - - ILLink.Substitutions.xml - diff --git a/src/Components/Forms/src/Properties/ILLink.Substitutions.xml b/src/Components/Forms/src/Properties/ILLink.Substitutions.xml deleted file mode 100644 index 6e9602f33f95..000000000000 --- a/src/Components/Forms/src/Properties/ILLink.Substitutions.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Components/Shared/src/HotReloadFeature.cs b/src/Components/Shared/src/HotReloadFeature.cs deleted file mode 100644 index 84788dd72885..000000000000 --- a/src/Components/Shared/src/HotReloadFeature.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.AspNetCore.Components.HotReload -{ - internal static class HotReloadFeature - { - /// - /// Gets a value that determines if hot reload is supported. Currently, the Debugger.IsSupported feature switch is used as a proxy for this. - /// Changing to a dedicated feature switch is tracked by https://github.com/dotnet/runtime/issues/51159. - /// - public static bool IsSupported { get; } = AppContext.TryGetSwitch("System.Diagnostics.Debugger.IsSupported", out var isSupported) ? isSupported : true; - } -} diff --git a/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHost.cs b/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHost.cs index f6bcd91b57e5..61848b6be0e8 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHost.cs +++ b/src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHost.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Reflection.Metadata; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.HotReload; @@ -138,7 +139,7 @@ internal async Task RunAsyncCore(CancellationToken cancellationToken, WebAssembl await manager.RestoreStateAsync(store); - if (HotReloadFeature.IsSupported) + if (MetadataUpdater.IsSupported) { await WebAssemblyHotReload.InitializeAsync(); } diff --git a/src/Components/WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs b/src/Components/WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs index 43d278891133..53b704417c0c 100644 --- a/src/Components/WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs +++ b/src/Components/WebAssembly/WebAssembly/src/HotReload/HotReloadAgent.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Reflection.Metadata; namespace Microsoft.Extensions.HotReload { @@ -196,7 +197,7 @@ public void ApplyDeltas(IReadOnlyList deltas) { if (TryGetModuleId(assembly) is Guid moduleId && moduleId == item.ModuleId) { - System.Reflection.Metadata.AssemblyExtensions.ApplyUpdate(assembly, item.MetadataDelta, item.ILDelta, ReadOnlySpan.Empty); + MetadataUpdater.ApplyUpdate(assembly, item.MetadataDelta, item.ILDelta, ReadOnlySpan.Empty); } } @@ -227,7 +228,7 @@ public void ApplyDeltas(Assembly assembly, IReadOnlyList deltas) foreach (var item in deltas) { - System.Reflection.Metadata.AssemblyExtensions.ApplyUpdate(assembly, item.MetadataDelta, item.ILDelta, ReadOnlySpan.Empty); + MetadataUpdater.ApplyUpdate(assembly, item.MetadataDelta, item.ILDelta, ReadOnlySpan.Empty); } _log("Deltas applied."); diff --git a/src/Components/WebAssembly/WebAssembly/src/HotReload/WebAssemblyHotReload.cs b/src/Components/WebAssembly/WebAssembly/src/HotReload/WebAssemblyHotReload.cs index 6fe29c04872a..2c2c0f527428 100644 --- a/src/Components/WebAssembly/WebAssembly/src/HotReload/WebAssemblyHotReload.cs +++ b/src/Components/WebAssembly/WebAssembly/src/HotReload/WebAssemblyHotReload.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.HotReload public static class WebAssemblyHotReload { private static HotReloadAgent? _hotReloadAgent; - private static UpdateDelta[] _updateDeltas = new[] + private static readonly UpdateDelta[] _updateDeltas = new[] { new UpdateDelta(), }; diff --git a/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj b/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj index ee34785ad87a..d959be3194a2 100644 --- a/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj +++ b/src/Components/WebAssembly/WebAssembly/src/Microsoft.AspNetCore.Components.WebAssembly.csproj @@ -33,7 +33,6 @@ - @@ -53,10 +52,6 @@ - - - - diff --git a/src/Components/WebAssembly/WebAssembly/src/Properties/ILLink.Substitutions.xml b/src/Components/WebAssembly/WebAssembly/src/Properties/ILLink.Substitutions.xml deleted file mode 100644 index 2b8260e080d5..000000000000 --- a/src/Components/WebAssembly/WebAssembly/src/Properties/ILLink.Substitutions.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Components/test/E2ETest/ServerExecutionTests/HotReloadTest.cs b/src/Components/test/E2ETest/ServerExecutionTests/HotReloadTest.cs index e813e232b83b..60eacf8b9894 100644 --- a/src/Components/test/E2ETest/ServerExecutionTests/HotReloadTest.cs +++ b/src/Components/test/E2ETest/ServerExecutionTests/HotReloadTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Net.Http; using System.Threading.Tasks; using BasicTestApp.HotReload; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; @@ -11,7 +12,6 @@ using TestServer; using Xunit; using Xunit.Abstractions; -using System.Net.Http; namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests { diff --git a/src/Components/test/testassets/TestServer/Controllers/UserController.cs b/src/Components/test/testassets/TestServer/Controllers/UserController.cs index d6e289c7279a..123588377734 100644 --- a/src/Components/test/testassets/TestServer/Controllers/UserController.cs +++ b/src/Components/test/testassets/TestServer/Controllers/UserController.cs @@ -1,3 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using System.Linq; using System.Security.Claims; diff --git a/src/Components/test/testassets/TestServer/HotReloadStartup.cs b/src/Components/test/testassets/TestServer/HotReloadStartup.cs index aeb99355c4f1..ef34ff90e959 100644 --- a/src/Components/test/testassets/TestServer/HotReloadStartup.cs +++ b/src/Components/test/testassets/TestServer/HotReloadStartup.cs @@ -3,6 +3,7 @@ using System.Globalization; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Components.HotReload; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -11,6 +12,11 @@ namespace TestServer { public class HotReloadStartup { + public HotReloadStartup() + { + TestableMetadataUpdate.TestIsSupported = true; + } + public void ConfigureServices(IServiceCollection services) { services.AddControllers(); diff --git a/src/Mvc/Mvc.Core/src/DependencyInjection/MvcCoreServiceCollectionExtensions.cs b/src/Mvc/Mvc.Core/src/DependencyInjection/MvcCoreServiceCollectionExtensions.cs index 1df7e1a93d7d..aaff9415150f 100644 --- a/src/Mvc/Mvc.Core/src/DependencyInjection/MvcCoreServiceCollectionExtensions.cs +++ b/src/Mvc/Mvc.Core/src/DependencyInjection/MvcCoreServiceCollectionExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Buffers; using System.Linq; +using System.Reflection.Metadata; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; @@ -61,7 +62,7 @@ public static IMvcCoreBuilder AddMvcCore(this IServiceCollection services) ConfigureDefaultServices(services); AddMvcCoreServices(services); - if (environment?.IsDevelopment() ?? false) + if (MetadataUpdater.IsSupported) { services.TryAddEnumerable( ServiceDescriptor.Singleton());