Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<_WasmCopyOutputSymbolsToOutputDirectory Condition="'$(_WasmCopyOutputSymbolsToOutputDirectory)'==''">true</_WasmCopyOutputSymbolsToOutputDirectory>
<_WasmEnableThreads>$(WasmEnableThreads)</_WasmEnableThreads>
<_WasmEnableThreads Condition="'$(_WasmEnableThreads)' == ''">false</_WasmEnableThreads>
<_WasmEmitTypeScriptDefinitions Condition="'$(WasmEmitTypeScriptDefinitions)' == ''">false</_WasmEmitTypeScriptDefinitions>

<_WasmEnableWebcil>$(WasmEnableWebcil)</_WasmEnableWebcil>
<_WasmEnableWebcil Condition="'$(_TargetingNET80OrLater)' != 'true'">false</_WasmEnableWebcil>
Expand Down Expand Up @@ -856,4 +857,23 @@ Copyright (c) .NET Foundation. All rights reserved.
<WasmAssembliesToBundle Include="@(ResolvedFileToPublish)" Exclude="@(_Exclude)" Condition="%(Extension) == '.dll'" />
</ItemGroup>
</Target>

<!-- Ensure dotnet.d.ts is available in wwwroot for TypeScript development experience when enabled -->
<Target Name="_EnsureDotnetTypeScriptDefinitions"
AfterTargets="_ResolveWasmConfiguration"
Condition="'$(_WasmEmitTypeScriptDefinitions)' == 'true'">
<PropertyGroup>
<_RuntimePackDir>$(MicrosoftNetCoreAppRuntimePackDir)</_RuntimePackDir>
<_RuntimePackDir Condition="'$(_RuntimePackDir)' == ''">%(ResolvedRuntimePack.PackageDirectory)</_RuntimePackDir>
<_RuntimePackNativeDir>$([MSBuild]::NormalizeDirectory($(_RuntimePackDir), 'runtimes', 'browser-wasm', 'native'))</_RuntimePackNativeDir>
<_DotnetTypesSourcePath>$([MSBuild]::NormalizeDirectory($(_RuntimePackNativeDir), 'dotnet.d.ts'))</_DotnetTypesSourcePath>
<_DotnetTypesDestPath>$(MSBuildProjectDirectory)\wwwroot\dotnet.d.ts</_DotnetTypesDestPath>
</PropertyGroup>

<!-- Copy dotnet.d.ts if source exists. MSBuild will skip if files are identical. -->
<Copy SourceFiles="$(_DotnetTypesSourcePath)"
DestinationFiles="$(_DotnetTypesDestPath)"
Condition="Exists('$(_DotnetTypesSourcePath)')"
SkipUnchangedFiles="true" />
</Target>
</Project>
32 changes: 32 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/Templates/WasmTemplateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,5 +317,37 @@ public async Task LibraryModeBuild(bool useWasmSdk)
}

}

[Theory]
[InlineData(Configuration.Debug, true)]
[InlineData(Configuration.Release, true)]
[InlineData(Configuration.Debug, false)]
[InlineData(Configuration.Release, false)]
public void TypeScriptDefinitionsCopiedToWwwrootOnBuild(Configuration config, bool emitTypeScriptDts)
{
string shouldEmit = emitTypeScriptDts ? "true" : "false";
string emitTypeScriptDtsProp = $"<WasmEmitTypeScriptDefinitions>{shouldEmit}</WasmEmitTypeScriptDefinitions>";
ProjectInfo info = CreateWasmTemplateProject(Template.WasmBrowser, config, aot: false, "tsdefs", extraProperties: emitTypeScriptDtsProp);

string projectDirectory = Path.GetDirectoryName(info.ProjectFilePath)!;
string dotnetDtsWwwrootPath = Path.Combine(projectDirectory, "wwwroot", "dotnet.d.ts");

// Verify dotnet.d.ts is not in wwwroot after creation
Assert.False(File.Exists(dotnetDtsWwwrootPath), $"dotnet.d.ts should not exist at {dotnetDtsWwwrootPath} after creation of the project");

// Build to trigger the _EnsureDotnetTypeScriptDefinitions target during the build phase
BuildProject(info, config, new BuildOptions());

// Verify dotnet.d.ts presence in the project's wwwroot directory after build
bool fileExists = File.Exists(dotnetDtsWwwrootPath);
if (emitTypeScriptDts)
{
Assert.True(fileExists, $"dotnet.d.ts should be created at {dotnetDtsWwwrootPath} after the build with WasmEmitTypeScriptDefinitions={shouldEmit}");
}
else
{
Assert.False(fileExists, $"dotnet.d.ts should not exist at {dotnetDtsWwwrootPath} after the build with WasmEmitTypeScriptDefinitions={shouldEmit}");
}
}
}
}
2 changes: 2 additions & 0 deletions src/mono/wasm/build/WasmApp.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
- AppBundle/_content contains web files from nuget packages (css, js, etc)
- $(WasmStripILAfterAOT) - Set to true to enable trimming away AOT compiled methods body (IL code)
Defaults to true.
- $(WasmEmitTypeScriptDefinitions) - Controls whether TypeScript definitions (dotnet.d.ts) should be copied to the project's `wwwroot`.
Defaults to false.
Public items:
- @(WasmExtraFilesToDeploy) - Files to copy to $(WasmAppDir).
Expand Down
Loading