Skip to content

Commit c4ba901

Browse files
author
Simon Zhao (BEYONDSOFT CONSULTING INC)
committed
Merge branch 'main' of https://github.com/dotnet/sdk into locfiles/4946f269-a968-4d8f-93bf-c45cc5ed2521
2 parents 31a9c34 + b64c645 commit c4ba901

File tree

39 files changed

+11311
-929
lines changed

39 files changed

+11311
-929
lines changed

NuGet.config

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
<!-- Begin: Package sources from dotnet-aspire -->
77
<!-- End: Package sources from dotnet-aspire -->
88
<!-- Begin: Package sources from dotnet-runtime -->
9-
<add key="darc-int-dotnet-runtime-3875b54" value="https://pkgs.dev.azure.com/dnceng/internal/_packaging/darc-int-dotnet-runtime-3875b54e/nuget/v3/index.json" />
109
<!-- End: Package sources from dotnet-runtime -->
1110
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
1211
<add key="dotnet6" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json" />
@@ -38,7 +37,6 @@
3837
<clear />
3938
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
4039
<!-- Begin: Package sources from dotnet-runtime -->
41-
<add key="darc-int-dotnet-runtime-3875b54" value="true" />
4240
<!-- End: Package sources from dotnet-runtime -->
4341
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
4442
</disabledPackageSources>

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/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -196,17 +196,17 @@ private sealed class CachedState
196196
minimumVSDefinedSDKVersion);
197197
}
198198

199-
string? dotnetExe =
200-
TryResolveDotnetExeFromSdkResolution(resolverResult)
199+
string? fullPathToMuxer =
200+
TryResolveMuxerFromSdkResolution(resolverResult)
201201
?? Path.Combine(dotnetRoot, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Constants.DotNetExe : Constants.DotNet);
202-
if (File.Exists(dotnetExe))
202+
if (File.Exists(fullPathToMuxer))
203203
{
204204
propertiesToAdd ??= new Dictionary<string, string?>();
205-
propertiesToAdd.Add(DotnetHostExperimentalKey, dotnetExe);
205+
propertiesToAdd.Add(DotnetHostExperimentalKey, fullPathToMuxer);
206206
}
207207
else
208208
{
209-
logger?.LogMessage($"Could not set '{DotnetHostExperimentalKey}' because dotnet executable '{dotnetExe}' does not exist.");
209+
logger?.LogMessage($"Could not set '{DotnetHostExperimentalKey}' because dotnet executable '{fullPathToMuxer}' does not exist.");
210210
}
211211

212212
string? runtimeVersion = dotnetRoot != null ?
@@ -288,22 +288,23 @@ private sealed class CachedState
288288
return factory.IndicateSuccess(msbuildSdkDir, netcoreSdkVersion, propertiesToAdd, itemsToAdd, warnings);
289289
}
290290

291-
/// <summary>Try to find the dotnet binary from the SDK resolution result upwards</summary>
292-
private static string? TryResolveDotnetExeFromSdkResolution(SdkResolutionResult resolverResult)
291+
/// <summary>
292+
/// Try to find the muxer binary from the SDK resolution result.
293+
/// </summary>
294+
/// <remarks>
295+
/// SDK layouts always have a defined relationship to the location of the muxer -
296+
/// the muxer binary should be exactly two directories above the SDK directory.
297+
/// </remarks>
298+
private static string? TryResolveMuxerFromSdkResolution(SdkResolutionResult resolverResult)
293299
{
294300
var expectedFileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Constants.DotNetExe : Constants.DotNet;
295301
var currentDir = resolverResult.ResolvedSdkDirectory;
296-
while (currentDir != null)
302+
var expectedDotnetRoot = Path.GetDirectoryName(Path.GetDirectoryName(currentDir));
303+
var expectedMuxerPath = Path.Combine(expectedDotnetRoot, expectedFileName);
304+
if (File.Exists(expectedMuxerPath))
297305
{
298-
var dotnetExe = Path.Combine(currentDir, expectedFileName);
299-
if (File.Exists(dotnetExe))
300-
{
301-
return dotnetExe;
302-
}
303-
304-
currentDir = Path.GetDirectoryName(currentDir);
306+
return expectedMuxerPath;
305307
}
306-
307308
return null;
308309
}
309310

0 commit comments

Comments
 (0)