Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions global.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"sdk": {
"version": "11.0.100-preview.3.26161.119",
"version": "11.0.100-preview.3.26166.111",
"allowPrerelease": true,
"rollForward": "major"
},
"tools": {
"dotnet": "11.0.100-preview.3.26161.119"
"dotnet": "11.0.100-preview.3.26166.111"
},
"msbuild-sdks": {
"Microsoft.DotNet.Arcade.Sdk": "11.0.0-beta.26166.111",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<_WasmProjectAssemblyBuild Include="@(WasmAssembliesFinal)" Condition="$(_WasmIntermediateAssemblyFileNames.Contains(';%(FileName)%(Extension);'))" />
<_WasmProjectAssemblyBuild Include="@(IntermediateAssembly)" Condition="@(_WasmProjectAssemblyBuild->Count()) == 0" />
<_WasmBuildAssetCandidates Include="@(ReferenceCopyLocalPaths)" />
<_WasmBuildAssetCandidates Include="@(WasmNativeAsset)" />
<_WasmBuildAssetCandidates Include="@(WasmNativeAsset)" WasmNativeBuildOutput="true" />
<_WasmBuildAssetCandidates Include="@(WasmAssembliesFinal)" />
<_WasmBuildAssetCandidates Remove="@(_WasmProjectAssemblyBuild)" />

Expand Down Expand Up @@ -357,19 +357,29 @@ Copyright (c) .NET Foundation. All rights reserved.

<ConvertDllsToWebcil Candidates="@(_BuildAssetsCandidates)" IntermediateOutputPath="$(_WasmBuildTmpWebcilPath)" OutputPath="$(_WasmBuildWebcilPath)" IsEnabled="$(_WasmEnableWebcil)">
<Output TaskParameter="WebcilCandidates" ItemName="_WebcilAssetsCandidates" />
<Output TaskParameter="PassThroughCandidates" ItemName="_WasmFrameworkCandidates" />
<Output TaskParameter="FileWrites" ItemName="FileWrites" />
</ConvertDllsToWebcil>

<!-- Remove pass-throughs from webcil candidates so each file is classified exactly once:
webcil-converted files → Computed (per-project in obj/webcil/)
pass-through files → Framework (materialized per-project by UpdatePackageStaticWebAssets) -->
<ItemGroup>
<_WebcilAssetsCandidates Remove="@(_WasmFrameworkCandidates)" />
</ItemGroup>

<ItemGroup>
<!-- Set per-item ContentRoot so each asset's Identity matches its actual file on disk -->
<_WebcilAssetsCandidates Update="@(_WebcilAssetsCandidates)" ContentRoot="%(RootDir)%(Directory)" />
<_WasmFrameworkCandidates Update="@(_WasmFrameworkCandidates)" ContentRoot="%(RootDir)%(Directory)" />
<_WasmFingerprintPatterns Include="WasmFiles" Pattern="*.wasm" Expression="#[.{fingerprint}]!" />
<_WasmFingerprintPatterns Include="DllFiles" Pattern="*.dll" Expression="#[.{fingerprint}]!" />
<_WasmFingerprintPatterns Include="DatFiles" Pattern="*.dat" Expression="#[.{fingerprint}]!" />
<_WasmFingerprintPatterns Include="Pdb" Pattern="*.pdb" Expression="#[.{fingerprint}]!" />
<_WasmFingerprintPatterns Include="Symbols" Pattern="*.js.symbols" Expression="#[.{fingerprint}]!" />
</ItemGroup>

<!-- Webcil-converted assets are per-project (Computed) — no materialization needed. -->
<DefineStaticWebAssets
CandidateAssets="@(_WebcilAssetsCandidates)"
SourceId="$(PackageId)"
Expand All @@ -385,6 +395,46 @@ Copyright (c) .NET Foundation. All rights reserved.
<Output TaskParameter="Assets" ItemName="WasmStaticWebAsset" />
</DefineStaticWebAssets>

<!-- Pass-through files are Framework assets: they originate from the runtime pack but
need to be adopted by each consuming project. DefineStaticWebAssets registers them
with SourceType="Framework", then UpdatePackageStaticWebAssets materializes them to
a per-project obj/fx/{SourceId}/ directory, giving each project a unique Identity. -->
<DefineStaticWebAssets
CandidateAssets="@(_WasmFrameworkCandidates)"
SourceId="$(PackageId)"
SourceType="Framework"
AssetKind="Build"
AssetRole="Primary"
CopyToOutputDirectory="PreserveNewest"
CopyToPublishDirectory="Never"
FingerprintCandidates="$(_WasmFingerprintAssets)"
FingerprintPatterns="@(FingerprintPatterns);@(_WasmFingerprintPatterns)"
BasePath="$(StaticWebAssetBasePath)"
>
<Output TaskParameter="Assets" ItemName="_WasmFrameworkAssets" />
</DefineStaticWebAssets>

<!-- Let the SDK task handle materialization: copies to obj/fx/{SourceId}/, transforms
metadata (SourceType→Discovered, SourceId→PackageId, AssetMode→CurrentProject),
and remaps any existing endpoints to the new materialized paths. -->
<UpdatePackageStaticWebAssets
Assets="@(_WasmFrameworkAssets)"
IntermediateOutputPath="$(IntermediateOutputPath)"
ProjectPackageId="$(PackageId)"
ProjectBasePath="$(StaticWebAssetBasePath)"
>
<Output TaskParameter="UpdatedAssets" ItemName="_WasmMaterializedFrameworkAssets" />
</UpdatePackageStaticWebAssets>

<!-- Materialized framework assets must be visible to referencing projects (e.g. Blazor WASM
hosted scenarios where the server project serves the client's framework files).
UpdatePackageStaticWebAssets defaults AssetMode to CurrentProject, but WASM framework
files need to flow through project references for publish and serving. -->
<ItemGroup>
<_WasmMaterializedFrameworkAssets Update="@(_WasmMaterializedFrameworkAssets)" AssetMode="All" />
<WasmStaticWebAsset Include="@(_WasmMaterializedFrameworkAssets)" />
</ItemGroup>

<DefineStaticWebAssets
CandidateAssets="@(_WasmDiscoveredFileCandidates)"
AssetTraitName="WasmResource"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ public class ConvertDllsToWebcil : Task
[Output]
public ITaskItem[] WebcilCandidates { get; set; }

/// <summary>
/// Non-DLL files from shared locations (runtime pack, NuGet cache) that were not
/// converted to webcil. These are candidates for Framework SourceType materialization.
/// When IsEnabled is false, all candidates (DLL and non-DLL) appear here.
/// Items with WasmNativeBuildOutput metadata (per-project native build outputs)
/// are excluded — they're already unique per project.
Comment on lines +33 to +35
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML doc for PassThroughCandidates says items with WasmNativeBuildOutput metadata are excluded, but Execute() assigns PassThroughCandidates = Candidates when IsEnabled is false, which will include those items. Please update the doc (or adjust the disabled-path behavior) so the exclusion rule matches what actually happens when WebCil is disabled.

Suggested change
/// When IsEnabled is false, all candidates (DLL and non-DLL) appear here.
/// Items with WasmNativeBuildOutput metadata (per-project native build outputs)
/// are excluded — they're already unique per project.
/// When <see cref="IsEnabled"/> is true, items with WasmNativeBuildOutput metadata
/// (per-project native build outputs) are excluded — they're already unique per project.
/// When <see cref="IsEnabled"/> is false, all candidates (DLL and non-DLL), including
/// those with WasmNativeBuildOutput metadata, appear here with no additional filtering.

Copilot uses AI. Check for mistakes.
/// </summary>
[Output]
public ITaskItem[] PassThroughCandidates { get; set; }

protected readonly List<string> _fileWrites = new();

[Output]
Expand All @@ -35,10 +45,15 @@ public class ConvertDllsToWebcil : Task
public override bool Execute()
{
var webcilCandidates = new List<ITaskItem>();
var passThroughCandidates = new List<ITaskItem>();

if (!IsEnabled)
{
// When webcil is disabled, no conversion occurs. All candidates pass
// through unchanged. All are also pass-through candidates since none
// were converted to webcil.
WebcilCandidates = Candidates;
PassThroughCandidates = Candidates;
return true;
}

Expand All @@ -56,7 +71,19 @@ public override bool Execute()

if (extension != ".dll")
{
// Non-DLL files always appear in WebcilCandidates (backward compat
// for publish and other callers that only consume WebcilCandidates).
webcilCandidates.Add(candidate);

// Additionally classify shared framework files as pass-throughs.
// Items with WasmNativeBuildOutput metadata are per-project native
// build outputs (e.g. dotnet.native.wasm from obj/wasm/for-build/)
// that don't need Framework materialization.
bool isNativeBuildOutput = !string.IsNullOrEmpty(candidate.GetMetadata("WasmNativeBuildOutput"));
if (!isNativeBuildOutput)
{
passThroughCandidates.Add(candidate);
}
continue;
}

Expand All @@ -75,6 +102,7 @@ public override bool Execute()
Directory.Delete(tmpDir, true);

WebcilCandidates = webcilCandidates.ToArray();
PassThroughCandidates = passThroughCandidates.ToArray();
return true;
}

Expand Down
Loading