Skip to content

Commit d08cf33

Browse files
authored
Merge branch 'main' into darc-main-835cd6c5-a3a2-4816-bd44-a1a27df4212f
2 parents 1e8de90 + b64c645 commit d08cf33

File tree

37 files changed

+11294
-911
lines changed

37 files changed

+11294
-911
lines changed

documentation/general/dotnet-run-file.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ Similarly, implicit build files like `Directory.Build.props` or `Directory.Packa
125125
> [!CAUTION]
126126
> Multi-file support is postponed for .NET 11.
127127
> In .NET 10, only the single file passed as the command-line argument to `dotnet run` is part of the compilation.
128-
> Specifically, the virtual project has properties `EnableDefaultCompileItems=false` and `EnableDefaultEmbeddedResourceItems=false`
129-
> (which can be customized via `#:property` directives), and a `Compile` item for the entry point file.
128+
> Specifically, the virtual project has property `EnableDefaultCompileItems=false`
129+
> (which can be customized via `#:property` directive), and a `Compile` item for the entry point file.
130130
> During [conversion](#grow-up), any `Content`, `None`, `Compile`, and `EmbeddedResource` items that do not have metadata `ExcludeFromFileBasedAppConversion=true`
131131
> and that are files inside the entry point file's directory tree are copied to the converted directory.
132132

eng/Version.Details.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,13 +561,13 @@
561561
<Uri>https://github.com/dotnet/arcade-services</Uri>
562562
<Sha>448a29d2d2e4e27303f728202602708ed45838f5</Sha>
563563
</Dependency>
564-
<Dependency Name="Microsoft.Testing.Platform" Version="1.8.0-preview.25364.2">
564+
<Dependency Name="Microsoft.Testing.Platform" Version="1.8.0-preview.25367.8">
565565
<Uri>https://github.com/microsoft/testfx</Uri>
566-
<Sha>ad90815c3000f49b310707d78c054400f5b8b214</Sha>
566+
<Sha>62a0339db2a558ec8bb67f9f17fe6491ccd56c5b</Sha>
567567
</Dependency>
568-
<Dependency Name="MSTest" Version="3.10.0-preview.25364.2">
568+
<Dependency Name="MSTest" Version="3.10.0-preview.25367.8">
569569
<Uri>https://github.com/microsoft/testfx</Uri>
570-
<Sha>ad90815c3000f49b310707d78c054400f5b8b214</Sha>
570+
<Sha>62a0339db2a558ec8bb67f9f17fe6491ccd56c5b</Sha>
571571
</Dependency>
572572
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="10.0.0-preview.7.25359.101">
573573
<Uri>https://github.com/dotnet/dotnet</Uri>

eng/Versions.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<UsingToolVSSDK>true</UsingToolVSSDK>
3131
<FlagNetStandard1XDependencies Condition="'$(DotNetBuildSourceOnly)' == 'true'">true</FlagNetStandard1XDependencies>
3232
<!-- This property is only used in the dotnet test integration tests. -->
33-
<MicrosoftTestingPlatformVersion>1.8.0-preview.25364.2</MicrosoftTestingPlatformVersion>
33+
<MicrosoftTestingPlatformVersion>1.8.0-preview.25367.8</MicrosoftTestingPlatformVersion>
3434
</PropertyGroup>
3535
<PropertyGroup Label="Servicing version information">
3636
<VersionFeature21>30</VersionFeature21>
@@ -307,7 +307,7 @@
307307
<AwesomeAssertionsVersion>8.0.2</AwesomeAssertionsVersion>
308308
<AwesomeAssertionsJsonVersion>8.0.0</AwesomeAssertionsJsonVersion>
309309
<MoqPackageVersion>4.18.4</MoqPackageVersion>
310-
<MSTestVersion>3.10.0-preview.25364.2</MSTestVersion>
310+
<MSTestVersion>3.10.0-preview.25367.8</MSTestVersion>
311311
<XunitCombinatorialVersion>1.3.2</XunitCombinatorialVersion>
312312
<MicrosoftDotNetInstallerWindowsSecurityTestDataPackageVersion>8.0.0-beta.23607.1</MicrosoftDotNetInstallerWindowsSecurityTestDataPackageVersion>
313313
<BenchmarkDotNetPackageVersion>0.14.0</BenchmarkDotNetPackageVersion>

sdk.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
<Project Path="src/BuiltInTools/HotReloadAgent.PipeRpc/Microsoft.DotNet.HotReload.Agent.PipeRpc.shproj" />
5353
<Project Path="src/BuiltInTools/HotReloadAgent/Microsoft.DotNet.HotReload.Agent.Package.csproj" />
5454
<Project Path="src/BuiltInTools/HotReloadAgent/Microsoft.DotNet.HotReload.Agent.shproj" />
55+
<Project Path="src/BuiltInTools/HotReloadAgent.WebAssembly.Browser/Microsoft.DotNet.HotReload.WebAssembly.Browser.csproj" />
5556
</Folder>
5657
<Folder Name="/src/Cli/">
5758
<Project Path="src/Cli/dotnet/dotnet.csproj" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Razor">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(SdkTargetFramework)</TargetFramework>
5+
<GenerateDocumentationFile>false</GenerateDocumentationFile>
6+
<GenerateDependencyFile>false</GenerateDependencyFile>
7+
<LangVersion>preview</LangVersion>
8+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
9+
10+
<!-- NuGet -->
11+
<IsPackable>true</IsPackable>
12+
<IsShipping>true</IsShipping>
13+
<IsShippingPackage>true</IsShippingPackage>
14+
<PackageId>Microsoft.DotNet.HotReload.WebAssembly.Browser</PackageId>
15+
<Description>HotReload package for WebAssembly</Description>
16+
<!-- Remove once https://github.com/NuGet/Home/issues/8583 is fixed -->
17+
<NoWarn>$(NoWarn);NU5128</NoWarn>
18+
</PropertyGroup>
19+
20+
<Import Project="..\HotReloadAgent\Microsoft.DotNet.HotReload.Agent.projitems" Label="Shared" />
21+
<Import Project="..\HotReloadAgent.Data\Microsoft.DotNet.HotReload.Agent.Data.projitems" Label="Shared" />
22+
23+
<ItemGroup>
24+
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" Key="$(MoqPublicKey)" />
25+
</ItemGroup>
26+
</Project>
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.ComponentModel;
5+
using System.Diagnostics.CodeAnalysis;
6+
using System.Globalization;
7+
using System.Linq;
8+
using System.Net.Http;
9+
using System.Reflection.Metadata;
10+
using System.Runtime.InteropServices.JavaScript;
11+
using System.Runtime.Versioning;
12+
using System.Text.Json;
13+
using System.Text.Json.Serialization;
14+
15+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
16+
17+
namespace Microsoft.DotNet.HotReload.WebAssembly.Browser;
18+
19+
/// <summary>
20+
/// Contains methods called by interop. Intended for framework use only, not supported for use in application
21+
/// code.
22+
/// </summary>
23+
[EditorBrowsable(EditorBrowsableState.Never)]
24+
[UnconditionalSuppressMessage(
25+
"Trimming",
26+
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
27+
Justification = "Hot Reload does not support trimming")]
28+
internal static partial class WebAssemblyHotReload
29+
{
30+
/// <summary>
31+
/// For framework use only.
32+
/// </summary>
33+
public readonly struct LogEntry
34+
{
35+
public string Message { get; init; }
36+
public int Severity { get; init; }
37+
}
38+
39+
/// <summary>
40+
/// For framework use only.
41+
/// </summary>
42+
internal sealed class Update
43+
{
44+
public int Id { get; set; }
45+
public Delta[] Deltas { get; set; } = default!;
46+
}
47+
48+
/// <summary>
49+
/// For framework use only.
50+
/// </summary>
51+
public readonly struct Delta
52+
{
53+
public string ModuleId { get; init; }
54+
public byte[] MetadataDelta { get; init; }
55+
public byte[] ILDelta { get; init; }
56+
public byte[] PdbDelta { get; init; }
57+
public int[] UpdatedTypes { get; init; }
58+
}
59+
60+
private static readonly JsonSerializerOptions s_jsonSerializerOptions = new(JsonSerializerDefaults.Web);
61+
62+
private static bool s_initialized;
63+
private static HotReloadAgent? s_hotReloadAgent;
64+
65+
[JSExport]
66+
[SupportedOSPlatform("browser")]
67+
public static async Task InitializeAsync(string baseUri)
68+
{
69+
if (MetadataUpdater.IsSupported && Environment.GetEnvironmentVariable("__ASPNETCORE_BROWSER_TOOLS") == "true" &&
70+
OperatingSystem.IsBrowser())
71+
{
72+
s_initialized = true;
73+
74+
var agent = new HotReloadAgent();
75+
76+
var existingAgent = Interlocked.CompareExchange(ref s_hotReloadAgent, agent, null);
77+
if (existingAgent != null)
78+
{
79+
throw new InvalidOperationException("Hot Reload agent already initialized");
80+
}
81+
82+
await ApplyPreviousDeltasAsync(agent, baseUri);
83+
}
84+
}
85+
86+
private static async ValueTask ApplyPreviousDeltasAsync(HotReloadAgent agent, string baseUri)
87+
{
88+
string errorMessage;
89+
90+
using var client = new HttpClient()
91+
{
92+
BaseAddress = new Uri(baseUri, UriKind.Absolute)
93+
};
94+
95+
try
96+
{
97+
var response = await client.GetAsync("/_framework/blazor-hotreload");
98+
if (response.IsSuccessStatusCode)
99+
{
100+
var deltasJson = await response.Content.ReadAsStringAsync();
101+
var updates = deltasJson != "" ? JsonSerializer.Deserialize<Update[]>(deltasJson, s_jsonSerializerOptions) : null;
102+
if (updates == null)
103+
{
104+
agent.Reporter.Report($"No previous updates to apply.", AgentMessageSeverity.Verbose);
105+
return;
106+
}
107+
108+
var i = 1;
109+
foreach (var update in updates)
110+
{
111+
agent.Reporter.Report($"Reapplying update {i}/{updates.Length}.", AgentMessageSeverity.Verbose);
112+
113+
agent.ApplyDeltas(
114+
update.Deltas.Select(d => new UpdateDelta(Guid.Parse(d.ModuleId, CultureInfo.InvariantCulture), d.MetadataDelta, d.ILDelta, d.PdbDelta, d.UpdatedTypes)));
115+
116+
i++;
117+
}
118+
119+
return;
120+
}
121+
122+
errorMessage = $"HTTP GET '/_framework/blazor-hotreload' returned {response.StatusCode}";
123+
}
124+
catch (Exception e)
125+
{
126+
errorMessage = e.ToString();
127+
}
128+
129+
agent.Reporter.Report($"Failed to retrieve and apply previous deltas from the server: {errorMessage}", AgentMessageSeverity.Error);
130+
}
131+
132+
private static HotReloadAgent? GetAgent()
133+
=> s_hotReloadAgent ?? (s_initialized ? throw new InvalidOperationException("Hot Reload agent not initialized") : null);
134+
135+
private static LogEntry[] ApplyHotReloadDeltas(Delta[] deltas, int loggingLevel)
136+
{
137+
var agent = GetAgent();
138+
if (agent == null)
139+
{
140+
return [];
141+
}
142+
143+
agent.ApplyDeltas(
144+
deltas.Select(d => new UpdateDelta(Guid.Parse(d.ModuleId, CultureInfo.InvariantCulture), d.MetadataDelta, d.ILDelta, d.PdbDelta, d.UpdatedTypes)));
145+
146+
return agent.Reporter.GetAndClearLogEntries((ResponseLoggingLevel)loggingLevel)
147+
.Select(log => new LogEntry() { Message = log.message, Severity = (int)log.severity }).ToArray();
148+
}
149+
150+
private static readonly WebAssemblyHotReloadJsonSerializerContext jsonContext = new(new(JsonSerializerDefaults.Web));
151+
152+
[JSExport]
153+
[SupportedOSPlatform("browser")]
154+
public static string GetApplyUpdateCapabilities()
155+
{
156+
return GetAgent()?.Capabilities ?? "";
157+
}
158+
159+
[JSExport]
160+
[SupportedOSPlatform("browser")]
161+
public static string? ApplyHotReloadDeltas(string deltasJson, int loggingLevel)
162+
{
163+
var deltas = JsonSerializer.Deserialize(deltasJson, jsonContext.DeltaArray);
164+
if (deltas == null)
165+
{
166+
return null;
167+
}
168+
169+
var result = ApplyHotReloadDeltas(deltas, loggingLevel);
170+
return result == null ? null : JsonSerializer.Serialize(result, jsonContext.LogEntryArray);
171+
}
172+
}
173+
174+
[JsonSerializable(typeof(WebAssemblyHotReload.Delta[]))]
175+
[JsonSerializable(typeof(WebAssemblyHotReload.LogEntry[]))]
176+
internal sealed partial class WebAssemblyHotReloadJsonSerializerContext : JsonSerializerContext
177+
{
178+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export async function onRuntimeConfigLoaded(config) {
2+
// If we have 'aspnetcore-browser-refresh', configure mono runtime for HotReload.
3+
if (config.debugLevel !== 0 && globalThis.window?.document?.querySelector("script[src*='aspnetcore-browser-refresh']")) {
4+
if (!config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"]) {
5+
config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
6+
}
7+
if (!config.environmentVariables["__ASPNETCORE_BROWSER_TOOLS"]) {
8+
config.environmentVariables["__ASPNETCORE_BROWSER_TOOLS"] = "true";
9+
}
10+
}
11+
12+
// Disable HotReload built-into the Blazor WebAssembly runtime
13+
config.environmentVariables["__BLAZOR_WEBASSEMBLY_LEGACY_HOTRELOAD"] = "false";
14+
}
15+
16+
export async function onRuntimeReady({ getAssemblyExports }) {
17+
const exports = await getAssemblyExports("Microsoft.DotNet.HotReload.WebAssembly.Browser");
18+
await exports.Microsoft.DotNet.HotReload.WebAssembly.Browser.WebAssemblyHotReload.InitializeAsync(document.baseURI);
19+
20+
if (!window.Blazor) {
21+
window.Blazor = {};
22+
23+
if (!window.Blazor._internal) {
24+
window.Blazor._internal = {};
25+
}
26+
}
27+
28+
window.Blazor._internal.applyHotReloadDeltas = (deltas, loggingLevel) => {
29+
const result = exports.Microsoft.DotNet.HotReload.WebAssembly.Browser.WebAssemblyHotReload.ApplyHotReloadDeltas(JSON.stringify(deltas), loggingLevel);
30+
return result ? JSON.parse(result) : [];
31+
};
32+
33+
window.Blazor._internal.getApplyUpdateCapabilities = () => {
34+
return exports.Microsoft.DotNet.HotReload.WebAssembly.Browser.WebAssemblyHotReload.GetApplyUpdateCapabilities() ?? '';
35+
};
36+
}

src/BuiltInTools/dotnet-watch.slnf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"src\\BuiltInTools\\HotReloadAgent.Data\\Microsoft.DotNet.HotReload.Agent.Data.shproj",
1414
"src\\BuiltInTools\\HotReloadAgent.PipeRpc\\Microsoft.DotNet.HotReload.Agent.PipeRpc.Package.csproj",
1515
"src\\BuiltInTools\\HotReloadAgent.PipeRpc\\Microsoft.DotNet.HotReload.Agent.PipeRpc.shproj",
16+
"src\\BuiltInTools\\HotReloadAgent.WebAssembly.Browser\\Microsoft.DotNet.HotReload.WebAssembly.Browser.csproj",
1617
"src\\BuiltInTools\\dotnet-watch\\dotnet-watch.csproj",
1718
"test\\Microsoft.AspNetCore.Watch.BrowserRefresh.Tests\\Microsoft.AspNetCore.Watch.BrowserRefresh.Tests.csproj",
1819
"test\\Microsoft.Extensions.DotNetDeltaApplier.Tests\\Microsoft.Extensions.DotNetDeltaApplier.Tests.csproj",

src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ NOTE: This file is imported from the following contexts, so be aware when writin
295295
ApphostsForShimRuntimeIdentifiers="@(_ApphostsForShimRuntimeIdentifiers)"
296296
IntermediateAssembly="@(IntermediateAssembly->'%(FullPath)')"
297297
OutputType="$(OutputType)"
298-
PackagedShimOutputDirectory="$([System.IO.Path]::Combine($(PackagedShimOutputRootDirectory), 'shims', $(_ToolPackShortTargetFrameworkName)))"
298+
PackagedShimOutputDirectory="$([MSBuild]::NormalizeDirectory($(PackagedShimOutputRootDirectory), 'shims', $(_ToolPackShortTargetFrameworkName)))"
299299
PackageId="$(PackageId)"
300300
PackageVersion="$(PackageVersion)"
301301
ShimRuntimeIdentifiers="@(_PackAsToolShimRuntimeIdentifiers)"
@@ -324,7 +324,7 @@ NOTE: This file is imported from the following contexts, so be aware when writin
324324

325325
<Target Name="_ComputeExpectedEmbeddedApphostPaths">
326326
<GetEmbeddedApphostPaths
327-
PackagedShimOutputDirectory="$([System.IO.Path]::Combine($(PackagedShimOutputRootDirectory), 'shims', $(_ToolPackShortTargetFrameworkName)))"
327+
PackagedShimOutputDirectory="$([MSBuild]::NormalizeDirectory($(PackagedShimOutputRootDirectory), 'shims', $(_ToolPackShortTargetFrameworkName)))"
328328
ShimRuntimeIdentifiers="@(_PackAsToolShimRuntimeIdentifiers)"
329329
ToolCommandName="$(ToolCommandName)">
330330

src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1289,7 +1289,7 @@ Copyright (c) .NET Foundation. All rights reserved.
12891289
</ItemGroup>
12901290

12911291
<GetEmbeddedApphostPaths
1292-
PackagedShimOutputDirectory="$([System.IO.Path]::Combine($(PackagedShimOutputRootDirectory), 'shims', $(TargetFramework)))"
1292+
PackagedShimOutputDirectory="$([MSBuild]::NormalizeDirectory($(PackagedShimOutputRootDirectory), 'shims', $(TargetFramework)))"
12931293
ShimRuntimeIdentifiers="@(_PackAsToolShimRuntimeIdentifiers)"
12941294
ToolCommandName="$(ToolCommandName)"
12951295
>

0 commit comments

Comments
 (0)