<MonoAOTCompilerTasksAssemblyPath>{MonoAOTCompilerTasksAssemblyPath}</MonoAOTCompilerTasksAssemblyPath>
<WasmAppBuilderTasksAssemblyPath>{WasmAppBuilderTasksAssemblyPath}</WasmAppBuilderTasksAssemblyPath>
<JsonToItemsTaskFactoryTasksAssemblyPath>{JsonToItemsTaskFactoryTasksAssemblyPath}</JsonToItemsTaskFactoryTasksAssemblyPath>
+ <RuntimeConfigParserTasksAssemblyPath>{RuntimeConfigParserTasksAssemblyPath}</RuntimeConfigParserTasksAssemblyPath>
<MicrosoftNetCoreAppRuntimePackRidDir>{MicrosoftNetCoreAppRuntimePackRidDir}</MicrosoftNetCoreAppRuntimePackRidDir>
<RepositoryEngineeringDir>{RepositoryEngineeringDir}</RepositoryEngineeringDir>
<TargetFramework>{TestTargetFramework}</TargetFramework>
.Replace('{MonoProjectRoot}', '$(MonoProjectRoot)')
.Replace('{MonoAOTCompilerTasksAssemblyPath}', '$(MonoAOTCompilerTasksAssemblyPath)')
.Replace('{JsonToItemsTaskFactoryTasksAssemblyPath}', '$(JsonToItemsTaskFactoryTasksAssemblyPath)')
+ .Replace('{RuntimeConfigParserTasksAssemblyPath}', '$(RuntimeConfigParserTasksAssemblyPath)')
.Replace('{WasmAppBuilderTasksAssemblyPath}', '$(WasmAppBuilderTasksAssemblyPath)')
.Replace('{MicrosoftNetCoreAppRuntimePackRidDir}', '$(MicrosoftNetCoreAppRuntimePackRidDir)'))"
Overwrite="true" />
AssemblyFile="$(RuntimeConfigParserTasksAssemblyPath)"
Condition="'$(RuntimeConfigParserTasksAssemblyPath)' != ''" />
- <Target Name="GenerateRuntimeConfig">
+ <Target Name="GenerateRuntimeConfig" Condition="'$(OutputType)' != 'library' and '$(TargetOS)' != 'Browser'">
<PropertyGroup>
<RuntimeConfigFilePath>$(PublishDir)$(AssemblyName).runtimeconfig.json</RuntimeConfigFilePath>
<ParsedRuntimeConfigFilePath>$(PublishDir)runtimeconfig.bin</ParsedRuntimeConfigFilePath>
</PropertyGroup>
- <ItemGroup Condition="'$(RunAOTCompilation)' == 'true'">
+ <ItemGroup>
<RuntimeConfigReservedProperties Include="RUNTIME_IDENTIFIER"/>
<RuntimeConfigReservedProperties Include="APP_CONTEXT_BASE_DIRECTORY"/>
</ItemGroup>
AssemblyFile="$(WasmBuildTasksAssemblyPath)" />
<Target Name="_BundleAOTTestWasmAppForHelix" DependsOnTargets="PrepareForWasmBuildApp">
+ <PropertyGroup>
+ <_MainAssemblyPath Condition="'%(WasmAssembliesToBundle.FileName)' == $(AssemblyName) and '%(WasmAssembliesToBundle.Extension)' == '.dll'">%(WasmAssembliesToBundle.Identity)</_MainAssemblyPath>
+ <RuntimeConfigFilePath>$([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json'))</RuntimeConfigFilePath>
+ </PropertyGroup>
+
<ItemGroup>
<BundleFiles Include="$(WasmMainJSPath)" TargetDir="publish" />
<BundleFiles Include="@(WasmAssembliesToBundle)" TargetDir="publish\%(WasmAssembliesToBundle.RecursiveDir)" />
+ <BundleFiles Include="$(RuntimeConfigFilePath)" TargetDir="publish" />
<BundleFiles Include="$(MonoProjectRoot)\wasm\data\aot-tests\*" TargetDir="publish" />
</ItemGroup>
<_WasmPropertyNames Include="WasmLinkIcalls" />
<_WasmPropertyNames Include="WasmDedup" />
<_WasmPropertyNames Include="IncludeSatelliteAssembliesInVFS" />
+ <_WasmPropertyNames Include="AssemblyName" />
<_WasmPropertiesToPass
Include="$(%(_WasmPropertyNames.Identity))"
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
<TestRuntime>true</TestRuntime>
- <IgnoreForCI Condition="'$(TargetOS)' == 'Browser'">true</IgnoreForCI> <!-- remove once https://github.com/dotnet/runtime/issues/38433 is fixed -->
</PropertyGroup>
<ItemGroup>
<Compile Include="ActivityTests.cs" />
}
}
- [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json
[Theory]
[MemberData(nameof(Encoding_TestData))]
public static void VerifyCodePageAttributes(int codepage, string name, string bodyName, string headerName, bool isBrowserDisplay,
Assert.Equal(windowsCodePage, encoding.WindowsCodePage);
}
- [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json
[Theory]
[MemberData(nameof(Normalization_TestData))]
public static void NormalizationTest(int codepage, bool normalized, bool normalizedC, bool normalizedD, bool normalizedKC, bool normalizedKD)
new CodePageMapping("x-unicode-2-0-utf-8", 65001)
};
- [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json
[Fact]
public void TestEncodingNameAndCopdepageNumber()
{
}
}
- [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json
[Fact]
public void GetEncoding_EncodingName()
{
}
}
- [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json
[Fact]
public void GetEncoding_WebName()
{
namespace System.Text.Tests
{
- [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json
public class UTF7EncodingEncode
{
public static IEnumerable<object[]> Encode_Basic_TestData()
namespace System.Text.Tests
{
- [ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)] // wasm doesn't honor runtimeconfig.json
public class UTF7EncodingTests
{
[Fact]
<HelixCorrelationPayload Include="$(WasmBuildTargetsDir)" Destination="build/wasm" />
<HelixCorrelationPayload Include="$(MonoAotCrossDir)" Destination="build/cross" />
<HelixCorrelationPayload Include="$(JsonToItemsTaskFactoryDir)" Destination="build/JsonToItemsTaskFactory" />
+ <HelixCorrelationPayload Include="$(RuntimeConfigParserDir)" Destination="build/RuntimeConfigParser" />
</ItemGroup>
<ItemGroup Condition="'$(TargetOS)' == 'Browser' and '$(Scenario)' != 'BuildWasmApps'">
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Security.Cryptography.Xml\tests\System.Security.Cryptography.Xml.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Security.Cryptography.X509Certificates\tests\System.Security.Cryptography.X509Certificates.Tests.csproj" />
- <!-- https://github.com/dotnet/runtime/issues/38433 -->
- <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj" />
-
<!-- Issue: https://github.com/dotnet/runtime/issues/55767 -->
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Runtime.Experimental\tests\System.Runtime.Experimental.Tests.csproj" />
</ItemGroup>
This should be a step towards eventually having this build as a sdk.
Refer to `WasmApp.targets` for more information about the properties/items used as inputs to the process.
+
+## Updating dependencies needed for building wasm apps
+
+For example, if the wasm targets are using a new task, then references to that
+need to be updated in a few places. Essentially, look for existing references
+to `MonoAOTCompiler`, or `WasmAppBuilder` in the relevant files, and duplicate
+them for the new task assembly.
+
+1. The task assembly dir, and its path need to be in two properties:
+ ```xml
+ <JsonToItemsTaskFactoryDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'JsonToItemsTaskFactory', 'Debug', '$(NetCoreAppToolCurrent)'))</JsonToItemsTaskFactoryDir>
+ <JsonToItemsTaskFactoryTasksAssemblyPath>$([MSBuild]::NormalizePath('$(JsonToItemsTaskFactoryDir)', 'JsonToItemsTaskFactory.dll'))</JsonToItemsTaskFactoryTasksAssemblyPath>
+ ```
+
+ And this needs to be set in:
+ - `Directory.Build.props`
+ - `src/mono/wasm/build/WasmApp.LocalBuild.props`
+ - `src/mono/wasm/build/WasmApp.LocalBuild.targets`
+ - `src/tests/Common/wasm-test-runner/WasmTestRunner.proj`
+
+2. The new dependency (eg. task assembly) needs to be sent to helix as a payload, see `src/libraries/sendtohelixhelp.proj`. Use `MonoAOTCompiler` as an example.
+
+3. Make changes similar to the one for existing dependent tasks in
+ - `eng/testing/linker/trimmingTests.targets`,
+ - `src/tests/Common/wasm-test-runner/WasmTestRunner.proj`
+ - `src/tests/Directory.Build.targets`
\ No newline at end of file
<Project>
<!-- This depends on the root Directory.Build.targets imported this file -->
<UsingTask TaskName="MonoAOTCompiler" AssemblyFile="$(MonoAOTCompilerTasksAssemblyPath)" />
+ <UsingTask TaskName="RuntimeConfigParserTask" AssemblyFile="$(RuntimeConfigParserTasksAssemblyPath)" />
<!-- TODO: this breaks runtime tests on Helix due to the file not being there for some reason. Once this is fixed we can remove the UpdateRuntimePack target here -->
<!--<Import Project="$(RepositoryEngineeringDir)targetingpacks.targets" Condition="'$(TargetingpacksTargetsImported)' != 'true'"/>-->
<WasmAppBuilderDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppBuilder', 'Debug', '$(_NetCoreAppToolCurrent)', 'publish'))</WasmAppBuilderDir>
<WasmBuildTasksDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmBuildTasks', 'Debug', '$(_NetCoreAppToolCurrent)', 'publish'))</WasmBuildTasksDir>
<MonoAOTCompilerDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MonoAOTCompiler', 'Debug', '$(_NetCoreAppToolCurrent)'))</MonoAOTCompilerDir>
+ <RuntimeConfigParserDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'RuntimeConfigParser', 'Debug', '$(_NetCoreAppToolCurrent)'))</RuntimeConfigParserDir>
<JsonToItemsTaskFactoryDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'JsonToItemsTaskFactory', 'Debug', '$(_NetCoreAppToolCurrent)'))</JsonToItemsTaskFactoryDir>
<MonoArtifactsPath>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'mono', '$(TargetOS).$(TargetArchitecture).$(RuntimeConfig)'))</MonoArtifactsPath>
<MicrosoftNetCoreAppRuntimePackLocationToUse>$([MSBuild]::NormalizeDirectory($(BuildBaseDir), 'microsoft.netcore.app.runtime.browser-wasm'))</MicrosoftNetCoreAppRuntimePackLocationToUse>
<MonoAOTCompilerDir>$([MSBuild]::NormalizeDirectory($(BuildBaseDir), 'MonoAOTCompiler'))</MonoAOTCompilerDir>
+ <RuntimeConfigParserDir>$([MSBuild]::NormalizeDirectory($(BuildBaseDir), 'RuntimeConfigParser'))</RuntimeConfigParserDir>
<JsonToItemsTaskFactoryDir>$([MSBuild]::NormalizeDirectory($(BuildBaseDir), 'JsonToItemsTaskFactory'))</JsonToItemsTaskFactoryDir>
<WasmAppBuilderDir>$([MSBuild]::NormalizeDirectory($(BuildBaseDir), 'WasmAppBuilder'))</WasmAppBuilderDir>
<WasmBuildTasksDir>$([MSBuild]::NormalizeDirectory($(BuildBaseDir), 'WasmBuildTasks'))</WasmBuildTasksDir>
<WasmAppBuilderTasksAssemblyPath>$([MSBuild]::NormalizePath('$(WasmAppBuilderDir)', 'WasmAppBuilder.dll'))</WasmAppBuilderTasksAssemblyPath>
<WasmBuildTasksAssemblyPath>$([MSBuild]::NormalizePath('$(WasmBuildTasksDir)', 'WasmBuildTasks.dll'))</WasmBuildTasksAssemblyPath>
<MonoAOTCompilerTasksAssemblyPath>$([MSBuild]::NormalizePath('$(MonoAOTCompilerDir)', 'MonoAOTCompiler.dll'))</MonoAOTCompilerTasksAssemblyPath>
+ <RuntimeConfigParserTasksAssemblyPath>$([MSBuild]::NormalizePath('$(RuntimeConfigParserDir)', 'RuntimeConfigParser.dll'))</RuntimeConfigParserTasksAssemblyPath>
<JsonToItemsTaskFactoryTasksAssemblyPath>$([MSBuild]::NormalizePath('$(JsonToItemsTaskFactoryDir)', 'JsonToItemsTaskFactory.dll'))</JsonToItemsTaskFactoryTasksAssemblyPath>
</PropertyGroup>
<Project>
<Import Project="$(MSBuildThisFileDirectory)WasmApp.targets" />
<UsingTask TaskName="MonoAOTCompiler" AssemblyFile="$(MonoAOTCompilerTasksAssemblyPath)" />
+ <UsingTask TaskName="RuntimeConfigParserTask" AssemblyFile="$(RuntimeConfigParserTasksAssemblyPath)" />
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
<WasmAppBuilderTasksAssemblyPath>$([MSBuild]::NormalizePath('$(WasmAppBuilderDir)', 'WasmAppBuilder.dll'))</WasmAppBuilderTasksAssemblyPath>
<WasmBuildTasksAssemblyPath>$([MSBuild]::NormalizePath('$(WasmBuildTasksDir)', 'WasmBuildTasks.dll'))</WasmBuildTasksAssemblyPath>
<MonoAOTCompilerTasksAssemblyPath>$([MSBuild]::NormalizePath('$(MonoAOTCompilerDir)', 'MonoAOTCompiler.dll'))</MonoAOTCompilerTasksAssemblyPath>
+ <RuntimeConfigParserTasksAssemblyPath>$([MSBuild]::NormalizePath('$(RuntimeConfigParserDir)', 'RuntimeConfigParser.dll'))</RuntimeConfigParserTasksAssemblyPath>
<JsonToItemsTaskFactoryTasksAssemblyPath>$([MSBuild]::NormalizePath('$(JsonToItemsTaskFactoryDir)', 'JsonToItemsTaskFactory.dll'))</JsonToItemsTaskFactoryTasksAssemblyPath>
</PropertyGroup>
<WasmMainAssemblyFileName Condition="'$(WasmMainAssemblyFileName)' == ''">$(TargetFileName)</WasmMainAssemblyFileName>
<WasmAppDir>$([MSBuild]::NormalizeDirectory($(WasmAppDir)))</WasmAppDir>
+
+ <_MainAssemblyPath Condition="'%(WasmAssembliesToBundle.FileName)' == $(AssemblyName) and '%(WasmAssembliesToBundle.Extension)' == '.dll' and $(WasmGenerateAppBundle) == 'true'">%(WasmAssembliesToBundle.Identity)</_MainAssemblyPath>
+ <_WasmRuntimeConfigFilePath Condition="$(_MainAssemblyPath) != ''">$([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json'))</_WasmRuntimeConfigFilePath>
</PropertyGroup>
+ <Warning Condition="'$(WasmGenerateAppBundle)' == 'true' and $(_MainAssemblyPath) == ''" Text="Could not find %24(AssemblyName)=$(AssemblyName) in the assemblies to be bundled.." />
+ <Warning Condition="'$(WasmGenerateAppBundle)' == 'true' and $(_WasmRuntimeConfigFilePath) != '' and !Exists($(_WasmRuntimeConfigFilePath))"
+ Text="Could not find $(_WasmRuntimeConfigFilePath) for $(_MainAssemblyPath)." />
+
<ItemGroup>
<_WasmAssembliesInternal Include="@(WasmAssembliesToBundle->Distinct())" />
</ItemGroup>
</Target>
- <Target Name="_WasmGenerateAppBundle" Condition="'$(WasmGenerateAppBundle)' == 'true'">
+ <Target Name="_WasmGenerateRuntimeConfig" Condition="Exists('$(_WasmRuntimeConfigFilePath)')">
+ <PropertyGroup>
+ <_ParsedRuntimeConfigFilePath>$([System.IO.Path]::GetDirectoryName($(_MainAssemblyPath)))\runtimeconfig.bin</_ParsedRuntimeConfigFilePath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <_RuntimeConfigReservedProperties Include="RUNTIME_IDENTIFIER"/>
+ <_RuntimeConfigReservedProperties Include="APP_CONTEXT_BASE_DIRECTORY"/>
+ </ItemGroup>
+
+ <!-- Parse *.runtimeconfig.json file -->
+ <RuntimeConfigParserTask
+ RuntimeConfigFile="$(_WasmRuntimeConfigFilePath)"
+ OutputFile="$(_ParsedRuntimeConfigFilePath)"
+ RuntimeConfigReservedProperties="@(_RuntimeConfigReservedProperties)">
+ </RuntimeConfigParserTask>
+
+ <ItemGroup>
+ <WasmFilesToIncludeInFileSystem Include="$(_ParsedRuntimeConfigFilePath)" />
+ </ItemGroup>
+ </Target>
+
+ <Target Name="_WasmGenerateAppBundle" Condition="'$(WasmGenerateAppBundle)' == 'true'" DependsOnTargets="_WasmGenerateRuntimeConfig">
<Error Condition="'$(WasmMainJSPath)' == ''" Text="%24(WasmMainJSPath) property needs to be set" />
<PropertyGroup>
#include <stdint.h>
#include <assert.h>
#include <dlfcn.h>
+#include <sys/stat.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/tokentype.h>
static MonoDomain *root_domain;
+#define RUNTIMECONFIG_BIN_FILE "runtimeconfig.bin"
+
static MonoString*
mono_wasm_invoke_js (MonoString *str, int *is_exception)
{
void mono_wasm_link_icu_shim (void);
+void
+cleanup_runtime_config (MonovmRuntimeConfigArguments *args, void *user_data)
+{
+ free (args);
+ free (user_data);
+}
+
EMSCRIPTEN_KEEPALIVE void
mono_wasm_load_runtime (const char *unused, int debug_level)
{
// corlib assemblies.
monoeg_g_setenv ("COMPlus_DebugWriteToStdErr", "1", 0);
#endif
-
+ // When the list of app context properties changes, please update RuntimeConfigReservedProperties for
+ // target _WasmGenerateRuntimeConfig in WasmApp.targets file
const char *appctx_keys[2];
appctx_keys [0] = "APP_CONTEXT_BASE_DIRECTORY";
appctx_keys [1] = "RUNTIME_IDENTIFIER";
appctx_values [0] = "/";
appctx_values [1] = "browser-wasm";
+ char *file_name = RUNTIMECONFIG_BIN_FILE;
+ int str_len = strlen (file_name) + 1; // +1 is for the "/"
+ char *file_path = (char *)malloc (sizeof (char) * (str_len +1)); // +1 is for the terminating null character
+ int num_char = snprintf (file_path, (str_len + 1), "/%s", file_name);
+ struct stat buffer;
+
+ assert (num_char > 0 && num_char == str_len);
+
+ if (stat (file_path, &buffer) == 0) {
+ MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments));
+ arg->kind = 0;
+ arg->runtimeconfig.name.path = file_path;
+ monovm_runtimeconfig_initialize (arg, cleanup_runtime_config, file_path);
+ } else {
+ free (file_path);
+ }
+
monovm_initialize (2, appctx_keys, appctx_values);
mini_parse_debug_option ("top-runtime-invoke-unhandled");
appctx_values[1] = bundle_path;
char *file_name = RUNTIMECONFIG_BIN_FILE;
- int str_len = strlen (bundle_path) + strlen (file_name) + 2;
- char *file_path = (char *)malloc (sizeof (char) * str_len);
- int num_char = snprintf (file_path, str_len, "%s/%s", bundle_path, file_name);
+ int str_len = strlen (bundle_path) + strlen (file_name) + 1; // +1 is for the "/"
+ char *file_path = (char *)malloc (sizeof (char) * (str_len +1)); // +1 is for the terminating null character
+ int num_char = snprintf (file_path, (str_len + 1), "%s/%s", bundle_path, file_name);
struct stat buffer;
LOG_INFO ("file_path: %s\n", file_path);
- assert (num_char > 0 && num_char < str_len);
+ assert (num_char > 0 && num_char == str_len);
if (stat (file_path, &buffer) == 0) {
MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments));
extraProperties: "<WasmBuildNative>true</WasmBuildNative>",
dotnetWasmFromRuntimePack: false);
+ [Theory]
+ [BuildAndRun]
+ public void PropertiesFromRuntimeConfigJson(BuildArgs buildArgs, RunHost host, string id)
+ {
+ buildArgs = buildArgs with { ProjectName = $"runtime_config_{buildArgs.Config}_{buildArgs.AOT}" };
+ buildArgs = ExpandBuildArgs(buildArgs);
+
+ string programText = @"
+ using System;
+ using System.Runtime.CompilerServices;
+
+ var config = AppContext.GetData(""test_runtimeconfig_json"");
+ Console.WriteLine ($""test_runtimeconfig_json: {(string)config}"");
+ return 42;
+ ";
+
+ string runtimeConfigTemplateJson = @"
+ {
+ ""configProperties"": {
+ ""abc"": ""4"",
+ ""test_runtimeconfig_json"": ""25""
+ }
+ }";
+
+ BuildProject(buildArgs,
+ initProject: () =>
+ {
+ File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText);
+ File.WriteAllText(Path.Combine(_projectDir!, "runtimeconfig.template.json"), runtimeConfigTemplateJson);
+ },
+ id: id,
+ dotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"));
+
+ RunAndTestWasmApp(buildArgs, expectedExitCode: 42,
+ test: output => Assert.Contains("test_runtimeconfig_json: 25", output), host: host, id: id);
+ }
+
+ [Theory]
+ [BuildAndRun]
+ public void PropertiesFromCsproj(BuildArgs buildArgs, RunHost host, string id)
+ {
+ buildArgs = buildArgs with { ProjectName = $"runtime_config_csproj_{buildArgs.Config}_{buildArgs.AOT}" };
+ buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "<ThreadPoolMaxThreads>20</ThreadPoolMaxThreads>");
+
+ string programText = @"
+ using System;
+ using System.Runtime.CompilerServices;
+
+ var config = AppContext.GetData(""System.Threading.ThreadPool.MaxThreads"");
+ Console.WriteLine ($""System.Threading.ThreadPool.MaxThreads: {(string)config}"");
+ return 42;
+ ";
+
+ BuildProject(buildArgs,
+ initProject: () =>
+ {
+ File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText);
+ },
+ id: id,
+ dotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"));
+
+ RunAndTestWasmApp(buildArgs, expectedExitCode: 42,
+ test: output => Assert.Contains("System.Threading.ThreadPool.MaxThreads: 20", output), host: host, id: id);
+ }
+
void TestMain(string projectName,
string programText,
BuildArgs buildArgs,
<WasmAppBuilderTasksAssemblyPath>$(CORE_ROOT)\WasmAppBuilder\WasmAppBuilder.dll</WasmAppBuilderTasksAssemblyPath>
<MonoAOTCompilerTasksAssemblyPath>$(CORE_ROOT)\MonoAOTCompiler\MonoAOTCompiler.dll</MonoAOTCompilerTasksAssemblyPath>
<JsonToItemsTaskFactoryTasksAssemblyPath>$(CORE_ROOT)\JsonToItemsTaskFactory\JsonToItemsTaskFactory.dll</JsonToItemsTaskFactoryTasksAssemblyPath>
+ <RuntimeConfigParserTasksAssemblyPath>$(CORE_ROOT)\RuntimeConfigParser\RuntimeConfigParser.dll</RuntimeConfigParserTasksAssemblyPath>
</PropertyGroup>
<Target Name="BuildApp" BeforeTargets="WasmBuildApp">
Include="$(ArtifactsBinDir)\JsonToItemsTaskFactory\Debug\$(NetCoreAppToolCurrent)\**"
TargetDir="JsonToItemsTaskFactory/"/>
+ <!-- RuntimeConfigParser always builds in Debug -->
+ <RunTimeDependencyCopyLocal
+ Include="$(ArtifactsBinDir)\RuntimeConfigParser\Debug\$(NetCoreAppToolCurrent)\**"
+ TargetDir="RuntimeConfigParser/"/>
+
<RunTimeDependencyCopyLocal
Include="$(RepoRoot)\src\tests\Common\wasm-test-runner\WasmTestRunner.proj"
TargetDir="wasm-test-runner/"/>
<RunAnalyzers>false</RunAnalyzers>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <IsTestProject>true</IsTestProject>
+ <IsTestProject Condition="'$(IsTestProject)' == ''">true</IsTestProject>
<IsFunctionalTest>true</IsFunctionalTest>
</PropertyGroup>
<TestRuntime>true</TestRuntime>
<DeltaScript>deltascript.json</DeltaScript>
<OutputType>library</OutputType>
- <IsTestProject>false</IsTestProject>
- <IsTestSupportProject>true</IsTestSupportProject>
<!-- to call AsssemblyExtensions.ApplyUpdate we need Optimize=false, EmitDebugInformation=true in all configurations -->
<Optimize>false</Optimize>
<EmitDebugInformation>true</EmitDebugInformation>
--- /dev/null
+<Project>
+ <PropertyGroup>
+ <IsTestProject>false</IsTestProject>
+ <IsTestSupportProject>true</IsTestSupportProject>
+ </PropertyGroup>
+ <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props, $(MSBuildThisFileDirectory)..))" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Sample
+{
+ public class Test
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine ("Hello, World!");
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static int TestMeaning()
+ {
+ var config = AppContext.GetData("test_runtimeconfig_json");
+ int result = ((string)config).Equals("25") ? 42 : 1;
+ return result;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TestRuntime>true</TestRuntime>
+ <Scenario>WasmTestOnBrowser</Scenario>
+ <ExpectedExitCode>42</ExpectedExitCode>
+ <WasmMainJSPath>runtime.js</WasmMainJSPath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ </ItemGroup>
+
+ <Target Name="AfterWasmBuildApp" AfterTargets="WasmBuildApp">
+ <Copy SourceFiles="$(MSBuildThisFileDirectory)\index.html" DestinationFolder="$(WasmAppDir)" />
+ </Target>
+
+</Project>
--- /dev/null
+<!DOCTYPE html>
+<!-- Licensed to the .NET Foundation under one or more agreements. -->
+<!-- The .NET Foundation licenses this file to you under the MIT license. -->
+<html>
+ <head>
+ <title>TESTS</title>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ </head>
+ <body onload="onLoad()">
+ <h3 id="header">Wasm Browser Sample</h3>
+ Result from Sample.Test.TestMeaning: <span id="out"></span>
+ <script type='text/javascript'>
+ var is_testing = false;
+ var onLoad = function() {
+ var url = new URL(decodeURI(window.location));
+ let args = url.searchParams.getAll('arg');
+ is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined);
+ };
+
+ var test_exit = function(exit_code)
+ {
+ if (!is_testing) {
+ console.log(`test_exit: ${exit_code}`);
+ return;
+ }
+
+ /* Set result in a tests_done element, to be read by xharness */
+ var tests_done_elem = document.createElement("label");
+ tests_done_elem.id = "tests_done";
+ tests_done_elem.innerHTML = exit_code.toString();
+ document.body.appendChild(tests_done_elem);
+
+ console.log(`WASM EXIT ${exit_code}`);
+ };
+
+ var App = {
+ init: function () {
+ var exit_code = BINDING.call_static_method("[WebAssembly.Browser.RuntimeConfig.Test] Sample.Test:TestMeaning", []);
+ document.getElementById("out").innerHTML = exit_code;
+
+ if (is_testing)
+ {
+ console.debug(`exit_code: ${exit_code}`);
+ test_exit(exit_code);
+ }
+ },
+ };
+ </script>
+ <script type="text/javascript" src="runtime.js"></script>
+
+ <script defer src="dotnet.js"></script>
+
+ </body>
+</html>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+var Module = {
+
+ config: null,
+
+ preInit: async function() {
+ await MONO.mono_wasm_load_config("./mono-config.json"); // sets Module.config implicitly
+ },
+
+ onRuntimeInitialized: function () {
+ if (!Module.config || Module.config.error) {
+ console.log("No config found");
+ test_exit(1);
+ throw(Module.config.error);
+ }
+
+ Module.config.loaded_cb = function () {
+ try {
+ App.init ();
+ } catch (error) {
+ test_exit(1);
+ throw (error);
+ }
+ };
+ Module.config.fetch_file_cb = function (asset) {
+ return fetch (asset, { credentials: 'same-origin' });
+ }
+
+ try
+ {
+ MONO.mono_load_runtime_and_bcl_args (Module.config);
+ } catch (error) {
+ test_exit(1);
+ throw(error);
+ }
+ },
+};
--- /dev/null
+{
+ "configProperties": {
+ "abc": "4",
+ "test_runtimeconfig_json": "25"
+ }
+}
\ No newline at end of file