Skip to content

Commit 46f8f1e

Browse files
maraflambdageek
andauthored
[browser] Enable threads in Wasm SDK (#85109)
Co-authored-by: Aleksey Kliger (λgeek) <[email protected]>
1 parent 6848447 commit 46f8f1e

File tree

4 files changed

+70
-12
lines changed

4 files changed

+70
-12
lines changed

src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ Copyright (c) .NET Foundation. All rights reserved.
169169
<_WasmInvariantGlobalization Condition="'$(_WasmInvariantGlobalization)' == ''">true</_WasmInvariantGlobalization>
170170
<_WasmCopyOutputSymbolsToOutputDirectory>$(CopyOutputSymbolsToOutputDirectory)</_WasmCopyOutputSymbolsToOutputDirectory>
171171
<_WasmCopyOutputSymbolsToOutputDirectory Condition="'$(_WasmCopyOutputSymbolsToOutputDirectory)'==''">true</_WasmCopyOutputSymbolsToOutputDirectory>
172+
<_WasmEnableThreads>$(WasmEnableThreads)</_WasmEnableThreads>
173+
<_WasmEnableThreads Condition="'$(_WasmEnableThreads)' == ''">false</_WasmEnableThreads>
172174
<_WasmEnableWebcil>$(WasmEnableWebcil)</_WasmEnableWebcil>
173175
<_WasmEnableWebcil Condition="'$(_WasmEnableWebcil)' == ''">false</_WasmEnableWebcil>
174176
<_BlazorWebAssemblyStartupMemoryCache>$(BlazorWebAssemblyStartupMemoryCache)</_BlazorWebAssemblyStartupMemoryCache>
@@ -203,6 +205,7 @@ Copyright (c) .NET Foundation. All rights reserved.
203205
CopySymbols="$(_WasmCopyOutputSymbolsToOutputDirectory)"
204206
OutputPath="$(OutputPath)"
205207
FingerprintDotNetJs="$(WasmFingerprintDotnetJs)"
208+
EnableThreads="$(_WasmEnableThreads)"
206209
>
207210
<Output TaskParameter="AssetCandidates" ItemName="_BuildAssetsCandidates" />
208211
<Output TaskParameter="FilesToRemove" ItemName="_WasmBuildFilesToRemove" />
@@ -374,6 +377,7 @@ Copyright (c) .NET Foundation. All rights reserved.
374377
ExistingAssets="@(_WasmPublishPrefilteredAssets)"
375378
DotNetJsVersion="$(_DotNetJsVersion)"
376379
FingerprintDotNetJs="$(WasmFingerprintDotnetJs)"
380+
EnableThreads="$(_WasmEnableThreads)"
377381
IsWebCilEnabled="$(_WasmEnableWebcil)"
378382
>
379383
<Output TaskParameter="NewCandidates" ItemName="_NewWasmPublishStaticWebAssets" />

src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,26 @@ namespace Microsoft.NET.Sdk.WebAssembly;
1212

1313
public class AssetsComputingHelper
1414
{
15+
private static readonly string[] monoPackageIds = new[]
16+
{
17+
"Microsoft.NETCore.App.Runtime.Mono.browser-wasm",
18+
"Microsoft.NETCore.App.Runtime.Mono.multithread.browser-wasm",
19+
"Microsoft.NETCore.App.Runtime.Mono.perftrace.browser-wasm",
20+
};
21+
1522
public static bool ShouldFilterCandidate(
1623
ITaskItem candidate,
1724
bool timezoneSupport,
1825
bool invariantGlobalization,
1926
bool copySymbols,
2027
string customIcuCandidateFilename,
28+
bool enableThreads,
2129
out string reason)
2230
{
2331
var extension = candidate.GetMetadata("Extension");
2432
var fileName = candidate.GetMetadata("FileName");
2533
var assetType = candidate.GetMetadata("AssetType");
26-
var fromMonoPackage = string.Equals(
27-
candidate.GetMetadata("NuGetPackageId"),
28-
"Microsoft.NETCore.App.Runtime.Mono.browser-wasm",
29-
StringComparison.Ordinal);
34+
bool fromMonoPackage = IsFromMonoPackage(candidate);
3035

3136
reason = extension switch
3237
{
@@ -45,7 +50,7 @@ public static bool ShouldFilterCandidate(
4550
".json" when fromMonoPackage && (fileName == "emcc-props" || fileName == "package") => $"{fileName}{extension} is not used by Blazor",
4651
".ts" when fromMonoPackage && fileName == "dotnet.d" => "dotnet type definition is not used by Blazor",
4752
".ts" when fromMonoPackage && fileName == "dotnet-legacy.d" => "dotnet type definition is not used by Blazor",
48-
".js" when assetType == "native" && fileName != "dotnet" => $"{fileName}{extension} is not used by Blazor",
53+
".js" when assetType == "native" && !(fileName == "dotnet" || enableThreads && fileName == "dotnet.worker") => $"{fileName}{extension} is not used by Blazor",
4954
".pdb" when !copySymbols => "copying symbols is disabled",
5055
".symbols" when fromMonoPackage => "extension .symbols is not required.",
5156
_ => null
@@ -54,6 +59,12 @@ public static bool ShouldFilterCandidate(
5459
return reason != null;
5560
}
5661

62+
private static bool IsFromMonoPackage(ITaskItem candidate)
63+
{
64+
string packageId = candidate.GetMetadata("NuGetPackageId");
65+
return monoPackageIds.Contains(packageId, StringComparer.Ordinal);
66+
}
67+
5768
public static string GetCandidateRelativePath(ITaskItem candidate)
5869
{
5970
var destinationSubPath = candidate.GetMetadata("DestinationSubPath");

src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public class ComputeWasmBuildAssets : Task
4545

4646
public bool FingerprintDotNetJs { get; set; }
4747

48+
public bool EnableThreads { get; set; }
49+
4850
[Output]
4951
public ITaskItem[] AssetCandidates { get; set; }
5052

@@ -79,7 +81,7 @@ public override bool Execute()
7981
for (int i = 0; i < Candidates.Length; i++)
8082
{
8183
var candidate = Candidates[i];
82-
if (AssetsComputingHelper.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, customIcuCandidateFilename, out var reason))
84+
if (AssetsComputingHelper.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, customIcuCandidateFilename, EnableThreads, out var reason))
8385
{
8486
Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' because '{1}'", candidate.ItemSpec, reason);
8587
filesToRemove.Add(candidate);
@@ -104,14 +106,15 @@ public override bool Execute()
104106
continue;
105107
}
106108

107-
if (candidate.GetMetadata("FileName") == "dotnet" && candidate.GetMetadata("Extension") == ".js")
109+
string candidateFileName = candidate.GetMetadata("FileName");
110+
if ((candidateFileName == "dotnet" || candidateFileName == "dotnet.worker") && candidate.GetMetadata("Extension") == ".js")
108111
{
109112
string newDotnetJSFileName = null;
110113
string newDotNetJSFullPath = null;
111114
if (FingerprintDotNetJs)
112115
{
113116
var itemHash = FileHasher.GetFileHash(candidate.ItemSpec);
114-
newDotnetJSFileName = $"dotnet.{candidate.GetMetadata("NuGetPackageVersion")}.{itemHash}.js";
117+
newDotnetJSFileName = $"{candidateFileName}.{candidate.GetMetadata("NuGetPackageVersion")}.{itemHash}.js";
115118

116119
var originalFileFullPath = Path.GetFullPath(candidate.ItemSpec);
117120
var originalFileDirectory = Path.GetDirectoryName(originalFileFullPath);

src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public class ComputeWasmPublishAssets : Task
5555

5656
public bool FingerprintDotNetJs { get; set; }
5757

58+
public bool EnableThreads { get; set; }
59+
5860
public bool IsWebCilEnabled { get; set; }
5961

6062
[Output]
@@ -163,8 +165,10 @@ private List<ITaskItem> ProcessNativeAssets(
163165
var key = kvp.Key;
164166
var asset = kvp.Value;
165167
var isDotNetJs = IsDotNetJs(key);
168+
var isDotNetWorkerJs = IsDotNetWorkerJs(key);
166169
var isDotNetWasm = IsDotNetWasm(key);
167-
if (!isDotNetJs && !isDotNetWasm)
170+
171+
if (!isDotNetJs && !isDotNetWasm && !isDotNetWorkerJs)
168172
{
169173
if (resolvedNativeAssetToPublish.TryGetValue(Path.GetFileName(asset.GetMetadata("OriginalItemSpec")), out var existing))
170174
{
@@ -197,11 +201,16 @@ private List<ITaskItem> ProcessNativeAssets(
197201
{
198202
var aotDotNetJs = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.js");
199203
ITaskItem newDotNetJs = null;
200-
if (aotDotNetJs != null && FingerprintDotNetJs)
204+
if (aotDotNetJs != null)
201205
{
202206
newDotNetJs = new TaskItem(Path.GetFullPath(aotDotNetJs.ItemSpec), asset.CloneCustomMetadata());
203207
newDotNetJs.SetMetadata("OriginalItemSpec", aotDotNetJs.ItemSpec);
204-
newDotNetJs.SetMetadata("RelativePath", $"_framework/{$"dotnet.{DotNetJsVersion}.{FileHasher.GetFileHash(aotDotNetJs.ItemSpec)}.js"}");
208+
209+
string relativePath = FingerprintDotNetJs
210+
? $"_framework/{$"dotnet.{DotNetJsVersion}.{FileHasher.GetFileHash(aotDotNetJs.ItemSpec)}.js"}"
211+
: "_framework/dotnet.js";
212+
213+
newDotNetJs.SetMetadata("RelativePath", relativePath);
205214

206215
updateMap.Add(asset.ItemSpec, newDotNetJs);
207216
Log.LogMessage(MessageImportance.Low, "Replacing asset '{0}' with AoT version '{1}'", asset.ItemSpec, newDotNetJs.ItemSpec);
@@ -221,6 +230,35 @@ private List<ITaskItem> ProcessNativeAssets(
221230
continue;
222231
}
223232

233+
if (isDotNetWorkerJs)
234+
{
235+
var aotDotNetWorkerJs = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.worker.js");
236+
ITaskItem newDotNetWorkerJs = null;
237+
if (aotDotNetWorkerJs != null)
238+
{
239+
newDotNetWorkerJs = new TaskItem(Path.GetFullPath(aotDotNetWorkerJs.ItemSpec), asset.CloneCustomMetadata());
240+
newDotNetWorkerJs.SetMetadata("OriginalItemSpec", aotDotNetWorkerJs.ItemSpec);
241+
newDotNetWorkerJs.SetMetadata("RelativePath", "_framework/dotnet.worker.js");
242+
243+
updateMap.Add(asset.ItemSpec, newDotNetWorkerJs);
244+
Log.LogMessage(MessageImportance.High, "Replacing asset '{0}' with AoT version '{1}'", asset.ItemSpec, newDotNetWorkerJs.ItemSpec);
245+
}
246+
else
247+
{
248+
newDotNetWorkerJs = new TaskItem(asset);
249+
newDotNetWorkerJs.SetMetadata("RelativePath", "_framework/dotnet.worker.js");
250+
Log.LogMessage(MessageImportance.High, "Promoting asset '{0}' to Publish asset.", asset.ItemSpec);
251+
}
252+
253+
ApplyPublishProperties(newDotNetWorkerJs);
254+
nativeStaticWebAssets.Add(newDotNetWorkerJs);
255+
if (resolvedNativeAssetToPublish.TryGetValue("dotnet.worker.js", out var resolved))
256+
{
257+
filesToRemove.Add(resolved);
258+
}
259+
continue;
260+
}
261+
224262
if (isDotNetWasm)
225263
{
226264
var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.wasm");
@@ -262,6 +300,8 @@ static bool IsDotNetJs(string key)
262300
return fileName.StartsWith("dotnet.", StringComparison.Ordinal) && fileName.EndsWith(".js", StringComparison.Ordinal) && !fileName.Contains("worker");
263301
}
264302

303+
static bool IsDotNetWorkerJs(string key) => string.Equals("dotnet.worker.js", Path.GetFileName(key), StringComparison.Ordinal);
304+
265305
static bool IsDotNetWasm(string key) => string.Equals("dotnet.wasm", Path.GetFileName(key), StringComparison.Ordinal);
266306
}
267307

@@ -540,7 +580,7 @@ private void GroupResolvedFilesToPublish(
540580

541581
foreach (var candidate in resolvedFilesToPublish)
542582
{
543-
if (AssetsComputingHelper.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, customIcuCandidateFilename, out var reason))
583+
if (AssetsComputingHelper.ShouldFilterCandidate(candidate, TimeZoneSupport, InvariantGlobalization, CopySymbols, customIcuCandidateFilename, EnableThreads, out var reason))
544584
{
545585
Log.LogMessage(MessageImportance.Low, "Skipping asset '{0}' because '{1}'", candidate.ItemSpec, reason);
546586
if (!resolvedFilesToPublishToRemove.ContainsKey(candidate.ItemSpec))

0 commit comments

Comments
 (0)