diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets
index 5f7dcb8c43b47..f0a62d03a9d70 100644
--- a/eng/liveBuilds.targets
+++ b/eng/liveBuilds.targets
@@ -195,11 +195,13 @@
diff --git a/eng/testing/tests.browser.targets b/eng/testing/tests.browser.targets
index d3589821589fc..ab394db81c9bc 100644
--- a/eng/testing/tests.browser.targets
+++ b/eng/testing/tests.browser.targets
@@ -105,7 +105,7 @@
<_XHarnessArgs Condition="'$(IsFunctionalTest)' == 'true'" >$(_XHarnessArgs) --expected-exit-code=$(ExpectedExitCode)
<_XHarnessArgs Condition="'$(WasmXHarnessArgs)' != ''" >$(_XHarnessArgs) $(WasmXHarnessArgs)
<_XHarnessArgs Condition="('$(WasmEnableThreads)' == 'true' or '$(WasmEnablePerfTracing)' == 'true') and '$(_XHarnessArs.Contains("--web-server-use-cop")' != 'true'">$(_XHarnessArgs) --web-server-use-cop
- <_XHarnessArgs >$(_XHarnessArgs) -s dotnet.js.symbols
+ <_XHarnessArgs >$(_XHarnessArgs) -s dotnet.native.js.symbols
<_XHarnessArgs Condition="'$(_UseWasmSymbolicator)' == 'true'" >$(_XHarnessArgs) --symbol-patterns wasm-symbol-patterns.txt
<_XHarnessArgs Condition="'$(_UseWasmSymbolicator)' == 'true'" >$(_XHarnessArgs) --symbolicator WasmSymbolicator.dll,Microsoft.WebAssembly.Internal.SymbolicatorWrapperForXHarness
<_XHarnessArgs Condition="'$(_WasmBrowserPathForTests)' != ''" >$(_XHarnessArgs) "--browser-path=$(_WasmBrowserPathForTests)"
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
index 5760758d70ecb..14c9aa9b4213d 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
@@ -237,11 +237,13 @@
-
-
+
+
+
+
-
+
@@ -250,7 +252,6 @@
-
@@ -271,6 +272,7 @@
+
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/SecondRuntimeTest.js b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/SecondRuntimeTest.js
index 7abbf83d1f7cd..fa0b5d9f52eb8 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/SecondRuntimeTest.js
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/SecondRuntimeTest.js
@@ -1,6 +1,11 @@
export async function runSecondRuntimeAndTestStaticState() {
- const { dotnet: dotnet2 } = await import('./dotnet.js?2');
- const runtime2 = await dotnet2.create();
+ const { dotnet: dotnet2 } = await import('./dotnet.js?instance=2');
+ const runtime2 = await dotnet2
+ .withStartupMemoryCache(false)
+ .withConfig({
+ assetUniqueQuery: "?instance=2",
+ })
+ .create();
const increment1 = await getIncrementStateFunction(App.runtime);
const increment2 = await getIncrementStateFunction(runtime2);
diff --git a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets
index 47b4cf3206231..78f63db4c3ef6 100644
--- a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets
+++ b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets
@@ -189,7 +189,7 @@ Copyright (c) .NET Foundation. All rights reserved.
+ Condition="@(WasmNativeAsset->Count()) > 0 and ( '%(FileName)' == 'dotnet' or '%(FileName)' == 'dotnet.native' ) and ('%(Extension)' == '.wasm' or '%(Extension)' == '.js')" />
+ true
$(WasmNativeWorkload7)
$(WasmNativeWorkload8)
$(WasmNativeWorkload)
diff --git a/src/mono/sample/wasm/Directory.Build.targets b/src/mono/sample/wasm/Directory.Build.targets
index 7ff3c4d09a751..88aceecfaed96 100644
--- a/src/mono/sample/wasm/Directory.Build.targets
+++ b/src/mono/sample/wasm/Directory.Build.targets
@@ -31,7 +31,8 @@
$(TargetFileName)
"
Outputs="
- bin/$(Configuration)/AppBundle/dotnet.wasm;
+ bin/$(Configuration)/AppBundle/dotnet.native.wasm;
+ bin/$(Configuration)/AppBundle/dotnet.native.js;
bin/$(Configuration)/AppBundle/$(_WasmMainJSFileName);
">
diff --git a/src/mono/sample/wasm/browser-advanced/index.html b/src/mono/sample/wasm/browser-advanced/index.html
index 0532ef8fcef32..3489dafc9474a 100644
--- a/src/mono/sample/wasm/browser-advanced/index.html
+++ b/src/mono/sample/wasm/browser-advanced/index.html
@@ -10,7 +10,9 @@
-
+
+
+
diff --git a/src/mono/sample/wasm/browser-bench/appstart-frame.html b/src/mono/sample/wasm/browser-bench/appstart-frame.html
index 4a1945c9aad6d..fbb1c16284933 100644
--- a/src/mono/sample/wasm/browser-bench/appstart-frame.html
+++ b/src/mono/sample/wasm/browser-bench/appstart-frame.html
@@ -10,7 +10,9 @@
-
+
+
+
diff --git a/src/mono/sample/wasm/browser-webpack/Wasm.Browser.WebPack.Sample.csproj b/src/mono/sample/wasm/browser-webpack/Wasm.Browser.WebPack.Sample.csproj
index cc956fb3e9ef4..bb694f24f38f5 100644
--- a/src/mono/sample/wasm/browser-webpack/Wasm.Browser.WebPack.Sample.csproj
+++ b/src/mono/sample/wasm/browser-webpack/Wasm.Browser.WebPack.Sample.csproj
@@ -10,13 +10,17 @@
-
+
+
+
diff --git a/src/mono/sample/wasm/node-webpack/Wasm.Node.WebPack.Sample.csproj b/src/mono/sample/wasm/node-webpack/Wasm.Node.WebPack.Sample.csproj
index c8e021906c4e8..b10e78238aef4 100644
--- a/src/mono/sample/wasm/node-webpack/Wasm.Node.WebPack.Sample.csproj
+++ b/src/mono/sample/wasm/node-webpack/Wasm.Node.WebPack.Sample.csproj
@@ -5,13 +5,17 @@
-
+
+
+
diff --git a/src/mono/wasm/README.md b/src/mono/wasm/README.md
index cfeea4b099526..e266fe31f6917 100644
--- a/src/mono/wasm/README.md
+++ b/src/mono/wasm/README.md
@@ -133,13 +133,13 @@ The wrapper script used to actually run these tests, accepts:
Exceptions thrown after the runtime starts get symbolicating from js itself. Exceptions before that, like asserts containing native traces get symbolicated by xharness using `src/mono/wasm/symbolicator`.
-If you need to symbolicate some traces manually, then you need the corresponding `dotnet.js.symbols` file. Then:
+If you need to symbolicate some traces manually, then you need the corresponding `dotnet.native.js.symbols` file. Then:
```console
-src/mono/wasm/symbolicator$ dotnet run /path/to/dotnet.js.symbols /path/to/file/with/traces
+src/mono/wasm/symbolicator$ dotnet run /path/to/dotnet.native.js.symbols /path/to/file/with/traces
```
-When not relinking, or not building with AOT, you can find `dotnet.js.symbols` in the runtime pack.
+When not relinking, or not building with AOT, you can find `dotnet.native.js.symbols` in the runtime pack.
## Debugger tests on macOS
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
index 3e2c0b2175a0a..363635e434ba6 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
@@ -33,11 +33,11 @@ public void DefaultTemplate_WithoutWorkload(string config)
// Build
BlazorBuildInternal(id, config, publish: false);
- AssertBlazorBootJson(config, isPublish: false);
+ AssertBlazorBootJson(config, isPublish: false, isNet7AndBelow: false);
// Publish
BlazorBuildInternal(id, config, publish: true);
- AssertBlazorBootJson(config, isPublish: true);
+ AssertBlazorBootJson(config, isPublish: true, isNet7AndBelow: false);
}
[Theory]
diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests2.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests2.cs
index 1c8dd2a32206e..467a23597f777 100644
--- a/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests2.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/MiscTests2.cs
@@ -127,7 +127,7 @@ private void BuildNet50Project(string config, bool aot, bool expectError, string
Assert.Contains("** UsingBrowserRuntimeWorkload: 'false'", result.Output);
string binFrameworkDir = FindBlazorBinFrameworkDir(config, forPublish: true, framework: "net5.0");
- AssertBlazorBootJson(config, isPublish: true, binFrameworkDir: binFrameworkDir);
+ AssertBlazorBootJson(config, isPublish: true, isNet7AndBelow: true, binFrameworkDir: binFrameworkDir);
// dotnet.wasm here would be from 5.0 nuget like:
// /Users/radical/.nuget/packages/microsoft.netcore.app.runtime.browser-wasm/5.0.9/runtimes/browser-wasm/native/dotnet.wasm
}
diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
index 6dc3e5e525468..cea2456182e46 100644
--- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
@@ -621,22 +621,22 @@ protected void AssertDotNetNativeFiles(NativeFilesType type, string config, bool
_ => throw new ArgumentOutOfRangeException(nameof(type))
};
- AssertSameFile(Path.Combine(srcDir, "dotnet.wasm"), Path.Combine(binFrameworkDir, "dotnet.wasm"), label);
+ AssertSameFile(Path.Combine(srcDir, "dotnet.native.wasm"), Path.Combine(binFrameworkDir, "dotnet.native.wasm"), label);
// find dotnet*js
string? dotnetJsPath = Directory.EnumerateFiles(binFrameworkDir)
- .Where(p => Path.GetFileName(p).StartsWith("dotnet.", StringComparison.OrdinalIgnoreCase) &&
+ .Where(p => Path.GetFileName(p).StartsWith("dotnet.native", StringComparison.OrdinalIgnoreCase) &&
Path.GetFileName(p).EndsWith(".js", StringComparison.OrdinalIgnoreCase))
.SingleOrDefault();
- Assert.True(!string.IsNullOrEmpty(dotnetJsPath), $"[{label}] Expected to find dotnet*js in {binFrameworkDir}");
- AssertSameFile(Path.Combine(srcDir, "dotnet.js"), dotnetJsPath!, label);
+ Assert.True(!string.IsNullOrEmpty(dotnetJsPath), $"[{label}] Expected to find dotnet.native*js in {binFrameworkDir}");
+ AssertSameFile(Path.Combine(srcDir, "dotnet.native.js"), dotnetJsPath!, label);
if (type != NativeFilesType.FromRuntimePack)
{
// check that the files are *not* from runtime pack
- AssertNotSameFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.wasm"), Path.Combine(binFrameworkDir, "dotnet.wasm"), label);
- AssertNotSameFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.js"), dotnetJsPath!, label);
+ AssertNotSameFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.native.wasm"), Path.Combine(binFrameworkDir, "dotnet.native.wasm"), label);
+ AssertNotSameFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.native.js"), dotnetJsPath!, label);
}
}
@@ -667,9 +667,11 @@ protected static void AssertBasicAppBundle(string bundleDir,
var filesToExist = new List()
{
mainJS,
- "dotnet.wasm",
+ "dotnet.native.wasm",
"mono-config.json",
- "dotnet.js"
+ "dotnet.js",
+ "dotnet.native.js",
+ "dotnet.runtime.js"
};
if (isBrowserProject)
@@ -751,20 +753,20 @@ void AssertIcuAssets()
protected static void AssertDotNetWasmJs(string bundleDir, bool fromRuntimePack, string targetFramework)
{
- AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.wasm"),
- Path.Combine(bundleDir, "dotnet.wasm"),
- "Expected dotnet.wasm to be same as the runtime pack",
+ AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.native.wasm"),
+ Path.Combine(bundleDir, "dotnet.native.wasm"),
+ "Expected dotnet.native.wasm to be same as the runtime pack",
same: fromRuntimePack);
- AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.js"),
- Path.Combine(bundleDir, "dotnet.js"),
- "Expected dotnet.js to be same as the runtime pack",
+ AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.native.js"),
+ Path.Combine(bundleDir, "dotnet.native.js"),
+ "Expected dotnet.native.js to be same as the runtime pack",
same: fromRuntimePack);
}
protected static void AssertDotNetJsSymbols(string bundleDir, bool fromRuntimePack, string targetFramework)
- => AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.js.symbols"),
- Path.Combine(bundleDir, "dotnet.js.symbols"),
+ => AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.native.js.symbols"),
+ Path.Combine(bundleDir, "dotnet.native.js.symbols"),
same: fromRuntimePack);
protected static void AssertFilesDontExist(string dir, string[] filenames, string? label = null)
@@ -819,22 +821,22 @@ protected void AssertBlazorBundle(string config, bool isPublish, bool dotnetWasm
{
binFrameworkDir ??= FindBlazorBinFrameworkDir(config, isPublish, targetFramework);
- AssertBlazorBootJson(config, isPublish, targetFramework, binFrameworkDir: binFrameworkDir);
- AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.wasm"),
- Path.Combine(binFrameworkDir, "dotnet.wasm"),
- "Expected dotnet.wasm to be same as the runtime pack",
+ AssertBlazorBootJson(config, isPublish, targetFramework != DefaultTargetFrameworkForBlazor, targetFramework, binFrameworkDir: binFrameworkDir);
+ AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.native.wasm"),
+ Path.Combine(binFrameworkDir, "dotnet.native.wasm"),
+ "Expected dotnet.native.wasm to be same as the runtime pack",
same: dotnetWasmFromRuntimePack);
- string? dotnetJsPath = Directory.EnumerateFiles(binFrameworkDir, "dotnet.*.js").FirstOrDefault();
+ string? dotnetJsPath = Directory.EnumerateFiles(binFrameworkDir, "dotnet.native.*.js").FirstOrDefault();
Assert.True(dotnetJsPath != null, $"Could not find blazor's dotnet*js in {binFrameworkDir}");
- AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.js"),
+ AssertFile(Path.Combine(s_buildEnv.GetRuntimeNativeDir(targetFramework), "dotnet.native.js"),
dotnetJsPath!,
- "Expected dotnet.js to be same as the runtime pack",
+ "Expected dotnet.native.js to be same as the runtime pack",
same: dotnetWasmFromRuntimePack);
}
- protected void AssertBlazorBootJson(string config, bool isPublish, string targetFramework = DefaultTargetFrameworkForBlazor, string? binFrameworkDir=null)
+ protected void AssertBlazorBootJson(string config, bool isPublish, bool isNet7AndBelow, string targetFramework = DefaultTargetFrameworkForBlazor, string? binFrameworkDir=null)
{
binFrameworkDir ??= FindBlazorBinFrameworkDir(config, isPublish, targetFramework);
@@ -847,7 +849,7 @@ protected void AssertBlazorBootJson(string config, bool isPublish, string target
Assert.NotNull(runtimeObj);
string msgPrefix=$"[{( isPublish ? "publish" : "build" )}]";
- Assert.True(runtimeObj!.Where(kvp => kvp.Key == "dotnet.wasm").Any(), $"{msgPrefix} Could not find dotnet.wasm entry in blazor.boot.json");
+ Assert.True(runtimeObj!.Where(kvp => kvp.Key == (isNet7AndBelow ? "dotnet.wasm" : "dotnet.native.wasm")).Any(), $"{msgPrefix} Could not find dotnet.native.wasm entry in blazor.boot.json");
Assert.True(runtimeObj!.Where(kvp => kvp.Key.StartsWith("dotnet.", StringComparison.OrdinalIgnoreCase) &&
kvp.Key.EndsWith(".js", StringComparison.OrdinalIgnoreCase)).Any(),
$"{msgPrefix} Could not find dotnet.*js in {bootJson}");
diff --git a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/FlagsChangeRebuildTest.cs b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/FlagsChangeRebuildTest.cs
index ffbc0fd33c6b6..67e7e32aba68b 100644
--- a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/FlagsChangeRebuildTest.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/FlagsChangeRebuildTest.cs
@@ -36,7 +36,7 @@ public void ExtraEmccFlagsSetButNoRealChange(BuildArgs buildArgs, string extraCF
(buildArgs, BuildPaths paths) = FirstNativeBuild(s_mainReturns42, nativeRelink: true, invariant: false, buildArgs, id);
var pathsDict = GetFilesTable(buildArgs, paths, unchanged: true);
if (extraLDFlags.Length > 0)
- pathsDict.UpdateTo(unchanged: false, "dotnet.wasm", "dotnet.js");
+ pathsDict.UpdateTo(unchanged: false, "dotnet.native.wasm", "dotnet.native.js");
var originalStat = StatFiles(pathsDict.Select(kvp => kvp.Value.fullPath));
diff --git a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs
index aac389bde66bc..d31f9906593b3 100644
--- a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs
@@ -164,8 +164,8 @@ internal void CompareStat(IDictionary oldStat, IDictionary oldStat, IDictionary kvp.Value.fullPath));
diff --git a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/SimpleSourceChangeRebuildTest.cs b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/SimpleSourceChangeRebuildTest.cs
index bbe7d60221671..f2bfb33b7bd0c 100644
--- a/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/SimpleSourceChangeRebuildTest.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/NativeRebuildTests/SimpleSourceChangeRebuildTest.cs
@@ -28,7 +28,7 @@ public void SimpleStringChangeInSource(BuildArgs buildArgs, bool nativeRelink, b
string mainAssembly = $"{buildArgs.ProjectName}.dll";
var pathsDict = GetFilesTable(buildArgs, paths, unchanged: true);
pathsDict.UpdateTo(unchanged: false, mainAssembly);
- pathsDict.UpdateTo(unchanged: !buildArgs.AOT, "dotnet.wasm", "dotnet.js");
+ pathsDict.UpdateTo(unchanged: !buildArgs.AOT, "dotnet.native.wasm", "dotnet.native.js");
if (buildArgs.AOT)
pathsDict.UpdateTo(unchanged: false, $"{mainAssembly}.bc", $"{mainAssembly}.o");
diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs
index 2d9100b6832d5..ea57866fc86fa 100644
--- a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs
@@ -401,7 +401,7 @@ public void ConsolePublishAndRun(string config, bool aot, bool relinking)
}
else
{
- AssertFilesDontExist(Path.Combine(GetBinDir(config), "AppBundle"), new[] { "dotnet.js.symbols" });
+ AssertFilesDontExist(Path.Combine(GetBinDir(config), "AppBundle"), new[] { "dotnet.native.js.symbols" });
}
string runArgs = $"run --no-build -c {config}";
diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets
index d7afe274a1cb2..85b5e1858cb41 100644
--- a/src/mono/wasm/build/WasmApp.Native.targets
+++ b/src/mono/wasm/build/WasmApp.Native.targets
@@ -448,7 +448,7 @@
<_EmccLinkStepArgs Include=""%(_WasmNativeFileForLinking.Identity)"" />
<_WasmLinkDependencies Include="@(_WasmNativeFileForLinking)" />
- <_EmccLinkStepArgs Include="-o "$(_WasmIntermediateOutputPath)dotnet.js"" />
+ <_EmccLinkStepArgs Include="-o "$(_WasmIntermediateOutputPath)dotnet.native.js"" />
<_WasmLinkDependencies Include="$(_EmccLinkRsp)" />
<_EmccLinkStepArgs Include="-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$(_EmccExportedLibraryFunction)" Condition="'$(_EmccExportedLibraryFunction)' != ''" />
@@ -466,7 +466,7 @@
@@ -478,9 +478,9 @@
-
-
-
+
+
+
@@ -488,8 +488,8 @@
-
-
+
@@ -503,10 +503,10 @@
-
-
-
-
+
+
+
+
<_WasmAssembliesInternal Remove="$(_WasmDedupAssembly)"/>
diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets
index 0d50ada7ad3a2..94bd9fe54f9d8 100644
--- a/src/mono/wasm/build/WasmApp.targets
+++ b/src/mono/wasm/build/WasmApp.targets
@@ -22,7 +22,7 @@
- $(WasmNativeDebugSymbols) - Build with native debug symbols, useful only with `$(RunAOTCompilation)`, or `$(WasmBuildNative)`
Defaults to true.
- - $(WasmEmitSymbolMap) - Generates a `dotnet.js.symbols` file with a map of wasm function number to name.
+ - $(WasmEmitSymbolMap) - Generates a `dotnet.native.js.symbols` file with a map of wasm function number to name.
- $(WasmDedup) - Whenever to dedup generic instances when using AOT. Defaults to true.
- $(WasmProfilers) - Profilers to use
@@ -328,10 +328,10 @@
false
- <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.wasm'">true
- <_HasDotnetJsWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.worker.js'">true
- <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.js.symbols'">true
- <_HasDotnetJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.js'">true
+ <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.wasm'">true
+ <_HasDotnetJsWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.worker.js'">true
+ <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js.symbols'">true
+ <_HasDotnetNativeJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js'">true
<_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and Exists('$(WasmIcuDataFileName)')">$(WasmIcuDataFileName)
<_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and !Exists('$(WasmIcuDataFileName)')">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(WasmIcuDataFileName)
@@ -343,13 +343,15 @@
-
-
-
-
+
+
+
+
+
+ Exists('$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.native.js.symbols')" />
diff --git a/src/mono/wasm/runtime/CMakeLists.txt b/src/mono/wasm/runtime/CMakeLists.txt
index 1a39d1520c873..bb311e32b6e27 100644
--- a/src/mono/wasm/runtime/CMakeLists.txt
+++ b/src/mono/wasm/runtime/CMakeLists.txt
@@ -7,14 +7,14 @@ option(DISABLE_WASM_USER_THREADS "defined if the build does not allow user threa
option(DISABLE_LEGACY_JS_INTEROP "defined if the build does not support legacy JavaScript interop" OFF)
set(CMAKE_EXECUTABLE_SUFFIX ".js")
-add_executable(dotnet corebindings.c driver.c pinvoke.c)
+add_executable(dotnet.native corebindings.c driver.c pinvoke.c)
-target_include_directories(dotnet PUBLIC ${MONO_INCLUDES} ${MONO_OBJ_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/include/wasm)
-target_compile_options(dotnet PUBLIC @${NATIVE_BIN_DIR}/src/emcc-default.rsp @${NATIVE_BIN_DIR}/src/emcc-compile.rsp -DGEN_PINVOKE=1)
+target_include_directories(dotnet.native PUBLIC ${MONO_INCLUDES} ${MONO_OBJ_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/include/wasm)
+target_compile_options(dotnet.native PUBLIC @${NATIVE_BIN_DIR}/src/emcc-default.rsp @${NATIVE_BIN_DIR}/src/emcc-compile.rsp -DGEN_PINVOKE=1)
-set_target_properties(dotnet PROPERTIES COMPILE_FLAGS ${CONFIGURATION_EMCC_FLAGS})
+set_target_properties(dotnet.native PROPERTIES COMPILE_FLAGS ${CONFIGURATION_EMCC_FLAGS})
-target_link_libraries(dotnet
+target_link_libraries(dotnet.native
PRIVATE
${ICU_LIB_DIR}/libicuuc.a
${ICU_LIB_DIR}/libicui18n.a
@@ -33,9 +33,9 @@ target_link_libraries(dotnet
${NATIVE_BIN_DIR}/libSystem.Globalization.Native.a
${NATIVE_BIN_DIR}/libSystem.IO.Compression.Native.a)
-set_target_properties(dotnet PROPERTIES
- LINK_DEPENDS "${NATIVE_BIN_DIR}/src/emcc-default.rsp;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.pre.js;${NATIVE_BIN_DIR}/src/es6/runtime.es6.iffe.js;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.lib.js;${NATIVE_BIN_DIR}/src/pal_random.lib.js;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js;"
- LINK_FLAGS "@${NATIVE_BIN_DIR}/src/emcc-default.rsp @${NATIVE_BIN_DIR}/src/emcc-link.rsp ${CONFIGURATION_LINK_FLAGS} --extern-pre-js ${NATIVE_BIN_DIR}/src/es6/runtime.es6.iffe.js --pre-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.pre.js --js-library ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.lib.js --js-library ${NATIVE_BIN_DIR}/src/pal_random.lib.js --extern-post-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js "
+set_target_properties(dotnet.native PROPERTIES
+ LINK_DEPENDS "${NATIVE_BIN_DIR}/src/emcc-default.rsp;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.pre.js;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.lib.js;${NATIVE_BIN_DIR}/src/pal_random.lib.js;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js;"
+ LINK_FLAGS "@${NATIVE_BIN_DIR}/src/emcc-default.rsp @${NATIVE_BIN_DIR}/src/emcc-link.rsp ${CONFIGURATION_LINK_FLAGS} --pre-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.pre.js --js-library ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.lib.js --js-library ${NATIVE_BIN_DIR}/src/pal_random.lib.js --extern-post-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js "
RUNTIME_OUTPUT_DIRECTORY "${NATIVE_BIN_DIR}")
set(ignoreMeWasmOptFlags "${CONFIGURATION_WASM_OPT_FLAGS}")
@@ -43,9 +43,9 @@ set(ignoreMeWasmOptAdditionalFlags "${WASM_OPT_ADDITIONAL_FLAGS}")
set(ignoreMeEmsdkPath "${EMSDK_PATH}")
if(CMAKE_BUILD_TYPE STREQUAL "Release")
- add_custom_command(TARGET dotnet
- POST_BUILD COMMAND ${EMSDK_PATH}/upstream/bin/wasm-opt --enable-exception-handling ${CONFIGURATION_WASM_OPT_FLAGS} --strip-dwarf ${NATIVE_BIN_DIR}/dotnet.wasm -o ${NATIVE_BIN_DIR}/dotnet.wasm
- COMMENT "Stripping debug symbols from dotnet.wasm using wasm-opt")
+ add_custom_command(TARGET dotnet.native
+ POST_BUILD COMMAND ${EMSDK_PATH}/upstream/bin/wasm-opt --enable-exception-handling ${CONFIGURATION_WASM_OPT_FLAGS} --strip-dwarf ${NATIVE_BIN_DIR}/dotnet.native.wasm -o ${NATIVE_BIN_DIR}/dotnet.native.wasm
+ COMMENT "Stripping debug symbols from dotnet.native.wasm using wasm-opt")
endif()
configure_file(wasm-config.h.in include/wasm/wasm-config.h)
diff --git a/src/mono/wasm/runtime/assets.ts b/src/mono/wasm/runtime/assets.ts
index 37977538ed3a0..489f482716826 100644
--- a/src/mono/wasm/runtime/assets.ts
+++ b/src/mono/wasm/runtime/assets.ts
@@ -3,410 +3,16 @@
import cwraps from "./cwraps";
import { mono_wasm_load_icu_data } from "./icu";
-import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./globals";
+import { ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WEB, Module, loaderHelpers, runtimeHelpers } from "./globals";
import { parseSymbolMapFile } from "./logging";
import { mono_wasm_load_bytes_into_heap } from "./memory";
import { endMeasure, MeasuredBlock, startMeasure } from "./profiler";
-import { createPromiseController, PromiseAndController } from "./promise-controller";
-import { delay } from "./promise-utils";
-import { abort_startup, beforeOnRuntimeInitialized, memorySnapshotSkippedOrDone } from "./startup";
-import { AssetEntryInternal, mono_assert } from "./types";
-import { AssetBehaviours, AssetEntry, LoadingResource, ResourceRequest } from "./types-api";
+import { AssetEntryInternal } from "./types/internal";
+import { AssetEntry } from "./types";
import { InstantiateWasmSuccessCallback, VoidPtr } from "./types/emscripten";
-const allAssetsInMemory = createPromiseController();
-const allDownloadsQueued = createPromiseController();
-let actual_downloaded_assets_count = 0;
-let actual_instantiated_assets_count = 0;
-let expected_downloaded_assets_count = 0;
-let expected_instantiated_assets_count = 0;
-const loaded_files: { url: string, file: string }[] = [];
-// in order to prevent net::ERR_INSUFFICIENT_RESOURCES if we start downloading too many files at same time
-let parallel_count = 0;
-let throttlingPromise: PromiseAndController | undefined;
-
-// don't `fetch` javaScript files
-const skipDownloadsByAssetTypes: {
- [k: string]: boolean
-} = {
- "js-module-threads": true,
- "dotnetwasm": true,
-};
-
-// `response.arrayBuffer()` can't be called twice. Some usecases are calling it on response in the instantiation.
-const skipBufferByAssetTypes: {
- [k: string]: boolean
-} = {
- "dotnetwasm": true,
- "symbols": true,
-};
-
-const containedInSnapshotByAssetTypes: {
- [k: string]: boolean
-} = {
- "resource": true,
- "assembly": true,
- "pdb": true,
- "heap": true,
- "icu": true,
- "js-module-threads": true,
- "dotnetwasm": true,
-};
-
-
-// these assets are instantiated differently than the main flow
-const skipInstantiateByAssetTypes: {
- [k: string]: boolean
-} = {
- "js-module-threads": true,
- "dotnetwasm": true,
- "symbols": true,
-};
-
-export function shouldLoadIcuAsset(asset: AssetEntryInternal): boolean {
- return !(asset.behavior == "icu" && asset.name != runtimeHelpers.preferredIcuAsset);
-}
-
-export function resolve_asset_path(behavior: AssetBehaviours) {
- const asset: AssetEntryInternal | undefined = runtimeHelpers.config.assets?.find(a => a.behavior == behavior);
- mono_assert(asset, () => `Can't find asset for ${behavior}`);
- if (!asset.resolvedUrl) {
- asset.resolvedUrl = resolve_path(asset, "");
- }
- return asset;
-}
-export async function mono_download_assets(): Promise {
- if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_download_assets");
- runtimeHelpers.maxParallelDownloads = runtimeHelpers.config.maxParallelDownloads || runtimeHelpers.maxParallelDownloads;
- runtimeHelpers.enableDownloadRetry = runtimeHelpers.config.enableDownloadRetry || runtimeHelpers.enableDownloadRetry;
- try {
- const alwaysLoadedAssets: AssetEntryInternal[] = [];
- const containedInSnapshotAssets: AssetEntryInternal[] = [];
- const promises_of_assets: Promise[] = [];
-
- for (const a of runtimeHelpers.config.assets!) {
- const asset: AssetEntryInternal = a;
- mono_assert(typeof asset === "object", "asset must be object");
- mono_assert(typeof asset.behavior === "string", "asset behavior must be known string");
- mono_assert(typeof asset.name === "string", "asset name must be string");
- mono_assert(!asset.resolvedUrl || typeof asset.resolvedUrl === "string", "asset resolvedUrl could be string");
- mono_assert(!asset.hash || typeof asset.hash === "string", "asset resolvedUrl could be string");
- mono_assert(!asset.pendingDownload || typeof asset.pendingDownload === "object", "asset pendingDownload could be object");
- if (containedInSnapshotByAssetTypes[asset.behavior]) {
- containedInSnapshotAssets.push(asset);
- } else {
- alwaysLoadedAssets.push(asset);
- }
- }
-
- const countAndStartDownload = (asset: AssetEntryInternal) => {
- if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
- expected_instantiated_assets_count++;
- }
- if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
- expected_downloaded_assets_count++;
- promises_of_assets.push(start_asset_download(asset));
- }
- };
-
- // start fetching assets in parallel, only assets which are not part of memory snapshot
- for (const asset of alwaysLoadedAssets) {
- countAndStartDownload(asset);
- }
-
- // continue after we know if memory snapshot is available or not
- await memorySnapshotSkippedOrDone.promise;
-
- // start fetching assets in parallel, only if memory snapshot is not available.
- for (const asset of containedInSnapshotAssets) {
- if (!runtimeHelpers.loadedMemorySnapshot) {
- countAndStartDownload(asset);
- } else {
- // Otherwise cleanup in case we were given pending download. It would be even better if we could abort the download.
- cleanupAsset(asset);
- // tell the debugger it is loaded
- if (asset.behavior == "resource" || asset.behavior == "assembly" || asset.behavior == "pdb") {
- const url = resolve_path(asset, "");
- const virtualName: string = typeof (asset.virtualPath) === "string"
- ? asset.virtualPath
- : asset.name;
- loaded_files.push({ url: url, file: virtualName });
- }
- }
- }
-
- allDownloadsQueued.promise_control.resolve();
-
- const promises_of_asset_instantiation: Promise[] = [];
- for (const downloadPromise of promises_of_assets) {
- promises_of_asset_instantiation.push((async () => {
- const asset = await downloadPromise;
- if (asset.buffer) {
- if (!skipInstantiateByAssetTypes[asset.behavior]) {
- const url = asset.pendingDownloadInternal!.url;
- mono_assert(asset.buffer && typeof asset.buffer === "object", "asset buffer must be array or buffer like");
- const data = new Uint8Array(asset.buffer!);
- cleanupAsset(asset);
-
- // wait till after onRuntimeInitialized and after memory snapshot is loaded or skipped
- await memorySnapshotSkippedOrDone.promise;
- await beforeOnRuntimeInitialized.promise;
- _instantiate_asset(asset, url, data);
- }
- if (asset.behavior === "symbols") {
- await instantiate_symbols_asset(asset);
- cleanupAsset(asset);
- }
- } else {
- const headersOnly = skipBufferByAssetTypes[asset.behavior];
- if (!headersOnly) {
- mono_assert(asset.isOptional, "Expected asset to have the downloaded buffer");
- if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
- expected_downloaded_assets_count--;
- }
- if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
- expected_instantiated_assets_count--;
- }
- } else {
- if (skipBufferByAssetTypes[asset.behavior]) {
- ++actual_downloaded_assets_count;
- }
- }
- }
- })());
- }
-
- // this await will get past the onRuntimeInitialized because we are not blocking via addRunDependency
- // and we are not awating it here
- Promise.all(promises_of_asset_instantiation).then(() => {
- allAssetsInMemory.promise_control.resolve();
- }).catch(e => {
- Module.err("MONO_WASM: Error in mono_download_assets: " + e);
- abort_startup(e, true);
- });
- // OPTIMIZATION explained:
- // we do it this way so that we could allocate memory immediately after asset is downloaded (and after onRuntimeInitialized which happened already)
- // spreading in time
- // rather than to block all downloads after onRuntimeInitialized or block onRuntimeInitialized after all downloads are done. That would create allocation burst.
- } catch (e: any) {
- Module.err("MONO_WASM: Error in mono_download_assets: " + e);
- throw e;
- }
-}
-
-// FIXME: Connection reset is probably the only good one for which we should retry
-export async function start_asset_download(asset: AssetEntryInternal): Promise {
- try {
- return await start_asset_download_with_throttle(asset);
- } catch (err: any) {
- if (!runtimeHelpers.enableDownloadRetry) {
- // we will not re-try if disabled
- throw err;
- }
- if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) {
- // we will not re-try on shell
- throw err;
- }
- if (asset.pendingDownload && asset.pendingDownloadInternal == asset.pendingDownload) {
- // we will not re-try with external source
- throw err;
- }
- if (asset.resolvedUrl && asset.resolvedUrl.indexOf("file://") != -1) {
- // we will not re-try with local file
- throw err;
- }
- if (err && err.status == 404) {
- // we will not re-try with 404
- throw err;
- }
- asset.pendingDownloadInternal = undefined;
- // second attempt only after all first attempts are queued
- await allDownloadsQueued.promise;
- try {
- return await start_asset_download_with_throttle(asset);
- } catch (err) {
- asset.pendingDownloadInternal = undefined;
- // third attempt after small delay
- await delay(100);
- return await start_asset_download_with_throttle(asset);
- }
- }
-}
-
-async function start_asset_download_with_throttle(asset: AssetEntryInternal): Promise {
- // we don't addRunDependency to allow download in parallel with onRuntimeInitialized event!
- while (throttlingPromise) {
- await throttlingPromise.promise;
- }
- try {
- ++parallel_count;
- if (parallel_count == runtimeHelpers.maxParallelDownloads) {
- if (runtimeHelpers.diagnosticTracing)
- console.debug("MONO_WASM: Throttling further parallel downloads");
- throttlingPromise = createPromiseController();
- }
-
- const response = await start_asset_download_sources(asset);
- if (!response) {
- return asset;
- }
- const skipBuffer = skipBufferByAssetTypes[asset.behavior];
- if (skipBuffer) {
- return asset;
- }
- asset.buffer = await response.arrayBuffer();
- ++actual_downloaded_assets_count;
- return asset;
- }
- finally {
- --parallel_count;
- if (throttlingPromise && parallel_count == runtimeHelpers.maxParallelDownloads - 1) {
- if (runtimeHelpers.diagnosticTracing)
- console.debug("MONO_WASM: Resuming more parallel downloads");
- const old_throttling = throttlingPromise;
- throttlingPromise = undefined;
- old_throttling.promise_control.resolve();
- }
- }
-}
-
-async function start_asset_download_sources(asset: AssetEntryInternal): Promise {
- // we don't addRunDependency to allow download in parallel with onRuntimeInitialized event!
- if (asset.pendingDownload) {
- asset.pendingDownloadInternal = asset.pendingDownload;
- }
- if (asset.pendingDownloadInternal && asset.pendingDownloadInternal.response) {
- return asset.pendingDownloadInternal.response;
- }
- if (asset.buffer) {
- const buffer = asset.buffer;
- asset.buffer = null as any; // GC
- asset.pendingDownloadInternal = {
- url: "undefined://" + asset.name,
- name: asset.name,
- response: Promise.resolve({
- arrayBuffer: () => buffer,
- headers: {
- get: () => undefined,
- }
- }) as any
- };
- return asset.pendingDownloadInternal.response;
- }
-
- const sourcesList = asset.loadRemote && runtimeHelpers.config.remoteSources ? runtimeHelpers.config.remoteSources : [""];
- let response: Response | undefined = undefined;
- for (let sourcePrefix of sourcesList) {
- sourcePrefix = sourcePrefix.trim();
- // HACK: Special-case because MSBuild doesn't allow "" as an attribute
- if (sourcePrefix === "./")
- sourcePrefix = "";
-
- const attemptUrl = resolve_path(asset, sourcePrefix);
- if (asset.name === attemptUrl) {
- if (runtimeHelpers.diagnosticTracing)
- console.debug(`MONO_WASM: Attempting to download '${attemptUrl}'`);
- } else {
- if (runtimeHelpers.diagnosticTracing)
- console.debug(`MONO_WASM: Attempting to download '${attemptUrl}' for ${asset.name}`);
- }
- try {
- asset.resolvedUrl = attemptUrl;
- const loadingResource = download_resource(asset);
- asset.pendingDownloadInternal = loadingResource;
- response = await loadingResource.response;
- if (!response || !response.ok) {
- continue;// next source
- }
- return response;
- }
- catch (err) {
- if (!response) {
- response = {
- ok: false,
- url: attemptUrl,
- status: 0,
- statusText: "" + err,
- } as any;
- }
- continue; //next source
- }
- }
- const isOkToFail = asset.isOptional || (asset.name.match(/\.pdb$/) && runtimeHelpers.config.ignorePdbLoadErrors);
- mono_assert(response, () => `Response undefined ${asset.name}`);
- if (!isOkToFail) {
- const err: any = new Error(`MONO_WASM: download '${response.url}' for ${asset.name} failed ${response.status} ${response.statusText}`);
- err.status = response.status;
- throw err;
- } else {
- Module.out(`MONO_WASM: optional download '${response.url}' for ${asset.name} failed ${response.status} ${response.statusText}`);
- return undefined;
- }
-}
-
-function resolve_path(asset: AssetEntry, sourcePrefix: string): string {
- mono_assert(sourcePrefix !== null && sourcePrefix !== undefined, () => `sourcePrefix must be provided for ${asset.name}`);
- let attemptUrl;
- const assemblyRootFolder = runtimeHelpers.config.assemblyRootFolder;
- if (!asset.resolvedUrl) {
- if (sourcePrefix === "") {
- if (asset.behavior === "assembly" || asset.behavior === "pdb") {
- attemptUrl = assemblyRootFolder
- ? (assemblyRootFolder + "/" + asset.name)
- : asset.name;
- }
- else if (asset.behavior === "resource") {
- const path = asset.culture && asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
- attemptUrl = assemblyRootFolder
- ? (assemblyRootFolder + "/" + path)
- : path;
- }
- else {
- attemptUrl = asset.name;
- }
- } else {
- attemptUrl = sourcePrefix + asset.name;
- }
- attemptUrl = runtimeHelpers.locateFile(attemptUrl);
- }
- else {
- attemptUrl = asset.resolvedUrl;
- }
- mono_assert(attemptUrl && typeof attemptUrl == "string", "attemptUrl need to be path or url string");
- return attemptUrl;
-}
-
-function download_resource(request: ResourceRequest): LoadingResource {
- try {
- if (typeof Module.downloadResource === "function") {
- const loading = Module.downloadResource(request);
- if (loading) return loading;
- }
- const options: any = {};
- if (request.hash) {
- options.integrity = request.hash;
- }
- const response = runtimeHelpers.fetch_like(request.resolvedUrl!, options);
- return {
- name: request.name, url: request.resolvedUrl!, response
- };
- } catch (err) {
- const response = {
- ok: false,
- url: request.resolvedUrl,
- status: 500,
- statusText: "ERR29: " + err,
- arrayBuffer: () => { throw err; },
- json: () => { throw err; }
- };
- return {
- name: request.name, url: request.resolvedUrl!, response: Promise.resolve(response)
- };
- }
-}
-
// this need to be run only after onRuntimeInitialized event, when the memory is ready
-function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) {
+export function instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array): void {
if (runtimeHelpers.diagnosticTracing)
console.debug(`MONO_WASM: Loaded:${asset.name} as ${asset.behavior} size ${bytes.length} from ${url}`);
const mark = startMeasure();
@@ -425,7 +31,7 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) {
case "resource":
case "assembly":
case "pdb":
- loaded_files.push({ url: url, file: virtualName });
+ loaderHelpers._loaded_files.push({ url: url, file: virtualName });
// falls through
case "heap":
case "icu":
@@ -475,8 +81,8 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) {
const hasPpdb = cwraps.mono_wasm_add_assembly(virtualName, offset!, bytes.length);
if (!hasPpdb) {
- const index = loaded_files.findIndex(element => element.file == virtualName);
- loaded_files.splice(index, 1);
+ const index = loaderHelpers._loaded_files.findIndex(element => element.file == virtualName);
+ loaderHelpers._loaded_files.splice(index, 1);
}
}
else if (asset.behavior === "pdb") {
@@ -490,7 +96,7 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) {
cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture || "", offset!, bytes.length);
}
endMeasure(mark, MeasuredBlock.instantiateAsset, asset.name);
- ++actual_instantiated_assets_count;
+ ++loaderHelpers.actual_instantiated_assets_count;
}
export async function instantiate_wasm_asset(
@@ -498,7 +104,7 @@ export async function instantiate_wasm_asset(
wasmModuleImports: WebAssembly.Imports,
successCallback: InstantiateWasmSuccessCallback,
): Promise {
- mono_assert(pendingAsset && pendingAsset.pendingDownloadInternal && pendingAsset.pendingDownloadInternal.response, "Can't load dotnet.wasm");
+ mono_assert(pendingAsset && pendingAsset.pendingDownloadInternal && pendingAsset.pendingDownloadInternal.response, "Can't load dotnet.native.wasm");
const response = await pendingAsset.pendingDownloadInternal.response;
const contentType = response.headers && response.headers.get ? response.headers.get("Content-Type") : undefined;
let compiledInstance: WebAssembly.Instance;
@@ -527,9 +133,7 @@ export async function instantiate_wasm_asset(
successCallback(compiledInstance, compiledModule);
}
-export async function instantiate_symbols_asset(
- pendingAsset: AssetEntryInternal,
-): Promise {
+export async function instantiate_symbols_asset(pendingAsset: AssetEntryInternal): Promise {
try {
const response = await pendingAsset.pendingDownloadInternal!.response;
const text = await response.text();
@@ -590,23 +194,16 @@ export function mono_wasm_load_data_archive(data: Uint8Array, prefix: string): b
export async function wait_for_all_assets() {
// wait for all assets in memory
- await allAssetsInMemory.promise;
+ await runtimeHelpers.allAssetsInMemory.promise;
if (runtimeHelpers.config.assets) {
- mono_assert(actual_downloaded_assets_count == expected_downloaded_assets_count, () => `Expected ${expected_downloaded_assets_count} assets to be downloaded, but only finished ${actual_downloaded_assets_count}`);
- mono_assert(actual_instantiated_assets_count == expected_instantiated_assets_count, () => `Expected ${expected_instantiated_assets_count} assets to be in memory, but only instantiated ${actual_instantiated_assets_count}`);
- loaded_files.forEach(value => runtimeHelpers.loadedFiles.push(value.url));
+ mono_assert(loaderHelpers.actual_downloaded_assets_count == loaderHelpers.expected_downloaded_assets_count, () => `Expected ${loaderHelpers.expected_downloaded_assets_count} assets to be downloaded, but only finished ${loaderHelpers.actual_downloaded_assets_count}`);
+ mono_assert(loaderHelpers.actual_instantiated_assets_count == loaderHelpers.expected_instantiated_assets_count, () => `Expected ${loaderHelpers.expected_instantiated_assets_count} assets to be in memory, but only instantiated ${loaderHelpers.actual_instantiated_assets_count}`);
+ loaderHelpers._loaded_files.forEach(value => loaderHelpers.loadedFiles.push(value.url));
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: all assets are loaded in wasm memory");
}
}
// Used by the debugger to enumerate loaded dlls and pdbs
export function mono_wasm_get_loaded_files(): string[] {
- return runtimeHelpers.loadedFiles;
-}
-
-export function cleanupAsset(asset: AssetEntryInternal) {
- // give GC chance to collect resources
- asset.pendingDownloadInternal = null as any; // GC
- asset.pendingDownload = null as any; // GC
- asset.buffer = null as any; // GC
+ return loaderHelpers.loadedFiles;
}
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/cancelable-promise.ts b/src/mono/wasm/runtime/cancelable-promise.ts
index b50e0b0040b69..1f696a1f31543 100644
--- a/src/mono/wasm/runtime/cancelable-promise.ts
+++ b/src/mono/wasm/runtime/cancelable-promise.ts
@@ -2,9 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { _lookup_js_owned_object } from "./gc-handles";
+import { createPromiseController, loaderHelpers } from "./globals";
import { TaskCallbackHolder } from "./marshal-to-cs";
-import { mono_assert, GCHandle } from "./types";
-import { createPromiseController, getPromiseController, ControllablePromise, assertIsControllablePromise } from "./promise-controller";
+import { ControllablePromise, GCHandle } from "./types/internal";
export const _are_promises_supported = ((typeof Promise === "object") || (typeof Promise === "function")) && (typeof Promise.resolve === "function");
@@ -29,8 +29,8 @@ export function mono_wasm_cancel_promise(task_holder_gc_handle: GCHandle): void
const promise = holder.promise;
mono_assert(!!promise, () => `Expected Promise for GCHandle ${task_holder_gc_handle}`);
- assertIsControllablePromise(promise);
- const promise_control = getPromiseController(promise);
+ loaderHelpers.assertIsControllablePromise(promise);
+ const promise_control = loaderHelpers.getPromiseController(promise);
promise_control.reject("OperationCanceledException");
}
diff --git a/src/mono/wasm/runtime/class-loader.ts b/src/mono/wasm/runtime/class-loader.ts
index 378b619428a87..892aa7bf02450 100644
--- a/src/mono/wasm/runtime/class-loader.ts
+++ b/src/mono/wasm/runtime/class-loader.ts
@@ -1,4 +1,4 @@
-import { MonoAssembly, MonoClass, MonoType, MonoTypeNull, MonoAssemblyNull } from "./types";
+import { MonoAssembly, MonoClass, MonoType, MonoTypeNull, MonoAssemblyNull } from "./types/internal";
import cwraps from "./cwraps";
const _assembly_cache_by_name = new Map();
@@ -38,40 +38,40 @@ function _set_cached_class(assembly: MonoAssembly, namespace: string, name: stri
classes.set(name, ptr);
}
-export function find_corlib_class(namespace: string, name: string, throw_on_failure?: boolean | undefined): MonoClass {
+export function find_corlib_class(namespace: string, name: string): MonoClass {
if (!_corlib)
_corlib = cwraps.mono_wasm_get_corlib();
let result = _find_cached_class(_corlib, namespace, name);
if (result !== undefined)
return result;
result = cwraps.mono_wasm_assembly_find_class(_corlib, namespace, name);
- if (throw_on_failure && !result)
+ if (!result)
throw new Error(`Failed to find corlib class ${namespace}.${name}`);
- _set_cached_class(_corlib, namespace, name, result);
+ _set_cached_class(_corlib, namespace, name, result!);
return result;
}
-export function find_class_in_assembly(assembly_name: string, namespace: string, name: string, throw_on_failure?: boolean | undefined): MonoClass {
+export function find_class_in_assembly(assembly_name: string, namespace: string, name: string): MonoClass {
const assembly = assembly_load(assembly_name);
let result = _find_cached_class(assembly, namespace, name);
if (result !== undefined)
return result;
result = cwraps.mono_wasm_assembly_find_class(assembly, namespace, name);
- if (throw_on_failure && !result)
+ if (!result)
throw new Error(`Failed to find class ${namespace}.${name} in ${assembly_name}`);
- _set_cached_class(assembly, namespace, name, result);
+ _set_cached_class(assembly, namespace, name, result!);
return result;
}
-export function find_corlib_type(namespace: string, name: string, throw_on_failure?: boolean | undefined): MonoType {
- const classPtr = find_corlib_class(namespace, name, throw_on_failure);
+export function find_corlib_type(namespace: string, name: string): MonoType {
+ const classPtr = find_corlib_class(namespace, name);
if (!classPtr)
return MonoTypeNull;
return cwraps.mono_wasm_class_get_type(classPtr);
}
-export function find_type_in_assembly(assembly_name: string, namespace: string, name: string, throw_on_failure?: boolean | undefined): MonoType {
- const classPtr = find_class_in_assembly(assembly_name, namespace, name, throw_on_failure);
+export function find_type_in_assembly(assembly_name: string, namespace: string, name: string): MonoType {
+ const classPtr = find_class_in_assembly(assembly_name, namespace, name);
if (!classPtr)
return MonoTypeNull;
return cwraps.mono_wasm_class_get_type(classPtr);
diff --git a/src/mono/wasm/runtime/config.ts b/src/mono/wasm/runtime/config.ts
deleted file mode 100644
index 34e92f032cbaa..0000000000000
--- a/src/mono/wasm/runtime/config.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { DotnetModuleInternal, MonoConfigInternal } from "./types";
-import { DotnetModuleConfig } from "./types-api";
-
-export function deep_merge_config(target: MonoConfigInternal, source: MonoConfigInternal): MonoConfigInternal {
- const providedConfig: MonoConfigInternal = { ...source };
- if (providedConfig.assets) {
- providedConfig.assets = [...(target.assets || []), ...(providedConfig.assets || [])];
- }
- if (providedConfig.environmentVariables) {
- providedConfig.environmentVariables = { ...(target.environmentVariables || {}), ...(providedConfig.environmentVariables || {}) };
- }
- if (providedConfig.startupOptions) {
- providedConfig.startupOptions = { ...(target.startupOptions || {}), ...(providedConfig.startupOptions || {}) };
- }
- if (providedConfig.runtimeOptions) {
- providedConfig.runtimeOptions = [...(target.runtimeOptions || []), ...(providedConfig.runtimeOptions || [])];
- }
- return Object.assign(target, providedConfig);
-}
-
-export function deep_merge_module(target: DotnetModuleInternal, source: DotnetModuleConfig): DotnetModuleInternal {
- const providedConfig: DotnetModuleConfig = { ...source };
- if (providedConfig.config) {
- if (!target.config) target.config = {};
- providedConfig.config = deep_merge_config(target.config, providedConfig.config);
- }
- return Object.assign(target, providedConfig);
-}
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/cwraps.ts b/src/mono/wasm/runtime/cwraps.ts
index 9540663fbd459..225cdef57e293 100644
--- a/src/mono/wasm/runtime/cwraps.ts
+++ b/src/mono/wasm/runtime/cwraps.ts
@@ -5,7 +5,7 @@ import type {
MonoArray, MonoAssembly, MonoClass,
MonoMethod, MonoObject, MonoString,
MonoType, MonoObjectRef, MonoStringRef, JSMarshalerArguments
-} from "./types";
+} from "./types/internal";
import type { VoidPtr, CharPtrPtr, Int32Ptr, CharPtr, ManagedPointer } from "./types/emscripten";
import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop";
import { disableLegacyJsInterop, Module } from "./globals";
diff --git a/src/mono/wasm/runtime/diagnostics-mock.d.ts b/src/mono/wasm/runtime/diagnostics-mock.d.ts
index b7153249ebc4d..59686e8797399 100644
--- a/src/mono/wasm/runtime/diagnostics-mock.d.ts
+++ b/src/mono/wasm/runtime/diagnostics-mock.d.ts
@@ -5,7 +5,6 @@
//! This is not considered public API with backward compatibility guarantees.
-declare const promise_control_symbol: unique symbol;
interface PromiseController {
isDone: boolean;
readonly promise: Promise;
@@ -13,7 +12,7 @@ interface PromiseController {
reject: (reason?: any) => void;
}
interface ControllablePromise extends Promise {
- [promise_control_symbol]: PromiseController;
+ __brand: "ControllablePromise";
}
interface PromiseAndController {
promise: ControllablePromise;
diff --git a/src/mono/wasm/runtime/diagnostics-mock.d.ts.sha256 b/src/mono/wasm/runtime/diagnostics-mock.d.ts.sha256
index 1b6e1a2ae0e54..0cfcc26b86906 100644
--- a/src/mono/wasm/runtime/diagnostics-mock.d.ts.sha256
+++ b/src/mono/wasm/runtime/diagnostics-mock.d.ts.sha256
@@ -1 +1 @@
-90231971bda6e6a32b2c5239c60176b9126469d29478f572b8a15ab7476cd791
\ No newline at end of file
+6d0ff454946223f77abe8e6c1e377489c33b2914da86120f6b2952b739ebec20
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/diagnostics/index.ts b/src/mono/wasm/runtime/diagnostics/index.ts
index 4987795e00167..2dea3bf0f2e08 100644
--- a/src/mono/wasm/runtime/diagnostics/index.ts
+++ b/src/mono/wasm/runtime/diagnostics/index.ts
@@ -5,7 +5,7 @@ import monoWasmThreads from "consts:monoWasmThreads";
import type {
DiagnosticOptions,
} from "./shared/types";
-import { is_nullish } from "../types";
+import { is_nullish } from "../types/internal";
import type { VoidPtr } from "../types/emscripten";
import { getController, startDiagnosticServer } from "./browser/controller";
import * as memory from "../memory";
diff --git a/src/mono/wasm/runtime/diagnostics/mock/environment.ts b/src/mono/wasm/runtime/diagnostics/mock/environment.ts
index c0508ca833537..d3d4822aacf69 100644
--- a/src/mono/wasm/runtime/diagnostics/mock/environment.ts
+++ b/src/mono/wasm/runtime/diagnostics/mock/environment.ts
@@ -1,14 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { createPromiseController } from "../../promise-controller";
import type { RemoveCommandSetAndId, EventPipeCommandCollectTracing2, EventPipeCommandStopTracing } from "../server_pthread/protocol-client-commands";
import type { FilterPredicate, MockEnvironment } from "./types";
import Serializer from "../server_pthread/ipc-protocol/base-serializer";
import { CommandSetId, EventPipeCommandId, ProcessCommandId } from "../server_pthread/ipc-protocol/types";
-import { assertNever, mono_assert } from "../../types";
-import { delay } from "../../promise-utils";
+import { assertNever } from "../../types/internal";
import { pthread_self } from "../../pthreads/worker";
+import { createPromiseController } from "../../globals";
function expectAdvertise(data: ArrayBuffer): boolean {
@@ -133,7 +132,7 @@ export function createMockEnvironment(): MockEnvironment {
postMessageToBrowser,
addEventListenerFromBrowser,
createPromiseController,
- delay,
+ delay: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)),
command,
reply,
expectAdvertise
diff --git a/src/mono/wasm/runtime/diagnostics/mock/export-types.ts b/src/mono/wasm/runtime/diagnostics/mock/export-types.ts
index 1117fccb5c373..6628e0c51953a 100644
--- a/src/mono/wasm/runtime/diagnostics/mock/export-types.ts
+++ b/src/mono/wasm/runtime/diagnostics/mock/export-types.ts
@@ -8,4 +8,4 @@ export type {
export type {
PromiseAndController,
-} from "../../promise-controller";
+} from "../../types/internal";
diff --git a/src/mono/wasm/runtime/diagnostics/mock/index.ts b/src/mono/wasm/runtime/diagnostics/mock/index.ts
index 38f418613967e..30d08017ebb6f 100644
--- a/src/mono/wasm/runtime/diagnostics/mock/index.ts
+++ b/src/mono/wasm/runtime/diagnostics/mock/index.ts
@@ -5,7 +5,7 @@ import monoDiagnosticsMock from "consts:monoDiagnosticsMock";
import { createMockEnvironment } from "./environment";
import type { MockEnvironment, MockScriptConnection } from "./export-types";
-import { assertNever } from "../../types";
+import { assertNever } from "../../types/internal";
export interface MockRemoteSocket extends EventTarget {
addEventListener(type: T, listener: (this: MockRemoteSocket, ev: WebSocketEventMap[T]) => any, options?: boolean | AddEventListenerOptions): void;
diff --git a/src/mono/wasm/runtime/diagnostics/mock/types.ts b/src/mono/wasm/runtime/diagnostics/mock/types.ts
index 92f8fe4b017de..30c533595413c 100644
--- a/src/mono/wasm/runtime/diagnostics/mock/types.ts
+++ b/src/mono/wasm/runtime/diagnostics/mock/types.ts
@@ -1,6 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import type { PromiseAndController } from "../../promise-controller";
+import type { PromiseAndController } from "../../types/internal";
import type {
RemoveCommandSetAndId,
EventPipeCommandCollectTracing2,
diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/index.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/index.ts
index 9d55897033a65..6180834a90650 100644
--- a/src/mono/wasm/runtime/diagnostics/server_pthread/index.ts
+++ b/src/mono/wasm/runtime/diagnostics/server_pthread/index.ts
@@ -4,9 +4,9 @@
///
import monoDiagnosticsMock from "consts:monoDiagnosticsMock";
-import { assertNever } from "../../types";
+import { PromiseAndController, assertNever } from "../../types/internal";
import { pthread_self } from "../../pthreads/worker";
-import { Module } from "../../globals";
+import { Module, createPromiseController } from "../../globals";
import cwraps from "../../cwraps";
import { EventPipeSessionIDImpl } from "../shared/types";
import { CharPtr } from "../../types/emscripten";
@@ -17,7 +17,6 @@ import {
import { importAndInstantiateMock } from "./mock-remote";
import type { Mock, MockRemoteSocket } from "../mock";
-import { PromiseAndController, createPromiseController } from "../../promise-controller";
import {
isEventPipeCommand,
isProcessCommand,
diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/ipc-protocol/serializer.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/ipc-protocol/serializer.ts
index 8f83d1253bc0a..0a4af3544a66c 100644
--- a/src/mono/wasm/runtime/diagnostics/server_pthread/ipc-protocol/serializer.ts
+++ b/src/mono/wasm/runtime/diagnostics/server_pthread/ipc-protocol/serializer.ts
@@ -3,7 +3,6 @@
import Serializer from "./base-serializer";
import { CommandSetId, ServerCommandId } from "./types";
-import { mono_assert } from "../../../types";
export function createBinaryCommandOKReply(payload?: Uint8Array): Uint8Array {
const len = Serializer.computeMessageByteLength(payload);
diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/mock-remote.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/mock-remote.ts
index f30b99175de85..97fe3804a2f1e 100644
--- a/src/mono/wasm/runtime/diagnostics/server_pthread/mock-remote.ts
+++ b/src/mono/wasm/runtime/diagnostics/server_pthread/mock-remote.ts
@@ -2,9 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
import monoDiagnosticsMock from "consts:monoDiagnosticsMock";
-import { runtimeHelpers } from "../../globals";
import type { Mock } from "../mock";
import { mock } from "../mock";
+import { runtimeHelpers } from "../../globals";
export function importAndInstantiateMock(mockURL: string): Promise {
if (monoDiagnosticsMock) {
diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/protocol-socket.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/protocol-socket.ts
index e66d24a681ed1..ffa8ce47bca10 100644
--- a/src/mono/wasm/runtime/diagnostics/server_pthread/protocol-socket.ts
+++ b/src/mono/wasm/runtime/diagnostics/server_pthread/protocol-socket.ts
@@ -9,7 +9,7 @@ import {
} from "./ipc-protocol/types";
import Magic from "./ipc-protocol/magic";
import Parser from "./ipc-protocol/base-parser";
-import { assertNever } from "../../types";
+import { assertNever } from "../../types/internal";
export const dotnetDiagnosticsServerProtocolCommandEvent = "dotnet:diagnostics:protocolCommand" as const;
diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/socket-connection.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/socket-connection.ts
index cc3a8d838524d..c2f8aae007f10 100644
--- a/src/mono/wasm/runtime/diagnostics/server_pthread/socket-connection.ts
+++ b/src/mono/wasm/runtime/diagnostics/server_pthread/socket-connection.ts
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { assertNever } from "../../types";
+import { assertNever } from "../../types/internal";
import { VoidPtr } from "../../types/emscripten";
import { Module } from "../../globals";
import type { CommonSocket } from "./common-socket";
diff --git a/src/mono/wasm/runtime/dotnet-legacy.d.ts b/src/mono/wasm/runtime/dotnet-legacy.d.ts
index 3dcc0104e6eee..ba286033fed3e 100644
--- a/src/mono/wasm/runtime/dotnet-legacy.d.ts
+++ b/src/mono/wasm/runtime/dotnet-legacy.d.ts
@@ -158,10 +158,6 @@ type MONOType = {
* @deprecated Please use config.assets instead
*/
mono_wasm_load_data_archive: (data: Uint8Array, prefix: string) => boolean;
- /**
- * @deprecated Please use configSrc instead
- */
- mono_wasm_load_config: (configFilePath: string) => Promise;
/**
* @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead.
*/
diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts
index 8b8f2e9d4d01e..d5cbed9f3354f 100644
--- a/src/mono/wasm/runtime/dotnet.d.ts
+++ b/src/mono/wasm/runtime/dotnet.d.ts
@@ -139,6 +139,10 @@ type MonoConfig = {
* application environment
*/
applicationEnvironment?: string;
+ /**
+ * query string to be used for asset loading
+ */
+ assetUniqueQuery?: string;
};
interface ResourceRequest {
name: string;
@@ -179,7 +183,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
-type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-threads" | "symbols";
+type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-threads" | "js-module-runtime" | "js-module-dotnet" | "js-module-native" | "symbols";
type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu".
"invariant" | // operate in invariant globalization mode.
"hybrid" | // operate in hybrid globalization mode with small ICU files, using native platform functions
@@ -252,6 +256,35 @@ type ModuleAPI = {
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise;
+interface IDisposable {
+ dispose(): void;
+ get isDisposed(): boolean;
+}
+interface IMemoryView extends IDisposable {
+ /**
+ * copies elements from provided source to the wasm memory.
+ * target has to have the elements of the same type as the underlying C# array.
+ * same as TypedArray.set()
+ */
+ set(source: TypedArray, targetOffset?: number): void;
+ /**
+ * copies elements from wasm memory to provided target.
+ * target has to have the elements of the same type as the underlying C# array.
+ */
+ copyTo(target: TypedArray, sourceOffset?: number): void;
+ /**
+ * same as TypedArray.slice()
+ */
+ slice(start?: number, end?: number): TypedArray;
+ get length(): number;
+ get byteLength(): number;
+}
+
+declare function mono_exit(exit_code: number, reason?: any): void;
+
+declare const dotnet: DotnetHostBuilder;
+declare const exit: typeof mono_exit;
+
interface BootJsonData {
readonly entryAssembly: string;
readonly resources: ResourceGroups;
@@ -297,35 +330,6 @@ declare enum ICUDataMode {
Custom = 3
}
-interface IDisposable {
- dispose(): void;
- get isDisposed(): boolean;
-}
-interface IMemoryView extends IDisposable {
- /**
- * copies elements from provided source to the wasm memory.
- * target has to have the elements of the same type as the underlying C# array.
- * same as TypedArray.set()
- */
- set(source: TypedArray, targetOffset?: number): void;
- /**
- * copies elements from wasm memory to provided target.
- * target has to have the elements of the same type as the underlying C# array.
- */
- copyTo(target: TypedArray, sourceOffset?: number): void;
- /**
- * same as TypedArray.slice()
- */
- slice(start?: number, end?: number): TypedArray;
- get length(): number;
- get byteLength(): number;
-}
-
-declare function mono_exit(exit_code: number, reason?: any): void;
-
-declare const dotnet: DotnetHostBuilder;
-declare const exit: typeof mono_exit;
-
declare global {
function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined;
}
diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js b/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js
index 7c42d93dd9c13..510b2bef4efd4 100644
--- a/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js
+++ b/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js
@@ -1,6 +1,2 @@
-var fetch = fetch || undefined; var require = require || undefined; var __dirname = __dirname || '';
-var createEmscripten = createDotnetRuntime;
-var unifyModuleConfig = __dotnet_runtime.unifyModuleConfig;
-export const dotnet = __dotnet_runtime.dotnet;
-export const exit = __dotnet_runtime.exit;
\ No newline at end of file
+var fetch = fetch || undefined; var require = require || undefined; var __dirname = __dirname || ''; var _nativeModuleLoaded = false;
diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js
index b23d198104955..68a88991766d2 100644
--- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js
+++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js
@@ -11,7 +11,6 @@ const DISABLE_LEGACY_JS_INTEROP = process.env.DISABLE_LEGACY_JS_INTEROP === "1";
function setup(disableLegacyJsInterop) {
const pthreadReplacements = {};
const dotnet_replacements = {
- scriptUrl: import.meta.url,
fetch: globalThis.fetch,
require,
updateMemoryViews,
@@ -27,30 +26,21 @@ function setup(disableLegacyJsInterop) {
#else
const ENVIRONMENT_IS_PTHREAD = false;
#endif
- if (ENVIRONMENT_IS_NODE) {
- dotnet_replacements.requirePromise = import(/* webpackIgnore: true */'module').then(mod => mod.createRequire(import.meta.url));
- dotnet_replacements.requirePromise.then(someRequire => {
- require = someRequire;
- });
- }
- __dotnet_runtime.passEmscriptenInternals({
- isWorker: ENVIRONMENT_IS_WORKER,
- isShell: ENVIRONMENT_IS_SHELL,
+ Module.__dotnet_runtime.passEmscriptenInternals({
isPThread: ENVIRONMENT_IS_PTHREAD,
disableLegacyJsInterop,
quit_, ExitStatus
});
+ Module.__dotnet_runtime.initializeReplacements(dotnet_replacements);
#if USE_PTHREADS
if (ENVIRONMENT_IS_PTHREAD) {
Module.config = {};
- __dotnet_runtime.initializeReplacements(dotnet_replacements);
- __dotnet_runtime.configureWorkerStartup(Module);
+ Module.__dotnet_runtime.configureWorkerStartup(Module);
} else {
#endif
- __dotnet_runtime.initializeReplacements(dotnet_replacements);
- __dotnet_runtime.configureEmscriptenStartup(Module);
+ Module.__dotnet_runtime.configureEmscriptenStartup(Module);
#if USE_PTHREADS
}
#endif
@@ -58,6 +48,7 @@ function setup(disableLegacyJsInterop) {
updateMemoryViews = dotnet_replacements.updateMemoryViews;
noExitRuntime = dotnet_replacements.noExitRuntime;
fetch = dotnet_replacements.fetch;
+ require = dotnet_replacements.require;
_scriptDir = __dirname = scriptDirectory = dotnet_replacements.scriptDirectory;
#if USE_PTHREADS
PThread.loadWasmModuleToWorker = pthreadReplacements.loadWasmModuleToWorker;
diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.pre.js b/src/mono/wasm/runtime/es6/dotnet.es6.pre.js
index 3ecc1bcdc9be7..9eb9b1c6b99e7 100644
--- a/src/mono/wasm/runtime/es6/dotnet.es6.pre.js
+++ b/src/mono/wasm/runtime/es6/dotnet.es6.pre.js
@@ -1 +1,3 @@
-createDotnetRuntime = Module = unifyModuleConfig(Module, createDotnetRuntime);
\ No newline at end of file
+if (_nativeModuleLoaded) throw new Error("Native module already loaded");
+_nativeModuleLoaded = true;
+createDotnetRuntime = Module = createDotnetRuntime(Module);
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/export-api.ts b/src/mono/wasm/runtime/export-api.ts
index e258beaa3801b..68b5a4f65ba65 100644
--- a/src/mono/wasm/runtime/export-api.ts
+++ b/src/mono/wasm/runtime/export-api.ts
@@ -1,14 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import type { MonoConfig, APIType } from "./types-api";
+import type { MonoConfig, APIType } from "./types";
-import { runtimeHelpers } from "./globals";
import { mono_wasm_get_assembly_exports } from "./invoke-cs";
import { mono_wasm_set_module_imports } from "./invoke-js";
import { getB32, getF32, getF64, getI16, getI32, getI52, getI64Big, getI8, getU16, getU32, getU52, getU8, setB32, setF32, setF64, setI16, setI32, setI52, setI64Big, setI8, setU16, setU32, setU52, setU8 } from "./memory";
import { mono_run_main, mono_run_main_and_exit } from "./run";
import { mono_wasm_setenv } from "./startup";
+import { runtimeHelpers } from "./globals";
export function export_api(): any {
const api: APIType = {
diff --git a/src/mono/wasm/runtime/exports.ts b/src/mono/wasm/runtime/exports.ts
index c7ea64155b8e5..407c14c8b3cf1 100644
--- a/src/mono/wasm/runtime/exports.ts
+++ b/src/mono/wasm/runtime/exports.ts
@@ -5,34 +5,33 @@ import ProductVersion from "consts:productVersion";
import GitHash from "consts:gitHash";
import BuildConfiguration from "consts:configuration";
import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop";
-import type { DotnetHostBuilder, RuntimeAPI } from "./types-api";
+import type { RuntimeAPI } from "./types";
-import { Module, disableLegacyJsInterop, exportedRuntimeAPI, passEmscriptenInternals, } from "./globals";
-import { is_nullish } from "./types";
+import { Module, disableLegacyJsInterop, exportedRuntimeAPI, passEmscriptenInternals, runtimeHelpers, setRuntimeGlobals, } from "./globals";
+import { GlobalObjects, is_nullish } from "./types/internal";
import { configureEmscriptenStartup, configureWorkerStartup } from "./startup";
import { create_weak_ref } from "./weak-ref";
import { export_internal } from "./exports-internal";
import { export_api } from "./export-api";
-import { mono_exit } from "./run";
-import { globalObjectsRoot, unifyModuleConfig } from "./run-outer";
-import { HostBuilder } from "./run-outer";
-import { initializeReplacements, init_polyfills } from "./polyfills";
+import { initializeReplacements } from "./polyfills";
// legacy
import { mono_bind_static_method } from "./net6-legacy/method-calls";
import { export_binding_api, export_internal_api, export_mono_api } from "./net6-legacy/exports-legacy";
import { initializeLegacyExports } from "./net6-legacy/globals";
+import { mono_wasm_stringify_as_error_with_stack } from "./logging";
+import { instantiate_asset, instantiate_symbols_asset } from "./assets";
+import { jiterpreter_dump_stats } from "./jiterpreter";
-function initializeExports(): RuntimeAPI {
+function initializeExports(globalObjects: GlobalObjects): RuntimeAPI {
const module = Module;
- const globals = globalObjectsRoot;
+ const globals = globalObjects;
const globalThisAny = globalThis as any;
if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) {
initializeLegacyExports(globals);
}
- init_polyfills();
// here we merge methods from the local objects into exported objects
if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) {
@@ -41,6 +40,13 @@ function initializeExports(): RuntimeAPI {
Object.assign(globals.internal, export_internal_api());
}
Object.assign(globals.internal, export_internal());
+ Object.assign(runtimeHelpers, {
+ stringify_as_error_with_stack: mono_wasm_stringify_as_error_with_stack,
+ instantiate_symbols_asset,
+ instantiate_asset,
+ jiterpreter_dump_stats,
+ });
+
const API = export_api();
Object.assign(exportedRuntimeAPI, {
INTERNAL: globals.internal,
@@ -135,9 +141,6 @@ class RuntimeList {
}
// export external API
-const dotnet: DotnetHostBuilder = new HostBuilder();
-const exit = mono_exit;
export {
- dotnet, exit,
- globalObjectsRoot as earlyExports, passEmscriptenInternals, initializeExports, initializeReplacements, unifyModuleConfig, configureEmscriptenStartup, configureWorkerStartup
+ passEmscriptenInternals, initializeExports, initializeReplacements, configureEmscriptenStartup, configureWorkerStartup, setRuntimeGlobals
};
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/gc-handles.ts b/src/mono/wasm/runtime/gc-handles.ts
index b1bc580d931b3..500b4626c697c 100644
--- a/src/mono/wasm/runtime/gc-handles.ts
+++ b/src/mono/wasm/runtime/gc-handles.ts
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { runtimeHelpers } from "./globals";
-import { GCHandle, GCHandleNull, JSHandle, JSHandleDisposed, JSHandleNull, mono_assert } from "./types";
+import { GCHandle, GCHandleNull, JSHandle, JSHandleDisposed, JSHandleNull } from "./types/internal";
import { create_weak_ref } from "./weak-ref";
const _use_finalization_registry = typeof globalThis.FinalizationRegistry === "function";
diff --git a/src/mono/wasm/runtime/globals.ts b/src/mono/wasm/runtime/globals.ts
index 1f032e37c966a..c3523c1b36915 100644
--- a/src/mono/wasm/runtime/globals.ts
+++ b/src/mono/wasm/runtime/globals.ts
@@ -5,66 +5,69 @@
///
///
-import { RuntimeAPI } from "./types-api";
-import type { DotnetModule, GlobalObjects, EmscriptenInternals, EmscriptenModuleInternal, RuntimeHelpers } from "./types";
-import type { EmscriptenModule } from "./types/emscripten";
+import { RuntimeAPI } from "./types/index";
+import type { GlobalObjects, EmscriptenInternals, RuntimeHelpers, LoaderHelpers, DotnetModuleInternal, PromiseAndController } from "./types/internal";
// these are our public API (except internal)
-export let Module: EmscriptenModule & DotnetModule & EmscriptenModuleInternal;
+export let Module: DotnetModuleInternal;
export let INTERNAL: any;
-// these are imported and re-exported from emscripten internals
export const ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string";
export const ENVIRONMENT_IS_WEB = typeof window == "object";
-export let ENVIRONMENT_IS_SHELL: boolean;
-export let ENVIRONMENT_IS_WORKER: boolean;
+export const ENVIRONMENT_IS_WORKER = typeof importScripts == "function";
+export const ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+// these are imported and re-exported from emscripten internals
export let ENVIRONMENT_IS_PTHREAD: boolean;
export let exportedRuntimeAPI: RuntimeAPI = null as any;
export let runtimeHelpers: RuntimeHelpers = null as any;
+export let loaderHelpers: LoaderHelpers = null as any;
// this is when we link with workload tools. The consts:WasmEnableLegacyJsInterop is when we compile with rollup.
export let disableLegacyJsInterop = false;
-export let earlyExports: GlobalObjects;
+export let _runtimeModuleLoaded = false; // please keep it in place also as rollup guard
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-export function passEmscriptenInternals(
- internals: EmscriptenInternals,
-): void {
- ENVIRONMENT_IS_SHELL = internals.isShell;
- ENVIRONMENT_IS_WORKER = internals.isWorker;
+export function passEmscriptenInternals(internals: EmscriptenInternals): void {
ENVIRONMENT_IS_PTHREAD = internals.isPThread;
disableLegacyJsInterop = internals.disableLegacyJsInterop;
runtimeHelpers.quit = internals.quit_;
runtimeHelpers.ExitStatus = internals.ExitStatus;
}
-export function setGlobalObjects(
- globalObjects: GlobalObjects,
-) {
- earlyExports = globalObjects;
+export function setRuntimeGlobals(globalObjects: GlobalObjects) {
+ if (_runtimeModuleLoaded) {
+ throw new Error("Runtime module already loaded");
+ }
+ _runtimeModuleLoaded = true;
Module = globalObjects.module;
INTERNAL = globalObjects.internal;
- runtimeHelpers = globalObjects.helpers;
+ runtimeHelpers = globalObjects.runtimeHelpers;
+ loaderHelpers = globalObjects.loaderHelpers;
exportedRuntimeAPI = globalObjects.api;
- Object.assign(globalObjects.module, {
- disableDotnet6Compatibility: true,
- config: { environmentVariables: {} }
+ Object.assign(runtimeHelpers, {
+ mono_wasm_bindings_is_ready: false,
+ javaScriptExports: {} as any,
+ enablePerfMeasure: true,
+ allAssetsInMemory: createPromiseController(),
+ dotnetReady: createPromiseController(),
+ memorySnapshotSkippedOrDone: createPromiseController(),
+ afterInstantiateWasm: createPromiseController(),
+ beforePreInit: createPromiseController(),
+ afterPreInit: createPromiseController(),
+ afterPreRun: createPromiseController(),
+ beforeOnRuntimeInitialized: createPromiseController(),
+ afterOnRuntimeInitialized: createPromiseController(),
+ afterPostRun: createPromiseController(),
});
+
Object.assign(globalObjects.module.config!, {}) as any;
- Object.assign(earlyExports.api, {
+ Object.assign(globalObjects.api, {
Module: globalObjects.module, ...globalObjects.module
});
- Object.assign(earlyExports.api, {
- INTERNAL: earlyExports.internal,
+ Object.assign(globalObjects.api, {
+ INTERNAL: globalObjects.internal,
});
- Object.assign(runtimeHelpers, {
- javaScriptExports: {} as any,
- mono_wasm_bindings_is_ready: false,
- maxParallelDownloads: 16,
- enableDownloadRetry: true,
- config: globalObjects.module.config,
- diagnosticTracing: false,
- enablePerfMeasure: true,
- loadedFiles: []
- } as Partial);
}
+
+export function createPromiseController(afterResolve?: () => void, afterReject?: () => void): PromiseAndController {
+ return loaderHelpers.createPromiseController(afterResolve, afterReject);
+}
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/http.ts b/src/mono/wasm/runtime/http.ts
index a3d676e91a90d..ef0ee24edba18 100644
--- a/src/mono/wasm/runtime/http.ts
+++ b/src/mono/wasm/runtime/http.ts
@@ -2,9 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { wrap_as_cancelable_promise } from "./cancelable-promise";
-import { Module, runtimeHelpers } from "./globals";
+import { Module, loaderHelpers } from "./globals";
import { MemoryViewType, Span } from "./marshal";
-import { mono_assert } from "./types";
import type { VoidPtr } from "./types/emscripten";
export function http_wasm_supports_streaming_response(): boolean {
@@ -56,7 +55,7 @@ export function http_wasm_fetch(url: string, header_names: string[], header_valu
}
return wrap_as_cancelable_promise(async () => {
- const res = await runtimeHelpers.fetch_like(url, options) as ResponseExtension;
+ const res = await loaderHelpers.fetch_like(url, options) as ResponseExtension;
res.__abort_controller = abort_controller;
return res;
});
@@ -66,11 +65,13 @@ function get_response_headers(res: ResponseExtension): void {
if (!res.__headerNames) {
res.__headerNames = [];
res.__headerValues = [];
- const entries: Iterable = (res.headers).entries();
+ if (res.headers && (res.headers).entries) {
+ const entries: Iterable = (res.headers).entries();
- for (const pair of entries) {
- res.__headerNames.push(pair[0]);
- res.__headerValues.push(pair[1]);
+ for (const pair of entries) {
+ res.__headerNames.push(pair[0]);
+ res.__headerValues.push(pair[1]);
+ }
}
}
}
diff --git a/src/mono/wasm/runtime/hybrid-globalization.ts b/src/mono/wasm/runtime/hybrid-globalization.ts
index 66cc3ebafb371..8e068a6fb6660 100644
--- a/src/mono/wasm/runtime/hybrid-globalization.ts
+++ b/src/mono/wasm/runtime/hybrid-globalization.ts
@@ -2,14 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { mono_wasm_new_external_root } from "./roots";
-import { MonoString, MonoStringRef } from "./types";
+import { MonoString, MonoStringRef } from "./types/internal";
import { Int32Ptr } from "./types/emscripten";
import { conv_string_root, js_string_to_mono_string_root, string_decoder } from "./strings";
import { setU16_unchecked } from "./memory";
-export function mono_wasm_change_case_invariant(exceptionMessage: Int32Ptr, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number) : void{
- try{
- const input = string_decoder.decode(src, (src + 2*srcLength));
+export function mono_wasm_change_case_invariant(exceptionMessage: Int32Ptr, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number): void {
+ try {
+ const input = string_decoder.decode(src, (src + 2 * srcLength));
let result = toUpper ? input.toUpperCase() : input.toLowerCase();
// Unicode defines some codepoints which expand into multiple codepoints,
// originally we do not support this expansion
@@ -30,7 +30,7 @@ export function mono_wasm_change_case(exceptionMessage: Int32Ptr, culture: MonoS
const cultureName = conv_string_root(cultureRoot);
if (!cultureName)
throw new Error("Cannot change case, the culture name is null.");
- const input = string_decoder.decode(src, (src + 2*srcLength));
+ const input = string_decoder.decode(src, (src + 2 * srcLength));
let result = toUpper ? input.toLocaleUpperCase(cultureName) : input.toLocaleLowerCase(cultureName);
if (result.length > destLength)
result = input;
diff --git a/src/mono/wasm/runtime/icu.ts b/src/mono/wasm/runtime/icu.ts
index f3b5b4586b164..28aa01ad727cf 100644
--- a/src/mono/wasm/runtime/icu.ts
+++ b/src/mono/wasm/runtime/icu.ts
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
import cwraps from "./cwraps";
-import { ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./globals";
import { VoidPtr } from "./types/emscripten";
// @offset must be the address of an ICU data archive in the native heap.
@@ -10,70 +9,3 @@ import { VoidPtr } from "./types/emscripten";
export function mono_wasm_load_icu_data(offset: VoidPtr): boolean {
return (cwraps.mono_wasm_load_icu_data(offset)) === 1;
}
-
-export function init_globalization() {
- runtimeHelpers.invariantMode = runtimeHelpers.config.globalizationMode === "invariant";
- runtimeHelpers.preferredIcuAsset = get_preferred_icu_asset();
-
- if (!runtimeHelpers.invariantMode) {
- if (runtimeHelpers.preferredIcuAsset) {
- if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: ICU data archive(s) available, disabling invariant mode");
- } else if (runtimeHelpers.config.globalizationMode !== "icu") {
- if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: ICU data archive(s) not available, using invariant globalization mode");
- runtimeHelpers.invariantMode = true;
- runtimeHelpers.preferredIcuAsset = null;
- } else {
- const msg = "invariant globalization mode is inactive and no ICU data archives are available";
- Module.err(`MONO_WASM: ERROR: ${msg}`);
- throw new Error(msg);
- }
- }
-
- const invariantEnv = "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT";
- const hybridEnv = "DOTNET_SYSTEM_GLOBALIZATION_HYBRID";
- const env_variables = runtimeHelpers.config.environmentVariables!;
- if (env_variables[hybridEnv] === undefined && runtimeHelpers.config.globalizationMode === "hybrid") {
- env_variables[hybridEnv] = "1";
- }
- else if (env_variables[invariantEnv] === undefined && runtimeHelpers.invariantMode) {
- env_variables[invariantEnv] = "1";
- }
- if (env_variables["TZ"] === undefined) {
- try {
- // this call is relatively expensive, so we call it during download of other assets
- const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || null;
- if (timezone) {
- env_variables!["TZ"] = timezone;
- }
- } catch {
- console.info("MONO_WASM: failed to detect timezone, will fallback to UTC");
- }
- }
-}
-
-export function get_preferred_icu_asset(): string | null {
- if (!runtimeHelpers.config.assets || runtimeHelpers.invariantMode)
- return null;
-
- // By setting user can define what ICU source file they want to load.
- // There is no need to check application's culture when is set.
- // If it was not set, then we have 3 "icu" assets in config and we should choose
- // only one for loading, the one that matches the application's locale.
- const icuAssets = runtimeHelpers.config.assets.filter(a => a["behavior"] == "icu");
- if (icuAssets.length === 1)
- return icuAssets[0].name;
-
- // reads the browsers locale / the OS's locale
- const preferredCulture = ENVIRONMENT_IS_WEB ? navigator.language : Intl.DateTimeFormat().resolvedOptions().locale;
- const prefix = preferredCulture.split("-")[0];
- const CJK = "icudt_CJK.dat";
- const EFIGS = "icudt_EFIGS.dat";
- const OTHERS = "icudt_no_CJK.dat";
-
- // not all "fr-*", "it-*", "de-*", "es-*" are in EFIGS, only the one that is mostly used
- if (prefix == "en" || ["fr", "fr-FR", "it", "it-IT", "de", "de-DE", "es", "es-ES"].includes(preferredCulture))
- return EFIGS;
- if (["zh", "ko", "ja"].includes(prefix))
- return CJK;
- return OTHERS;
-}
diff --git a/src/mono/wasm/runtime/invoke-cs.ts b/src/mono/wasm/runtime/invoke-cs.ts
index 340b3afa41405..5ab7d467e6dbf 100644
--- a/src/mono/wasm/runtime/invoke-cs.ts
+++ b/src/mono/wasm/runtime/invoke-cs.ts
@@ -11,7 +11,7 @@ import {
} from "./marshal";
import { mono_wasm_new_external_root, mono_wasm_new_root } from "./roots";
import { conv_string, conv_string_root } from "./strings";
-import { mono_assert, MonoObjectRef, MonoStringRef, MonoString, MonoObject, MonoMethod, JSMarshalerArguments, JSFunctionSignature, BoundMarshalerToCs, BoundMarshalerToJs, VoidPtrNull, MonoObjectRefNull, MonoObjectNull } from "./types";
+import { MonoObjectRef, MonoStringRef, MonoString, MonoObject, MonoMethod, JSMarshalerArguments, JSFunctionSignature, BoundMarshalerToCs, BoundMarshalerToJs, VoidPtrNull, MonoObjectRefNull, MonoObjectNull } from "./types/internal";
import { Int32Ptr } from "./types/emscripten";
import cwraps from "./cwraps";
import { assembly_load } from "./class-loader";
diff --git a/src/mono/wasm/runtime/invoke-js.ts b/src/mono/wasm/runtime/invoke-js.ts
index 6cb566f024aa1..4080ff1885a52 100644
--- a/src/mono/wasm/runtime/invoke-js.ts
+++ b/src/mono/wasm/runtime/invoke-js.ts
@@ -5,7 +5,7 @@ import { marshal_exception_to_cs, bind_arg_marshal_to_cs } from "./marshal-to-cs
import { get_signature_argument_count, bound_js_function_symbol, get_sig, get_signature_version, get_signature_type, imported_js_function_symbol } from "./marshal";
import { setI32_unchecked } from "./memory";
import { conv_string_root, js_string_to_mono_string_root } from "./strings";
-import { mono_assert, MonoObject, MonoObjectRef, MonoString, MonoStringRef, JSFunctionSignature, JSMarshalerArguments, WasmRoot, BoundMarshalerToJs, JSFnHandle, BoundMarshalerToCs, JSHandle, MarshalerType } from "./types";
+import { MonoObject, MonoObjectRef, MonoString, MonoStringRef, JSFunctionSignature, JSMarshalerArguments, WasmRoot, BoundMarshalerToJs, JSFnHandle, BoundMarshalerToCs, JSHandle, MarshalerType } from "./types/internal";
import { Int32Ptr } from "./types/emscripten";
import { INTERNAL, Module, runtimeHelpers } from "./globals";
import { bind_arg_marshal_to_js } from "./marshal-to-js";
diff --git a/src/mono/wasm/runtime/jiterpreter-interp-entry.ts b/src/mono/wasm/runtime/jiterpreter-interp-entry.ts
index ed94dc0283549..36c016bf5b0ec 100644
--- a/src/mono/wasm/runtime/jiterpreter-interp-entry.ts
+++ b/src/mono/wasm/runtime/jiterpreter-interp-entry.ts
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { mono_assert, MonoMethod, MonoType } from "./types";
+import { MonoMethod, MonoType } from "./types/internal";
import { NativePointer } from "./types/emscripten";
import { Module } from "./globals";
import {
diff --git a/src/mono/wasm/runtime/jiterpreter-jit-call.ts b/src/mono/wasm/runtime/jiterpreter-jit-call.ts
index b1bf6a52a75a5..ef349c6807eb4 100644
--- a/src/mono/wasm/runtime/jiterpreter-jit-call.ts
+++ b/src/mono/wasm/runtime/jiterpreter-jit-call.ts
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { mono_assert, MonoType, MonoMethod } from "./types";
+import { MonoType, MonoMethod } from "./types/internal";
import { NativePointer, Int32Ptr, VoidPtr } from "./types/emscripten";
import { Module, runtimeHelpers } from "./globals";
import {
diff --git a/src/mono/wasm/runtime/jiterpreter-support.ts b/src/mono/wasm/runtime/jiterpreter-support.ts
index bc4df330047f3..dfecf497dc811 100644
--- a/src/mono/wasm/runtime/jiterpreter-support.ts
+++ b/src/mono/wasm/runtime/jiterpreter-support.ts
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { mono_assert } from "./types";
import { NativePointer, ManagedPointer, VoidPtr } from "./types/emscripten";
import { Module, runtimeHelpers } from "./globals";
import { WasmOpcode, WasmSimdOpcode } from "./jiterpreter-opcodes";
diff --git a/src/mono/wasm/runtime/jiterpreter-trace-generator.ts b/src/mono/wasm/runtime/jiterpreter-trace-generator.ts
index 11ec48a595892..5243e11d61dc6 100644
--- a/src/mono/wasm/runtime/jiterpreter-trace-generator.ts
+++ b/src/mono/wasm/runtime/jiterpreter-trace-generator.ts
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { mono_assert, MonoMethod } from "./types";
+import { MonoMethod } from "./types/internal";
import { Module } from "./globals";
import { NativePointer } from "./types/emscripten";
import {
@@ -44,25 +44,25 @@ import {
/*
struct MonoVTable {
- MonoClass *klass; // 0
- MonoGCDescriptor gc_descr; // 4
- MonoDomain *domain; // 8
- gpointer type; // 12
- guint8 *interface_bitmap; // 16
- guint32 max_interface_id; // 20
- guint8 rank; // 21
- guint8 initialized; // 22
- guint8 flags;
+ MonoClass *klass; // 0
+ MonoGCDescriptor gc_descr; // 4
+ MonoDomain *domain; // 8
+ gpointer type; // 12
+ guint8 *interface_bitmap; // 16
+ guint32 max_interface_id; // 20
+ guint8 rank; // 21
+ guint8 initialized; // 22
+ guint8 flags;
*/
/*
struct InterpFrame {
- InterpFrame *parent; // 0
- InterpMethod *imethod; // 4
- stackval *retval; // 8
- stackval *stack; // 12
- InterpFrame *next_free; // 16
- InterpState state; // 20
+ InterpFrame *parent; // 0
+ InterpMethod *imethod; // 4
+ stackval *retval; // 8
+ stackval *stack; // 12
+ InterpFrame *next_free; // 16
+ InterpState state; // 20
};
struct InterpMethod {
@@ -87,55 +87,55 @@ const enum JiterpSpecialOpcode {
}
// indexPlusOne so that ip[1] in the interpreter becomes getArgU16(ip, 1)
-function getArgU16 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgU16(ip: MintOpcodePtr, indexPlusOne: number) {
return getU16(ip + (2 * indexPlusOne));
}
-function getArgI16 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgI16(ip: MintOpcodePtr, indexPlusOne: number) {
return getI16(ip + (2 * indexPlusOne));
}
-function getArgI32 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgI32(ip: MintOpcodePtr, indexPlusOne: number) {
const src = ip + (2 * indexPlusOne);
return getI32_unaligned(src);
}
-function getArgU32 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgU32(ip: MintOpcodePtr, indexPlusOne: number) {
const src = ip + (2 * indexPlusOne);
return getU32_unaligned(src);
}
-function getArgF32 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgF32(ip: MintOpcodePtr, indexPlusOne: number) {
const src = ip + (2 * indexPlusOne);
return getF32_unaligned(src);
}
-function getArgF64 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgF64(ip: MintOpcodePtr, indexPlusOne: number) {
const src = ip + (2 * indexPlusOne);
return getF64_unaligned(src);
}
-function get_imethod (frame: NativePointer) {
+function get_imethod(frame: NativePointer) {
// FIXME: Encoding this data directly into the trace will prevent trace reuse
const iMethod = getU32_unaligned(frame + getMemberOffset(JiterpMember.Imethod));
return iMethod;
}
-function get_imethod_data (frame: NativePointer, index: number) {
+function get_imethod_data(frame: NativePointer, index: number) {
// FIXME: Encoding this data directly into the trace will prevent trace reuse
const pData = getU32_unaligned(get_imethod(frame) + getMemberOffset(JiterpMember.DataItems));
const dataOffset = pData + (index * sizeOfDataItem);
return getU32_unaligned(dataOffset);
}
-function get_imethod_clause_data_offset (frame: NativePointer, index: number) {
+function get_imethod_clause_data_offset(frame: NativePointer, index: number) {
// FIXME: Encoding this data directly into the trace will prevent trace reuse
const pData = getU32_unaligned(get_imethod(frame) + getMemberOffset(JiterpMember.ClauseDataOffsets));
const dataOffset = pData + (index * sizeOfDataItem);
return getU32_unaligned(dataOffset);
}
-function is_backward_branch_target (
+function is_backward_branch_target(
ip: MintOpcodePtr, startOfBody: MintOpcodePtr,
backwardBranchTable: Uint16Array | null
) {
@@ -153,16 +153,16 @@ function is_backward_branch_target (
const knownConstantValues = new Map();
-function get_known_constant_value (localOffset: number) : number | undefined {
+function get_known_constant_value(localOffset: number): number | undefined {
return knownConstantValues.get(localOffset);
}
-export function generateWasmBody (
+export function generateWasmBody(
frame: NativePointer, traceName: string, ip: MintOpcodePtr,
startOfBody: MintOpcodePtr, endOfBody: MintOpcodePtr,
builder: WasmBuilder, instrumentedTraceId: number,
backwardBranchTable: Uint16Array | null
-) : number {
+): number {
const abort = 0;
let isFirstInstruction = true, isConditionallyExecuted = false,
firstOpcodeInBlock = true, containsSimd = false,
@@ -388,10 +388,10 @@ export function generateWasmBody (
const sizeOffset = getArgU16(ip, 3),
valueOffset = getArgU16(ip, 2),
destOffset = getArgU16(ip, 1);
- /*
- constantSize = get_known_constant_value(sizeOffset),
- constantValue = get_known_constant_value(valueOffset);
- */
+ /*
+ constantSize = get_known_constant_value(sizeOffset),
+ constantValue = get_known_constant_value(valueOffset);
+ */
// TODO: Handle constant size initblks. Not sure if they matter though
// FIXME: This will cause an erroneous bailout if dest and size are both 0
@@ -1108,7 +1108,7 @@ export function generateWasmBody (
case MintOpcode.MINT_CONV_I8_R4:
case MintOpcode.MINT_CONV_I8_R8: {
const isF32 = (opcode === MintOpcode.MINT_CONV_I4_R4) ||
- (opcode === MintOpcode.MINT_CONV_I8_R4),
+ (opcode === MintOpcode.MINT_CONV_I8_R4),
isI64 = (opcode === MintOpcode.MINT_CONV_I8_R4) ||
(opcode === MintOpcode.MINT_CONV_I8_R8),
limit = isI64
@@ -1446,32 +1446,32 @@ export function generateWasmBody (
return result;
}
-const notNullSince : Map = new Map();
+const notNullSince: Map = new Map();
let cknullOffset = -1;
-function eraseInferredState () {
+function eraseInferredState() {
cknullOffset = -1;
notNullSince.clear();
knownConstantValues.clear();
}
-function invalidate_local (offset: number) {
+function invalidate_local(offset: number) {
if (cknullOffset === offset)
cknullOffset = -1;
notNullSince.delete(offset);
knownConstantValues.delete(offset);
}
-function invalidate_local_range (start: number, bytes: number) {
+function invalidate_local_range(start: number, bytes: number) {
for (let i = 0; i < bytes; i += 1)
invalidate_local(start + i);
}
-function append_branch_target_block (builder: WasmBuilder, ip: MintOpcodePtr, isBackBranchTarget: boolean) {
+function append_branch_target_block(builder: WasmBuilder, ip: MintOpcodePtr, isBackBranchTarget: boolean) {
builder.cfg.startBranchBlock(ip, isBackBranchTarget);
}
-function append_ldloc (builder: WasmBuilder, offset: number, opcodeOrPrefix: WasmOpcode, simdOpcode?: WasmSimdOpcode) {
+function append_ldloc(builder: WasmBuilder, offset: number, opcodeOrPrefix: WasmOpcode, simdOpcode?: WasmSimdOpcode) {
builder.local("pLocals");
builder.appendU8(opcodeOrPrefix);
if (simdOpcode !== undefined) {
@@ -1489,7 +1489,7 @@ function append_ldloc (builder: WasmBuilder, offset: number, opcodeOrPrefix: Was
// where the offset+alignment pair is referred to as a 'memarg' by the spec.
// The actual store operation is equivalent to `pBase[offset] = value` (alignment has no
// observable impact on behavior, other than causing compilation failures if out of range)
-function append_stloc_tail (builder: WasmBuilder, offset: number, opcodeOrPrefix: WasmOpcode, simdOpcode?: WasmSimdOpcode) {
+function append_stloc_tail(builder: WasmBuilder, offset: number, opcodeOrPrefix: WasmOpcode, simdOpcode?: WasmSimdOpcode) {
builder.appendU8(opcodeOrPrefix);
if (simdOpcode !== undefined) {
// This looks wrong but I assure you it's correct.
@@ -1506,7 +1506,7 @@ function append_stloc_tail (builder: WasmBuilder, offset: number, opcodeOrPrefix
// used for writes
// Pass transient=true if the address will not persist after use (so it can't be used to later
// modify the contents of this local)
-function append_ldloca (builder: WasmBuilder, localOffset: number, bytesInvalidated?: number) {
+function append_ldloca(builder: WasmBuilder, localOffset: number, bytesInvalidated?: number) {
if (typeof (bytesInvalidated) !== "number")
bytesInvalidated = 512;
// FIXME: We need to know how big this variable is so we can invalidate the whole space it occupies
@@ -1515,7 +1515,7 @@ function append_ldloca (builder: WasmBuilder, localOffset: number, bytesInvalida
builder.lea("pLocals", localOffset);
}
-function append_memset_local (builder: WasmBuilder, localOffset: number, value: number, count: number) {
+function append_memset_local(builder: WasmBuilder, localOffset: number, value: number, count: number) {
invalidate_local_range(localOffset, count);
// spec: pop n, pop val, pop d, fill from d[0] to d[n] with value val
@@ -1527,7 +1527,7 @@ function append_memset_local (builder: WasmBuilder, localOffset: number, value:
append_memset_dest(builder, value, count);
}
-function append_memmove_local_local (builder: WasmBuilder, destLocalOffset: number, sourceLocalOffset: number, count: number) {
+function append_memmove_local_local(builder: WasmBuilder, destLocalOffset: number, sourceLocalOffset: number, count: number) {
invalidate_local_range(destLocalOffset, count);
if (try_append_memmove_fast(builder, destLocalOffset, sourceLocalOffset, count, false))
@@ -1539,12 +1539,12 @@ function append_memmove_local_local (builder: WasmBuilder, destLocalOffset: numb
append_memmove_dest_src(builder, count);
}
-function isAddressTaken (builder: WasmBuilder, localOffset: number) {
+function isAddressTaken(builder: WasmBuilder, localOffset: number) {
return cwraps.mono_jiterp_is_imethod_var_address_taken(get_imethod(builder.frame), localOffset) !== 0;
}
// Loads the specified i32 value and then bails out if it is null, leaving it in the cknull_ptr local.
-function append_ldloc_cknull (builder: WasmBuilder, localOffset: number, ip: MintOpcodePtr, leaveOnStack: boolean) {
+function append_ldloc_cknull(builder: WasmBuilder, localOffset: number, ip: MintOpcodePtr, leaveOnStack: boolean) {
const optimize = builder.allowNullCheckOptimization &&
notNullSince.has(localOffset) &&
!isAddressTaken(builder, localOffset);
@@ -1597,22 +1597,22 @@ function append_ldloc_cknull (builder: WasmBuilder, localOffset: number, ip: Min
cknullOffset = -1;
}
-const ldcTable : { [opcode: number]: [WasmOpcode, number] } = {
+const ldcTable: { [opcode: number]: [WasmOpcode, number] } = {
[MintOpcode.MINT_LDC_I4_M1]: [WasmOpcode.i32_const, -1],
- [MintOpcode.MINT_LDC_I4_0]: [WasmOpcode.i32_const, 0 ],
- [MintOpcode.MINT_LDC_I4_1]: [WasmOpcode.i32_const, 1 ],
- [MintOpcode.MINT_LDC_I4_2]: [WasmOpcode.i32_const, 2 ],
- [MintOpcode.MINT_LDC_I4_3]: [WasmOpcode.i32_const, 3 ],
- [MintOpcode.MINT_LDC_I4_4]: [WasmOpcode.i32_const, 4 ],
- [MintOpcode.MINT_LDC_I4_5]: [WasmOpcode.i32_const, 5 ],
- [MintOpcode.MINT_LDC_I4_6]: [WasmOpcode.i32_const, 6 ],
- [MintOpcode.MINT_LDC_I4_7]: [WasmOpcode.i32_const, 7 ],
- [MintOpcode.MINT_LDC_I4_8]: [WasmOpcode.i32_const, 8 ],
+ [MintOpcode.MINT_LDC_I4_0]: [WasmOpcode.i32_const, 0],
+ [MintOpcode.MINT_LDC_I4_1]: [WasmOpcode.i32_const, 1],
+ [MintOpcode.MINT_LDC_I4_2]: [WasmOpcode.i32_const, 2],
+ [MintOpcode.MINT_LDC_I4_3]: [WasmOpcode.i32_const, 3],
+ [MintOpcode.MINT_LDC_I4_4]: [WasmOpcode.i32_const, 4],
+ [MintOpcode.MINT_LDC_I4_5]: [WasmOpcode.i32_const, 5],
+ [MintOpcode.MINT_LDC_I4_6]: [WasmOpcode.i32_const, 6],
+ [MintOpcode.MINT_LDC_I4_7]: [WasmOpcode.i32_const, 7],
+ [MintOpcode.MINT_LDC_I4_8]: [WasmOpcode.i32_const, 8],
};
-function emit_ldc (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode) : boolean {
+function emit_ldc(builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode): boolean {
let storeType = WasmOpcode.i32_store;
- let value : number | undefined;
+ let value: number | undefined;
const tableEntry = ldcTable[opcode];
if (tableEntry) {
@@ -1682,7 +1682,7 @@ function emit_ldc (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode)
return true;
}
-function emit_mov (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode) : boolean {
+function emit_mov(builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode): boolean {
let loadOp = WasmOpcode.i32_load, storeOp = WasmOpcode.i32_store;
switch (opcode) {
case MintOpcode.MINT_MOV_I4_I1:
@@ -1745,7 +1745,7 @@ function emit_mov (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode)
return true;
}
-function append_vtable_initialize (builder: WasmBuilder, pVtable: NativePointer, ip: MintOpcodePtr) {
+function append_vtable_initialize(builder: WasmBuilder, pVtable: NativePointer, ip: MintOpcodePtr) {
// TODO: Actually initialize the vtable instead of just checking and bailing out?
builder.block();
// FIXME: This will prevent us from reusing traces between runs since the vtables can move
@@ -1760,17 +1760,18 @@ function append_vtable_initialize (builder: WasmBuilder, pVtable: NativePointer,
builder.endBlock();
}
-function emit_fieldop (
+function emit_fieldop(
builder: WasmBuilder, frame: NativePointer,
ip: MintOpcodePtr, opcode: MintOpcode
-) : boolean {
+): boolean {
const isLoad = (
(opcode >= MintOpcode.MINT_LDFLD_I1) &&
(opcode <= MintOpcode.MINT_LDFLDA_UNSAFE)
- ) || (
- (opcode >= MintOpcode.MINT_LDSFLD_I1) &&
- (opcode <= MintOpcode.MINT_LDSFLD_W)
- );
+ ) ||
+ (
+ (opcode >= MintOpcode.MINT_LDSFLD_I1) &&
+ (opcode <= MintOpcode.MINT_LDSFLD_W)
+ );
const objectOffset = getArgU16(ip, isLoad ? 2 : 1),
fieldOffset = getArgU16(ip, 3),
@@ -1945,17 +1946,18 @@ function emit_fieldop (
}
}
-function emit_sfieldop (
+function emit_sfieldop(
builder: WasmBuilder, frame: NativePointer,
ip: MintOpcodePtr, opcode: MintOpcode
-) : boolean {
+): boolean {
const isLoad = (
(opcode >= MintOpcode.MINT_LDFLD_I1) &&
(opcode <= MintOpcode.MINT_LDFLDA_UNSAFE)
- ) || (
- (opcode >= MintOpcode.MINT_LDSFLD_I1) &&
- (opcode <= MintOpcode.MINT_LDSFLD_W)
- );
+ ) ||
+ (
+ (opcode >= MintOpcode.MINT_LDSFLD_I1) &&
+ (opcode <= MintOpcode.MINT_LDSFLD_W)
+ );
const localOffset = getArgU16(ip, 1),
pVtable = get_imethod_data(frame, getArgU16(ip, 2)),
@@ -2056,7 +2058,7 @@ type OpRec3 = [WasmOpcode, WasmOpcode, WasmOpcode];
// operator, lhsLoadOperator, rhsLoadOperator, storeOperator
type OpRec4 = [WasmOpcode, WasmOpcode, WasmOpcode, WasmOpcode];
-const floatToIntTable : { [opcode: number]: WasmOpcode } = {
+const floatToIntTable: { [opcode: number]: WasmOpcode } = {
[MintOpcode.MINT_CONV_I4_R4]: WasmOpcode.i32_trunc_s_f32,
[MintOpcode.MINT_CONV_I8_R4]: WasmOpcode.i64_trunc_s_f32,
[MintOpcode.MINT_CONV_I4_R8]: WasmOpcode.i32_trunc_s_f64,
@@ -2064,25 +2066,25 @@ const floatToIntTable : { [opcode: number]: WasmOpcode } = {
};
// thanks for making this as complex as possible, typescript
-const unopTable : { [opcode: number]: OpRec3 | undefined } = {
- [MintOpcode.MINT_CEQ0_I4]: [WasmOpcode.i32_eqz, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_ADD1_I4]: [WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_SUB1_I4]: [WasmOpcode.i32_sub, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_NEG_I4]: [WasmOpcode.i32_sub, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_NOT_I4]: [WasmOpcode.i32_xor, WasmOpcode.i32_load, WasmOpcode.i32_store],
-
- [MintOpcode.MINT_ADD1_I8]: [WasmOpcode.i64_add, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_SUB1_I8]: [WasmOpcode.i64_sub, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_NEG_I8]: [WasmOpcode.i64_sub, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_NOT_I8]: [WasmOpcode.i64_xor, WasmOpcode.i64_load, WasmOpcode.i64_store],
-
- [MintOpcode.MINT_ADD_I4_IMM]: [WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_MUL_I4_IMM]: [WasmOpcode.i32_mul, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_ADD_I8_IMM]: [WasmOpcode.i64_add, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_MUL_I8_IMM]: [WasmOpcode.i64_mul, WasmOpcode.i64_load, WasmOpcode.i64_store],
-
- [MintOpcode.MINT_NEG_R4]: [WasmOpcode.f32_neg, WasmOpcode.f32_load, WasmOpcode.f32_store],
- [MintOpcode.MINT_NEG_R8]: [WasmOpcode.f64_neg, WasmOpcode.f64_load, WasmOpcode.f64_store],
+const unopTable: { [opcode: number]: OpRec3 | undefined } = {
+ [MintOpcode.MINT_CEQ0_I4]: [WasmOpcode.i32_eqz, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_ADD1_I4]: [WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_SUB1_I4]: [WasmOpcode.i32_sub, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_NEG_I4]: [WasmOpcode.i32_sub, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_NOT_I4]: [WasmOpcode.i32_xor, WasmOpcode.i32_load, WasmOpcode.i32_store],
+
+ [MintOpcode.MINT_ADD1_I8]: [WasmOpcode.i64_add, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_SUB1_I8]: [WasmOpcode.i64_sub, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_NEG_I8]: [WasmOpcode.i64_sub, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_NOT_I8]: [WasmOpcode.i64_xor, WasmOpcode.i64_load, WasmOpcode.i64_store],
+
+ [MintOpcode.MINT_ADD_I4_IMM]: [WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_MUL_I4_IMM]: [WasmOpcode.i32_mul, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_ADD_I8_IMM]: [WasmOpcode.i64_add, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_MUL_I8_IMM]: [WasmOpcode.i64_mul, WasmOpcode.i64_load, WasmOpcode.i64_store],
+
+ [MintOpcode.MINT_NEG_R4]: [WasmOpcode.f32_neg, WasmOpcode.f32_load, WasmOpcode.f32_store],
+ [MintOpcode.MINT_NEG_R8]: [WasmOpcode.f64_neg, WasmOpcode.f64_load, WasmOpcode.f64_store],
[MintOpcode.MINT_CONV_R4_I4]: [WasmOpcode.f32_convert_s_i32, WasmOpcode.i32_load, WasmOpcode.f32_store],
[MintOpcode.MINT_CONV_R8_I4]: [WasmOpcode.f64_convert_s_i32, WasmOpcode.i32_load, WasmOpcode.f64_store],
@@ -2090,45 +2092,45 @@ const unopTable : { [opcode: number]: OpRec3 | undefined } = {
[MintOpcode.MINT_CONV_R4_I8]: [WasmOpcode.f32_convert_s_i64, WasmOpcode.i64_load, WasmOpcode.f32_store],
[MintOpcode.MINT_CONV_R8_I8]: [WasmOpcode.f64_convert_s_i64, WasmOpcode.i64_load, WasmOpcode.f64_store],
[MintOpcode.MINT_CONV_R_UN_I8]: [WasmOpcode.f64_convert_u_i64, WasmOpcode.i64_load, WasmOpcode.f64_store],
- [MintOpcode.MINT_CONV_R8_R4]: [WasmOpcode.f64_promote_f32, WasmOpcode.f32_load, WasmOpcode.f64_store],
- [MintOpcode.MINT_CONV_R4_R8]: [WasmOpcode.f32_demote_f64, WasmOpcode.f64_load, WasmOpcode.f32_store],
-
- [MintOpcode.MINT_CONV_I8_I4]: [WasmOpcode.nop, WasmOpcode.i64_load32_s, WasmOpcode.i64_store],
- [MintOpcode.MINT_CONV_I8_U4]: [WasmOpcode.nop, WasmOpcode.i64_load32_u, WasmOpcode.i64_store],
-
- [MintOpcode.MINT_CONV_U1_I4]: [WasmOpcode.i32_and, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CONV_U2_I4]: [WasmOpcode.i32_and, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CONV_I1_I4]: [WasmOpcode.i32_shr_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CONV_I2_I4]: [WasmOpcode.i32_shr_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
-
- [MintOpcode.MINT_CONV_U1_I8]: [WasmOpcode.i32_and, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CONV_U2_I8]: [WasmOpcode.i32_and, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CONV_I1_I8]: [WasmOpcode.i32_shr_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CONV_I2_I8]: [WasmOpcode.i32_shr_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
-
- [MintOpcode.MINT_SHL_I4_IMM]: [WasmOpcode.i32_shl, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_SHL_I8_IMM]: [WasmOpcode.i64_shl, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_SHR_I4_IMM]: [WasmOpcode.i32_shr_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_SHR_I8_IMM]: [WasmOpcode.i64_shr_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_SHR_UN_I4_IMM]: [WasmOpcode.i32_shr_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_SHR_UN_I8_IMM]: [WasmOpcode.i64_shr_u, WasmOpcode.i64_load, WasmOpcode.i64_store],
-
- [MintOpcode.MINT_ROL_I4_IMM]: [WasmOpcode.i32_rotl, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_ROL_I8_IMM]: [WasmOpcode.i64_rotl, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_ROR_I4_IMM]: [WasmOpcode.i32_rotr, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_ROR_I8_IMM]: [WasmOpcode.i64_rotr, WasmOpcode.i64_load, WasmOpcode.i64_store],
-
- [MintOpcode.MINT_CLZ_I4]: [WasmOpcode.i32_clz, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CTZ_I4]: [WasmOpcode.i32_ctz, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_POPCNT_I4]: [WasmOpcode.i32_popcnt, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CLZ_I8]: [WasmOpcode.i64_clz, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_CTZ_I8]: [WasmOpcode.i64_ctz, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_POPCNT_I8]: [WasmOpcode.i64_popcnt, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_CONV_R8_R4]: [WasmOpcode.f64_promote_f32, WasmOpcode.f32_load, WasmOpcode.f64_store],
+ [MintOpcode.MINT_CONV_R4_R8]: [WasmOpcode.f32_demote_f64, WasmOpcode.f64_load, WasmOpcode.f32_store],
+
+ [MintOpcode.MINT_CONV_I8_I4]: [WasmOpcode.nop, WasmOpcode.i64_load32_s, WasmOpcode.i64_store],
+ [MintOpcode.MINT_CONV_I8_U4]: [WasmOpcode.nop, WasmOpcode.i64_load32_u, WasmOpcode.i64_store],
+
+ [MintOpcode.MINT_CONV_U1_I4]: [WasmOpcode.i32_and, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CONV_U2_I4]: [WasmOpcode.i32_and, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CONV_I1_I4]: [WasmOpcode.i32_shr_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CONV_I2_I4]: [WasmOpcode.i32_shr_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+
+ [MintOpcode.MINT_CONV_U1_I8]: [WasmOpcode.i32_and, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CONV_U2_I8]: [WasmOpcode.i32_and, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CONV_I1_I8]: [WasmOpcode.i32_shr_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CONV_I2_I8]: [WasmOpcode.i32_shr_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
+
+ [MintOpcode.MINT_SHL_I4_IMM]: [WasmOpcode.i32_shl, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_SHL_I8_IMM]: [WasmOpcode.i64_shl, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_SHR_I4_IMM]: [WasmOpcode.i32_shr_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_SHR_I8_IMM]: [WasmOpcode.i64_shr_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_SHR_UN_I4_IMM]: [WasmOpcode.i32_shr_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_SHR_UN_I8_IMM]: [WasmOpcode.i64_shr_u, WasmOpcode.i64_load, WasmOpcode.i64_store],
+
+ [MintOpcode.MINT_ROL_I4_IMM]: [WasmOpcode.i32_rotl, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_ROL_I8_IMM]: [WasmOpcode.i64_rotl, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_ROR_I4_IMM]: [WasmOpcode.i32_rotr, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_ROR_I8_IMM]: [WasmOpcode.i64_rotr, WasmOpcode.i64_load, WasmOpcode.i64_store],
+
+ [MintOpcode.MINT_CLZ_I4]: [WasmOpcode.i32_clz, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CTZ_I4]: [WasmOpcode.i32_ctz, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_POPCNT_I4]: [WasmOpcode.i32_popcnt, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CLZ_I8]: [WasmOpcode.i64_clz, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_CTZ_I8]: [WasmOpcode.i64_ctz, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_POPCNT_I8]: [WasmOpcode.i64_popcnt, WasmOpcode.i64_load, WasmOpcode.i64_store],
};
// HACK: Generating correct wasm for these is non-trivial so we hand them off to C.
// The opcode specifies whether the operands need to be promoted first.
-const intrinsicFpBinops : { [opcode: number] : WasmOpcode } = {
+const intrinsicFpBinops: { [opcode: number]: WasmOpcode } = {
[MintOpcode.MINT_CEQ_R4]: WasmOpcode.f64_promote_f32,
[MintOpcode.MINT_CEQ_R8]: WasmOpcode.nop,
[MintOpcode.MINT_CNE_R4]: WasmOpcode.f64_promote_f32,
@@ -2153,160 +2155,160 @@ const intrinsicFpBinops : { [opcode: number] : WasmOpcode } = {
[JiterpSpecialOpcode.CNE_UN_R8]: WasmOpcode.nop,
};
-const binopTable : { [opcode: number]: OpRec3 | OpRec4 | undefined } = {
- [MintOpcode.MINT_ADD_I4]: [WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_ADD_OVF_I4]:[WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_ADD_OVF_UN_I4]:[WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_SUB_I4]: [WasmOpcode.i32_sub, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_MUL_I4]: [WasmOpcode.i32_mul, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_MUL_OVF_I4]:[WasmOpcode.i32_mul, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_MUL_OVF_UN_I4]:[WasmOpcode.i32_mul,WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_DIV_I4]: [WasmOpcode.i32_div_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+const binopTable: { [opcode: number]: OpRec3 | OpRec4 | undefined } = {
+ [MintOpcode.MINT_ADD_I4]: [WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_ADD_OVF_I4]: [WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_ADD_OVF_UN_I4]: [WasmOpcode.i32_add, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_SUB_I4]: [WasmOpcode.i32_sub, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_MUL_I4]: [WasmOpcode.i32_mul, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_MUL_OVF_I4]: [WasmOpcode.i32_mul, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_MUL_OVF_UN_I4]: [WasmOpcode.i32_mul, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_DIV_I4]: [WasmOpcode.i32_div_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
[MintOpcode.MINT_DIV_UN_I4]: [WasmOpcode.i32_div_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_REM_I4]: [WasmOpcode.i32_rem_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_REM_I4]: [WasmOpcode.i32_rem_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
[MintOpcode.MINT_REM_UN_I4]: [WasmOpcode.i32_rem_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_AND_I4]: [WasmOpcode.i32_and, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_OR_I4]: [WasmOpcode.i32_or, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_XOR_I4]: [WasmOpcode.i32_xor, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_SHL_I4]: [WasmOpcode.i32_shl, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_SHR_I4]: [WasmOpcode.i32_shr_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_AND_I4]: [WasmOpcode.i32_and, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_OR_I4]: [WasmOpcode.i32_or, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_XOR_I4]: [WasmOpcode.i32_xor, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_SHL_I4]: [WasmOpcode.i32_shl, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_SHR_I4]: [WasmOpcode.i32_shr_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
[MintOpcode.MINT_SHR_UN_I4]: [WasmOpcode.i32_shr_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_ADD_I8]: [WasmOpcode.i64_add, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_SUB_I8]: [WasmOpcode.i64_sub, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_MUL_I8]: [WasmOpcode.i64_mul, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_DIV_I8]: [WasmOpcode.i64_div_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_REM_I8]: [WasmOpcode.i64_rem_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_ADD_I8]: [WasmOpcode.i64_add, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_SUB_I8]: [WasmOpcode.i64_sub, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_MUL_I8]: [WasmOpcode.i64_mul, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_DIV_I8]: [WasmOpcode.i64_div_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_REM_I8]: [WasmOpcode.i64_rem_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
[MintOpcode.MINT_DIV_UN_I8]: [WasmOpcode.i64_div_u, WasmOpcode.i64_load, WasmOpcode.i64_store],
[MintOpcode.MINT_REM_UN_I8]: [WasmOpcode.i64_rem_u, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_AND_I8]: [WasmOpcode.i64_and, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_OR_I8]: [WasmOpcode.i64_or, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_XOR_I8]: [WasmOpcode.i64_xor, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_SHL_I8]: [WasmOpcode.i64_shl, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_SHR_I8]: [WasmOpcode.i64_shr_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_AND_I8]: [WasmOpcode.i64_and, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_OR_I8]: [WasmOpcode.i64_or, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_XOR_I8]: [WasmOpcode.i64_xor, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_SHL_I8]: [WasmOpcode.i64_shl, WasmOpcode.i64_load, WasmOpcode.i64_store],
+ [MintOpcode.MINT_SHR_I8]: [WasmOpcode.i64_shr_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
[MintOpcode.MINT_SHR_UN_I8]: [WasmOpcode.i64_shr_u, WasmOpcode.i64_load, WasmOpcode.i64_store],
- [MintOpcode.MINT_ADD_R4]: [WasmOpcode.f32_add, WasmOpcode.f32_load, WasmOpcode.f32_store],
- [MintOpcode.MINT_SUB_R4]: [WasmOpcode.f32_sub, WasmOpcode.f32_load, WasmOpcode.f32_store],
- [MintOpcode.MINT_MUL_R4]: [WasmOpcode.f32_mul, WasmOpcode.f32_load, WasmOpcode.f32_store],
- [MintOpcode.MINT_DIV_R4]: [WasmOpcode.f32_div, WasmOpcode.f32_load, WasmOpcode.f32_store],
-
- [MintOpcode.MINT_ADD_R8]: [WasmOpcode.f64_add, WasmOpcode.f64_load, WasmOpcode.f64_store],
- [MintOpcode.MINT_SUB_R8]: [WasmOpcode.f64_sub, WasmOpcode.f64_load, WasmOpcode.f64_store],
- [MintOpcode.MINT_MUL_R8]: [WasmOpcode.f64_mul, WasmOpcode.f64_load, WasmOpcode.f64_store],
- [MintOpcode.MINT_DIV_R8]: [WasmOpcode.f64_div, WasmOpcode.f64_load, WasmOpcode.f64_store],
-
- [MintOpcode.MINT_CEQ_I4]: [WasmOpcode.i32_eq, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CNE_I4]: [WasmOpcode.i32_ne, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CLT_I4]: [WasmOpcode.i32_lt_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CGT_I4]: [WasmOpcode.i32_gt_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CLE_I4]: [WasmOpcode.i32_le_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CGE_I4]: [WasmOpcode.i32_ge_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
-
- [MintOpcode.MINT_CLT_UN_I4]: [WasmOpcode.i32_lt_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CGT_UN_I4]: [WasmOpcode.i32_gt_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CLE_UN_I4]: [WasmOpcode.i32_le_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CGE_UN_I4]: [WasmOpcode.i32_ge_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
-
- [MintOpcode.MINT_CEQ_I8]: [WasmOpcode.i64_eq, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CNE_I8]: [WasmOpcode.i64_ne, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CLT_I8]: [WasmOpcode.i64_lt_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CGT_I8]: [WasmOpcode.i64_gt_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CLE_I8]: [WasmOpcode.i64_le_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CGE_I8]: [WasmOpcode.i64_ge_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
-
- [MintOpcode.MINT_CLT_UN_I8]: [WasmOpcode.i64_lt_u, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CGT_UN_I8]: [WasmOpcode.i64_gt_u, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CLE_UN_I8]: [WasmOpcode.i64_le_u, WasmOpcode.i64_load, WasmOpcode.i32_store],
- [MintOpcode.MINT_CGE_UN_I8]: [WasmOpcode.i64_ge_u, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_ADD_R4]: [WasmOpcode.f32_add, WasmOpcode.f32_load, WasmOpcode.f32_store],
+ [MintOpcode.MINT_SUB_R4]: [WasmOpcode.f32_sub, WasmOpcode.f32_load, WasmOpcode.f32_store],
+ [MintOpcode.MINT_MUL_R4]: [WasmOpcode.f32_mul, WasmOpcode.f32_load, WasmOpcode.f32_store],
+ [MintOpcode.MINT_DIV_R4]: [WasmOpcode.f32_div, WasmOpcode.f32_load, WasmOpcode.f32_store],
+
+ [MintOpcode.MINT_ADD_R8]: [WasmOpcode.f64_add, WasmOpcode.f64_load, WasmOpcode.f64_store],
+ [MintOpcode.MINT_SUB_R8]: [WasmOpcode.f64_sub, WasmOpcode.f64_load, WasmOpcode.f64_store],
+ [MintOpcode.MINT_MUL_R8]: [WasmOpcode.f64_mul, WasmOpcode.f64_load, WasmOpcode.f64_store],
+ [MintOpcode.MINT_DIV_R8]: [WasmOpcode.f64_div, WasmOpcode.f64_load, WasmOpcode.f64_store],
+
+ [MintOpcode.MINT_CEQ_I4]: [WasmOpcode.i32_eq, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CNE_I4]: [WasmOpcode.i32_ne, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CLT_I4]: [WasmOpcode.i32_lt_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CGT_I4]: [WasmOpcode.i32_gt_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CLE_I4]: [WasmOpcode.i32_le_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CGE_I4]: [WasmOpcode.i32_ge_s, WasmOpcode.i32_load, WasmOpcode.i32_store],
+
+ [MintOpcode.MINT_CLT_UN_I4]: [WasmOpcode.i32_lt_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CGT_UN_I4]: [WasmOpcode.i32_gt_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CLE_UN_I4]: [WasmOpcode.i32_le_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CGE_UN_I4]: [WasmOpcode.i32_ge_u, WasmOpcode.i32_load, WasmOpcode.i32_store],
+
+ [MintOpcode.MINT_CEQ_I8]: [WasmOpcode.i64_eq, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CNE_I8]: [WasmOpcode.i64_ne, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CLT_I8]: [WasmOpcode.i64_lt_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CGT_I8]: [WasmOpcode.i64_gt_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CLE_I8]: [WasmOpcode.i64_le_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CGE_I8]: [WasmOpcode.i64_ge_s, WasmOpcode.i64_load, WasmOpcode.i32_store],
+
+ [MintOpcode.MINT_CLT_UN_I8]: [WasmOpcode.i64_lt_u, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CGT_UN_I8]: [WasmOpcode.i64_gt_u, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CLE_UN_I8]: [WasmOpcode.i64_le_u, WasmOpcode.i64_load, WasmOpcode.i32_store],
+ [MintOpcode.MINT_CGE_UN_I8]: [WasmOpcode.i64_ge_u, WasmOpcode.i64_load, WasmOpcode.i32_store],
};
-const relopbranchTable : { [opcode: number]: [comparisonOpcode: MintOpcode, immediateOpcode: WasmOpcode | false, isSafepoint: boolean] | MintOpcode | undefined } = {
- [MintOpcode.MINT_BEQ_I4_S]: MintOpcode.MINT_CEQ_I4,
- [MintOpcode.MINT_BNE_UN_I4_S]: MintOpcode.MINT_CNE_I4,
- [MintOpcode.MINT_BGT_I4_S]: MintOpcode.MINT_CGT_I4,
- [MintOpcode.MINT_BGT_UN_I4_S]: MintOpcode.MINT_CGT_UN_I4,
- [MintOpcode.MINT_BLT_I4_S]: MintOpcode.MINT_CLT_I4,
- [MintOpcode.MINT_BLT_UN_I4_S]: MintOpcode.MINT_CLT_UN_I4,
- [MintOpcode.MINT_BGE_I4_S]: MintOpcode.MINT_CGE_I4,
- [MintOpcode.MINT_BGE_UN_I4_S]: MintOpcode.MINT_CGE_UN_I4,
- [MintOpcode.MINT_BLE_I4_S]: MintOpcode.MINT_CLE_I4,
- [MintOpcode.MINT_BLE_UN_I4_S]: MintOpcode.MINT_CLE_UN_I4,
-
- [MintOpcode.MINT_BEQ_I4_SP]: [MintOpcode.MINT_CEQ_I4, false, true],
- [MintOpcode.MINT_BNE_UN_I4_SP]: [MintOpcode.MINT_CNE_I4, false, true],
- [MintOpcode.MINT_BGT_I4_SP]: [MintOpcode.MINT_CGT_I4, false, true],
- [MintOpcode.MINT_BGT_UN_I4_SP]: [MintOpcode.MINT_CGT_UN_I4, false, true],
- [MintOpcode.MINT_BLT_I4_SP]: [MintOpcode.MINT_CLT_I4, false, true],
- [MintOpcode.MINT_BLT_UN_I4_SP]: [MintOpcode.MINT_CLT_UN_I4, false, true],
- [MintOpcode.MINT_BGE_I4_SP]: [MintOpcode.MINT_CGE_I4, false, true],
- [MintOpcode.MINT_BGE_UN_I4_SP]: [MintOpcode.MINT_CGE_UN_I4, false, true],
- [MintOpcode.MINT_BLE_I4_SP]: [MintOpcode.MINT_CLE_I4, false, true],
- [MintOpcode.MINT_BLE_UN_I4_SP]: [MintOpcode.MINT_CLE_UN_I4, false, true],
-
- [MintOpcode.MINT_BEQ_I4_IMM_SP]: [MintOpcode.MINT_CEQ_I4, WasmOpcode.i32_const, true],
- [MintOpcode.MINT_BNE_UN_I4_IMM_SP]: [MintOpcode.MINT_CNE_I4, WasmOpcode.i32_const, true],
- [MintOpcode.MINT_BGT_I4_IMM_SP]: [MintOpcode.MINT_CGT_I4, WasmOpcode.i32_const, true],
+const relopbranchTable: { [opcode: number]: [comparisonOpcode: MintOpcode, immediateOpcode: WasmOpcode | false, isSafepoint: boolean] | MintOpcode | undefined } = {
+ [MintOpcode.MINT_BEQ_I4_S]: MintOpcode.MINT_CEQ_I4,
+ [MintOpcode.MINT_BNE_UN_I4_S]: MintOpcode.MINT_CNE_I4,
+ [MintOpcode.MINT_BGT_I4_S]: MintOpcode.MINT_CGT_I4,
+ [MintOpcode.MINT_BGT_UN_I4_S]: MintOpcode.MINT_CGT_UN_I4,
+ [MintOpcode.MINT_BLT_I4_S]: MintOpcode.MINT_CLT_I4,
+ [MintOpcode.MINT_BLT_UN_I4_S]: MintOpcode.MINT_CLT_UN_I4,
+ [MintOpcode.MINT_BGE_I4_S]: MintOpcode.MINT_CGE_I4,
+ [MintOpcode.MINT_BGE_UN_I4_S]: MintOpcode.MINT_CGE_UN_I4,
+ [MintOpcode.MINT_BLE_I4_S]: MintOpcode.MINT_CLE_I4,
+ [MintOpcode.MINT_BLE_UN_I4_S]: MintOpcode.MINT_CLE_UN_I4,
+
+ [MintOpcode.MINT_BEQ_I4_SP]: [MintOpcode.MINT_CEQ_I4, false, true],
+ [MintOpcode.MINT_BNE_UN_I4_SP]: [MintOpcode.MINT_CNE_I4, false, true],
+ [MintOpcode.MINT_BGT_I4_SP]: [MintOpcode.MINT_CGT_I4, false, true],
+ [MintOpcode.MINT_BGT_UN_I4_SP]: [MintOpcode.MINT_CGT_UN_I4, false, true],
+ [MintOpcode.MINT_BLT_I4_SP]: [MintOpcode.MINT_CLT_I4, false, true],
+ [MintOpcode.MINT_BLT_UN_I4_SP]: [MintOpcode.MINT_CLT_UN_I4, false, true],
+ [MintOpcode.MINT_BGE_I4_SP]: [MintOpcode.MINT_CGE_I4, false, true],
+ [MintOpcode.MINT_BGE_UN_I4_SP]: [MintOpcode.MINT_CGE_UN_I4, false, true],
+ [MintOpcode.MINT_BLE_I4_SP]: [MintOpcode.MINT_CLE_I4, false, true],
+ [MintOpcode.MINT_BLE_UN_I4_SP]: [MintOpcode.MINT_CLE_UN_I4, false, true],
+
+ [MintOpcode.MINT_BEQ_I4_IMM_SP]: [MintOpcode.MINT_CEQ_I4, WasmOpcode.i32_const, true],
+ [MintOpcode.MINT_BNE_UN_I4_IMM_SP]: [MintOpcode.MINT_CNE_I4, WasmOpcode.i32_const, true],
+ [MintOpcode.MINT_BGT_I4_IMM_SP]: [MintOpcode.MINT_CGT_I4, WasmOpcode.i32_const, true],
[MintOpcode.MINT_BGT_UN_I4_IMM_SP]: [MintOpcode.MINT_CGT_UN_I4, WasmOpcode.i32_const, true],
- [MintOpcode.MINT_BLT_I4_IMM_SP]: [MintOpcode.MINT_CLT_I4, WasmOpcode.i32_const, true],
+ [MintOpcode.MINT_BLT_I4_IMM_SP]: [MintOpcode.MINT_CLT_I4, WasmOpcode.i32_const, true],
[MintOpcode.MINT_BLT_UN_I4_IMM_SP]: [MintOpcode.MINT_CLT_UN_I4, WasmOpcode.i32_const, true],
- [MintOpcode.MINT_BGE_I4_IMM_SP]: [MintOpcode.MINT_CGE_I4, WasmOpcode.i32_const, true],
+ [MintOpcode.MINT_BGE_I4_IMM_SP]: [MintOpcode.MINT_CGE_I4, WasmOpcode.i32_const, true],
[MintOpcode.MINT_BGE_UN_I4_IMM_SP]: [MintOpcode.MINT_CGE_UN_I4, WasmOpcode.i32_const, true],
- [MintOpcode.MINT_BLE_I4_IMM_SP]: [MintOpcode.MINT_CLE_I4, WasmOpcode.i32_const, true],
+ [MintOpcode.MINT_BLE_I4_IMM_SP]: [MintOpcode.MINT_CLE_I4, WasmOpcode.i32_const, true],
[MintOpcode.MINT_BLE_UN_I4_IMM_SP]: [MintOpcode.MINT_CLE_UN_I4, WasmOpcode.i32_const, true],
- [MintOpcode.MINT_BEQ_I8_S]: MintOpcode.MINT_CEQ_I8,
- [MintOpcode.MINT_BNE_UN_I8_S]: MintOpcode.MINT_CNE_I8,
- [MintOpcode.MINT_BGT_I8_S]: MintOpcode.MINT_CGT_I8,
- [MintOpcode.MINT_BGT_UN_I8_S]: MintOpcode.MINT_CGT_UN_I8,
- [MintOpcode.MINT_BLT_I8_S]: MintOpcode.MINT_CLT_I8,
- [MintOpcode.MINT_BLT_UN_I8_S]: MintOpcode.MINT_CLT_UN_I8,
- [MintOpcode.MINT_BGE_I8_S]: MintOpcode.MINT_CGE_I8,
- [MintOpcode.MINT_BGE_UN_I8_S]: MintOpcode.MINT_CGE_UN_I8,
- [MintOpcode.MINT_BLE_I8_S]: MintOpcode.MINT_CLE_I8,
- [MintOpcode.MINT_BLE_UN_I8_S]: MintOpcode.MINT_CLE_UN_I8,
-
- [MintOpcode.MINT_BEQ_I8_IMM_SP]: [MintOpcode.MINT_CEQ_I8, WasmOpcode.i64_const, true],
+ [MintOpcode.MINT_BEQ_I8_S]: MintOpcode.MINT_CEQ_I8,
+ [MintOpcode.MINT_BNE_UN_I8_S]: MintOpcode.MINT_CNE_I8,
+ [MintOpcode.MINT_BGT_I8_S]: MintOpcode.MINT_CGT_I8,
+ [MintOpcode.MINT_BGT_UN_I8_S]: MintOpcode.MINT_CGT_UN_I8,
+ [MintOpcode.MINT_BLT_I8_S]: MintOpcode.MINT_CLT_I8,
+ [MintOpcode.MINT_BLT_UN_I8_S]: MintOpcode.MINT_CLT_UN_I8,
+ [MintOpcode.MINT_BGE_I8_S]: MintOpcode.MINT_CGE_I8,
+ [MintOpcode.MINT_BGE_UN_I8_S]: MintOpcode.MINT_CGE_UN_I8,
+ [MintOpcode.MINT_BLE_I8_S]: MintOpcode.MINT_CLE_I8,
+ [MintOpcode.MINT_BLE_UN_I8_S]: MintOpcode.MINT_CLE_UN_I8,
+
+ [MintOpcode.MINT_BEQ_I8_IMM_SP]: [MintOpcode.MINT_CEQ_I8, WasmOpcode.i64_const, true],
// FIXME: Missing compare opcode
// [MintOpcode.MINT_BNE_UN_I8_IMM_SP]: [MintOpcode.MINT_CNE_UN_I8, WasmOpcode.i64_const, true],
- [MintOpcode.MINT_BGT_I8_IMM_SP]: [MintOpcode.MINT_CGT_I8, WasmOpcode.i64_const, true],
+ [MintOpcode.MINT_BGT_I8_IMM_SP]: [MintOpcode.MINT_CGT_I8, WasmOpcode.i64_const, true],
[MintOpcode.MINT_BGT_UN_I8_IMM_SP]: [MintOpcode.MINT_CGT_UN_I8, WasmOpcode.i64_const, true],
- [MintOpcode.MINT_BLT_I8_IMM_SP]: [MintOpcode.MINT_CLT_I8, WasmOpcode.i64_const, true],
+ [MintOpcode.MINT_BLT_I8_IMM_SP]: [MintOpcode.MINT_CLT_I8, WasmOpcode.i64_const, true],
[MintOpcode.MINT_BLT_UN_I8_IMM_SP]: [MintOpcode.MINT_CLT_UN_I8, WasmOpcode.i64_const, true],
- [MintOpcode.MINT_BGE_I8_IMM_SP]: [MintOpcode.MINT_CGE_I8, WasmOpcode.i64_const, true],
+ [MintOpcode.MINT_BGE_I8_IMM_SP]: [MintOpcode.MINT_CGE_I8, WasmOpcode.i64_const, true],
[MintOpcode.MINT_BGE_UN_I8_IMM_SP]: [MintOpcode.MINT_CGE_UN_I8, WasmOpcode.i64_const, true],
- [MintOpcode.MINT_BLE_I8_IMM_SP]: [MintOpcode.MINT_CLE_I8, WasmOpcode.i64_const, true],
+ [MintOpcode.MINT_BLE_I8_IMM_SP]: [MintOpcode.MINT_CLE_I8, WasmOpcode.i64_const, true],
[MintOpcode.MINT_BLE_UN_I8_IMM_SP]: [MintOpcode.MINT_CLE_UN_I8, WasmOpcode.i64_const, true],
- [MintOpcode.MINT_BEQ_R4_S]: MintOpcode.MINT_CEQ_R4,
- [MintOpcode.MINT_BNE_UN_R4_S]: JiterpSpecialOpcode.CNE_UN_R4,
- [MintOpcode.MINT_BGT_R4_S]: MintOpcode.MINT_CGT_R4,
- [MintOpcode.MINT_BGT_UN_R4_S]: MintOpcode.MINT_CGT_UN_R4,
- [MintOpcode.MINT_BLT_R4_S]: MintOpcode.MINT_CLT_R4,
- [MintOpcode.MINT_BLT_UN_R4_S]: MintOpcode.MINT_CLT_UN_R4,
- [MintOpcode.MINT_BGE_R4_S]: MintOpcode.MINT_CGE_R4,
- [MintOpcode.MINT_BGE_UN_R4_S]: JiterpSpecialOpcode.CGE_UN_R4,
- [MintOpcode.MINT_BLE_R4_S]: MintOpcode.MINT_CLE_R4,
- [MintOpcode.MINT_BLE_UN_R4_S]: JiterpSpecialOpcode.CLE_UN_R4,
-
- [MintOpcode.MINT_BEQ_R8_S]: MintOpcode.MINT_CEQ_R8,
- [MintOpcode.MINT_BNE_UN_R8_S]: JiterpSpecialOpcode.CNE_UN_R8,
- [MintOpcode.MINT_BGT_R8_S]: MintOpcode.MINT_CGT_R8,
- [MintOpcode.MINT_BGT_UN_R8_S]: MintOpcode.MINT_CGT_UN_R8,
- [MintOpcode.MINT_BLT_R8_S]: MintOpcode.MINT_CLT_R8,
- [MintOpcode.MINT_BLT_UN_R8_S]: MintOpcode.MINT_CLT_UN_R8,
- [MintOpcode.MINT_BGE_R8_S]: MintOpcode.MINT_CGE_R8,
- [MintOpcode.MINT_BGE_UN_R8_S]: JiterpSpecialOpcode.CGE_UN_R8,
- [MintOpcode.MINT_BLE_R8_S]: MintOpcode.MINT_CLE_R8,
- [MintOpcode.MINT_BLE_UN_R8_S]: JiterpSpecialOpcode.CLE_UN_R8,
+ [MintOpcode.MINT_BEQ_R4_S]: MintOpcode.MINT_CEQ_R4,
+ [MintOpcode.MINT_BNE_UN_R4_S]: JiterpSpecialOpcode.CNE_UN_R4,
+ [MintOpcode.MINT_BGT_R4_S]: MintOpcode.MINT_CGT_R4,
+ [MintOpcode.MINT_BGT_UN_R4_S]: MintOpcode.MINT_CGT_UN_R4,
+ [MintOpcode.MINT_BLT_R4_S]: MintOpcode.MINT_CLT_R4,
+ [MintOpcode.MINT_BLT_UN_R4_S]: MintOpcode.MINT_CLT_UN_R4,
+ [MintOpcode.MINT_BGE_R4_S]: MintOpcode.MINT_CGE_R4,
+ [MintOpcode.MINT_BGE_UN_R4_S]: JiterpSpecialOpcode.CGE_UN_R4,
+ [MintOpcode.MINT_BLE_R4_S]: MintOpcode.MINT_CLE_R4,
+ [MintOpcode.MINT_BLE_UN_R4_S]: JiterpSpecialOpcode.CLE_UN_R4,
+
+ [MintOpcode.MINT_BEQ_R8_S]: MintOpcode.MINT_CEQ_R8,
+ [MintOpcode.MINT_BNE_UN_R8_S]: JiterpSpecialOpcode.CNE_UN_R8,
+ [MintOpcode.MINT_BGT_R8_S]: MintOpcode.MINT_CGT_R8,
+ [MintOpcode.MINT_BGT_UN_R8_S]: MintOpcode.MINT_CGT_UN_R8,
+ [MintOpcode.MINT_BLT_R8_S]: MintOpcode.MINT_CLT_R8,
+ [MintOpcode.MINT_BLT_UN_R8_S]: MintOpcode.MINT_CLT_UN_R8,
+ [MintOpcode.MINT_BGE_R8_S]: MintOpcode.MINT_CGE_R8,
+ [MintOpcode.MINT_BGE_UN_R8_S]: JiterpSpecialOpcode.CGE_UN_R8,
+ [MintOpcode.MINT_BLE_R8_S]: MintOpcode.MINT_CLE_R8,
+ [MintOpcode.MINT_BLE_UN_R8_S]: JiterpSpecialOpcode.CLE_UN_R8,
};
-function emit_binop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode) : boolean {
+function emit_binop(builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode): boolean {
// operands are popped right to left, which means you build the arg list left to right
- let lhsLoadOp : WasmOpcode, rhsLoadOp : WasmOpcode, storeOp : WasmOpcode,
+ let lhsLoadOp: WasmOpcode, rhsLoadOp: WasmOpcode, storeOp: WasmOpcode,
lhsVar = "math_lhs32", rhsVar = "math_rhs32",
- info : OpRec3 | OpRec4 | undefined,
+ info: OpRec3 | OpRec4 | undefined,
operandsCached = false;
const intrinsicFpBinop = intrinsicFpBinops[opcode];
@@ -2454,7 +2456,7 @@ function emit_binop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode
return true;
}
-function emit_unop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode) : boolean {
+function emit_unop(builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode): boolean {
// operands are popped right to left, which means you build the arg list left to right
const info = unopTable[opcode];
if (!info)
@@ -2577,7 +2579,7 @@ function emit_unop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode)
return true;
}
-function append_call_handler_store_ret_ip (
+function append_call_handler_store_ret_ip(
builder: WasmBuilder, ip: MintOpcodePtr,
frame: NativePointer, opcode: MintOpcode
) {
@@ -2597,10 +2599,10 @@ function append_call_handler_store_ret_ip (
builder.callHandlerReturnAddresses.push(retIp);
}
-function emit_branch (
+function emit_branch(
builder: WasmBuilder, ip: MintOpcodePtr,
frame: NativePointer, opcode: MintOpcode, displacement?: number
-) : boolean {
+): boolean {
const isSafepoint = (opcode >= MintOpcode.MINT_BRFALSE_I4_SP) &&
(opcode <= MintOpcode.MINT_BLT_UN_I8_IMM_SP);
eraseInferredState();
@@ -2761,10 +2763,10 @@ function emit_branch (
return true;
}
-function emit_relop_branch (
+function emit_relop_branch(
builder: WasmBuilder, ip: MintOpcodePtr,
frame: NativePointer, opcode: MintOpcode
-) : boolean {
+): boolean {
const relopBranchInfo = relopbranchTable[opcode];
if (!relopBranchInfo)
return false;
@@ -2824,61 +2826,61 @@ function emit_relop_branch (
return emit_branch(builder, ip, frame, opcode, displacement);
}
-const mathIntrinsicTable : { [opcode: number] : [isUnary: boolean, isF32: boolean, opcodeOrFuncName: WasmOpcode | string] } = {
- [MintOpcode.MINT_SQRT]: [true, false, WasmOpcode.f64_sqrt],
- [MintOpcode.MINT_SQRTF]: [true, true, WasmOpcode.f32_sqrt],
- [MintOpcode.MINT_CEILING]: [true, false, WasmOpcode.f64_ceil],
- [MintOpcode.MINT_CEILINGF]: [true, true, WasmOpcode.f32_ceil],
- [MintOpcode.MINT_FLOOR]: [true, false, WasmOpcode.f64_floor],
- [MintOpcode.MINT_FLOORF]: [true, true, WasmOpcode.f32_floor],
- [MintOpcode.MINT_ABS]: [true, false, WasmOpcode.f64_abs],
- [MintOpcode.MINT_ABSF]: [true, true, WasmOpcode.f32_abs],
-
- [MintOpcode.MINT_ACOS]: [true, false, "acos"],
- [MintOpcode.MINT_ACOSF]: [true, true, "acosf"],
- [MintOpcode.MINT_ACOSH]: [true, false, "acosh"],
- [MintOpcode.MINT_ACOSHF]: [true, true, "acoshf"],
- [MintOpcode.MINT_COS]: [true, false, "cos"],
- [MintOpcode.MINT_COSF]: [true, true, "cosf"],
- [MintOpcode.MINT_ASIN]: [true, false, "asin"],
- [MintOpcode.MINT_ASINF]: [true, true, "asinf"],
- [MintOpcode.MINT_ASINH]: [true, false, "asinh"],
- [MintOpcode.MINT_ASINHF]: [true, true, "asinhf"],
- [MintOpcode.MINT_SIN]: [true, false, "sin"],
- [MintOpcode.MINT_SINF]: [true, true, "sinf"],
- [MintOpcode.MINT_ATAN]: [true, false, "atan"],
- [MintOpcode.MINT_ATANF]: [true, true, "atanf"],
- [MintOpcode.MINT_ATANH]: [true, false, "atanh"],
- [MintOpcode.MINT_ATANHF]: [true, true, "atanhf"],
- [MintOpcode.MINT_TAN]: [true, false, "tan"],
- [MintOpcode.MINT_TANF]: [true, true, "tanf"],
- [MintOpcode.MINT_CBRT]: [true, false, "cbrt"],
- [MintOpcode.MINT_CBRTF]: [true, true, "cbrtf"],
- [MintOpcode.MINT_EXP]: [true, false, "exp"],
- [MintOpcode.MINT_EXPF]: [true, true, "expf"],
- [MintOpcode.MINT_LOG]: [true, false, "log"],
- [MintOpcode.MINT_LOGF]: [true, true, "logf"],
- [MintOpcode.MINT_LOG2]: [true, false, "log2"],
- [MintOpcode.MINT_LOG2F]: [true, true, "log2f"],
- [MintOpcode.MINT_LOG10]: [true, false, "log10"],
- [MintOpcode.MINT_LOG10F]: [true, true, "log10f"],
-
- [MintOpcode.MINT_MIN]: [false, false, WasmOpcode.f64_min],
- [MintOpcode.MINT_MINF]: [false, true, WasmOpcode.f32_min],
- [MintOpcode.MINT_MAX]: [false, false, WasmOpcode.f64_max],
- [MintOpcode.MINT_MAXF]: [false, true, WasmOpcode.f32_max],
-
- [MintOpcode.MINT_ATAN2]: [false, false, "atan2"],
- [MintOpcode.MINT_ATAN2F]: [false, true, "atan2f"],
- [MintOpcode.MINT_POW]: [false, false, "pow"],
- [MintOpcode.MINT_POWF]: [false, true, "powf"],
- [MintOpcode.MINT_REM_R8]: [false, false, "fmod"],
- [MintOpcode.MINT_REM_R4]: [false, true, "fmodf"],
+const mathIntrinsicTable: { [opcode: number]: [isUnary: boolean, isF32: boolean, opcodeOrFuncName: WasmOpcode | string] } = {
+ [MintOpcode.MINT_SQRT]: [true, false, WasmOpcode.f64_sqrt],
+ [MintOpcode.MINT_SQRTF]: [true, true, WasmOpcode.f32_sqrt],
+ [MintOpcode.MINT_CEILING]: [true, false, WasmOpcode.f64_ceil],
+ [MintOpcode.MINT_CEILINGF]: [true, true, WasmOpcode.f32_ceil],
+ [MintOpcode.MINT_FLOOR]: [true, false, WasmOpcode.f64_floor],
+ [MintOpcode.MINT_FLOORF]: [true, true, WasmOpcode.f32_floor],
+ [MintOpcode.MINT_ABS]: [true, false, WasmOpcode.f64_abs],
+ [MintOpcode.MINT_ABSF]: [true, true, WasmOpcode.f32_abs],
+
+ [MintOpcode.MINT_ACOS]: [true, false, "acos"],
+ [MintOpcode.MINT_ACOSF]: [true, true, "acosf"],
+ [MintOpcode.MINT_ACOSH]: [true, false, "acosh"],
+ [MintOpcode.MINT_ACOSHF]: [true, true, "acoshf"],
+ [MintOpcode.MINT_COS]: [true, false, "cos"],
+ [MintOpcode.MINT_COSF]: [true, true, "cosf"],
+ [MintOpcode.MINT_ASIN]: [true, false, "asin"],
+ [MintOpcode.MINT_ASINF]: [true, true, "asinf"],
+ [MintOpcode.MINT_ASINH]: [true, false, "asinh"],
+ [MintOpcode.MINT_ASINHF]: [true, true, "asinhf"],
+ [MintOpcode.MINT_SIN]: [true, false, "sin"],
+ [MintOpcode.MINT_SINF]: [true, true, "sinf"],
+ [MintOpcode.MINT_ATAN]: [true, false, "atan"],
+ [MintOpcode.MINT_ATANF]: [true, true, "atanf"],
+ [MintOpcode.MINT_ATANH]: [true, false, "atanh"],
+ [MintOpcode.MINT_ATANHF]: [true, true, "atanhf"],
+ [MintOpcode.MINT_TAN]: [true, false, "tan"],
+ [MintOpcode.MINT_TANF]: [true, true, "tanf"],
+ [MintOpcode.MINT_CBRT]: [true, false, "cbrt"],
+ [MintOpcode.MINT_CBRTF]: [true, true, "cbrtf"],
+ [MintOpcode.MINT_EXP]: [true, false, "exp"],
+ [MintOpcode.MINT_EXPF]: [true, true, "expf"],
+ [MintOpcode.MINT_LOG]: [true, false, "log"],
+ [MintOpcode.MINT_LOGF]: [true, true, "logf"],
+ [MintOpcode.MINT_LOG2]: [true, false, "log2"],
+ [MintOpcode.MINT_LOG2F]: [true, true, "log2f"],
+ [MintOpcode.MINT_LOG10]: [true, false, "log10"],
+ [MintOpcode.MINT_LOG10F]: [true, true, "log10f"],
+
+ [MintOpcode.MINT_MIN]: [false, false, WasmOpcode.f64_min],
+ [MintOpcode.MINT_MINF]: [false, true, WasmOpcode.f32_min],
+ [MintOpcode.MINT_MAX]: [false, false, WasmOpcode.f64_max],
+ [MintOpcode.MINT_MAXF]: [false, true, WasmOpcode.f32_max],
+
+ [MintOpcode.MINT_ATAN2]: [false, false, "atan2"],
+ [MintOpcode.MINT_ATAN2F]: [false, true, "atan2f"],
+ [MintOpcode.MINT_POW]: [false, false, "pow"],
+ [MintOpcode.MINT_POWF]: [false, true, "powf"],
+ [MintOpcode.MINT_REM_R8]: [false, false, "fmod"],
+ [MintOpcode.MINT_REM_R4]: [false, true, "fmodf"],
};
-function emit_math_intrinsic (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode) : boolean {
- let isUnary : boolean, isF32 : boolean, name: string | undefined;
- let wasmOp : WasmOpcode | undefined;
+function emit_math_intrinsic(builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode): boolean {
+ let isUnary: boolean, isF32: boolean, name: string | undefined;
+ let wasmOp: WasmOpcode | undefined;
const destOffset = getArgU16(ip, 1),
srcOffset = getArgU16(ip, 2),
rhsOffset = getArgU16(ip, 3);
@@ -2924,7 +2926,7 @@ function emit_math_intrinsic (builder: WasmBuilder, ip: MintOpcodePtr, opcode: M
}
}
-function emit_indirectop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode) : boolean {
+function emit_indirectop(builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode): boolean {
const isLoad = (opcode >= MintOpcode.MINT_LDIND_I1) &&
(opcode <= MintOpcode.MINT_LDIND_OFFSET_ADD_MUL_IMM_I8);
const isAddMul = (
@@ -2934,17 +2936,19 @@ function emit_indirectop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintO
const isOffset = (
(opcode >= MintOpcode.MINT_LDIND_OFFSET_I1) &&
(opcode <= MintOpcode.MINT_LDIND_OFFSET_IMM_I8)
- ) || (
- (opcode >= MintOpcode.MINT_STIND_OFFSET_I1) &&
- (opcode <= MintOpcode.MINT_STIND_OFFSET_IMM_I8)
- ) || isAddMul;
+ ) ||
+ (
+ (opcode >= MintOpcode.MINT_STIND_OFFSET_I1) &&
+ (opcode <= MintOpcode.MINT_STIND_OFFSET_IMM_I8)
+ ) || isAddMul;
const isImm = (
(opcode >= MintOpcode.MINT_LDIND_OFFSET_IMM_I1) &&
(opcode <= MintOpcode.MINT_LDIND_OFFSET_IMM_I8)
- ) || (
- (opcode >= MintOpcode.MINT_STIND_OFFSET_IMM_I1) &&
- (opcode <= MintOpcode.MINT_STIND_OFFSET_IMM_I8)
- ) || isAddMul;
+ ) ||
+ (
+ (opcode >= MintOpcode.MINT_STIND_OFFSET_IMM_I1) &&
+ (opcode <= MintOpcode.MINT_STIND_OFFSET_IMM_I8)
+ ) || isAddMul;
let valueVarIndex, addressVarIndex, offsetVarIndex = -1, constantOffset = 0,
constantMultiplier = 1;
@@ -2984,7 +2988,7 @@ function emit_indirectop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintO
valueVarIndex = getArgU16(ip, 2);
}
- let getter : WasmOpcode, setter = WasmOpcode.i32_store;
+ let getter: WasmOpcode, setter = WasmOpcode.i32_store;
switch (opcode) {
case MintOpcode.MINT_LDIND_I1:
case MintOpcode.MINT_LDIND_OFFSET_I1:
@@ -3120,7 +3124,7 @@ function emit_indirectop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintO
return true;
}
-function append_getelema1 (
+function append_getelema1(
builder: WasmBuilder, ip: MintOpcodePtr,
objectOffset: number, indexOffset: number, elementSize: number
) {
@@ -3157,11 +3161,9 @@ function append_getelema1 (
// append_getelema1 leaves the address on the stack
}
-function emit_arrayop (builder: WasmBuilder, frame: NativePointer, ip: MintOpcodePtr, opcode: MintOpcode) : boolean {
- const isLoad = (
- (opcode <= MintOpcode.MINT_LDELEMA_TC) &&
- (opcode >= MintOpcode.MINT_LDELEM_I1)
- ) || (opcode === MintOpcode.MINT_LDLEN),
+function emit_arrayop(builder: WasmBuilder, frame: NativePointer, ip: MintOpcodePtr, opcode: MintOpcode): boolean {
+ const isLoad = ((opcode <= MintOpcode.MINT_LDELEMA_TC) && (opcode >= MintOpcode.MINT_LDELEM_I1)) ||
+ (opcode === MintOpcode.MINT_LDLEN),
objectOffset = getArgU16(ip, isLoad ? 2 : 1),
valueOffset = getArgU16(ip, isLoad ? 1 : 3),
indexOffset = getArgU16(ip, isLoad ? 3 : 2);
@@ -3313,9 +3315,9 @@ function emit_arrayop (builder: WasmBuilder, frame: NativePointer, ip: MintOpcod
const vec128Test =
"0061736d0100000001040160000003020100070801047465737400000a090107004100fd111a0b";
-let wasmSimdSupported : boolean | undefined;
+let wasmSimdSupported: boolean | undefined;
-function getIsWasmSimdSupported () : boolean {
+function getIsWasmSimdSupported(): boolean {
if (wasmSimdSupported !== undefined)
return wasmSimdSupported;
@@ -3334,10 +3336,10 @@ function getIsWasmSimdSupported () : boolean {
return wasmSimdSupported;
}
-function get_import_name (
+function get_import_name(
builder: WasmBuilder, typeName: string,
functionPtr: number
-) : string {
+): string {
const name = `${typeName}_${functionPtr.toString(16)}`;
if (typeof (builder.importedFunctions[name]) !== "object")
builder.defineImportedFunction("s", name, typeName, false, functionPtr);
@@ -3366,11 +3368,11 @@ const simdCreateStoreOps = {
[MintOpcode.MINT_SIMD_V128_I8_CREATE]: WasmOpcode.i64_store,
};
-function emit_simd (
+function emit_simd(
builder: WasmBuilder, ip: MintOpcodePtr,
opcode: MintOpcode, opname: string,
argCount: number, index: number
-) : boolean {
+): boolean {
// First, if compiling an intrinsic attempt to emit the special vectorized implementation
// We only do this if SIMD is enabled since we'll be using the v128 opcodes.
if (builder.options.enableSimd && getIsWasmSimdSupported()) {
@@ -3467,24 +3469,24 @@ function emit_simd (
}
}
-function append_simd_store (builder: WasmBuilder, ip: MintOpcodePtr) {
+function append_simd_store(builder: WasmBuilder, ip: MintOpcodePtr) {
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_store);
}
-function append_simd_2_load (builder: WasmBuilder, ip: MintOpcodePtr, loadOp?: WasmSimdOpcode) {
+function append_simd_2_load(builder: WasmBuilder, ip: MintOpcodePtr, loadOp?: WasmSimdOpcode) {
builder.local("pLocals");
// This || is harmless since v128_load is 0
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.PREFIX_simd, loadOp || WasmSimdOpcode.v128_load);
}
-function append_simd_3_load (builder: WasmBuilder, ip: MintOpcodePtr) {
+function append_simd_3_load(builder: WasmBuilder, ip: MintOpcodePtr) {
builder.local("pLocals");
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load);
// FIXME: Can rhs be a scalar? We handle shifts separately already
append_ldloc(builder, getArgU16(ip, 3), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load);
}
-function append_simd_4_load (builder: WasmBuilder, ip: MintOpcodePtr) {
+function append_simd_4_load(builder: WasmBuilder, ip: MintOpcodePtr) {
builder.local("pLocals");
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load);
append_ldloc(builder, getArgU16(ip, 3), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load);
@@ -3507,14 +3509,14 @@ const simdShiftTable = new Set([
SimdIntrinsic3.V128_I8_URIGHT_SHIFT,
]);
-function append_stloc_simd_zero (builder: WasmBuilder, offset: number) {
+function append_stloc_simd_zero(builder: WasmBuilder, offset: number) {
builder.local("pLocals");
builder.appendSimd(WasmSimdOpcode.v128_const);
builder.appendBytes(new Uint8Array(sizeOfV128));
append_stloc_tail(builder, offset, WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_store);
}
-function emit_simd_2 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic2) : boolean {
+function emit_simd_2(builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic2): boolean {
const simple = cwraps.mono_jiterp_get_simd_opcode(1, index);
if (simple) {
append_simd_2_load(builder, ip);
@@ -3575,7 +3577,7 @@ function emit_simd_2 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrin
}
}
-function emit_simd_3 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic3) : boolean {
+function emit_simd_3(builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic3): boolean {
const simple = cwraps.mono_jiterp_get_simd_opcode(2, index);
if (simple) {
const isShift = simdShiftTable.has(index);
@@ -3611,7 +3613,7 @@ function emit_simd_3 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrin
return false;
}
-function emit_simd_4 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic4) : boolean {
+function emit_simd_4(builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic4): boolean {
const simple = cwraps.mono_jiterp_get_simd_opcode(3, index);
if (simple) {
append_simd_4_load(builder, ip);
@@ -3636,7 +3638,7 @@ function emit_simd_4 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrin
}
}
-function append_safepoint (builder: WasmBuilder, ip: MintOpcodePtr) {
+function append_safepoint(builder: WasmBuilder, ip: MintOpcodePtr) {
// Check whether a safepoint is required
builder.ptr_const(cwraps.mono_jiterp_get_polling_required_address());
builder.appendU8(WasmOpcode.i32_load);
diff --git a/src/mono/wasm/runtime/jiterpreter.ts b/src/mono/wasm/runtime/jiterpreter.ts
index 2bb9354443c53..81fe2382d55c3 100644
--- a/src/mono/wasm/runtime/jiterpreter.ts
+++ b/src/mono/wasm/runtime/jiterpreter.ts
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { mono_assert, MonoMethod } from "./types";
+import { MonoMethod } from "./types/internal";
import { NativePointer } from "./types/emscripten";
import { Module, runtimeHelpers } from "./globals";
import {
@@ -329,7 +329,7 @@ function wrap_trace_function(
if (!_wrap_trace_function) {
// If we used a regular closure, the js console would print the entirety of
- // dotnet.js when printing an error stack trace, which is... not helpful
+ // dotnet.native.js when printing an error stack trace, which is... not helpful
const js = `return function trace_enter (locals) {
let threw = true;
try {
diff --git a/src/mono/wasm/runtime/loader/assets.ts b/src/mono/wasm/runtime/loader/assets.ts
new file mode 100644
index 0000000000000..a99f80a754a33
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/assets.ts
@@ -0,0 +1,419 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import type { AssetEntryInternal, PromiseAndController } from "../types/internal";
+import type { AssetBehaviours, AssetEntry, LoadingResource, ResourceRequest } from "../types";
+import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, loaderHelpers, runtimeHelpers } from "./globals";
+import { createPromiseController } from "./promise-controller";
+
+
+let throttlingPromise: PromiseAndController | undefined;
+// in order to prevent net::ERR_INSUFFICIENT_RESOURCES if we start downloading too many files at same time
+let parallel_count = 0;
+
+// don't `fetch` javaScript files
+const skipDownloadsByAssetTypes: {
+ [k: string]: boolean
+} = {
+ "js-module-threads": true,
+ "js-module-runtime": true,
+ "js-module-native": true,
+ "js-module-dotnet": true,
+ "dotnetwasm": true,
+};
+
+// `response.arrayBuffer()` can't be called twice. Some usecases are calling it on response in the instantiation.
+const skipBufferByAssetTypes: {
+ [k: string]: boolean
+} = {
+ "dotnetwasm": true,
+ "symbols": true,
+};
+
+const containedInSnapshotByAssetTypes: {
+ [k: string]: boolean
+} = {
+ "resource": true,
+ "assembly": true,
+ "pdb": true,
+ "heap": true,
+ "icu": true,
+ "js-module-threads": true,
+ "js-module-runtime": true,
+ "js-module-native": true,
+ "js-module-dotnet": true,
+ "dotnetwasm": true,
+};
+
+// these assets are instantiated differently than the main flow
+const skipInstantiateByAssetTypes: {
+ [k: string]: boolean
+} = {
+ "js-module-threads": true,
+ "js-module-runtime": true,
+ "js-module-native": true,
+ "js-module-dotnet": true,
+ "dotnetwasm": true,
+ "symbols": true,
+};
+
+export function shouldLoadIcuAsset(asset: AssetEntryInternal): boolean {
+ return !(asset.behavior == "icu" && asset.name != loaderHelpers.preferredIcuAsset);
+}
+
+export function resolve_asset_path(behavior: AssetBehaviours): AssetEntryInternal {
+ const asset: AssetEntryInternal | undefined = loaderHelpers.config.assets?.find(a => a.behavior == behavior);
+ mono_assert(asset, () => `Can't find asset for ${behavior}`);
+ if (!asset.resolvedUrl) {
+ asset.resolvedUrl = resolve_path(asset, "");
+ }
+ return asset;
+}
+export async function mono_download_assets(): Promise {
+ if (loaderHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_download_assets");
+ loaderHelpers.maxParallelDownloads = loaderHelpers.config.maxParallelDownloads || loaderHelpers.maxParallelDownloads;
+ loaderHelpers.enableDownloadRetry = loaderHelpers.config.enableDownloadRetry || loaderHelpers.enableDownloadRetry;
+ try {
+ const alwaysLoadedAssets: AssetEntryInternal[] = [];
+ const containedInSnapshotAssets: AssetEntryInternal[] = [];
+ const promises_of_assets: Promise[] = [];
+
+ for (const a of loaderHelpers.config.assets!) {
+ const asset: AssetEntryInternal = a;
+ mono_assert(typeof asset === "object", "asset must be object");
+ mono_assert(typeof asset.behavior === "string", "asset behavior must be known string");
+ mono_assert(typeof asset.name === "string", "asset name must be string");
+ mono_assert(!asset.resolvedUrl || typeof asset.resolvedUrl === "string", "asset resolvedUrl could be string");
+ mono_assert(!asset.hash || typeof asset.hash === "string", "asset resolvedUrl could be string");
+ mono_assert(!asset.pendingDownload || typeof asset.pendingDownload === "object", "asset pendingDownload could be object");
+ if (containedInSnapshotByAssetTypes[asset.behavior]) {
+ containedInSnapshotAssets.push(asset);
+ } else {
+ alwaysLoadedAssets.push(asset);
+ }
+ }
+
+ const countAndStartDownload = (asset: AssetEntryInternal) => {
+ if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
+ loaderHelpers.expected_instantiated_assets_count++;
+ }
+ if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
+ loaderHelpers.expected_downloaded_assets_count++;
+ promises_of_assets.push(start_asset_download(asset));
+ }
+ };
+
+ // start fetching assets in parallel, only assets which are not part of memory snapshot
+ for (const asset of alwaysLoadedAssets) {
+ countAndStartDownload(asset);
+ }
+
+ // continue after the dotnet.runtime.js was loaded
+ await loaderHelpers.runtimeModuleLoaded.promise;
+
+ // continue after we know if memory snapshot is available or not
+ await runtimeHelpers.memorySnapshotSkippedOrDone.promise;
+
+ // start fetching assets in parallel, only if memory snapshot is not available.
+ for (const asset of containedInSnapshotAssets) {
+ if (!runtimeHelpers.loadedMemorySnapshot) {
+ countAndStartDownload(asset);
+ } else {
+ // Otherwise cleanup in case we were given pending download. It would be even better if we could abort the download.
+ cleanupAsset(asset);
+ // tell the debugger it is loaded
+ if (asset.behavior == "resource" || asset.behavior == "assembly" || asset.behavior == "pdb") {
+ const url = resolve_path(asset, "");
+ const virtualName: string = typeof (asset.virtualPath) === "string"
+ ? asset.virtualPath
+ : asset.name;
+ loaderHelpers._loaded_files.push({ url: url, file: virtualName });
+ }
+ }
+ }
+
+ loaderHelpers.allDownloadsQueued.promise_control.resolve();
+ await loaderHelpers.runtimeModuleLoaded.promise;
+
+ const promises_of_asset_instantiation: Promise[] = [];
+ for (const downloadPromise of promises_of_assets) {
+ promises_of_asset_instantiation.push((async () => {
+ const asset = await downloadPromise;
+ if (asset.buffer) {
+ if (!skipInstantiateByAssetTypes[asset.behavior]) {
+ const url = asset.pendingDownloadInternal!.url;
+ mono_assert(asset.buffer && typeof asset.buffer === "object", "asset buffer must be array or buffer like");
+ const data = new Uint8Array(asset.buffer!);
+ cleanupAsset(asset);
+
+ // wait till after onRuntimeInitialized and after memory snapshot is loaded or skipped
+
+ await runtimeHelpers.beforeOnRuntimeInitialized.promise;
+ await runtimeHelpers.memorySnapshotSkippedOrDone.promise;
+ runtimeHelpers.instantiate_asset(asset, url, data);
+ }
+ if (asset.behavior === "symbols") {
+ await runtimeHelpers.instantiate_symbols_asset(asset);
+ cleanupAsset(asset);
+ }
+ } else {
+ const headersOnly = skipBufferByAssetTypes[asset.behavior];
+ if (!headersOnly) {
+ mono_assert(asset.isOptional, "Expected asset to have the downloaded buffer");
+ if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
+ loaderHelpers.expected_downloaded_assets_count--;
+ }
+ if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
+ loaderHelpers.expected_instantiated_assets_count--;
+ }
+ } else {
+ if (skipBufferByAssetTypes[asset.behavior]) {
+ ++loaderHelpers.actual_downloaded_assets_count;
+ }
+ }
+ }
+ })());
+ }
+
+ // this await will get past the onRuntimeInitialized because we are not blocking via addRunDependency
+ // and we are not awating it here
+ Promise.all(promises_of_asset_instantiation).then(() => {
+ runtimeHelpers.allAssetsInMemory.promise_control.resolve();
+ }).catch(e => {
+ loaderHelpers.err("MONO_WASM: Error in mono_download_assets: " + e);
+ loaderHelpers.abort_startup(e, true);
+ });
+ // OPTIMIZATION explained:
+ // we do it this way so that we could allocate memory immediately after asset is downloaded (and after onRuntimeInitialized which happened already)
+ // spreading in time
+ // rather than to block all downloads after onRuntimeInitialized or block onRuntimeInitialized after all downloads are done. That would create allocation burst.
+ } catch (e: any) {
+ loaderHelpers.err("MONO_WASM: Error in mono_download_assets: " + e);
+ throw e;
+ }
+}
+
+export function delay(ms: number): Promise {
+ return new Promise(resolve => setTimeout(resolve, ms));
+}
+
+// FIXME: Connection reset is probably the only good one for which we should retry
+export async function start_asset_download(asset: AssetEntryInternal): Promise {
+ try {
+ return await start_asset_download_with_throttle(asset);
+ } catch (err: any) {
+ if (!loaderHelpers.enableDownloadRetry) {
+ // we will not re-try if disabled
+ throw err;
+ }
+ if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) {
+ // we will not re-try on shell
+ throw err;
+ }
+ if (asset.pendingDownload && asset.pendingDownloadInternal == asset.pendingDownload) {
+ // we will not re-try with external source
+ throw err;
+ }
+ if (asset.resolvedUrl && asset.resolvedUrl.indexOf("file://") != -1) {
+ // we will not re-try with local file
+ throw err;
+ }
+ if (err && err.status == 404) {
+ // we will not re-try with 404
+ throw err;
+ }
+ asset.pendingDownloadInternal = undefined;
+ // second attempt only after all first attempts are queued
+ await loaderHelpers.allDownloadsQueued.promise;
+ try {
+ return await start_asset_download_with_throttle(asset);
+ } catch (err) {
+ asset.pendingDownloadInternal = undefined;
+ // third attempt after small delay
+ await delay(100);
+ return await start_asset_download_with_throttle(asset);
+ }
+ }
+}
+
+async function start_asset_download_with_throttle(asset: AssetEntryInternal): Promise {
+ // we don't addRunDependency to allow download in parallel with onRuntimeInitialized event!
+ while (throttlingPromise) {
+ await throttlingPromise.promise;
+ }
+ try {
+ ++parallel_count;
+ if (parallel_count == loaderHelpers.maxParallelDownloads) {
+ if (loaderHelpers.diagnosticTracing)
+ console.debug("MONO_WASM: Throttling further parallel downloads");
+ throttlingPromise = createPromiseController();
+ }
+
+ const response = await start_asset_download_sources(asset);
+ if (!response) {
+ return asset;
+ }
+ const skipBuffer = skipBufferByAssetTypes[asset.behavior];
+ if (skipBuffer) {
+ return asset;
+ }
+ asset.buffer = await response.arrayBuffer();
+ ++loaderHelpers.actual_downloaded_assets_count;
+ return asset;
+ }
+ finally {
+ --parallel_count;
+ if (throttlingPromise && parallel_count == loaderHelpers.maxParallelDownloads - 1) {
+ if (loaderHelpers.diagnosticTracing)
+ console.debug("MONO_WASM: Resuming more parallel downloads");
+ const old_throttling = throttlingPromise;
+ throttlingPromise = undefined;
+ old_throttling.promise_control.resolve();
+ }
+ }
+}
+
+async function start_asset_download_sources(asset: AssetEntryInternal): Promise {
+ // we don't addRunDependency to allow download in parallel with onRuntimeInitialized event!
+ if (asset.pendingDownload) {
+ asset.pendingDownloadInternal = asset.pendingDownload;
+ }
+ if (asset.pendingDownloadInternal && asset.pendingDownloadInternal.response) {
+ return asset.pendingDownloadInternal.response;
+ }
+ if (asset.buffer) {
+ const buffer = asset.buffer;
+ asset.buffer = null as any; // GC
+ asset.pendingDownloadInternal = {
+ url: "undefined://" + asset.name,
+ name: asset.name,
+ response: Promise.resolve({
+ arrayBuffer: () => buffer,
+ headers: {
+ get: () => undefined,
+ }
+ }) as any
+ };
+ return asset.pendingDownloadInternal.response;
+ }
+
+ const sourcesList = asset.loadRemote && loaderHelpers.config.remoteSources ? loaderHelpers.config.remoteSources : [""];
+ let response: Response | undefined = undefined;
+ for (let sourcePrefix of sourcesList) {
+ sourcePrefix = sourcePrefix.trim();
+ // HACK: Special-case because MSBuild doesn't allow "" as an attribute
+ if (sourcePrefix === "./")
+ sourcePrefix = "";
+
+ const attemptUrl = resolve_path(asset, sourcePrefix);
+ if (asset.name === attemptUrl) {
+ if (loaderHelpers.diagnosticTracing)
+ console.debug(`MONO_WASM: Attempting to download '${attemptUrl}'`);
+ } else {
+ if (loaderHelpers.diagnosticTracing)
+ console.debug(`MONO_WASM: Attempting to download '${attemptUrl}' for ${asset.name}`);
+ }
+ try {
+ asset.resolvedUrl = attemptUrl;
+ const loadingResource = download_resource(asset);
+ asset.pendingDownloadInternal = loadingResource;
+ response = await loadingResource.response;
+ if (!response || !response.ok) {
+ continue;// next source
+ }
+ return response;
+ }
+ catch (err) {
+ if (!response) {
+ response = {
+ ok: false,
+ url: attemptUrl,
+ status: 0,
+ statusText: "" + err,
+ } as any;
+ }
+ continue; //next source
+ }
+ }
+ const isOkToFail = asset.isOptional || (asset.name.match(/\.pdb$/) && loaderHelpers.config.ignorePdbLoadErrors);
+ mono_assert(response, () => `Response undefined ${asset.name}`);
+ if (!isOkToFail) {
+ const err: any = new Error(`MONO_WASM: download '${response.url}' for ${asset.name} failed ${response.status} ${response.statusText}`);
+ err.status = response.status;
+ throw err;
+ } else {
+ loaderHelpers.out(`MONO_WASM: optional download '${response.url}' for ${asset.name} failed ${response.status} ${response.statusText}`);
+ return undefined;
+ }
+}
+
+function resolve_path(asset: AssetEntry, sourcePrefix: string): string {
+ mono_assert(sourcePrefix !== null && sourcePrefix !== undefined, () => `sourcePrefix must be provided for ${asset.name}`);
+ let attemptUrl;
+ const assemblyRootFolder = loaderHelpers.config.assemblyRootFolder;
+ if (!asset.resolvedUrl) {
+ if (sourcePrefix === "") {
+ if (asset.behavior === "assembly" || asset.behavior === "pdb") {
+ attemptUrl = assemblyRootFolder
+ ? (assemblyRootFolder + "/" + asset.name)
+ : asset.name;
+ }
+ else if (asset.behavior === "resource") {
+ const path = asset.culture && asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
+ attemptUrl = assemblyRootFolder
+ ? (assemblyRootFolder + "/" + path)
+ : path;
+ }
+ else {
+ attemptUrl = asset.name;
+ }
+ } else {
+ attemptUrl = sourcePrefix + asset.name;
+ }
+ attemptUrl = loaderHelpers.locateFile(attemptUrl);
+ if (loaderHelpers.assetUniqueQuery) {
+ attemptUrl = attemptUrl + loaderHelpers.assetUniqueQuery;
+ }
+ }
+ else {
+ attemptUrl = asset.resolvedUrl;
+ }
+ mono_assert(attemptUrl && typeof attemptUrl == "string", "attemptUrl need to be path or url string");
+ return attemptUrl;
+}
+
+function download_resource(request: ResourceRequest): LoadingResource {
+ try {
+ if (typeof loaderHelpers.downloadResource === "function") {
+ const loading = loaderHelpers.downloadResource(request);
+ if (loading) return loading;
+ }
+ const options: any = {};
+ if (request.hash) {
+ options.integrity = request.hash;
+ }
+ const response = loaderHelpers.fetch_like(request.resolvedUrl!, options);
+ return {
+ name: request.name, url: request.resolvedUrl!, response
+ };
+ } catch (err) {
+ const response = {
+ ok: false,
+ url: request.resolvedUrl,
+ status: 500,
+ statusText: "ERR29: " + err,
+ arrayBuffer: () => { throw err; },
+ json: () => { throw err; }
+ };
+ return {
+ name: request.name, url: request.resolvedUrl!, response: Promise.resolve(response)
+ };
+ }
+}
+
+export function cleanupAsset(asset: AssetEntryInternal) {
+ // give GC chance to collect resources
+ asset.pendingDownloadInternal = null as any; // GC
+ asset.pendingDownload = null as any; // GC
+ asset.buffer = null as any; // GC
+}
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/blazor/BootConfig.ts b/src/mono/wasm/runtime/loader/blazor/BootConfig.ts
similarity index 50%
rename from src/mono/wasm/runtime/blazor/BootConfig.ts
rename to src/mono/wasm/runtime/loader/blazor/BootConfig.ts
index 48c033b7368b3..d136a18b7b99a 100644
--- a/src/mono/wasm/runtime/blazor/BootConfig.ts
+++ b/src/mono/wasm/runtime/loader/blazor/BootConfig.ts
@@ -1,8 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { Module } from "../globals";
-import { WebAssemblyBootResourceType } from "../types-api";
+import type { BootJsonData } from "../../types/blazor";
+import type { WebAssemblyBootResourceType } from "../../types";
+import { loaderHelpers } from "../globals";
type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise | null | undefined;
@@ -25,7 +26,7 @@ export class BootConfigResult {
bootConfigResponse = await loaderResponse;
}
- const applicationEnvironment = environment || (Module.getApplicationEnvironment && Module.getApplicationEnvironment(bootConfigResponse)) || "Production";
+ const applicationEnvironment = environment || (loaderHelpers.getApplicationEnvironment && loaderHelpers.getApplicationEnvironment(bootConfigResponse)) || "Production";
const bootConfig: BootJsonData = await bootConfigResponse.json();
bootConfig.modifiableAssemblies = bootConfigResponse.headers.get("DOTNET-MODIFIABLE-ASSEMBLIES");
bootConfig.aspnetCoreBrowserTools = bootConfigResponse.headers.get("ASPNETCORE-BROWSER-TOOLS");
@@ -42,48 +43,3 @@ export class BootConfigResult {
}
}
-// Keep in sync with Microsoft.NET.Sdk.WebAssembly.BootJsonData from the WasmSDK
-export interface BootJsonData {
- readonly entryAssembly: string;
- readonly resources: ResourceGroups;
- /** Gets a value that determines if this boot config was produced from a non-published build (i.e. dotnet build or dotnet run) */
- readonly debugBuild: boolean;
- readonly linkerEnabled: boolean;
- readonly cacheBootResources: boolean;
- readonly config: string[];
- readonly icuDataMode: ICUDataMode;
- readonly startupMemoryCache: boolean | undefined;
- readonly runtimeOptions: string[] | undefined;
-
- // These properties are tacked on, and not found in the boot.json file
- modifiableAssemblies: string | null;
- aspnetCoreBrowserTools: string | null;
-}
-
-export type BootJsonDataExtension = { [extensionName: string]: ResourceList };
-
-export interface ResourceGroups {
- readonly assembly: ResourceList;
- readonly lazyAssembly: ResourceList;
- readonly pdb?: ResourceList;
- readonly runtime: ResourceList;
- readonly satelliteResources?: { [cultureName: string]: ResourceList };
- readonly libraryInitializers?: ResourceList,
- readonly extensions?: BootJsonDataExtension
- readonly runtimeAssets: ExtendedResourceList;
-}
-
-export type ResourceList = { [name: string]: string };
-export type ExtendedResourceList = {
- [name: string]: {
- hash: string,
- behavior: string
- }
-};
-
-export enum ICUDataMode {
- Sharded,
- All,
- Invariant,
- Custom
-}
diff --git a/src/mono/wasm/runtime/blazor/WebAssemblyResourceLoader.ts b/src/mono/wasm/runtime/loader/blazor/WebAssemblyResourceLoader.ts
similarity index 98%
rename from src/mono/wasm/runtime/blazor/WebAssemblyResourceLoader.ts
rename to src/mono/wasm/runtime/loader/blazor/WebAssemblyResourceLoader.ts
index c0840f6edb1ad..8af4dba109e0d 100644
--- a/src/mono/wasm/runtime/blazor/WebAssemblyResourceLoader.ts
+++ b/src/mono/wasm/runtime/loader/blazor/WebAssemblyResourceLoader.ts
@@ -1,9 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { WebAssemblyBootResourceType, WebAssemblyStartOptions } from "../types-api";
+import type { WebAssemblyBootResourceType, WebAssemblyStartOptions } from "../../types";
+import type { BootJsonData, ResourceList } from "../../types/blazor";
import { toAbsoluteUri } from "./_Polyfill";
-import { BootJsonData, ResourceList } from "./BootConfig";
const networkFetchCacheMode = "no-cache";
export class WebAssemblyResourceLoader {
diff --git a/src/mono/wasm/runtime/blazor/_Integration.ts b/src/mono/wasm/runtime/loader/blazor/_Integration.ts
similarity index 73%
rename from src/mono/wasm/runtime/blazor/_Integration.ts
rename to src/mono/wasm/runtime/loader/blazor/_Integration.ts
index 64896bfaa013c..e81f60707e187 100644
--- a/src/mono/wasm/runtime/blazor/_Integration.ts
+++ b/src/mono/wasm/runtime/loader/blazor/_Integration.ts
@@ -1,29 +1,79 @@
-import { INTERNAL, Module } from "../globals";
-import { MonoConfigInternal } from "../types";
-import { AssetEntry, LoadingResource, WebAssemblyBootResourceType } from "../types-api";
-import { BootConfigResult, BootJsonData, ICUDataMode } from "./BootConfig";
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import type { DotnetModuleInternal, MonoConfigInternal } from "../../types/internal";
+import type { AssetBehaviours, AssetEntry, LoadingResource, WebAssemblyBootResourceType } from "../../types";
+import type { BootJsonData } from "../../types/blazor";
+
+import { INTERNAL, loaderHelpers } from "../globals";
+import { BootConfigResult } from "./BootConfig";
import { WebAssemblyResourceLoader } from "./WebAssemblyResourceLoader";
import { hasDebuggingEnabled } from "./_Polyfill";
+import { ICUDataMode } from "../../types/blazor";
-export async function loadBootConfig(config: MonoConfigInternal,) {
+let resourceLoader: WebAssemblyResourceLoader;
+
+export async function loadBootConfig(config: MonoConfigInternal, module: DotnetModuleInternal) {
const candidateOptions = config.startupOptions ?? {};
const environment = candidateOptions.environment;
const bootConfigPromise = BootConfigResult.initAsync(candidateOptions.loadBootResource, environment);
-
const bootConfigResult: BootConfigResult = await bootConfigPromise;
-
- const resourceLoader = await WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, candidateOptions || {});
-
- INTERNAL.resourceLoader = resourceLoader;
-
- const newConfig = mapBootConfigToMonoConfig(Module.config as MonoConfigInternal, resourceLoader, bootConfigResult.applicationEnvironment);
- Module.config = newConfig;
+ INTERNAL.resourceLoader = resourceLoader = await WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, candidateOptions || {});
+ mapBootConfigToMonoConfig(loaderHelpers.config, bootConfigResult.applicationEnvironment);
+ setupModuleForBlazor(module);
}
let resourcesLoaded = 0;
let totalResources = 0;
-export function mapBootConfigToMonoConfig(moduleConfig: MonoConfigInternal, resourceLoader: WebAssemblyResourceLoader, applicationEnvironment: string): MonoConfigInternal {
+const behaviorByName = (name: string): AssetBehaviours | "other" => {
+ return name === "dotnet.timezones.blat" ? "vfs"
+ : name === "dotnet.native.wasm" ? "dotnetwasm"
+ : (name.startsWith("dotnet.native.worker") && name.endsWith(".js")) ? "js-module-threads"
+ : (name.startsWith("dotnet.native") && name.endsWith(".js")) ? "js-module-native"
+ : (name.startsWith("dotnet.runtime") && name.endsWith(".js")) ? "js-module-runtime"
+ : (name.startsWith("dotnet") && name.endsWith(".js")) ? "js-module-dotnet"
+ : name.startsWith("icudt") ? "icu"
+ : "other";
+};
+
+const monoToBlazorAssetTypeMap: { [key: string]: WebAssemblyBootResourceType | undefined } = {
+ "assembly": "assembly",
+ "pdb": "pdb",
+ "icu": "globalization",
+ "vfs": "globalization",
+ "dotnetwasm": "dotnetwasm",
+};
+
+export function setupModuleForBlazor(module: DotnetModuleInternal) {
+ // it would not `loadResource` on types for which there is no typesMap mapping
+ const downloadResource = (asset: AssetEntry): LoadingResource | undefined => {
+ // GOTCHA: the mapping to blazor asset type may not cover all mono owned asset types in the future in which case:
+ // A) we may need to add such asset types to the mapping and to WebAssemblyBootResourceType
+ // B) or we could add generic "runtime" type to WebAssemblyBootResourceType as fallback
+ // C) or we could return `undefined` and let the runtime to load the asset. In which case the progress will not be reported on it and blazor will not be able to cache it.
+ const type = monoToBlazorAssetTypeMap[asset.behavior];
+ if (type !== undefined) {
+ const res = resourceLoader.loadResource(asset.name, asset.resolvedUrl!, asset.hash!, type);
+ asset.pendingDownload = res;
+
+ totalResources++;
+ res.response.then(() => {
+ resourcesLoaded++;
+ if (module.onDownloadResourceProgress)
+ module.onDownloadResourceProgress(resourcesLoaded, totalResources);
+ });
+
+ return res;
+ }
+ return undefined;
+ };
+
+ module.downloadResource = downloadResource;
+ module.disableDotnet6Compatibility = false;
+}
+
+export function mapBootConfigToMonoConfig(moduleConfig: MonoConfigInternal, applicationEnvironment: string) {
const resources = resourceLoader.bootConfig.resources;
const assets: AssetEntry[] = [];
@@ -39,10 +89,10 @@ export function mapBootConfigToMonoConfig(moduleConfig: MonoConfigInternal, reso
moduleConfig.enableDownloadRetry = false; // disable retry downloads
moduleConfig.mainAssemblyName = resourceLoader.bootConfig.entryAssembly;
- moduleConfig = {
+ // FIXME this mix of both formats is ugly temporary hack
+ Object.assign(moduleConfig, {
...resourceLoader.bootConfig,
- ...moduleConfig
- };
+ });
if (resourceLoader.bootConfig.startupMemoryCache !== undefined) {
moduleConfig.startupMemoryCache = resourceLoader.bootConfig.startupMemoryCache;
@@ -52,58 +102,12 @@ export function mapBootConfigToMonoConfig(moduleConfig: MonoConfigInternal, reso
moduleConfig.runtimeOptions = [...(moduleConfig.runtimeOptions || []), ...resourceLoader.bootConfig.runtimeOptions];
}
- const monoToBlazorAssetTypeMap: { [key: string]: WebAssemblyBootResourceType | undefined } = {
- "assembly": "assembly",
- "pdb": "pdb",
- "icu": "globalization",
- "vfs": "globalization",
- "dotnetwasm": "dotnetwasm",
- };
-
- const behaviorByName = (name: string) => {
- return name === "dotnet.timezones.blat" ? "vfs"
- : name === "dotnet.wasm" ? "dotnetwasm"
- : (name.startsWith("dotnet.worker") && name.endsWith(".js")) ? "js-module-threads"
- : (name.startsWith("dotnet") && name.endsWith(".js")) ? "js-module-dotnet"
- : name.startsWith("icudt") ? "icu"
- : "other";
- };
-
- // it would not `loadResource` on types for which there is no typesMap mapping
- const downloadResource = (asset: AssetEntry): LoadingResource | undefined => {
- // GOTCHA: the mapping to blazor asset type may not cover all mono owned asset types in the future in which case:
- // A) we may need to add such asset types to the mapping and to WebAssemblyBootResourceType
- // B) or we could add generic "runtime" type to WebAssemblyBootResourceType as fallback
- // C) or we could return `undefined` and let the runtime to load the asset. In which case the progress will not be reported on it and blazor will not be able to cache it.
- const type = monoToBlazorAssetTypeMap[asset.behavior];
- if (type !== undefined) {
- const res = resourceLoader.loadResource(asset.name, asset.resolvedUrl!, asset.hash!, type);
- asset.pendingDownload = res;
-
- totalResources++;
- res.response.then(() => {
- resourcesLoaded++;
- if (Module.onDownloadResourceProgress)
- Module.onDownloadResourceProgress(resourcesLoaded, totalResources);
- });
-
- return res;
- }
- return undefined;
- };
-
- Module.downloadResource = downloadResource;
- Module.disableDotnet6Compatibility = false;
-
// any runtime owned assets, with proper behavior already set
for (const name in resources.runtimeAssets) {
const asset = resources.runtimeAssets[name] as AssetEntry;
asset.name = name;
asset.resolvedUrl = `_framework/${name}`;
assets.push(asset);
- if (asset.behavior === "dotnetwasm") {
- downloadResource(asset);
- }
}
for (const name in resources.assembly) {
const asset: AssetEntry = {
@@ -113,7 +117,6 @@ export function mapBootConfigToMonoConfig(moduleConfig: MonoConfigInternal, reso
behavior: "assembly",
};
assets.push(asset);
- downloadResource(asset);
}
if (hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb) {
for (const name in resources.pdb) {
@@ -124,7 +127,6 @@ export function mapBootConfigToMonoConfig(moduleConfig: MonoConfigInternal, reso
behavior: "pdb",
};
assets.push(asset);
- downloadResource(asset);
}
}
const applicationCulture = resourceLoader.startOptions.applicationCulture || (navigator.languages && navigator.languages[0]);
@@ -145,9 +147,11 @@ export function mapBootConfigToMonoConfig(moduleConfig: MonoConfigInternal, reso
} else if (behavior === "dotnetwasm") {
continue;
}
+
+ const resolvedUrl = name.endsWith(".js") ? `./${name}` : `_framework/${name}`;
const asset: AssetEntry = {
name,
- resolvedUrl: `_framework/${name}`,
+ resolvedUrl,
hash: resources.runtime[name],
behavior,
};
@@ -175,8 +179,6 @@ export function mapBootConfigToMonoConfig(moduleConfig: MonoConfigInternal, reso
if (resourceLoader.bootConfig.runtimeOptions) {
moduleConfig.runtimeOptions = [...(moduleConfig.runtimeOptions || []), ...(resourceLoader.bootConfig.runtimeOptions || [])];
}
-
- return moduleConfig;
}
function getICUResourceName(bootConfig: BootJsonData, culture: string | undefined): string {
@@ -217,4 +219,5 @@ function getICUResourceName(bootConfig: BootJsonData, culture: string | undefine
return "icudt_CJK.dat";
}
return "icudt_no_CJK.dat";
-}
\ No newline at end of file
+}
+
diff --git a/src/mono/wasm/runtime/blazor/_Polyfill.ts b/src/mono/wasm/runtime/loader/blazor/_Polyfill.ts
similarity index 87%
rename from src/mono/wasm/runtime/blazor/_Polyfill.ts
rename to src/mono/wasm/runtime/loader/blazor/_Polyfill.ts
index dc4aded75cc92..4eeefe2060dd9 100644
--- a/src/mono/wasm/runtime/blazor/_Polyfill.ts
+++ b/src/mono/wasm/runtime/loader/blazor/_Polyfill.ts
@@ -1,4 +1,7 @@
-import { BootJsonData } from "./BootConfig";
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import type { BootJsonData } from "../../types/blazor";
let testAnchor: HTMLAnchorElement;
export function toAbsoluteUri(relativeUri: string): string {
diff --git a/src/mono/wasm/runtime/loader/config.ts b/src/mono/wasm/runtime/loader/config.ts
new file mode 100644
index 0000000000000..28fa63462cce0
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/config.ts
@@ -0,0 +1,111 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import BuildConfiguration from "consts:configuration";
+import type { DotnetModuleInternal, MonoConfigInternal } from "../types/internal";
+import type { DotnetModuleConfig } from "../types";
+import { exportedRuntimeAPI, loaderHelpers, runtimeHelpers } from "./globals";
+import { loadBootConfig } from "./blazor/_Integration";
+
+export function deep_merge_config(target: MonoConfigInternal, source: MonoConfigInternal): MonoConfigInternal {
+ const providedConfig: MonoConfigInternal = { ...source };
+ if (providedConfig.assets) {
+ providedConfig.assets = [...(target.assets || []), ...(providedConfig.assets || [])];
+ }
+ if (providedConfig.environmentVariables) {
+ providedConfig.environmentVariables = { ...(target.environmentVariables || {}), ...(providedConfig.environmentVariables || {}) };
+ }
+ if (providedConfig.startupOptions) {
+ providedConfig.startupOptions = { ...(target.startupOptions || {}), ...(providedConfig.startupOptions || {}) };
+ }
+ if (providedConfig.runtimeOptions) {
+ providedConfig.runtimeOptions = [...(target.runtimeOptions || []), ...(providedConfig.runtimeOptions || [])];
+ }
+ return Object.assign(target, providedConfig);
+}
+
+export function deep_merge_module(target: DotnetModuleInternal, source: DotnetModuleConfig): DotnetModuleInternal {
+ const providedConfig: DotnetModuleConfig = { ...source };
+ if (providedConfig.config) {
+ if (!target.config) target.config = {};
+ providedConfig.config = deep_merge_config(target.config, providedConfig.config);
+ }
+ return Object.assign(target, providedConfig);
+}
+
+export function normalizeConfig() {
+ // normalize
+ const config = loaderHelpers.config;
+
+ config.environmentVariables = config.environmentVariables || {};
+ config.assets = config.assets || [];
+ config.runtimeOptions = config.runtimeOptions || [];
+ config.globalizationMode = config.globalizationMode || "auto";
+
+ if (config.debugLevel === undefined && BuildConfiguration === "Debug") {
+ config.debugLevel = -1;
+ }
+ if (config.diagnosticTracing === undefined && BuildConfiguration === "Debug") {
+ config.diagnosticTracing = true;
+ }
+ runtimeHelpers.diagnosticTracing = loaderHelpers.diagnosticTracing = !!config.diagnosticTracing;
+ loaderHelpers.assetUniqueQuery = config.assetUniqueQuery;
+ runtimeHelpers.waitForDebugger = config.waitForDebugger;
+ config.startupMemoryCache = !!config.startupMemoryCache;
+ if (config.startupMemoryCache && runtimeHelpers.waitForDebugger) {
+ if (loaderHelpers.diagnosticTracing) console.info("MONO_WASM: Disabling startupMemoryCache because waitForDebugger is set");
+ config.startupMemoryCache = false;
+ }
+
+ runtimeHelpers.enablePerfMeasure = !!config.browserProfilerOptions
+ && globalThis.performance
+ && typeof globalThis.performance.measure === "function";
+
+}
+
+let configLoaded = false;
+export async function mono_wasm_load_config(module: DotnetModuleInternal): Promise {
+ const configFilePath = module.configSrc;
+ if (configLoaded) {
+ await loaderHelpers.afterConfigLoaded.promise;
+ return;
+ }
+ configLoaded = true;
+ if (!configFilePath) {
+ normalizeConfig();
+ loaderHelpers.afterConfigLoaded.promise_control.resolve(loaderHelpers.config);
+ return;
+ }
+ if (loaderHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_load_config");
+ try {
+ const resolveSrc = loaderHelpers.locateFile(configFilePath);
+ const configResponse = await loaderHelpers.fetch_like(resolveSrc);
+ const loadedConfig: MonoConfigInternal = (await configResponse.json()) || {};
+ if (loaderHelpers.config.startupOptions) {
+ await loadBootConfig(loaderHelpers.config, module);
+ } else {
+ if (loadedConfig.environmentVariables && typeof (loadedConfig.environmentVariables) !== "object")
+ throw new Error("Expected config.environmentVariables to be unset or a dictionary-style object");
+ deep_merge_config(loaderHelpers.config, loadedConfig);
+ }
+
+ normalizeConfig();
+
+ if (module.onConfigLoaded) {
+ try {
+ await module.onConfigLoaded(loaderHelpers.config, exportedRuntimeAPI);
+ normalizeConfig();
+ }
+ catch (err: any) {
+ console.error("MONO_WASM: onConfigLoaded() failed", err);
+ throw err;
+ }
+ }
+ loaderHelpers.afterConfigLoaded.promise_control.resolve(loaderHelpers.config);
+ } catch (err) {
+ const errMessage = `Failed to load config file ${configFilePath} ${err}`;
+ loaderHelpers.config = module.config = { message: errMessage, error: err, isError: true };
+ loaderHelpers.abort_startup(errMessage, true);
+ throw err;
+ }
+}
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/loader/exit.ts b/src/mono/wasm/runtime/loader/exit.ts
new file mode 100644
index 0000000000000..ff3b62b436a90
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/exit.ts
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WEB, INTERNAL, loaderHelpers, runtimeHelpers } from "./globals";
+import { consoleWebSocket } from "./logging";
+
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+export function abort_startup(reason: any, should_exit: boolean): void {
+ if (loaderHelpers.diagnosticTracing) console.trace("MONO_WASM: abort_startup");
+ loaderHelpers.allDownloadsQueued.promise_control.reject(reason);
+ loaderHelpers.afterConfigLoaded.promise_control.reject(reason);
+ loaderHelpers.wasmDownloadPromise.promise_control.reject(reason);
+ loaderHelpers.runtimeModuleLoaded.promise_control.reject(reason);
+ if (runtimeHelpers.dotnetReady) {
+ runtimeHelpers.dotnetReady.promise_control.reject(reason);
+ runtimeHelpers.memorySnapshotSkippedOrDone.promise_control.reject(reason);
+ runtimeHelpers.afterInstantiateWasm.promise_control.reject(reason);
+ runtimeHelpers.beforePreInit.promise_control.reject(reason);
+ runtimeHelpers.afterPreInit.promise_control.reject(reason);
+ runtimeHelpers.afterPreRun.promise_control.reject(reason);
+ runtimeHelpers.beforeOnRuntimeInitialized.promise_control.reject(reason);
+ runtimeHelpers.afterOnRuntimeInitialized.promise_control.reject(reason);
+ runtimeHelpers.afterPostRun.promise_control.reject(reason);
+ }
+ if (typeof reason !== "object" || reason.silent !== true) {
+ if (should_exit || ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) {
+ mono_exit(1, reason);
+ }
+ throw reason;
+ }
+}
+
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+export function mono_exit(exit_code: number, reason?: any): void {
+ if (loaderHelpers.config && loaderHelpers.config.asyncFlushOnExit && exit_code === 0) {
+ // this would NOT call Node's exit() immediately, it's a hanging promise
+ (async () => {
+ try {
+ await flush_node_streams();
+ }
+ finally {
+ set_exit_code_and_quit_now(exit_code, reason);
+ }
+ })();
+ // we need to throw, rather than let the caller continue the normal execution
+ // in the middle of some code, which expects this to stop the process
+ throw runtimeHelpers.ExitStatus
+ ? new runtimeHelpers.ExitStatus(exit_code)
+ : reason
+ ? reason
+ : new Error("Stop with exit code " + exit_code);
+ } else {
+ set_exit_code_and_quit_now(exit_code, reason);
+ }
+}
+
+async function flush_node_streams() {
+ try {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore:
+ const process = await import(/* webpackIgnore: true */"process");
+ const flushStream = (stream: any) => {
+ return new Promise((resolve, reject) => {
+ stream.on("error", (error: any) => reject(error));
+ stream.write("", function () { resolve(); });
+ });
+ };
+ const stderrFlushed = flushStream(process.stderr);
+ const stdoutFlushed = flushStream(process.stdout);
+ await Promise.all([stdoutFlushed, stderrFlushed]);
+ } catch (err) {
+ console.error(`flushing std* streams failed: ${err}`);
+ }
+}
+
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+function set_exit_code_and_quit_now(exit_code: number, reason?: any): void {
+ if (runtimeHelpers.ExitStatus) {
+ if (reason && !(reason instanceof runtimeHelpers.ExitStatus)) {
+ if (!loaderHelpers.config.logExitCode) {
+ if (reason instanceof Error && runtimeHelpers.stringify_as_error_with_stack)
+ loaderHelpers.err(runtimeHelpers.stringify_as_error_with_stack(reason));
+ else if (typeof reason == "string")
+ loaderHelpers.err(reason);
+ else
+ loaderHelpers.err(JSON.stringify(reason));
+ }
+ }
+ else if (!reason) {
+ reason = new runtimeHelpers.ExitStatus(exit_code);
+ } else if (typeof reason.status === "number") {
+ exit_code = reason.status;
+ }
+ }
+ logErrorOnExit(exit_code, reason);
+ try {
+ if (runtimeHelpers.jiterpreter_dump_stats) runtimeHelpers.jiterpreter_dump_stats(false);
+ } catch {
+ // eslint-disable-next-line @typescript-eslint/no-extra-semi
+ ;
+ }
+
+ appendElementOnExit(exit_code);
+ if (exit_code !== 0 || !ENVIRONMENT_IS_WEB) {
+ if (ENVIRONMENT_IS_NODE && INTERNAL.process) {
+ INTERNAL.process.exit(exit_code);
+ throw reason;
+ }
+ else if (runtimeHelpers.quit) {
+ runtimeHelpers.quit(exit_code, reason);
+ } else {
+ throw reason;
+ }
+ }
+}
+
+function appendElementOnExit(exit_code: number) {
+ if (ENVIRONMENT_IS_WEB && loaderHelpers.config && loaderHelpers.config.appendElementOnExit) {
+ //Tell xharness WasmBrowserTestRunner what was the exit code
+ const tests_done_elem = document.createElement("label");
+ tests_done_elem.id = "tests_done";
+ if (exit_code) tests_done_elem.style.background = "red";
+ tests_done_elem.innerHTML = exit_code.toString();
+ document.body.appendChild(tests_done_elem);
+ }
+}
+
+function logErrorOnExit(exit_code: number, reason?: any) {
+ if (loaderHelpers.config && loaderHelpers.config.logExitCode) {
+ if (exit_code != 0 && reason) {
+ if (reason instanceof Error && runtimeHelpers.stringify_as_error_with_stack)
+ console.error(runtimeHelpers.stringify_as_error_with_stack(reason));
+ else if (typeof reason == "string")
+ console.error(reason);
+ else
+ console.error(JSON.stringify(reason));
+ }
+ if (consoleWebSocket) {
+ const stop_when_ws_buffer_empty = () => {
+ if (consoleWebSocket.bufferedAmount == 0) {
+ // tell xharness WasmTestMessagesProcessor we are done.
+ // note this sends last few bytes into the same WS
+ console.log("WASM EXIT " + exit_code);
+ }
+ else {
+ setTimeout(stop_when_ws_buffer_empty, 100);
+ }
+ };
+ stop_when_ws_buffer_empty();
+ } else {
+ console.log("WASM EXIT " + exit_code);
+ }
+ }
+}
diff --git a/src/mono/wasm/runtime/loader/globals.ts b/src/mono/wasm/runtime/loader/globals.ts
new file mode 100644
index 0000000000000..f221d467e3b82
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/globals.ts
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import type { AssetEntryInternal, GlobalObjects, LoaderHelpers, RuntimeHelpers } from "../types/internal";
+import type { MonoConfig, RuntimeAPI } from "../types";
+import { abort_startup, mono_exit } from "./exit";
+import { assertIsControllablePromise, createPromiseController, getPromiseController } from "./promise-controller";
+import { mono_download_assets, resolve_asset_path } from "./assets";
+import { setup_proxy_console } from "./logging";
+
+export const ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string";
+export const ENVIRONMENT_IS_WEB = typeof window == "object";
+export const ENVIRONMENT_IS_WORKER = typeof importScripts == "function";
+export const ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+
+export let runtimeHelpers: RuntimeHelpers = null as any;
+export let loaderHelpers: LoaderHelpers = null as any;
+export let exportedRuntimeAPI: RuntimeAPI = null as any;
+export let INTERNAL: any;
+export let _loaderModuleLoaded = false; // please keep it in place also as rollup guard
+
+export function setLoaderGlobals(
+ globalObjects: GlobalObjects,
+) {
+ if (_loaderModuleLoaded) {
+ throw new Error("Loader module already loaded");
+ }
+ _loaderModuleLoaded = true;
+ runtimeHelpers = globalObjects.runtimeHelpers;
+ loaderHelpers = globalObjects.loaderHelpers;
+ exportedRuntimeAPI = globalObjects.api;
+ INTERNAL = globalObjects.internal;
+ Object.assign(exportedRuntimeAPI, {
+ INTERNAL
+ });
+
+ Object.assign(globalObjects.module, {
+ disableDotnet6Compatibility: true,
+ config: { environmentVariables: {} }
+ });
+ Object.assign(runtimeHelpers, {
+ config: globalObjects.module.config,
+ diagnosticTracing: false,
+ });
+ Object.assign(loaderHelpers, {
+ config: globalObjects.module.config,
+ diagnosticTracing: false,
+
+ maxParallelDownloads: 16,
+ enableDownloadRetry: true,
+
+ _loaded_files: [],
+ loadedFiles: [],
+ actual_downloaded_assets_count: 0,
+ actual_instantiated_assets_count: 0,
+ expected_downloaded_assets_count: 0,
+ expected_instantiated_assets_count: 0,
+
+ afterConfigLoaded: createPromiseController(),
+ allDownloadsQueued: createPromiseController(),
+ wasmDownloadPromise: createPromiseController(),
+ runtimeModuleLoaded: createPromiseController(),
+
+ abort_startup,
+ mono_exit,
+ createPromiseController,
+ getPromiseController,
+ assertIsControllablePromise,
+ mono_download_assets,
+ resolve_asset_path,
+ setup_proxy_console,
+
+ } as Partial);
+}
diff --git a/src/mono/wasm/runtime/loader/icu.ts b/src/mono/wasm/runtime/loader/icu.ts
new file mode 100644
index 0000000000000..39e2bccd14b29
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/icu.ts
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import { ENVIRONMENT_IS_WEB, loaderHelpers } from "./globals";
+
+export function init_globalization() {
+ loaderHelpers.invariantMode = loaderHelpers.config.globalizationMode === "invariant";
+ loaderHelpers.preferredIcuAsset = get_preferred_icu_asset();
+
+ if (!loaderHelpers.invariantMode) {
+ if (loaderHelpers.preferredIcuAsset) {
+ if (loaderHelpers.diagnosticTracing) console.debug("MONO_WASM: ICU data archive(s) available, disabling invariant mode");
+ } else if (loaderHelpers.config.globalizationMode !== "icu") {
+ if (loaderHelpers.diagnosticTracing) console.debug("MONO_WASM: ICU data archive(s) not available, using invariant globalization mode");
+ loaderHelpers.invariantMode = true;
+ loaderHelpers.preferredIcuAsset = null;
+ } else {
+ const msg = "invariant globalization mode is inactive and no ICU data archives are available";
+ loaderHelpers.err(`MONO_WASM: ERROR: ${msg}`);
+ throw new Error(msg);
+ }
+ }
+
+ const invariantEnv = "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT";
+ const hybridEnv = "DOTNET_SYSTEM_GLOBALIZATION_HYBRID";
+ const env_variables = loaderHelpers.config.environmentVariables!;
+ if (env_variables[hybridEnv] === undefined && loaderHelpers.config.globalizationMode === "hybrid") {
+ env_variables[hybridEnv] = "1";
+ }
+ else if (env_variables[invariantEnv] === undefined && loaderHelpers.invariantMode) {
+ env_variables[invariantEnv] = "1";
+ }
+ if (env_variables["TZ"] === undefined) {
+ try {
+ // this call is relatively expensive, so we call it during download of other assets
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || null;
+ if (timezone) {
+ env_variables!["TZ"] = timezone;
+ }
+ } catch {
+ console.info("MONO_WASM: failed to detect timezone, will fallback to UTC");
+ }
+ }
+}
+
+export function get_preferred_icu_asset(): string | null {
+ if (!loaderHelpers.config.assets || loaderHelpers.invariantMode)
+ return null;
+
+ // By setting user can define what ICU source file they want to load.
+ // There is no need to check application's culture when is set.
+ // If it was not set, then we have 3 "icu" assets in config and we should choose
+ // only one for loading, the one that matches the application's locale.
+ const icuAssets = loaderHelpers.config.assets.filter(a => a["behavior"] == "icu");
+ if (icuAssets.length === 1)
+ return icuAssets[0].name;
+
+ // reads the browsers locale / the OS's locale
+ const preferredCulture = ENVIRONMENT_IS_WEB ? navigator.language : Intl.DateTimeFormat().resolvedOptions().locale;
+ const prefix = preferredCulture.split("-")[0];
+ const CJK = "icudt_CJK.dat";
+ const EFIGS = "icudt_EFIGS.dat";
+ const OTHERS = "icudt_no_CJK.dat";
+
+ // not all "fr-*", "it-*", "de-*", "es-*" are in EFIGS, only the one that is mostly used
+ if (prefix == "en" || ["fr", "fr-FR", "it", "it-IT", "de", "de-DE", "es", "es-ES"].includes(preferredCulture))
+ return EFIGS;
+ if (["zh", "ko", "ja"].includes(prefix))
+ return CJK;
+ return OTHERS;
+}
diff --git a/src/mono/wasm/runtime/loader/index.ts b/src/mono/wasm/runtime/loader/index.ts
new file mode 100644
index 0000000000000..9c2f0d00f181c
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/index.ts
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import type { DotnetHostBuilder } from "../types";
+import { mono_exit } from "./exit";
+import { HostBuilder, createEmscripten } from "./run";
+
+// export external API
+const dotnet: DotnetHostBuilder = new HostBuilder();
+const exit = mono_exit;
+const legacyEntrypoint = createEmscripten;
+
+export { dotnet, exit };
+export default legacyEntrypoint;
diff --git a/src/mono/wasm/runtime/loader/logging.ts b/src/mono/wasm/runtime/loader/logging.ts
new file mode 100644
index 0000000000000..7be1ec67bd022
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/logging.ts
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+export let consoleWebSocket: WebSocket;
+
+export function setup_proxy_console(id: string, console: Console, origin: string): void {
+ // this need to be copy, in order to keep reference to original methods
+ const originalConsole = {
+ log: console.log,
+ error: console.error
+ };
+ const anyConsole = console as any;
+
+ function proxyConsoleMethod(prefix: string, func: any, asJson: boolean) {
+ return function (...args: any[]) {
+ try {
+ let payload = args[0];
+ if (payload === undefined) payload = "undefined";
+ else if (payload === null) payload = "null";
+ else if (typeof payload === "function") payload = payload.toString();
+ else if (typeof payload !== "string") {
+ try {
+ payload = JSON.stringify(payload);
+ } catch (e) {
+ payload = payload.toString();
+ }
+ }
+
+ if (typeof payload === "string") {
+ if (payload[0] == "[") {
+ const now = new Date().toISOString();
+ if (id !== "main") {
+ payload = `[${id}][${now}] ${payload}`;
+ } else {
+ payload = `[${now}] ${payload}`;
+ }
+ } else if (id !== "main") {
+ payload = `[${id}] ${payload}`;
+ }
+ }
+
+ if (asJson) {
+ func(JSON.stringify({
+ method: prefix,
+ payload: payload,
+ arguments: args
+ }));
+ } else {
+ func([prefix + payload, ...args.slice(1)]);
+ }
+ } catch (err) {
+ originalConsole.error(`proxyConsole failed: ${err}`);
+ }
+ };
+ }
+
+ const methods = ["debug", "trace", "warn", "info", "error"];
+ for (const m of methods) {
+ if (typeof (anyConsole[m]) !== "function") {
+ anyConsole[m] = proxyConsoleMethod(`console.${m}: `, console.log, false);
+ }
+ }
+
+ const consoleUrl = `${origin}/console`.replace("https://", "wss://").replace("http://", "ws://");
+
+ consoleWebSocket = new WebSocket(consoleUrl);
+ consoleWebSocket.addEventListener("open", () => {
+ originalConsole.log(`browser: [${id}] Console websocket connected.`);
+ });
+ consoleWebSocket.addEventListener("error", (event) => {
+ originalConsole.error(`[${id}] websocket error: ${event}`, event);
+ });
+ consoleWebSocket.addEventListener("close", (event) => {
+ originalConsole.error(`[${id}] websocket closed: ${event}`, event);
+ });
+
+ const send = (msg: string) => {
+ if (consoleWebSocket.readyState === WebSocket.OPEN) {
+ consoleWebSocket.send(msg);
+ }
+ else {
+ originalConsole.log(msg);
+ }
+ };
+
+ for (const m of ["log", ...methods])
+ anyConsole[m] = proxyConsoleMethod(`console.${m}`, send, true);
+}
diff --git a/src/mono/wasm/runtime/loader/polyfills.ts b/src/mono/wasm/runtime/loader/polyfills.ts
new file mode 100644
index 0000000000000..dd757148528be
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/polyfills.ts
@@ -0,0 +1,124 @@
+
+import type { DotnetModuleInternal } from "../types/internal";
+import { INTERNAL, ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, loaderHelpers } from "./globals";
+
+let node_fs: any | undefined = undefined;
+let node_url: any | undefined = undefined;
+
+export async function init_polyfills(module: DotnetModuleInternal): Promise {
+
+ loaderHelpers.scriptUrl = normalizeFileUrl(/* webpackIgnore: true */import.meta.url);
+ loaderHelpers.scriptDirectory = normalizeDirectoryUrl(loaderHelpers.scriptUrl);
+ loaderHelpers.locateFile = (path) => {
+ if (isPathAbsolute(path)) return path;
+ return loaderHelpers.scriptDirectory + path;
+ };
+ loaderHelpers.downloadResource = module.downloadResource;
+ loaderHelpers.fetch_like = fetch_like;
+ loaderHelpers.out = console.log;
+ loaderHelpers.err = console.error;
+ loaderHelpers.getApplicationEnvironment = module.getApplicationEnvironment;
+
+ if (ENVIRONMENT_IS_NODE) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore:
+ INTERNAL.require = await import(/* webpackIgnore: true */"module").then(mod => mod.createRequire(/* webpackIgnore: true */import.meta.url));
+ } else {
+ INTERNAL.require = Promise.resolve(() => { throw new Error("require not supported"); });
+ }
+
+ if (typeof globalThis.URL === "undefined") {
+ globalThis.URL = class URL {
+ private url;
+ constructor(url: string) {
+ this.url = url;
+ }
+ toString() {
+ return this.url;
+ }
+ } as any;
+ }
+}
+
+const hasFetch = typeof (globalThis.fetch) === "function";
+export async function fetch_like(url: string, init?: RequestInit): Promise {
+ try {
+ if (ENVIRONMENT_IS_NODE) {
+ const isFileUrl = url.startsWith("file://");
+ if (!isFileUrl && hasFetch) {
+ return globalThis.fetch(url, init || { credentials: "same-origin" });
+ }
+ if (!node_fs) {
+ node_url = INTERNAL.require("url");
+ node_fs = INTERNAL.require("fs");
+ }
+ if (isFileUrl) {
+ url = node_url.fileURLToPath(url);
+ }
+
+ const arrayBuffer = await node_fs.promises.readFile(url);
+ return {
+ ok: true,
+ headers: [],
+ url,
+ arrayBuffer: () => arrayBuffer,
+ json: () => JSON.parse(arrayBuffer)
+ };
+ }
+ else if (hasFetch) {
+ return globalThis.fetch(url, init || { credentials: "same-origin" });
+ }
+ else if (typeof (read) === "function") {
+ // note that it can't open files with unicode names, like Strae.xml
+ // https://bugs.chromium.org/p/v8/issues/detail?id=12541
+ return {
+ ok: true,
+ url,
+ arrayBuffer: () => {
+ return new Uint8Array(read(url, "binary"));
+ },
+ json: () => {
+ return JSON.parse(read(url, "utf8"));
+ }
+ };
+ }
+ }
+ catch (e: any) {
+ return {
+ ok: false,
+ url,
+ status: 500,
+ statusText: "ERR28: " + e,
+ arrayBuffer: () => { throw e; },
+ json: () => { throw e; }
+ };
+ }
+ throw new Error("No fetch implementation available");
+}
+
+function normalizeFileUrl(filename: string) {
+ // unix vs windows
+ // remove query string
+ return filename.replace(/\\/g, "/").replace(/[?#].*/, "");
+}
+
+function normalizeDirectoryUrl(dir: string) {
+ return dir.slice(0, dir.lastIndexOf("/")) + "/";
+}
+
+const protocolRx = /^[a-zA-Z][a-zA-Z\d+\-.]*?:\/\//;
+const windowsAbsoluteRx = /[a-zA-Z]:[\\/]/;
+function isPathAbsolute(path: string): boolean {
+ if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
+ // unix /x.json
+ // windows \x.json
+ // windows C:\x.json
+ // windows C:/x.json
+ return path.startsWith("/") || path.startsWith("\\") || path.indexOf("///") !== -1 || windowsAbsoluteRx.test(path);
+ }
+
+ // anything with protocol is always absolute
+ // windows file:///C:/x.json
+ // windows http://C:/x.json
+ return protocolRx.test(path);
+}
diff --git a/src/mono/wasm/runtime/promise-controller.ts b/src/mono/wasm/runtime/loader/promise-controller.ts
similarity index 69%
rename from src/mono/wasm/runtime/promise-controller.ts
rename to src/mono/wasm/runtime/loader/promise-controller.ts
index f31c199143f2b..d46719c8b041f 100644
--- a/src/mono/wasm/runtime/promise-controller.ts
+++ b/src/mono/wasm/runtime/loader/promise-controller.ts
@@ -1,32 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import {
- mono_assert
-} from "./types";
+
+import type { ControllablePromise, PromiseAndController, PromiseController } from "../types/internal";
/// a unique symbol used to mark a promise as controllable
export const promise_control_symbol = Symbol.for("wasm promise_control");
-/// A PromiseController encapsulates a Promise together with easy access to its resolve and reject functions.
-/// It's a bit like a TaskCompletionSource in .NET
-export interface PromiseController {
- isDone: boolean;
- readonly promise: Promise;
- resolve: (value: T | PromiseLike) => void;
- reject: (reason?: any) => void;
-}
-
-/// A Promise with a controller attached
-export interface ControllablePromise extends Promise {
- [promise_control_symbol]: PromiseController;
-}
-
-/// Just a pair of a promise and its controller
-export interface PromiseAndController {
- promise: ControllablePromise;
- promise_control: PromiseController;
-}
-
/// Creates a new promise together with a controller that can be used to resolve or reject that promise.
/// Optionally takes callbacks to be called immediately after a promise is resolved or rejected.
export function createPromiseController(afterResolve?: () => void, afterReject?: () => void): PromiseAndController {
@@ -57,17 +36,17 @@ export function createPromiseController(afterResolve?: () => void, afterRejec
});
(promise_control).promise = promise;
const controllablePromise = promise as ControllablePromise;
- controllablePromise[promise_control_symbol] = promise_control;
+ (controllablePromise as any)[promise_control_symbol] = promise_control;
return { promise: controllablePromise, promise_control: promise_control };
}
export function getPromiseController(promise: ControllablePromise): PromiseController;
export function getPromiseController(promise: Promise): PromiseController | undefined {
- return (promise as ControllablePromise)[promise_control_symbol];
+ return (promise as any)[promise_control_symbol];
}
export function isControllablePromise(promise: Promise): promise is ControllablePromise {
- return (promise as ControllablePromise)[promise_control_symbol] !== undefined;
+ return (promise as any)[promise_control_symbol] !== undefined;
}
export function assertIsControllablePromise(promise: Promise): asserts promise is ControllablePromise {
diff --git a/src/mono/wasm/runtime/run-outer.ts b/src/mono/wasm/runtime/loader/run.ts
similarity index 75%
rename from src/mono/wasm/runtime/run-outer.ts
rename to src/mono/wasm/runtime/loader/run.ts
index 0321cd8e57410..3c762a01afa79 100644
--- a/src/mono/wasm/runtime/run-outer.ts
+++ b/src/mono/wasm/runtime/loader/run.ts
@@ -1,28 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-// WARNING: code in this file is executed before any of the emscripten code, so there is very little initialized already
+import type { MonoConfig, DotnetHostBuilder, DotnetModuleConfig, RuntimeAPI, WebAssemblyStartOptions } from "../types";
+import type { MonoConfigInternal, GlobalObjects, EmscriptenModuleInternal, RuntimeModuleExportsInternal, NativeModuleExportsInternal, } from "../types/internal";
-import type { MonoConfig, DotnetHostBuilder, DotnetModuleConfig, RuntimeAPI, WebAssemblyStartOptions } from "./types-api";
-import type { MonoConfigInternal, GlobalObjects, EmscriptenModuleInternal } from "./types";
-
-import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WEB, setGlobalObjects } from "./globals";
-import { mono_exit } from "./run";
-import { mono_assert } from "./types";
+import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WEB, exportedRuntimeAPI, setLoaderGlobals } from "./globals";
+import { deep_merge_config, deep_merge_module, mono_wasm_load_config } from "./config";
+import { mono_exit } from "./exit";
import { setup_proxy_console } from "./logging";
-import { deep_merge_config, deep_merge_module } from "./config";
-import { initializeExports } from "./exports";
+import { resolve_asset_path, start_asset_download } from "./assets";
+import { init_polyfills } from "./polyfills";
+import { runtimeHelpers, loaderHelpers } from "./globals";
+import { init_globalization } from "./icu";
+import { setupPreloadChannelToMainThread } from "./worker";
+
export const globalObjectsRoot: GlobalObjects = {
mono: {},
binding: {},
internal: {},
module: {},
- helpers: {},
+ loaderHelpers: {},
+ runtimeHelpers: {},
api: {}
} as any;
-setGlobalObjects(globalObjectsRoot);
+setLoaderGlobals(globalObjectsRoot);
const module = globalObjectsRoot.module;
const monoConfig = module.config as MonoConfigInternal;
@@ -347,9 +350,8 @@ export class HostBuilder implements DotnetHostBuilder {
}
}
-export function unifyModuleConfig(originalModule: EmscriptenModuleInternal, moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): DotnetModuleConfig {
- initializeExports();
- Object.assign(module, { ready: originalModule.ready });
+export async function createEmscripten(moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise {
+ // extract ModuleConfig
if (typeof moduleFactory === "function") {
const extension = moduleFactory(globalObjectsRoot.api) as any;
if (extension.ready) {
@@ -365,5 +367,78 @@ export function unifyModuleConfig(originalModule: EmscriptenModuleInternal, modu
throw new Error("MONO_WASM: Can't use moduleFactory callback of createDotnetRuntime function.");
}
+ return module.ENVIRONMENT_IS_PTHREAD
+ ? createEmscriptenWorker()
+ : createEmscriptenMain();
+}
+
+function importModules() {
+ runtimeHelpers.runtimeModuleUrl = resolve_asset_path("js-module-runtime").resolvedUrl!;
+ runtimeHelpers.nativeModuleUrl = resolve_asset_path("js-module-native").resolvedUrl!;
+ return [
+ // keep js module names dynamic by using config, in the future we can use feature detection to load different flavors
+ import(runtimeHelpers.runtimeModuleUrl),
+ import(runtimeHelpers.nativeModuleUrl),
+ ];
+}
+
+function initializeModules(es6Modules: [RuntimeModuleExportsInternal, NativeModuleExportsInternal]) {
+ const { initializeExports, initializeReplacements, configureEmscriptenStartup, configureWorkerStartup, setRuntimeGlobals, passEmscriptenInternals } = es6Modules[0];
+ const { default: emscriptenFactory } = es6Modules[1];
+ setRuntimeGlobals(globalObjectsRoot);
+ initializeExports(globalObjectsRoot);
+ loaderHelpers.runtimeModuleLoaded.promise_control.resolve();
+
+ emscriptenFactory((originalModule: EmscriptenModuleInternal) => {
+ Object.assign(module, {
+ ready: originalModule.ready,
+ __dotnet_runtime: {
+ initializeReplacements, configureEmscriptenStartup, configureWorkerStartup, passEmscriptenInternals
+ }
+ });
+
+ return module;
+ });
+}
+
+async function createEmscriptenMain(): Promise {
+ if (!module.configSrc && (!module.config || Object.keys(module.config).length === 0 || !module.config.assets)) {
+ // if config file location nor assets are provided
+ module.configSrc = "./mono-config.json";
+ }
+
+ await init_polyfills(module);
+
+ // download config
+ await mono_wasm_load_config(module);
+
+ const promises = importModules();
+
+ const wasmModuleAsset = resolve_asset_path("dotnetwasm");
+ start_asset_download(wasmModuleAsset).then(asset => {
+ loaderHelpers.wasmDownloadPromise.promise_control.resolve(asset);
+ });
+
+ init_globalization();
+ // TODO call mono_download_assets(); here in parallel ?
+ const es6Modules = await Promise.all(promises);
+ initializeModules(es6Modules as any);
+
+ await runtimeHelpers.dotnetReady.promise;
+
+ return exportedRuntimeAPI;
+}
+
+async function createEmscriptenWorker(): Promise {
+ await init_polyfills(module);
+
+ setupPreloadChannelToMainThread();
+
+ await loaderHelpers.afterConfigLoaded.promise;
+
+ const promises = importModules();
+ const es6Modules = await Promise.all(promises);
+ initializeModules(es6Modules as any);
+
return module;
}
diff --git a/src/mono/wasm/runtime/loader/worker.ts b/src/mono/wasm/runtime/loader/worker.ts
new file mode 100644
index 0000000000000..b4d67066fb8a3
--- /dev/null
+++ b/src/mono/wasm/runtime/loader/worker.ts
@@ -0,0 +1,53 @@
+import { MonoConfig } from "../types";
+import { MonoConfigInternal } from "../types/internal";
+import { deep_merge_config } from "./config";
+import { ENVIRONMENT_IS_WEB, loaderHelpers } from "./globals";
+
+export const monoSymbol = "__mono_message_please_dont_collide__"; //Symbol("mono");
+
+export function setupPreloadChannelToMainThread() {
+ const channel = new MessageChannel();
+ const workerPort = channel.port1;
+ const mainPort = channel.port2;
+ workerPort.addEventListener("message", (event) => {
+ const config = JSON.parse(event.data.config) as MonoConfig;
+ onMonoConfigReceived(config);
+ workerPort.close();
+ mainPort.close();
+ }, { once: true });
+ workerPort.start();
+ self.postMessage(makePreloadMonoMessage(mainPort), [mainPort]);
+}
+
+let workerMonoConfigReceived = false;
+
+// called when the main thread sends us the mono config
+function onMonoConfigReceived(config: MonoConfigInternal): void {
+ if (workerMonoConfigReceived) {
+ console.debug("MONO_WASM: mono config already received");
+ return;
+ }
+
+ deep_merge_config(loaderHelpers.config, config);
+ console.debug("MONO_WASM: mono config received");
+ workerMonoConfigReceived = true;
+ loaderHelpers.afterConfigLoaded.promise_control.resolve(loaderHelpers.config);
+
+ if (ENVIRONMENT_IS_WEB && config.forwardConsoleLogsToWS && typeof globalThis.WebSocket != "undefined") {
+ loaderHelpers.setup_proxy_console("pthread-worker", console, self.location.href);
+ }
+}
+
+export function makePreloadMonoMessage(port: TPort): any {
+ return {
+ [monoSymbol]: {
+ mono_cmd: WorkerMonoCommandType.preload,
+ port
+ }
+ };
+}
+
+const enum WorkerMonoCommandType {
+ channel_created = "channel_created",
+ preload = "preload",
+}
diff --git a/src/mono/wasm/runtime/logging.ts b/src/mono/wasm/runtime/logging.ts
index 5f3910e30499f..d0f93c27b0436 100644
--- a/src/mono/wasm/runtime/logging.ts
+++ b/src/mono/wasm/runtime/logging.ts
@@ -106,91 +106,6 @@ export function mono_wasm_trace_logger(log_domain_ptr: CharPtr, log_level_ptr: C
}
}
-export let consoleWebSocket: WebSocket;
-
-export function setup_proxy_console(id: string, console: Console, origin: string): void {
- // this need to be copy, in order to keep reference to original methods
- const originalConsole = {
- log: console.log,
- error: console.error
- };
- const anyConsole = console as any;
-
- function proxyConsoleMethod(prefix: string, func: any, asJson: boolean) {
- return function (...args: any[]) {
- try {
- let payload = args[0];
- if (payload === undefined) payload = "undefined";
- else if (payload === null) payload = "null";
- else if (typeof payload === "function") payload = payload.toString();
- else if (typeof payload !== "string") {
- try {
- payload = JSON.stringify(payload);
- } catch (e) {
- payload = payload.toString();
- }
- }
-
- if (typeof payload === "string") {
- if (payload[0] == "[") {
- const now = new Date().toISOString();
- if (id !== "main") {
- payload = `[${id}][${now}] ${payload}`;
- } else {
- payload = `[${now}] ${payload}`;
- }
- } else if (id !== "main") {
- payload = `[${id}] ${payload}`;
- }
- }
-
- if (asJson) {
- func(JSON.stringify({
- method: prefix,
- payload: payload,
- arguments: args
- }));
- } else {
- func([prefix + payload, ...args.slice(1)]);
- }
- } catch (err) {
- originalConsole.error(`proxyConsole failed: ${err}`);
- }
- };
- }
-
- const methods = ["debug", "trace", "warn", "info", "error"];
- for (const m of methods) {
- if (typeof (anyConsole[m]) !== "function") {
- anyConsole[m] = proxyConsoleMethod(`console.${m}: `, console.log, false);
- }
- }
-
- const consoleUrl = `${origin}/console`.replace("https://", "wss://").replace("http://", "ws://");
-
- consoleWebSocket = new WebSocket(consoleUrl);
- consoleWebSocket.addEventListener("open", () => {
- originalConsole.log(`browser: [${id}] Console websocket connected.`);
- });
- consoleWebSocket.addEventListener("error", (event) => {
- originalConsole.error(`[${id}] websocket error: ${event}`, event);
- });
- consoleWebSocket.addEventListener("close", (event) => {
- originalConsole.error(`[${id}] websocket closed: ${event}`, event);
- });
-
- const send = (msg: string) => {
- if (consoleWebSocket.readyState === WebSocket.OPEN) {
- consoleWebSocket.send(msg);
- }
- else {
- originalConsole.log(msg);
- }
- };
-
- for (const m of ["log", ...methods])
- anyConsole[m] = proxyConsoleMethod(`console.${m}`, send, true);
-}
export function parseSymbolMapFile(text: string) {
text.split(/[\r\n]/).forEach((line: string) => {
diff --git a/src/mono/wasm/runtime/managed-exports.ts b/src/mono/wasm/runtime/managed-exports.ts
index 4892052af5720..bc54e51b85bdd 100644
--- a/src/mono/wasm/runtime/managed-exports.ts
+++ b/src/mono/wasm/runtime/managed-exports.ts
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { GCHandle, MarshalerToCs, MarshalerToJs, MarshalerType, MonoMethod, mono_assert } from "./types";
+import { GCHandle, MarshalerToCs, MarshalerToJs, MarshalerType, MonoMethod } from "./types/internal";
import cwraps from "./cwraps";
import { runtimeHelpers, ENVIRONMENT_IS_PTHREAD, Module } from "./globals";
import { alloc_stack_frame, get_arg, get_arg_gc_handle, set_arg_type, set_gc_handle } from "./marshal";
diff --git a/src/mono/wasm/runtime/marshal-to-cs.ts b/src/mono/wasm/runtime/marshal-to-cs.ts
index cc596738cd07f..fbdd3629b6814 100644
--- a/src/mono/wasm/runtime/marshal-to-cs.ts
+++ b/src/mono/wasm/runtime/marshal-to-cs.ts
@@ -17,7 +17,7 @@ import {
import { get_marshaler_to_js_by_type } from "./marshal-to-js";
import { _zero_region } from "./memory";
import { js_string_to_mono_string_root } from "./strings";
-import { mono_assert, GCHandle, GCHandleNull, JSMarshalerArgument, JSMarshalerArguments, JSMarshalerType, MarshalerToCs, MarshalerToJs, BoundMarshalerToCs, MarshalerType } from "./types";
+import { GCHandle, GCHandleNull, JSMarshalerArgument, JSMarshalerArguments, JSMarshalerType, MarshalerToCs, MarshalerToJs, BoundMarshalerToCs, MarshalerType } from "./types/internal";
import { TypedArray } from "./types/emscripten";
import { addUnsettledPromise, settleUnsettledPromise } from "./pthreads/shared/eventloop";
diff --git a/src/mono/wasm/runtime/marshal-to-js.ts b/src/mono/wasm/runtime/marshal-to-js.ts
index 6590bacd12cef..1cbf461e6a7f0 100644
--- a/src/mono/wasm/runtime/marshal-to-js.ts
+++ b/src/mono/wasm/runtime/marshal-to-js.ts
@@ -1,10 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { createPromiseController, assertIsControllablePromise, getPromiseController } from "./promise-controller";
import cwraps from "./cwraps";
import { _lookup_js_owned_object, mono_wasm_get_jsobj_from_js_handle, mono_wasm_get_js_handle, setup_managed_proxy } from "./gc-handles";
-import { Module, runtimeHelpers } from "./globals";
+import { Module, createPromiseController, loaderHelpers, runtimeHelpers } from "./globals";
import {
ManagedObject, ManagedError,
get_arg_gc_handle, get_arg_js_handle, get_arg_type, get_arg_i32, get_arg_f64, get_arg_i52, get_arg_i16, get_arg_u8, get_arg_f32,
@@ -14,7 +13,7 @@ import {
ArraySegment, Span, MemoryViewType, get_signature_arg3_type, get_arg_i64_big, get_arg_intptr, get_arg_element_type, JavaScriptMarshalerArgSize
} from "./marshal";
import { conv_string_root } from "./strings";
-import { mono_assert, JSHandleNull, GCHandleNull, JSMarshalerArgument, JSMarshalerArguments, JSMarshalerType, MarshalerToCs, MarshalerToJs, BoundMarshalerToJs, MarshalerType } from "./types";
+import { JSHandleNull, GCHandleNull, JSMarshalerArgument, JSMarshalerArguments, JSMarshalerType, MarshalerToCs, MarshalerToJs, BoundMarshalerToJs, MarshalerType } from "./types/internal";
import { TypedArray } from "./types/emscripten";
import { get_marshaler_to_cs_by_type } from "./marshal-to-cs";
@@ -225,8 +224,8 @@ export function marshal_task_to_js(arg: JSMarshalerArgument, _?: MarshalerType,
}
const promise = mono_wasm_get_jsobj_from_js_handle(js_handle);
mono_assert(!!promise, () => `ERR28: promise not found for js_handle: ${js_handle} `);
- assertIsControllablePromise(promise);
- const promise_control = getPromiseController(promise);
+ loaderHelpers.assertIsControllablePromise(promise);
+ const promise_control = loaderHelpers.getPromiseController(promise);
const orig_resolve = promise_control.resolve;
promise_control.resolve = (argInner: JSMarshalerArgument) => {
@@ -281,8 +280,8 @@ export function mono_wasm_marshal_promise(args: JSMarshalerArguments): void {
// resolve existing promise
const promise = mono_wasm_get_jsobj_from_js_handle(js_handle);
mono_assert(!!promise, () => `ERR25: promise not found for js_handle: ${js_handle} `);
- assertIsControllablePromise(promise);
- const promise_control = getPromiseController(promise);
+ loaderHelpers.assertIsControllablePromise(promise);
+ const promise_control = loaderHelpers.getPromiseController(promise);
if (exc_type !== MarshalerType.None) {
const reason = marshal_exception_to_js(exc);
diff --git a/src/mono/wasm/runtime/marshal.ts b/src/mono/wasm/runtime/marshal.ts
index 5cc7a9eab5cad..9fc17c720bbe8 100644
--- a/src/mono/wasm/runtime/marshal.ts
+++ b/src/mono/wasm/runtime/marshal.ts
@@ -5,7 +5,7 @@ import { js_owned_gc_handle_symbol, teardown_managed_proxy } from "./gc-handles"
import { Module, runtimeHelpers } from "./globals";
import { getF32, getF64, getI16, getI32, getI64Big, getU16, getU32, getU8, setF32, setF64, setI16, setI32, setI64Big, setU16, setU32, setU8 } from "./memory";
import { mono_wasm_new_external_root } from "./roots";
-import { mono_assert, GCHandle, JSHandle, MonoObject, MonoString, GCHandleNull, JSMarshalerArguments, JSFunctionSignature, JSMarshalerType, JSMarshalerArgument, MarshalerToJs, MarshalerToCs, WasmRoot, MarshalerType } from "./types";
+import { GCHandle, JSHandle, MonoObject, MonoString, GCHandleNull, JSMarshalerArguments, JSFunctionSignature, JSMarshalerType, JSMarshalerArgument, MarshalerToJs, MarshalerToCs, WasmRoot, MarshalerType } from "./types/internal";
import { CharPtr, TypedArray, VoidPtr } from "./types/emscripten";
export const cs_to_js_marshalers = new Map();
diff --git a/src/mono/wasm/runtime/memory.ts b/src/mono/wasm/runtime/memory.ts
index 5ab35b8a12b76..83e94171a5327 100644
--- a/src/mono/wasm/runtime/memory.ts
+++ b/src/mono/wasm/runtime/memory.ts
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
import monoWasmThreads from "consts:monoWasmThreads";
-import { mono_assert, MemOffset, NumberOrPointer } from "./types";
+import { MemOffset, NumberOrPointer } from "./types/internal";
import { VoidPtr, CharPtr } from "./types/emscripten";
import cwraps, { I52Error } from "./cwraps";
import { Module, runtimeHelpers } from "./globals";
diff --git a/src/mono/wasm/runtime/modularize-dotnet.md b/src/mono/wasm/runtime/modularize-dotnet.md
index 63f4122f4e7fa..4b23e3790af35 100644
--- a/src/mono/wasm/runtime/modularize-dotnet.md
+++ b/src/mono/wasm/runtime/modularize-dotnet.md
@@ -1,5 +1,5 @@
# Linked javascript files
-They are emcc way how to extend the dotnet.js script during linking, by appending the scripts.
+They are emcc way how to extend the dotnet.native.js script during linking, by appending the scripts.
See https://emscripten.org/docs/tools_reference/emcc.html#emcc-pre-js
There are `-extern-pre-js`,`-pre-js`, `-post-js`, `-extern-post-js`.
diff --git a/src/mono/wasm/runtime/net6-legacy/buffers.ts b/src/mono/wasm/runtime/net6-legacy/buffers.ts
index 0a33b6991b0bd..533a161cd24b6 100644
--- a/src/mono/wasm/runtime/net6-legacy/buffers.ts
+++ b/src/mono/wasm/runtime/net6-legacy/buffers.ts
@@ -4,7 +4,7 @@
import { Module } from "../globals";
import { wrap_error_root, wrap_no_error_root } from "../invoke-js";
import { mono_wasm_new_external_root } from "../roots";
-import { MonoArray, MonoObjectRef, MonoObject } from "../types";
+import { MonoArray, MonoObjectRef, MonoObject } from "../types/internal";
import { Int32Ptr, TypedArray } from "../types/emscripten";
import { js_to_mono_obj_root } from "./js-to-cs";
diff --git a/src/mono/wasm/runtime/net6-legacy/corebindings.ts b/src/mono/wasm/runtime/net6-legacy/corebindings.ts
index 489df81ece89a..fd4d85aa02130 100644
--- a/src/mono/wasm/runtime/net6-legacy/corebindings.ts
+++ b/src/mono/wasm/runtime/net6-legacy/corebindings.ts
@@ -1,12 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { JSHandle, GCHandle, MonoObjectRef, MonoMethod, MonoObject, WasmRoot } from "../types";
+import { JSHandle, GCHandle, MonoObjectRef, MonoMethod, MonoObject, WasmRoot, PromiseController } from "../types/internal";
import { mono_bind_method, _create_primitive_converters } from "./method-binding";
import { mono_wasm_new_root } from "../roots";
import { Module, runtimeHelpers } from "../globals";
import cwraps from "../cwraps";
-import { PromiseController } from "../promise-controller";
import { legacyHelpers, wasm_type_symbol } from "./globals";
import { find_corlib_class } from "../class-loader";
type SigLine = [lazy: boolean, jsname: string, csname: string, signature: string/*ArgsMarshalString*/];
diff --git a/src/mono/wasm/runtime/net6-legacy/cs-to-js.ts b/src/mono/wasm/runtime/net6-legacy/cs-to-js.ts
index 2aefab4afb7a7..0585daae7b2a4 100644
--- a/src/mono/wasm/runtime/net6-legacy/cs-to-js.ts
+++ b/src/mono/wasm/runtime/net6-legacy/cs-to-js.ts
@@ -1,21 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+import { Int32Ptr, VoidPtr } from "../types/emscripten";
+import { MarshalType, MonoType, MarshalError, MonoTypeNull, MonoArray, MonoArrayNull, MonoObject, MonoObjectNull, GCHandle, MonoStringRef, MonoObjectRef, MonoString, JSHandleDisposed, is_nullish, WasmRoot } from "../types/internal";
import { _are_promises_supported } from "../cancelable-promise";
import { legacy_c_functions as cwraps } from "../cwraps";
import { mono_wasm_get_jsobj_from_js_handle, _lookup_js_owned_object, setup_managed_proxy, mono_wasm_get_js_handle, teardown_managed_proxy, assert_not_disposed } from "../gc-handles";
import { wrap_error_root, wrap_no_error_root } from "../invoke-js";
import { ManagedObject } from "../marshal";
import { getU32, getI32, getF32, getF64, setI32_unchecked } from "../memory";
-import { createPromiseController } from "../promise-controller";
import { mono_wasm_new_root, mono_wasm_new_external_root } from "../roots";
import { conv_string_root } from "../strings";
-import { MarshalType, MonoType, MarshalError, MonoTypeNull, MonoArray, MonoArrayNull, MonoObject, MonoObjectNull, GCHandle, MonoStringRef, MonoObjectRef, MonoString, JSHandleDisposed, is_nullish, WasmRoot } from "../types";
-import { Int32Ptr, VoidPtr } from "../types/emscripten";
import { legacyManagedExports } from "./corebindings";
import { legacyHelpers } from "./globals";
import { js_to_mono_obj_root } from "./js-to-cs";
import { mono_bind_method, mono_method_get_call_signature_ref } from "./method-binding";
+import { createPromiseController } from "../globals";
const delegate_invoke_symbol = Symbol.for("wasm delegate_invoke");
diff --git a/src/mono/wasm/runtime/net6-legacy/export-types.ts b/src/mono/wasm/runtime/net6-legacy/export-types.ts
index 921689525e34a..7d9e4d0bc0729 100644
--- a/src/mono/wasm/runtime/net6-legacy/export-types.ts
+++ b/src/mono/wasm/runtime/net6-legacy/export-types.ts
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import type { MemOffset, MonoArray, MonoObject, MonoObjectRef, MonoString, NumberOrPointer, WasmRoot, WasmRootBuffer } from "../types";
+import type { MemOffset, MonoArray, MonoObject, MonoObjectRef, MonoString, NumberOrPointer, WasmRoot, WasmRootBuffer } from "../types/internal";
import type { VoidPtr } from "../types/emscripten";
/**
@@ -106,10 +106,6 @@ export type MONOType = {
* @deprecated Please use config.assets instead
*/
mono_wasm_load_data_archive: (data: Uint8Array, prefix: string) => boolean;
- /**
- * @deprecated Please use configSrc instead
- */
- mono_wasm_load_config: (configFilePath: string) => Promise;
/**
* @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead.
*/
diff --git a/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts b/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts
index 0c45c2749357a..fc661b45b9fc2 100644
--- a/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts
+++ b/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts
@@ -4,11 +4,10 @@
import { legacy_c_functions as cwraps } from "../cwraps";
import { mono_wasm_runtime_ready } from "../debug";
import { mono_wasm_load_icu_data } from "../icu";
-import { runtimeHelpers } from "../globals";
import { mono_wasm_load_bytes_into_heap, setB32, setI8, setI16, setI32, setI52, setU52, setI64Big, setU8, setU16, setU32, setF32, setF64, getB32, getI8, getI16, getI32, getI52, getU52, getI64Big, getU8, getU16, getU32, getF32, getF64 } from "../memory";
import { mono_wasm_new_root_buffer, mono_wasm_new_root, mono_wasm_new_external_root, mono_wasm_release_roots } from "../roots";
import { mono_run_main, mono_run_main_and_exit } from "../run";
-import { mono_wasm_setenv, mono_wasm_load_config } from "../startup";
+import { mono_wasm_setenv } from "../startup";
import { js_string_to_mono_string, conv_string, js_string_to_mono_string_root, conv_string_root } from "../strings";
import { mono_array_to_js_array, unbox_mono_obj, unbox_mono_obj_root, mono_array_root_to_js_array } from "./cs-to-js";
import { js_typed_array_to_array, js_to_mono_obj, js_typed_array_to_array_root, js_to_mono_obj_root } from "./js-to-cs";
@@ -17,6 +16,7 @@ import { mono_wasm_load_runtime } from "../startup";
import { BINDINGType, MONOType } from "./export-types";
import { mono_wasm_load_data_archive } from "../assets";
import { mono_method_resolve } from "./method-binding";
+import { runtimeHelpers } from "../globals";
export function export_mono_api(): MONOType {
return {
@@ -26,7 +26,6 @@ export function export_mono_api(): MONOType {
mono_wasm_load_icu_data,
mono_wasm_runtime_ready,
mono_wasm_load_data_archive,
- mono_wasm_load_config,
mono_wasm_new_root_buffer,
mono_wasm_new_root,
mono_wasm_new_external_root,
diff --git a/src/mono/wasm/runtime/net6-legacy/globals.ts b/src/mono/wasm/runtime/net6-legacy/globals.ts
index cf69addeaee4a..3aabbe0830f38 100644
--- a/src/mono/wasm/runtime/net6-legacy/globals.ts
+++ b/src/mono/wasm/runtime/net6-legacy/globals.ts
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import type { GlobalObjects, MonoClass } from "../types";
+import type { GlobalObjects, MonoClass } from "../types/internal";
import type { VoidPtr } from "../types/emscripten";
import type { BINDINGType, MONOType } from "./export-types";
diff --git a/src/mono/wasm/runtime/net6-legacy/js-to-cs.ts b/src/mono/wasm/runtime/net6-legacy/js-to-cs.ts
index f4f81ef5615d7..21558c8624841 100644
--- a/src/mono/wasm/runtime/net6-legacy/js-to-cs.ts
+++ b/src/mono/wasm/runtime/net6-legacy/js-to-cs.ts
@@ -9,7 +9,7 @@ import { wrap_error_root, wrap_no_error_root } from "../invoke-js";
import { setI32_unchecked, setU32_unchecked, setF64, setB32 } from "../memory";
import { mono_wasm_new_root, mono_wasm_release_roots, mono_wasm_new_external_root } from "../roots";
import { js_string_to_mono_string_root, js_string_to_mono_string_interned_root } from "../strings";
-import { MonoObject, is_nullish, MonoClass, MonoArray, MonoMethod, MonoObjectNull, JSHandle, MonoObjectRef, JSHandleNull, JSHandleDisposed, WasmRoot } from "../types";
+import { MonoObject, is_nullish, MonoClass, MonoArray, MonoMethod, MonoObjectNull, JSHandle, MonoObjectRef, JSHandleNull, JSHandleDisposed, WasmRoot } from "../types/internal";
import { TypedArray, Int32Ptr } from "../types/emscripten";
import { has_backing_array_buffer } from "./buffers";
import { legacyManagedExports } from "./corebindings";
diff --git a/src/mono/wasm/runtime/net6-legacy/method-binding.ts b/src/mono/wasm/runtime/net6-legacy/method-binding.ts
index 780301959061f..4cab645fb1825 100644
--- a/src/mono/wasm/runtime/net6-legacy/method-binding.ts
+++ b/src/mono/wasm/runtime/net6-legacy/method-binding.ts
@@ -8,7 +8,7 @@ import { parseFQN } from "../invoke-cs";
import { setI32, setU32, setF32, setF64, setU52, setI52, setB32, setI32_unchecked, setU32_unchecked, _zero_region, _create_temp_frame, getB32, getI32, getU32, getF32, getF64 } from "../memory";
import { mono_wasm_new_external_root, mono_wasm_new_root } from "../roots";
import { js_string_to_mono_string_root, js_string_to_mono_string_interned_root, conv_string_root } from "../strings";
-import { MonoMethod, MonoObject, MonoType, MonoClass, mono_assert, VoidPtrNull, MarshalType, MonoString, MonoObjectNull, WasmRootBuffer, WasmRoot } from "../types";
+import { MonoMethod, MonoObject, MonoType, MonoClass, VoidPtrNull, MarshalType, MonoString, MonoObjectNull, WasmRootBuffer, WasmRoot } from "../types/internal";
import { VoidPtr } from "../types/emscripten";
import { legacyManagedExports } from "./corebindings";
import { get_js_owned_object_by_gc_handle_ref, _unbox_mono_obj_root_with_known_nonprimitive_type } from "./cs-to-js";
diff --git a/src/mono/wasm/runtime/net6-legacy/method-calls.ts b/src/mono/wasm/runtime/net6-legacy/method-calls.ts
index cf9fee9430ebd..330e7c0c44b02 100644
--- a/src/mono/wasm/runtime/net6-legacy/method-calls.ts
+++ b/src/mono/wasm/runtime/net6-legacy/method-calls.ts
@@ -9,7 +9,7 @@ import { _release_temp_frame } from "../memory";
import { mono_wasm_new_external_root, mono_wasm_new_root } from "../roots";
import { find_entry_point } from "../run";
import { conv_string_root, js_string_to_mono_string_root } from "../strings";
-import { JSHandle, MonoStringRef, MonoObjectRef, MonoArray, MonoString, MonoObject, is_nullish, mono_assert, WasmRoot } from "../types";
+import { JSHandle, MonoStringRef, MonoObjectRef, MonoArray, MonoString, MonoObject, is_nullish, WasmRoot } from "../types/internal";
import { Int32Ptr, VoidPtr } from "../types/emscripten";
import { mono_array_root_to_js_array, unbox_mono_obj_root } from "./cs-to-js";
import { js_array_to_mono_array, js_to_mono_obj_root } from "./js-to-cs";
diff --git a/src/mono/wasm/runtime/polyfills.ts b/src/mono/wasm/runtime/polyfills.ts
index 4edfffe60f467..597821b56768c 100644
--- a/src/mono/wasm/runtime/polyfills.ts
+++ b/src/mono/wasm/runtime/polyfills.ts
@@ -3,31 +3,56 @@
import BuildConfiguration from "consts:configuration";
import MonoWasmThreads from "consts:monoWasmThreads";
-import type { DotnetModuleConfigImports, EmscriptenReplacements } from "./types";
+import type { EmscriptenReplacements } from "./types/internal";
import type { TypedArray } from "./types/emscripten";
-import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WORKER, ENVIRONMENT_IS_WEB, INTERNAL, Module, runtimeHelpers } from "./globals";
+import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WEB, INTERNAL, Module, loaderHelpers, runtimeHelpers } from "./globals";
import { replaceEmscriptenPThreadLibrary } from "./pthreads/shared/emscripten-replacements";
-let node_fs: any | undefined = undefined;
-let node_url: any | undefined = undefined;
-
-export function init_polyfills(): void {
+const dummyPerformance = {
+ now: function () {
+ return Date.now();
+ }
+};
+export function initializeReplacements(replacements: EmscriptenReplacements): void {
// performance.now() is used by emscripten and doesn't work in JSC
if (typeof globalThis.performance === "undefined") {
globalThis.performance = dummyPerformance as any;
}
- if (typeof globalThis.URL === "undefined") {
- globalThis.URL = class URL {
- private url;
- constructor(url: string) {
- this.url = url;
- }
- toString() {
- return this.url;
- }
- } as any;
+ replacements.require = INTERNAL.require;
+
+ // script location
+ replacements.scriptDirectory = loaderHelpers.scriptDirectory;
+ if (Module.locateFile === Module.__locateFile) {
+ Module.locateFile = loaderHelpers.locateFile;
+ }
+
+ if (BuildConfiguration === "Debug") {
+ console.debug(`MONO_WASM: starting script ${loaderHelpers.scriptUrl}`);
+ console.debug(`MONO_WASM: starting in ${loaderHelpers.scriptDirectory}`);
+ }
+
+ // prefer fetch_like over global fetch for assets
+ replacements.fetch = loaderHelpers.fetch_like;
+
+ // misc
+ replacements.noExitRuntime = ENVIRONMENT_IS_WEB;
+
+ // threads
+ if (MonoWasmThreads) {
+ if (replacements.pthreadReplacements) {
+ replaceEmscriptenPThreadLibrary(replacements.pthreadReplacements);
+ }
}
+
+ // memory
+ const originalUpdateMemoryViews = replacements.updateMemoryViews;
+ runtimeHelpers.updateMemoryViews = replacements.updateMemoryViews = () => {
+ originalUpdateMemoryViews();
+ };
+}
+
+export async function init_polyfills_async(): Promise {
// v8 shell doesn't have Event and EventTarget
if (MonoWasmThreads && typeof globalThis.Event === "undefined") {
globalThis.Event = class Event {
@@ -119,73 +144,8 @@ export function init_polyfills(): void {
}
};
}
-}
-
-export function initializeReplacements(replacements: EmscriptenReplacements): void {
- // require replacement
- const imports = Module.imports = (Module.imports || {}) as DotnetModuleConfigImports;
- const requireWrapper = (wrappedRequire: Function) => (name: string) => {
- const resolved = (Module.imports)[name];
- if (resolved) {
- return resolved;
- }
- return wrappedRequire(name);
- };
- if (imports.require) {
- runtimeHelpers.requirePromise = replacements.requirePromise = Promise.resolve(requireWrapper(imports.require));
- }
- else if (replacements.require) {
- runtimeHelpers.requirePromise = replacements.requirePromise = Promise.resolve(requireWrapper(replacements.require));
- } else if (replacements.requirePromise) {
- runtimeHelpers.requirePromise = replacements.requirePromise.then(require => requireWrapper(require));
- } else {
- runtimeHelpers.requirePromise = replacements.requirePromise = Promise.resolve(requireWrapper((name: string) => {
- throw new Error(`Please provide Module.imports.${name} or Module.imports.require`);
- }));
- }
-
- // script location
- runtimeHelpers.scriptDirectory = replacements.scriptDirectory = detectScriptDirectory(replacements);
- Module.mainScriptUrlOrBlob = replacements.scriptUrl;// this is needed by worker threads
- if (BuildConfiguration === "Debug") {
- console.debug(`MONO_WASM: starting script ${replacements.scriptUrl}`);
- console.debug(`MONO_WASM: starting in ${runtimeHelpers.scriptDirectory}`);
- }
- if (Module.__locateFile === Module.locateFile) {
- // above it's our early version, we could replace it with better
- Module.locateFile = runtimeHelpers.locateFile = (path) => {
- if (isPathAbsolute(path)) return path;
- return runtimeHelpers.scriptDirectory + path;
- };
- } else {
- // we use what was given to us
- runtimeHelpers.locateFile = Module.locateFile!;
- }
-
- // prefer fetch_like over global fetch for assets
- replacements.fetch = runtimeHelpers.fetch_like = imports.fetch || fetch_like;
-
- // misc
- replacements.noExitRuntime = ENVIRONMENT_IS_WEB;
-
- // threads
- if (MonoWasmThreads) {
- if (replacements.pthreadReplacements) {
- replaceEmscriptenPThreadLibrary(replacements.pthreadReplacements);
- }
- }
-
- // memory
- const originalUpdateMemoryViews = replacements.updateMemoryViews;
- runtimeHelpers.updateMemoryViews = replacements.updateMemoryViews = () => {
- originalUpdateMemoryViews();
- };
-}
-
-export async function init_polyfills_async(): Promise {
if (ENVIRONMENT_IS_NODE) {
// wait for locateFile setup on NodeJs
- INTERNAL.require = await runtimeHelpers.requirePromise;
if (globalThis.performance === dummyPerformance) {
const { performance } = INTERNAL.require("perf_hooks");
globalThis.performance = performance;
@@ -223,106 +183,4 @@ export async function init_polyfills_async(): Promise {
runtimeHelpers.subtle = globalThis.crypto?.subtle;
}
-const dummyPerformance = {
- now: function () {
- return Date.now();
- }
-};
-export async function fetch_like(url: string, init?: RequestInit): Promise {
- const imports = Module.imports as DotnetModuleConfigImports;
- const hasFetch = typeof (globalThis.fetch) === "function";
- try {
- if (typeof (imports.fetch) === "function") {
- return imports.fetch(url, init || { credentials: "same-origin" });
- }
- else if (ENVIRONMENT_IS_NODE) {
- const isFileUrl = url.startsWith("file://");
- if (!isFileUrl && hasFetch) {
- return globalThis.fetch(url, init || { credentials: "same-origin" });
- }
- if (!node_fs) {
- const node_require = await runtimeHelpers.requirePromise;
- node_url = node_require("url");
- node_fs = node_require("fs");
- }
- if (isFileUrl) {
- url = node_url.fileURLToPath(url);
- }
-
- const arrayBuffer = await node_fs.promises.readFile(url);
- return {
- ok: true,
- headers: [],
- url,
- arrayBuffer: () => arrayBuffer,
- json: () => JSON.parse(arrayBuffer)
- };
- }
- else if (hasFetch) {
- return globalThis.fetch(url, init || { credentials: "same-origin" });
- }
- else if (typeof (read) === "function") {
- // note that it can't open files with unicode names, like Strae.xml
- // https://bugs.chromium.org/p/v8/issues/detail?id=12541
- const arrayBuffer = new Uint8Array(read(url, "binary"));
- return {
- ok: true,
- url,
- arrayBuffer: () => arrayBuffer,
- json: () => JSON.parse(Module.UTF8ArrayToString(arrayBuffer, 0, arrayBuffer.length))
- };
- }
- }
- catch (e: any) {
- return {
- ok: false,
- url,
- status: 500,
- statusText: "ERR28: " + e,
- arrayBuffer: () => { throw e; },
- json: () => { throw e; }
- };
- }
- throw new Error("No fetch implementation available");
-}
-
-function normalizeFileUrl(filename: string) {
- // unix vs windows
- // remove query string
- return filename.replace(/\\/g, "/").replace(/[?#].*/, "");
-}
-
-function normalizeDirectoryUrl(dir: string) {
- return dir.slice(0, dir.lastIndexOf("/")) + "/";
-}
-
-export function detectScriptDirectory(replacements: EmscriptenReplacements): string {
- if (ENVIRONMENT_IS_WORKER) {
- // Check worker, not web, since window could be polyfilled
- replacements.scriptUrl = self.location.href;
- }
- if (!replacements.scriptUrl) {
- // probably V8 shell in non ES6
- replacements.scriptUrl = "./dotnet.js";
- }
- replacements.scriptUrl = normalizeFileUrl(replacements.scriptUrl);
- return normalizeDirectoryUrl(replacements.scriptUrl);
-}
-
-const protocolRx = /^[a-zA-Z][a-zA-Z\d+\-.]*?:\/\//;
-const windowsAbsoluteRx = /[a-zA-Z]:[\\/]/;
-function isPathAbsolute(path: string): boolean {
- if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
- // unix /x.json
- // windows \x.json
- // windows C:\x.json
- // windows C:/x.json
- return path.startsWith("/") || path.startsWith("\\") || path.indexOf("///") !== -1 || windowsAbsoluteRx.test(path);
- }
-
- // anything with protocol is always absolute
- // windows file:///C:/x.json
- // windows http://C:/x.json
- return protocolRx.test(path);
-}
diff --git a/src/mono/wasm/runtime/profiler.ts b/src/mono/wasm/runtime/profiler.ts
index fbaa646d903bb..021273c2f82b9 100644
--- a/src/mono/wasm/runtime/profiler.ts
+++ b/src/mono/wasm/runtime/profiler.ts
@@ -2,9 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./globals";
-import { AOTProfilerOptions, BrowserProfilerOptions } from "./types";
+import { MonoMethod, AOTProfilerOptions, BrowserProfilerOptions } from "./types/internal";
import cwraps from "./cwraps";
-import { MonoMethod } from "./types";
// Initialize the AOT profiler with OPTIONS.
// Requires the AOT profiler to be linked into the app.
diff --git a/src/mono/wasm/runtime/promise-utils.ts b/src/mono/wasm/runtime/promise-utils.ts
deleted file mode 100644
index 6b1e57ee73738..0000000000000
--- a/src/mono/wasm/runtime/promise-utils.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/// Make a promise that resolves after a given number of milliseconds.
-export function delay(ms: number): Promise {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-
diff --git a/src/mono/wasm/runtime/pthreads/browser/index.ts b/src/mono/wasm/runtime/pthreads/browser/index.ts
index 9910fcea2daea..0fbefa9cf9443 100644
--- a/src/mono/wasm/runtime/pthreads/browser/index.ts
+++ b/src/mono/wasm/runtime/pthreads/browser/index.ts
@@ -4,11 +4,10 @@
import { isMonoWorkerMessageChannelCreated, monoSymbol, makeMonoThreadMessageApplyMonoConfig, isMonoWorkerMessagePreload, MonoWorkerMessage } from "../shared";
import { pthread_ptr } from "../shared/types";
import { MonoThreadMessage } from "../shared";
-import { PromiseController, createPromiseController } from "../../promise-controller";
-import { mono_assert } from "../../types";
import Internals from "../shared/emscripten-internals";
-import { runtimeHelpers } from "../../globals";
-import { MonoConfig } from "../../types-api";
+import { createPromiseController, runtimeHelpers } from "../../globals";
+import { PromiseController } from "../../types/internal";
+import { MonoConfig } from "../../types";
const threads: Map = new Map();
diff --git a/src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts b/src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts
index 681a64bb21a71..be5962ef6269d 100644
--- a/src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts
+++ b/src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts
@@ -2,13 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
import MonoWasmThreads from "consts:monoWasmThreads";
-import { PThreadReplacements } from "../../types";
import { afterLoadWasmModuleToWorker } from "../browser";
import { afterThreadInitTLS } from "../worker";
import Internals from "./emscripten-internals";
-import { resolve_asset_path } from "../../assets";
-import { mono_assert } from "../../types";
-import { runtimeHelpers } from "../../globals";
+import { loaderHelpers, runtimeHelpers } from "../../globals";
+import { PThreadReplacements } from "../../types/internal";
/** @module emscripten-replacements Replacements for individual functions in the emscripten PThreads library.
* These have a hard dependency on the version of Emscripten that we are using and may need to be kept in sync with
@@ -37,7 +35,7 @@ export function replaceEmscriptenPThreadLibrary(replacements: PThreadReplacement
function replacementAllocateUnusedWorker(): void {
if (runtimeHelpers.diagnosticTracing)
console.debug("MONO_WASM: replacementAllocateUnusedWorker");
- const asset = resolve_asset_path("js-module-threads");
+ const asset = loaderHelpers.resolve_asset_path("js-module-threads");
const uri = asset.resolvedUrl;
mono_assert(uri !== undefined, "could not resolve the uri for the js-module-threads asset");
const worker = new Worker(uri);
diff --git a/src/mono/wasm/runtime/pthreads/shared/index.ts b/src/mono/wasm/runtime/pthreads/shared/index.ts
index e5a8d655f3a63..73cb190d446b5 100644
--- a/src/mono/wasm/runtime/pthreads/shared/index.ts
+++ b/src/mono/wasm/runtime/pthreads/shared/index.ts
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { Module } from "../../globals";
-import { MonoConfig } from "../../types-api";
+import { MonoConfig } from "../../types";
import { pthread_ptr } from "./types";
export interface PThreadInfo {
@@ -105,15 +105,6 @@ export function makeChannelCreatedMonoMessage(thread_id: pthread_ptr, por
};
}
-export function makePreloadMonoMessage(port: TPort): MonoWorkerMessagePreload {
- return {
- [monoSymbol]: {
- mono_cmd: WorkerMonoCommandType.preload,
- port
- }
- };
-}
-
export function isMonoWorkerMessage(message: unknown): message is MonoWorkerMessage {
return message !== undefined && typeof message === "object" && message !== null && monoSymbol in message;
}
diff --git a/src/mono/wasm/runtime/pthreads/worker/index.ts b/src/mono/wasm/runtime/pthreads/worker/index.ts
index 5669377e88b4c..8d8c7e6d19aa4 100644
--- a/src/mono/wasm/runtime/pthreads/worker/index.ts
+++ b/src/mono/wasm/runtime/pthreads/worker/index.ts
@@ -4,10 +4,10 @@
///
import MonoWasmThreads from "consts:monoWasmThreads";
-import { Module, ENVIRONMENT_IS_PTHREAD, runtimeHelpers, ENVIRONMENT_IS_WEB } from "../../globals";
-import { makeChannelCreatedMonoMessage, makePreloadMonoMessage } from "../shared";
+import { Module, ENVIRONMENT_IS_PTHREAD, runtimeHelpers } from "../../globals";
+import { makeChannelCreatedMonoMessage } from "../shared";
import type { pthread_ptr } from "../shared/types";
-import { is_nullish, MonoConfigInternal, mono_assert } from "../../types";
+import { is_nullish } from "../../types/internal";
import type { MonoThreadMessage } from "../shared";
import {
PThreadSelf,
@@ -16,9 +16,7 @@ import {
dotnetPthreadAttached,
WorkerThreadEventTarget
} from "./events";
-import { setup_proxy_console } from "../../logging";
-import { afterConfigLoaded, preRunWorker } from "../../startup";
-import { MonoConfig } from "../../types-api";
+import { preRunWorker } from "../../startup";
// re-export some of the events types
export {
@@ -64,19 +62,6 @@ function monoDedicatedChannelMessageFromMainToWorker(event: MessageEvent
console.debug("MONO_WASM: got message from main on the dedicated channel", event.data);
}
-export function setupPreloadChannelToMainThread() {
- const channel = new MessageChannel();
- const workerPort = channel.port1;
- const mainPort = channel.port2;
- workerPort.addEventListener("message", (event) => {
- const config = JSON.parse(event.data.config) as MonoConfig;
- onMonoConfigReceived(config);
- workerPort.close();
- mainPort.close();
- }, { once: true });
- workerPort.start();
- self.postMessage(makePreloadMonoMessage(mainPort), [mainPort]);
-}
function setupChannelToMainThread(pthread_ptr: pthread_ptr): PThreadSelf {
console.debug("MONO_WASM: creating a channel", pthread_ptr);
@@ -90,25 +75,6 @@ function setupChannelToMainThread(pthread_ptr: pthread_ptr): PThreadSelf {
return pthread_self;
}
-let workerMonoConfigReceived = false;
-
-// called when the main thread sends us the mono config
-function onMonoConfigReceived(config: MonoConfigInternal): void {
- if (workerMonoConfigReceived) {
- console.debug("MONO_WASM: mono config already received");
- return;
- }
-
- console.debug("MONO_WASM: mono config received");
- config = runtimeHelpers.config = Module.config = Object.assign(Module.config || {} as any, config);
- workerMonoConfigReceived = true;
-
- afterConfigLoaded.promise_control.resolve(config);
-
- if (ENVIRONMENT_IS_WEB && config.forwardConsoleLogsToWS && typeof globalThis.WebSocket != "undefined") {
- setup_proxy_console("pthread-worker", console, self.location.href);
- }
-}
/// This is an implementation detail function.
/// Called in the worker thread from mono when a pthread becomes attached to the mono runtime.
diff --git a/src/mono/wasm/runtime/rollup.config.js b/src/mono/wasm/runtime/rollup.config.js
index a666eebd725f9..dd8c7b8f89125 100644
--- a/src/mono/wasm/runtime/rollup.config.js
+++ b/src/mono/wasm/runtime/rollup.config.js
@@ -31,16 +31,11 @@ const terserConfig = {
keep_fnames: /(mono_wasm_runtime_ready|mono_wasm_fire_debugger_agent_message_with_data|mono_wasm_fire_debugger_agent_message_with_data_to_pause|mono_wasm_set_timeout_exec)/,
keep_classnames: /(ManagedObject|ManagedError|Span|ArraySegment|WasmRootBuffer|SessionOptionsBuilder)/,
},
- format: {
- wrap_iife: true
- }
};
const plugins = isDebug ? [writeOnChangePlugin()] : [terser(terserConfig), writeOnChangePlugin()];
const banner = "//! Licensed to the .NET Foundation under one or more agreements.\n//! The .NET Foundation licenses this file to you under the MIT license.\n";
const banner_dts = banner + "//!\n//! This is generated file, see src/mono/wasm/runtime/rollup.config.js\n\n//! This is not considered public API with backward compatibility guarantees. \n";
// emcc doesn't know how to load ES6 module, that's why we need the whole rollup.js
-const format = "iife";
-const name = "__dotnet_runtime";
const inlineAssert = [
{
pattern: /mono_assert\(([^,]*), *"([^"]*)"\);/gm,
@@ -50,10 +45,24 @@ const inlineAssert = [
{
pattern: /mono_assert\(([^,]*), \(\) => *`([^`]*)`\);/gm,
replacement: "if (!($1)) throw new Error(`Assert failed: $2`); // inlined mono_assert"
- }, {
- pattern: /^\s*mono_assert/gm,
- failure: "previous regexp didn't inline all mono_assert statements"
- }];
+ }
+];
+const checkAssert =
+{
+ pattern: /^\s*mono_assert/gm,
+ failure: "previous regexp didn't inline all mono_assert statements"
+};
+const checkNoLoader =
+{
+ pattern: /_loaderModuleLoaded/gm,
+ failure: "module should not contain loaderModuleLoaded member. This is probably duplicated code in the output caused by a dependency outside on the loader module."
+};
+const checkNoRuntime =
+{
+ pattern: /_runtimeModuleLoaded/gm,
+ failure: "module should not contain runtimeModuleLoaded member. This is probably duplicated code in the output caused by a dependency on the runtime module."
+};
+
let gitHash;
try {
@@ -85,29 +94,26 @@ const typescriptConfigOptions = {
include: ["**/*.ts", "../../../../artifacts/bin/native/generated/**/*.ts"]
};
-const outputCodePlugins = [regexReplace(inlineAssert), consts({ productVersion, configuration, monoWasmThreads, monoDiagnosticsMock, gitHash, WasmEnableLegacyJsInterop }), typescript(typescriptConfigOptions)];
-
-const externalDependencies = [
-];
+const outputCodePlugins = [consts({ productVersion, configuration, monoWasmThreads, monoDiagnosticsMock, gitHash, WasmEnableLegacyJsInterop }), typescript(typescriptConfigOptions)];
+const externalDependencies = ["module"];
-const iffeConfig = {
+const loaderConfig = {
treeshake: !isDebug,
- input: "exports.ts",
+ input: "./loader/index.ts",
output: [
{
- file: nativeBinDir + "/src/es6/runtime.es6.iffe.js",
- name,
+ format: "es",
+ file: nativeBinDir + "/dotnet.js",
banner,
- format,
plugins,
}
],
external: externalDependencies,
- plugins: outputCodePlugins,
+ plugins: [regexReplace(inlineAssert), regexCheck([checkAssert, checkNoRuntime]), ...outputCodePlugins],
onwarn: onwarn
};
const typesConfig = {
- input: "./export-types.ts",
+ input: "./types/export-types.ts",
output: [
{
format: "es",
@@ -119,6 +125,21 @@ const typesConfig = {
external: externalDependencies,
plugins: [dts()],
};
+const runtimeConfig = {
+ treeshake: !isDebug,
+ input: "exports.ts",
+ output: [
+ {
+ format: "es",
+ file: nativeBinDir + "/dotnet.runtime.js",
+ banner,
+ plugins,
+ }
+ ],
+ external: externalDependencies,
+ plugins: [regexReplace(inlineAssert), regexCheck([checkAssert, checkNoLoader]), ...outputCodePlugins],
+ onwarn: onwarn
+};
const legacyConfig = {
input: "./net6-legacy/export-types.ts",
output: [
@@ -189,7 +210,8 @@ function makeWorkerConfig(workerName, workerInputSourcePath) {
const workerConfigs = findWebWorkerInputs("./workers").map((workerInput) => makeWorkerConfig(workerInput.workerName, workerInput.path));
const allConfigs = [
- iffeConfig,
+ loaderConfig,
+ runtimeConfig,
typesConfig,
legacyConfig,
].concat(workerConfigs)
@@ -254,11 +276,45 @@ function checkFileExists(file) {
.catch(() => false);
}
+function regexCheck(checks = []) {
+ const filter = createFilter("**/*.ts");
+
+ return {
+ name: "regexCheck",
+
+ renderChunk(code, chunk) {
+ const id = chunk.fileName;
+ if (!filter(id)) return null;
+ return executeCheck(this, code, id);
+ },
+
+ transform(code, id) {
+ if (!filter(id)) return null;
+ return executeCheck(this, code, id);
+ }
+ };
+
+ function executeCheck(self, code, id) {
+ // self.warn("executeCheck" + id);
+ for (const rep of checks) {
+ const { pattern, failure } = rep;
+ const match = pattern.test(code);
+ if (match) {
+ self.error(failure + " " + id);
+ return null;
+ }
+ }
+
+ return null;
+ }
+}
+
+
function regexReplace(replacements = []) {
const filter = createFilter("**/*.ts");
return {
- name: "replace",
+ name: "regexReplace",
renderChunk(code, chunk) {
const id = chunk.fileName;
@@ -272,21 +328,12 @@ function regexReplace(replacements = []) {
}
};
- function executeReplacement(self, code, id) {
+ function executeReplacement(_, code) {
// TODO use MagicString for sourcemap support
let fixed = code;
for (const rep of replacements) {
- const { pattern, replacement, failure } = rep;
- if (failure) {
- const match = pattern.test(fixed);
- if (match) {
- self.error(failure + " " + id, pattern.lastIndex);
- return null;
- }
- }
- else {
- fixed = fixed.replace(pattern, replacement);
- }
+ const { pattern, replacement } = rep;
+ fixed = fixed.replace(pattern, replacement);
}
if (fixed == code) {
diff --git a/src/mono/wasm/runtime/roots.ts b/src/mono/wasm/runtime/roots.ts
index 05b49a0b81df0..30d0bdc0554c5 100644
--- a/src/mono/wasm/runtime/roots.ts
+++ b/src/mono/wasm/runtime/roots.ts
@@ -4,7 +4,7 @@
import cwraps from "./cwraps";
import { Module } from "./globals";
import { VoidPtr, ManagedPointer, NativePointer } from "./types/emscripten";
-import { MonoObjectRef, MonoObjectRefNull, MonoObject, is_nullish, WasmRoot, WasmRootBuffer } from "./types";
+import { MonoObjectRef, MonoObjectRefNull, MonoObject, is_nullish, WasmRoot, WasmRootBuffer } from "./types/internal";
import { _zero_region } from "./memory";
const maxScratchRoots = 8192;
diff --git a/src/mono/wasm/runtime/run.ts b/src/mono/wasm/runtime/run.ts
index 9b92f33555e65..bdbb2f8e7bfa8 100644
--- a/src/mono/wasm/runtime/run.ts
+++ b/src/mono/wasm/runtime/run.ts
@@ -1,14 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WEB, INTERNAL, Module, runtimeHelpers } from "./globals";
+import { loaderHelpers, runtimeHelpers } from "./globals";
import { mono_wasm_wait_for_debugger } from "./debug";
-import { abort_startup, mono_wasm_set_main_args } from "./startup";
+import { mono_wasm_set_main_args } from "./startup";
import cwraps from "./cwraps";
import { assembly_load } from "./class-loader";
-import { mono_assert } from "./types";
-import { consoleWebSocket, mono_wasm_stringify_as_error_with_stack } from "./logging";
-import { jiterpreter_dump_stats } from "./jiterpreter";
/**
* Possible signatures are described here https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line
@@ -16,13 +13,13 @@ import { jiterpreter_dump_stats } from "./jiterpreter";
export async function mono_run_main_and_exit(main_assembly_name: string, args: string[]): Promise {
try {
const result = await mono_run_main(main_assembly_name, args);
- mono_exit(result);
+ loaderHelpers.mono_exit(result);
return result;
} catch (error) {
if (error instanceof runtimeHelpers.ExitStatus) {
return error.status;
}
- mono_exit(1, error);
+ loaderHelpers.mono_exit(1, error);
return 1;
}
}
@@ -56,131 +53,3 @@ export function find_entry_point(assembly: string) {
return method;
}
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-export function mono_on_abort(error: any): void {
- abort_startup(error, false);
- mono_exit(1, error);
-}
-
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-export function mono_exit(exit_code: number, reason?: any): void {
- if (runtimeHelpers.config && runtimeHelpers.config.asyncFlushOnExit && exit_code === 0) {
- // this would NOT call Node's exit() immediately, it's a hanging promise
- (async () => {
- try {
- await flush_node_streams();
- }
- finally {
- set_exit_code_and_quit_now(exit_code, reason);
- }
- })();
- // we need to throw, rather than let the caller continue the normal execution
- // in the middle of some code, which expects this to stop the process
- throw runtimeHelpers.ExitStatus
- ? new runtimeHelpers.ExitStatus(exit_code)
- : reason
- ? reason
- : new Error("Stop with exit code " + exit_code);
- } else {
- set_exit_code_and_quit_now(exit_code, reason);
- }
-}
-
-async function flush_node_streams() {
- try {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore:
- const process = await import(/* webpackIgnore: true */"process");
- const flushStream = (stream: any) => {
- return new Promise((resolve, reject) => {
- stream.on("error", (error: any) => reject(error));
- stream.write("", function () { resolve(); });
- });
- };
- const stderrFlushed = flushStream(process.stderr);
- const stdoutFlushed = flushStream(process.stdout);
- await Promise.all([stdoutFlushed, stderrFlushed]);
- } catch (err) {
- console.error(`flushing std* streams failed: ${err}`);
- }
-}
-
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-function set_exit_code_and_quit_now(exit_code: number, reason?: any): void {
- if (runtimeHelpers.ExitStatus) {
- if (reason && !(reason instanceof runtimeHelpers.ExitStatus)) {
- if (!runtimeHelpers.config.logExitCode) {
- if (reason instanceof Error)
- Module.err(mono_wasm_stringify_as_error_with_stack(reason));
- else if (typeof reason == "string")
- Module.err(reason);
- else
- Module.err(JSON.stringify(reason));
- }
- }
- else if (!reason) {
- reason = new runtimeHelpers.ExitStatus(exit_code);
- } else if (typeof reason.status === "number") {
- exit_code = reason.status;
- }
- }
- logErrorOnExit(exit_code, reason);
- appendElementOnExit(exit_code);
- if (exit_code !== 0 || !ENVIRONMENT_IS_WEB) {
- if (ENVIRONMENT_IS_NODE && INTERNAL.process) {
- INTERNAL.process.exit(exit_code);
- throw reason;
- }
- else if (runtimeHelpers.quit) {
- runtimeHelpers.quit(exit_code, reason);
- } else {
- throw reason;
- }
- }
-}
-
-function appendElementOnExit(exit_code: number) {
- if (ENVIRONMENT_IS_WEB && runtimeHelpers.config && runtimeHelpers.config.appendElementOnExit) {
- //Tell xharness WasmBrowserTestRunner what was the exit code
- const tests_done_elem = document.createElement("label");
- tests_done_elem.id = "tests_done";
- if (exit_code) tests_done_elem.style.background = "red";
- tests_done_elem.innerHTML = exit_code.toString();
- document.body.appendChild(tests_done_elem);
- }
-}
-
-function logErrorOnExit(exit_code: number, reason?: any) {
- if (runtimeHelpers.config && runtimeHelpers.config.logExitCode) {
- if (exit_code != 0 && reason) {
- if (reason instanceof Error)
- console.error(mono_wasm_stringify_as_error_with_stack(reason));
- else if (typeof reason == "string")
- console.error(reason);
- else
- console.error(JSON.stringify(reason));
- }
- if (consoleWebSocket) {
- const stop_when_ws_buffer_empty = () => {
- if (consoleWebSocket.bufferedAmount == 0) {
- // tell xharness WasmTestMessagesProcessor we are done.
- // note this sends last few bytes into the same WS
- console.log("WASM EXIT " + exit_code);
- }
- else {
- setTimeout(stop_when_ws_buffer_empty, 100);
- }
- };
- stop_when_ws_buffer_empty();
- } else {
- console.log("WASM EXIT " + exit_code);
- }
- }
-
- try {
- jiterpreter_dump_stats(false);
- } catch {
- // eslint-disable-next-line @typescript-eslint/no-extra-semi
- ;
- }
-}
diff --git a/src/mono/wasm/runtime/snapshot.ts b/src/mono/wasm/runtime/snapshot.ts
index cf225916edeea..02b9e452e7bda 100644
--- a/src/mono/wasm/runtime/snapshot.ts
+++ b/src/mono/wasm/runtime/snapshot.ts
@@ -4,7 +4,7 @@
import ProductVersion from "consts:productVersion";
import GitHash from "consts:gitHash";
import MonoWasmThreads from "consts:monoWasmThreads";
-import { ENVIRONMENT_IS_WEB, runtimeHelpers } from "./globals";
+import { ENVIRONMENT_IS_WEB, loaderHelpers, runtimeHelpers } from "./globals";
const memoryPrefix = "https://dotnet.generated.invalid/wasm-memory";
@@ -159,7 +159,7 @@ async function getCacheKey(): Promise {
// Now we remove assets collection from the hash.
delete inputs.assets;
// some things are calculated at runtime, so we need to add them to the hash
- inputs.preferredIcuAsset = runtimeHelpers.preferredIcuAsset;
+ inputs.preferredIcuAsset = loaderHelpers.preferredIcuAsset;
// timezone is part of env variables, so it is already in the hash
// some things are not relevant for memory snapshot
@@ -175,6 +175,7 @@ async function getCacheKey(): Promise {
delete inputs.maxParallelDownloads;
delete inputs.enableDownloadRetry;
delete inputs.exitAfterSnapshot;
+ delete inputs.assetUniqueQuery;
inputs.GitHash = GitHash;
inputs.ProductVersion = ProductVersion;
diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts
index 1ae473cf24338..848629bc7639e 100644
--- a/src/mono/wasm/runtime/startup.ts
+++ b/src/mono/wasm/runtime/startup.ts
@@ -1,54 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import BuildConfiguration from "consts:configuration";
import MonoWasmThreads from "consts:monoWasmThreads";
import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop";
-import type { MonoConfig } from "./types-api";
-import type { MonoConfigInternal, DotnetModuleInternal } from "./types";
-import { mono_assert, CharPtrNull } from "./types";
-import { disableLegacyJsInterop, ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, exportedRuntimeAPI, INTERNAL, Module, runtimeHelpers } from "./globals";
+import { DotnetModuleInternal, CharPtrNull } from "./types/internal";
+import { disableLegacyJsInterop, exportedRuntimeAPI, INTERNAL, loaderHelpers, Module, runtimeHelpers } from "./globals";
import cwraps, { init_c_exports } from "./cwraps";
import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug";
import { toBase64StringImpl } from "./base64";
import { mono_wasm_init_aot_profiler, mono_wasm_init_browser_profiler } from "./profiler";
-import { mono_on_abort, mono_exit } from "./run";
import { initialize_marshalers_to_cs } from "./marshal-to-cs";
import { initialize_marshalers_to_js } from "./marshal-to-js";
import { init_polyfills_async } from "./polyfills";
import * as pthreads_worker from "./pthreads/worker";
-import { createPromiseController } from "./promise-controller";
import { string_decoder } from "./strings";
import { init_managed_exports } from "./managed-exports";
import { cwraps_internal } from "./exports-internal";
import { CharPtr, InstantiateWasmCallBack, InstantiateWasmSuccessCallback } from "./types/emscripten";
-import { instantiate_wasm_asset, mono_download_assets, resolve_asset_path, start_asset_download, wait_for_all_assets } from "./assets";
+import { instantiate_wasm_asset, wait_for_all_assets } from "./assets";
import { mono_wasm_init_diagnostics } from "./diagnostics";
import { preAllocatePThreadWorkerPool, instantiateWasmPThreadWorkerPool } from "./pthreads/browser";
import { export_linker } from "./exports-linker";
import { endMeasure, MeasuredBlock, startMeasure } from "./profiler";
import { getMemorySnapshot, storeMemorySnapshot, getMemorySnapshotSize } from "./snapshot";
-import { loadBootConfig } from "./blazor/_Integration";
// legacy
import { init_legacy_exports } from "./net6-legacy/corebindings";
import { cwraps_binding_api, cwraps_mono_api } from "./net6-legacy/exports-legacy";
import { BINDING, MONO } from "./net6-legacy/globals";
-import { init_globalization } from "./icu";
-
-let config: MonoConfigInternal = undefined as any;
-let configLoaded = false;
-export const dotnetReady = createPromiseController();
-export const afterConfigLoaded = createPromiseController();
-export const memorySnapshotSkippedOrDone = createPromiseController();
-export const afterInstantiateWasm = createPromiseController();
-export const beforePreInit = createPromiseController();
-export const afterPreInit = createPromiseController();
-export const afterPreRun = createPromiseController();
-export const beforeOnRuntimeInitialized = createPromiseController();
-export const afterOnRuntimeInitialized = createPromiseController();
-export const afterPostRun = createPromiseController();
+
// default size if MonoConfig.pthreadPoolSize is undefined
const MONO_PTHREAD_POOL_SIZE = 4;
@@ -58,14 +39,9 @@ const MONO_PTHREAD_POOL_SIZE = 4;
export function configureEmscriptenStartup(module: DotnetModuleInternal): void {
const mark = startMeasure();
- if (!module.configSrc && (!module.config || Object.keys(module.config).length === 0 || !module.config.assets)) {
- // if config file location nor assets are provided
- module.configSrc = "./mono-config.json";
- }
-
- if (!module["locateFile"]) {
+ if (!module.locateFile) {
// this is dummy plug so that wasmBinaryFile doesn't try to use URL class
- module["locateFile"] = module["__locateFile"] = (path) => runtimeHelpers.scriptDirectory + path;
+ module.locateFile = module.__locateFile = (path) => loaderHelpers.scriptDirectory + path;
}
if (!module.out) {
@@ -75,6 +51,9 @@ export function configureEmscriptenStartup(module: DotnetModuleInternal): void {
if (!module.err) {
module.err = console.error.bind(console);
}
+ loaderHelpers.out = module.out;
+ loaderHelpers.err = module.err;
+ module.mainScriptUrlOrBlob = loaderHelpers.scriptUrl;// this is needed by worker threads
// these all could be overridden on DotnetModuleConfig, we are chaing them to async below, as opposed to emscripten
// when user set configSrc or config, we are running our default startup sequence.
@@ -86,7 +65,7 @@ export function configureEmscriptenStartup(module: DotnetModuleInternal): void {
const userOnRuntimeInitialized: () => void = module.onRuntimeInitialized ? module.onRuntimeInitialized : () => { };
// execution order == [0] ==
- // - default or user Module.instantiateWasm (will start downloading dotnet.wasm)
+ // - default or user Module.instantiateWasm (will start downloading dotnet.native.wasm)
module.instantiateWasm = (imports, callback) => instantiateWasm(imports, callback, userInstantiateWasm);
// execution order == [1] ==
module.preInit = [() => preInit(userPreInit)];
@@ -100,20 +79,23 @@ export function configureEmscriptenStartup(module: DotnetModuleInternal): void {
module.ready.then(async () => {
// wait for previous stage
- await afterPostRun.promise;
+ await runtimeHelpers.afterPostRun.promise;
// startup end
endMeasure(mark, MeasuredBlock.emscriptenStartup);
// - here we resolve the promise returned by createDotnetRuntime export
// - any code after createDotnetRuntime is executed now
- dotnetReady.promise_control.resolve(exportedRuntimeAPI);
+ runtimeHelpers.dotnetReady.promise_control.resolve(exportedRuntimeAPI);
runtimeHelpers.runtimeReady = true;
}).catch(err => {
- dotnetReady.promise_control.reject(err);
+ runtimeHelpers.dotnetReady.promise_control.reject(err);
});
- module.ready = dotnetReady.promise;
+ module.ready = runtimeHelpers.dotnetReady.promise;
// execution order == [*] ==
if (!module.onAbort) {
- module.onAbort = () => mono_on_abort;
+ module.onAbort = (error) => {
+ loaderHelpers.abort_startup(error, false);
+ loaderHelpers.mono_exit(1, error);
+ };
}
}
@@ -123,19 +105,13 @@ function instantiateWasm(
userInstantiateWasm?: InstantiateWasmCallBack): any[] {
// this is called so early that even Module exports like addRunDependency don't exist yet
- if (!Module.configSrc && !Module.config && !userInstantiateWasm) {
- Module.out("MONO_WASM: configSrc nor config was specified");
- }
- normalizeConfig();
-
const mark = startMeasure();
if (userInstantiateWasm) {
- init_globalization();
// user wasm instantiation doesn't support memory snapshots
- memorySnapshotSkippedOrDone.promise_control.resolve();
+ runtimeHelpers.memorySnapshotSkippedOrDone.promise_control.resolve();
const exports = userInstantiateWasm(imports, (instance: WebAssembly.Instance, module: WebAssembly.Module | undefined) => {
endMeasure(mark, MeasuredBlock.instantiateWasm);
- afterInstantiateWasm.promise_control.resolve();
+ runtimeHelpers.afterInstantiateWasm.promise_control.resolve();
successCallback(instance, module);
});
return exports;
@@ -150,9 +126,8 @@ async function instantiateWasmWorker(
successCallback: InstantiateWasmSuccessCallback
): Promise {
// wait for the config to arrive by message from the main thread
- await afterConfigLoaded.promise;
+ await loaderHelpers.afterConfigLoaded.promise;
- normalizeConfig();
replace_linker_placeholders(imports, export_linker());
// Instantiate from the module posted from the main thread.
@@ -168,12 +143,12 @@ function preInit(userPreInit: (() => void)[]) {
try {
mono_wasm_pre_init_essential(false);
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: preInit");
- beforePreInit.promise_control.resolve();
+ runtimeHelpers.beforePreInit.promise_control.resolve();
// all user Module.preInit callbacks
userPreInit.forEach(fn => fn());
} catch (err) {
_print_error("MONO_WASM: user preInint() failed", err);
- abort_startup(err, true);
+ loaderHelpers.abort_startup(err, true);
throw err;
}
// this will start immediately but return on first await.
@@ -190,11 +165,11 @@ function preInit(userPreInit: (() => void)[]) {
endMeasure(mark, MeasuredBlock.preInit);
} catch (err) {
- abort_startup(err, true);
+ loaderHelpers.abort_startup(err, true);
throw err;
}
// signal next stage
- afterPreInit.promise_control.resolve();
+ runtimeHelpers.afterPreInit.promise_control.resolve();
Module.removeRunDependency("mono_pre_init");
})();
}
@@ -204,14 +179,14 @@ async function preInitWorkerAsync() {
const mark = startMeasure();
try {
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: preInitWorker");
- beforePreInit.promise_control.resolve();
+ runtimeHelpers.beforePreInit.promise_control.resolve();
mono_wasm_pre_init_essential(true);
await init_polyfills_async();
- afterPreInit.promise_control.resolve();
+ runtimeHelpers.afterPreInit.promise_control.resolve();
endMeasure(mark, MeasuredBlock.preInitWorker);
} catch (err) {
_print_error("MONO_WASM: user preInitWorker() failed", err);
- abort_startup(err, true);
+ loaderHelpers.abort_startup(err, true);
throw err;
}
}
@@ -222,19 +197,19 @@ export function preRunWorker() {
bindings_init();
endMeasure(mark, MeasuredBlock.preRunWorker);
} catch (err) {
- abort_startup(err, true);
+ loaderHelpers.abort_startup(err, true);
throw err;
}
// signal next stage
- afterPreRun.promise_control.resolve();
+ runtimeHelpers.afterPreRun.promise_control.resolve();
}
async function preRunAsync(userPreRun: (() => void)[]) {
Module.addRunDependency("mono_pre_run_async");
// wait for previous stages
try {
- await afterInstantiateWasm.promise;
- await afterPreInit.promise;
+ await runtimeHelpers.afterInstantiateWasm.promise;
+ await runtimeHelpers.afterPreInit.promise;
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: preRunAsync");
const mark = startMeasure();
// all user Module.preRun callbacks
@@ -242,46 +217,46 @@ async function preRunAsync(userPreRun: (() => void)[]) {
endMeasure(mark, MeasuredBlock.preRun);
} catch (err) {
_print_error("MONO_WASM: user callback preRun() failed", err);
- abort_startup(err, true);
+ loaderHelpers.abort_startup(err, true);
throw err;
}
// signal next stage
- afterPreRun.promise_control.resolve();
+ runtimeHelpers.afterPreRun.promise_control.resolve();
Module.removeRunDependency("mono_pre_run_async");
}
async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) {
try {
// wait for previous stage
- await afterPreRun.promise;
+ await runtimeHelpers.afterPreRun.promise;
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: onRuntimeInitialized");
const mark = startMeasure();
// signal this stage, this will allow pending assets to allocate memory
- beforeOnRuntimeInitialized.promise_control.resolve();
+ runtimeHelpers.beforeOnRuntimeInitialized.promise_control.resolve();
await wait_for_all_assets();
// Diagnostics early are not supported with memory snapshot. See below how we enable them later.
// Please disable startupMemoryCache in order to be able to diagnose or pause runtime startup.
- if (MonoWasmThreads && !config.startupMemoryCache) {
+ if (MonoWasmThreads && !runtimeHelpers.config.startupMemoryCache) {
await mono_wasm_init_diagnostics();
}
// load runtime and apply environment settings (if necessary)
await mono_wasm_before_memory_snapshot();
- if (config.exitAfterSnapshot) {
+ if (runtimeHelpers.config.exitAfterSnapshot) {
const reason = runtimeHelpers.ExitStatus
? new runtimeHelpers.ExitStatus(0)
: new Error("Snapshot taken, exiting because exitAfterSnapshot was set.");
reason.silent = true;
- abort_startup(reason, false);
+ loaderHelpers.abort_startup(reason, false);
return;
}
if (MonoWasmThreads) {
- if (config.startupMemoryCache) {
+ if (runtimeHelpers.config.startupMemoryCache) {
// we could enable diagnostics after the snapshot is taken
await mono_wasm_init_diagnostics();
}
@@ -296,7 +271,7 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) {
string_decoder.init_fields();
});
- if (config.startupOptions && INTERNAL.resourceLoader) {
+ if (runtimeHelpers.config.startupOptions && INTERNAL.resourceLoader) {
if (INTERNAL.resourceLoader.bootConfig.debugBuild && INTERNAL.resourceLoader.bootConfig.cacheBootResources) {
INTERNAL.resourceLoader.logToConsole();
}
@@ -316,17 +291,17 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) {
endMeasure(mark, MeasuredBlock.onRuntimeInitialized);
} catch (err) {
_print_error("MONO_WASM: onRuntimeInitializedAsync() failed", err);
- abort_startup(err, true);
+ loaderHelpers.abort_startup(err, true);
throw err;
}
// signal next stage
- afterOnRuntimeInitialized.promise_control.resolve();
+ runtimeHelpers.afterOnRuntimeInitialized.promise_control.resolve();
}
async function postRunAsync(userpostRun: (() => void)[]) {
// wait for previous stage
try {
- await afterOnRuntimeInitialized.promise;
+ await runtimeHelpers.afterOnRuntimeInitialized.promise;
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: postRunAsync");
const mark = startMeasure();
@@ -339,36 +314,13 @@ async function postRunAsync(userpostRun: (() => void)[]) {
endMeasure(mark, MeasuredBlock.postRun);
} catch (err) {
_print_error("MONO_WASM: user callback posRun() failed", err);
- abort_startup(err, true);
+ loaderHelpers.abort_startup(err, true);
throw err;
}
// signal next stage
- afterPostRun.promise_control.resolve();
+ runtimeHelpers.afterPostRun.promise_control.resolve();
}
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-export function abort_startup(reason: any, should_exit: boolean): void {
- if (runtimeHelpers.diagnosticTracing) console.trace("MONO_WASM: abort_startup");
- dotnetReady.promise_control.reject(reason);
- memorySnapshotSkippedOrDone.promise_control.reject(reason);
- afterInstantiateWasm.promise_control.reject(reason);
- beforePreInit.promise_control.reject(reason);
- afterPreInit.promise_control.reject(reason);
- afterPreRun.promise_control.reject(reason);
- beforeOnRuntimeInitialized.promise_control.reject(reason);
- afterOnRuntimeInitialized.promise_control.reject(reason);
- afterPostRun.promise_control.reject(reason);
- if (typeof reason !== "object" || reason.silent !== true) {
- if (should_exit) {
- mono_exit(1, reason);
- }
- else if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) {
- const wasm_exit = cwraps.mono_wasm_exit;
- wasm_exit(1);
- }
- throw reason;
- }
-}
function mono_wasm_pre_init_essential(isWorker: boolean): void {
if (!isWorker)
@@ -384,7 +336,7 @@ function mono_wasm_pre_init_essential(isWorker: boolean): void {
}
// removeRunDependency triggers the dependenciesFulfilled callback (runCaller) in
// emscripten - on a worker since we don't have any other dependencies that causes run() to get
- // called too soon; and then it will get called a second time when dotnet.js calls it directly.
+ // called too soon; and then it will get called a second time when dotnet.native.js calls it directly.
// on a worker run() short-cirtcuits and just calls readyPromiseResolve, initRuntime and postMessage.
// sending postMessage twice will break instantiateWasmPThreadWorkerPool on the main thread.
if (!isWorker)
@@ -396,10 +348,9 @@ async function mono_wasm_pre_init_essential_async(): Promise {
Module.addRunDependency("mono_wasm_pre_init_essential_async");
await init_polyfills_async();
- await mono_wasm_load_config(Module.configSrc);
if (MonoWasmThreads) {
- preAllocatePThreadWorkerPool(MONO_PTHREAD_POOL_SIZE, config);
+ preAllocatePThreadWorkerPool(MONO_PTHREAD_POOL_SIZE, runtimeHelpers.config);
}
Module.removeRunDependency("mono_wasm_pre_init_essential_async");
@@ -409,7 +360,7 @@ async function mono_wasm_pre_init_full(): Promise {
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_pre_init_full");
Module.addRunDependency("mono_wasm_pre_init_full");
- await mono_download_assets();
+ await loaderHelpers.mono_download_assets();
Module.removeRunDependency("mono_wasm_pre_init_full");
}
@@ -509,30 +460,24 @@ async function instantiate_wasm_module(
// this is called so early that even Module exports like addRunDependency don't exist yet
try {
let memorySize: number | undefined = undefined;
- await mono_wasm_load_config(Module.configSrc);
+ await loaderHelpers.afterConfigLoaded;
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: instantiate_wasm_module");
- const assetToLoad = resolve_asset_path("dotnetwasm");
- // FIXME: this would not apply re-try (on connection reset during download) for dotnet.wasm because we could not download the buffer before we pass it to instantiate_wasm_asset
- const wasmDownloadPromise = start_asset_download(assetToLoad);
-
- // this is right time as we have free CPU time to do this
- init_globalization();
- if (config.startupMemoryCache) {
+ if (runtimeHelpers.config.startupMemoryCache) {
memorySize = await getMemorySnapshotSize();
runtimeHelpers.loadedMemorySnapshot = !!memorySize;
runtimeHelpers.storeMemorySnapshotPending = !runtimeHelpers.loadedMemorySnapshot;
}
if (!runtimeHelpers.loadedMemorySnapshot) {
// we should start downloading DLLs etc as they are not in the snapshot
- memorySnapshotSkippedOrDone.promise_control.resolve();
+ runtimeHelpers.memorySnapshotSkippedOrDone.promise_control.resolve();
}
- await wasmDownloadPromise;
- await beforePreInit.promise;
+ await runtimeHelpers.beforePreInit.promise;
Module.addRunDependency("instantiate_wasm_module");
replace_linker_placeholders(imports, export_linker());
+ const assetToLoad = await loaderHelpers.wasmDownloadPromise.promise;
await instantiate_wasm_asset(assetToLoad, imports, successCallback);
assetToLoad.pendingDownloadInternal = null as any; // GC
assetToLoad.pendingDownload = null as any; // GC
@@ -552,12 +497,12 @@ async function instantiate_wasm_module(
runtimeHelpers.loadedMemorySnapshot = false;
}
// now we know if the loading of memory succeeded or not, we can start loading the rest of the assets
- memorySnapshotSkippedOrDone.promise_control.resolve();
+ runtimeHelpers.memorySnapshotSkippedOrDone.promise_control.resolve();
}
- afterInstantiateWasm.promise_control.resolve();
+ runtimeHelpers.afterInstantiateWasm.promise_control.resolve();
} catch (err) {
_print_error("MONO_WASM: instantiate_wasm_module() failed", err);
- abort_startup(err, true);
+ loaderHelpers.abort_startup(err, true);
throw err;
}
Module.removeRunDependency("instantiate_wasm_module");
@@ -576,30 +521,30 @@ async function mono_wasm_before_memory_snapshot() {
return;
}
- for (const k in config.environmentVariables) {
- const v = config.environmentVariables![k];
+ for (const k in runtimeHelpers.config.environmentVariables) {
+ const v = runtimeHelpers.config.environmentVariables![k];
if (typeof (v) === "string")
mono_wasm_setenv(k, v);
else
throw new Error(`Expected environment variable '${k}' to be a string but it was ${typeof v}: '${v}'`);
}
- if (config.startupMemoryCache) {
+ if (runtimeHelpers.config.startupMemoryCache) {
// disable the trampoline for now, we will re-enable it after we stored the snapshot
cwraps.mono_jiterp_update_jit_call_dispatcher(0);
}
- if (config.runtimeOptions)
- mono_wasm_set_runtime_options(config.runtimeOptions);
+ if (runtimeHelpers.config.runtimeOptions)
+ mono_wasm_set_runtime_options(runtimeHelpers.config.runtimeOptions);
- if (config.aotProfilerOptions)
- mono_wasm_init_aot_profiler(config.aotProfilerOptions);
+ if (runtimeHelpers.config.aotProfilerOptions)
+ mono_wasm_init_aot_profiler(runtimeHelpers.config.aotProfilerOptions);
- if (config.browserProfilerOptions)
- mono_wasm_init_browser_profiler(config.browserProfilerOptions);
+ if (runtimeHelpers.config.browserProfilerOptions)
+ mono_wasm_init_browser_profiler(runtimeHelpers.config.browserProfilerOptions);
- mono_wasm_load_runtime("unused", config.debugLevel);
+ mono_wasm_load_runtime("unused", runtimeHelpers.config.debugLevel);
// we didn't have snapshot yet and the feature is enabled. Take snapshot now.
- if (config.startupMemoryCache) {
+ if (runtimeHelpers.config.startupMemoryCache) {
// this would install the mono_jiterp_do_jit_call_indirect
cwraps.mono_jiterp_update_jit_call_dispatcher(-1);
await storeMemorySnapshot(Module.HEAP8.buffer);
@@ -615,7 +560,7 @@ export function mono_wasm_load_runtime(unused?: string, debugLevel?: number): vo
const mark = startMeasure();
if (debugLevel == undefined) {
debugLevel = 0;
- if (config && config.debugLevel) {
+ if (runtimeHelpers.config.debugLevel) {
debugLevel = 0 + debugLevel;
}
}
@@ -624,7 +569,7 @@ export function mono_wasm_load_runtime(unused?: string, debugLevel?: number): vo
} catch (err: any) {
_print_error("MONO_WASM: mono_wasm_load_runtime () failed", err);
- abort_startup(err, false);
+ loaderHelpers.abort_startup(err, false);
}
}
@@ -650,91 +595,6 @@ export function bindings_init(): void {
}
}
-/**
- * Loads the mono config file (typically called mono-config.json) asynchroniously
- * Note: the run dependencies are so emsdk actually awaits it in order.
- *
- * @param {string} configFilePath - relative path to the config file
- * @throws Will throw an error if the config file loading fails
- */
-export async function mono_wasm_load_config(configFilePath?: string): Promise {
- if (configLoaded) {
- await afterConfigLoaded.promise;
- return;
- }
- configLoaded = true;
- if (!configFilePath) {
- normalizeConfig();
- afterConfigLoaded.promise_control.resolve(config);
- return;
- }
- if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_load_config");
- try {
- if (config.startupOptions) {
- await loadBootConfig(config);
- } else {
- const resolveSrc = runtimeHelpers.locateFile(configFilePath);
- const configResponse = await runtimeHelpers.fetch_like(resolveSrc);
- const loadedConfig: MonoConfigInternal = (await configResponse.json()) || {};
- if (loadedConfig.environmentVariables && typeof (loadedConfig.environmentVariables) !== "object")
- throw new Error("Expected config.environmentVariables to be unset or a dictionary-style object");
-
- // merge
- loadedConfig.assets = [...(loadedConfig.assets || []), ...(config.assets || [])];
- loadedConfig.environmentVariables = { ...(loadedConfig.environmentVariables || {}), ...(config.environmentVariables || {}) };
- loadedConfig.runtimeOptions = [...(loadedConfig.runtimeOptions || []), ...(config.runtimeOptions || [])];
- config = runtimeHelpers.config = Module.config = Object.assign(Module.config as any, loadedConfig);
- }
-
- normalizeConfig();
-
- if (Module.onConfigLoaded) {
- try {
- await Module.onConfigLoaded(config, exportedRuntimeAPI);
- normalizeConfig();
- }
- catch (err: any) {
- _print_error("MONO_WASM: onConfigLoaded() failed", err);
- throw err;
- }
- }
- afterConfigLoaded.promise_control.resolve(config);
- } catch (err) {
- const errMessage = `Failed to load config file ${configFilePath} ${err}`;
- config = runtimeHelpers.config = Module.config = { message: errMessage, error: err, isError: true };
- abort_startup(errMessage, true);
- throw err;
- }
-}
-
-function normalizeConfig() {
- // normalize
- Module.config = config = runtimeHelpers.config = Object.assign(runtimeHelpers.config, Module.config || {});
-
- config.environmentVariables = config.environmentVariables || {};
- config.assets = config.assets || [];
- config.runtimeOptions = config.runtimeOptions || [];
- config.globalizationMode = config.globalizationMode || "auto";
-
- if (config.debugLevel === undefined && BuildConfiguration === "Debug") {
- config.debugLevel = -1;
- }
- if (config.diagnosticTracing === undefined && BuildConfiguration === "Debug") {
- config.diagnosticTracing = true;
- }
- runtimeHelpers.diagnosticTracing = !!config.diagnosticTracing;
- runtimeHelpers.waitForDebugger = config.waitForDebugger;
- config.startupMemoryCache = !!config.startupMemoryCache;
- if (config.startupMemoryCache && runtimeHelpers.waitForDebugger) {
- if (runtimeHelpers.diagnosticTracing) console.info("MONO_WASM: Disabling startupMemoryCache because waitForDebugger is set");
- config.startupMemoryCache = false;
- }
-
- runtimeHelpers.enablePerfMeasure = !!config.browserProfilerOptions
- && globalThis.performance
- && typeof globalThis.performance.measure === "function";
-
-}
export function mono_wasm_asm_loaded(assembly_name: CharPtr, assembly_ptr: number, assembly_len: number, pdb_ptr: number, pdb_len: number): void {
// Only trigger this codepath for assemblies loaded after app is ready
@@ -780,7 +640,6 @@ export function mono_wasm_set_main_args(name: string, allRuntimeArguments: strin
/// 2. Emscripten does not run any event but preInit in the workers.
/// 3. At the point when this executes there is no pthread assigned to the worker yet.
export async function configureWorkerStartup(module: DotnetModuleInternal): Promise {
- pthreads_worker.setupPreloadChannelToMainThread();
// This is a good place for subsystems to attach listeners for pthreads_worker.currentWorkerThreadEvents
pthreads_worker.currentWorkerThreadEvents.addEventListener(pthreads_worker.dotnetPthreadCreated, (ev) => {
if (runtimeHelpers.diagnosticTracing)
@@ -790,5 +649,5 @@ export async function configureWorkerStartup(module: DotnetModuleInternal): Prom
// these are the only events which are called on worker
module.preInit = [() => preInitWorkerAsync()];
module.instantiateWasm = instantiateWasmWorker;
- await afterPreInit.promise;
+ await runtimeHelpers.afterPreInit.promise;
}
diff --git a/src/mono/wasm/runtime/strings.ts b/src/mono/wasm/runtime/strings.ts
index 9ec559ff21999..52f6c8dbbe373 100644
--- a/src/mono/wasm/runtime/strings.ts
+++ b/src/mono/wasm/runtime/strings.ts
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { mono_wasm_new_root_buffer } from "./roots";
-import { MonoString, MonoStringNull, is_nullish, WasmRoot, WasmRootBuffer } from "./types";
+import { MonoString, MonoStringNull, is_nullish, WasmRoot, WasmRootBuffer } from "./types/internal";
import { Module } from "./globals";
import cwraps from "./cwraps";
import { mono_wasm_new_root } from "./roots";
diff --git a/src/mono/wasm/runtime/types/blazor.ts b/src/mono/wasm/runtime/types/blazor.ts
new file mode 100644
index 0000000000000..95f88fd101775
--- /dev/null
+++ b/src/mono/wasm/runtime/types/blazor.ts
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+// Keep in sync with Microsoft.NET.Sdk.WebAssembly.BootJsonData from the WasmSDK
+export interface BootJsonData {
+ readonly entryAssembly: string;
+ readonly resources: ResourceGroups;
+ /** Gets a value that determines if this boot config was produced from a non-published build (i.e. dotnet build or dotnet run) */
+ readonly debugBuild: boolean;
+ readonly linkerEnabled: boolean;
+ readonly cacheBootResources: boolean;
+ readonly config: string[];
+ readonly icuDataMode: ICUDataMode;
+ readonly startupMemoryCache: boolean | undefined;
+ readonly runtimeOptions: string[] | undefined;
+
+ // These properties are tacked on, and not found in the boot.json file
+ modifiableAssemblies: string | null;
+ aspnetCoreBrowserTools: string | null;
+}
+
+export type BootJsonDataExtension = { [extensionName: string]: ResourceList };
+
+export interface ResourceGroups {
+ readonly assembly: ResourceList;
+ readonly lazyAssembly: ResourceList;
+ readonly pdb?: ResourceList;
+ readonly runtime: ResourceList;
+ readonly satelliteResources?: { [cultureName: string]: ResourceList };
+ readonly libraryInitializers?: ResourceList,
+ readonly extensions?: BootJsonDataExtension
+ readonly runtimeAssets: ExtendedResourceList;
+}
+
+export type ResourceList = { [name: string]: string };
+export type ExtendedResourceList = {
+ [name: string]: {
+ hash: string,
+ behavior: string
+ }
+};
+
+export enum ICUDataMode {
+ Sharded = 0,
+ All = 1,
+ Invariant = 2,
+ Custom = 3
+}
diff --git a/src/mono/wasm/runtime/types/consts.d.ts b/src/mono/wasm/runtime/types/consts.d.ts
index 11a7e5439e311..a86668b13fa8a 100644
--- a/src/mono/wasm/runtime/types/consts.d.ts
+++ b/src/mono/wasm/runtime/types/consts.d.ts
@@ -18,4 +18,6 @@ declare module "consts:monoDiagnosticsMock" {
export default constant;
}
-declare function createEmscripten(module: any): Promise;
+// see src\mono\wasm\runtime\rollup.config.js
+// inline this, because the lambda could allocate closure on hot path otherwise
+declare function mono_assert(condition: unknown, messageFactory: string | (() => string)): asserts condition;
diff --git a/src/mono/wasm/runtime/export-types.ts b/src/mono/wasm/runtime/types/export-types.ts
similarity index 80%
rename from src/mono/wasm/runtime/export-types.ts
rename to src/mono/wasm/runtime/types/export-types.ts
index f81661e365e1f..379b817aa9585 100644
--- a/src/mono/wasm/runtime/export-types.ts
+++ b/src/mono/wasm/runtime/types/export-types.ts
@@ -1,11 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import type { BootJsonData, ICUDataMode } from "./blazor/BootConfig";
-import type { IMemoryView } from "./marshal";
-import type { CreateDotnetRuntimeType, DotnetModuleConfig, RuntimeAPI, MonoConfig, ModuleAPI, AssetEntry, ResourceRequest } from "./types-api";
-import type { EmscriptenModule } from "./types/emscripten";
-import type { dotnet, exit } from "./exports";
+import type { IMemoryView } from "../marshal";
+import type { CreateDotnetRuntimeType, DotnetModuleConfig, RuntimeAPI, MonoConfig, ModuleAPI, AssetEntry, ResourceRequest } from ".";
+import type { EmscriptenModule } from "./emscripten";
+import type { dotnet, exit } from "../loader/index";
+import type { BootJsonData, ICUDataMode } from "./blazor";
// -----------------------------------------------------------
// this files has all public exports from the dotnet.js module
diff --git a/src/mono/wasm/runtime/types-api.ts b/src/mono/wasm/runtime/types/index.ts
similarity index 94%
rename from src/mono/wasm/runtime/types-api.ts
rename to src/mono/wasm/runtime/types/index.ts
index 3fd1c327e0c1d..8698b65f5f59a 100644
--- a/src/mono/wasm/runtime/types-api.ts
+++ b/src/mono/wasm/runtime/types/index.ts
@@ -1,4 +1,7 @@
-import type { EmscriptenModule, NativePointer } from "./types/emscripten";
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import type { EmscriptenModule, NativePointer } from "./emscripten";
export interface DotnetHostBuilder {
withConfig(config: MonoConfig): DotnetHostBuilder
@@ -79,7 +82,11 @@ export type MonoConfig = {
/**
* application environment
*/
- applicationEnvironment?: string
+ applicationEnvironment?: string,
+ /**
+ * query string to be used for asset loading
+ */
+ assetUniqueQuery?: string,
};
export interface ResourceRequest {
@@ -134,6 +141,9 @@ export type AssetBehaviours =
| "vfs" // load asset into the virtual filesystem (for fopen, File.Open, etc)
| "dotnetwasm" // the binary of the dotnet runtime
| "js-module-threads" // the javascript module for threads
+ | "js-module-runtime" // the javascript module for threads
+ | "js-module-dotnet" // the javascript module for threads
+ | "js-module-native" // the javascript module for threads
| "symbols" // the javascript module for threads
export type GlobalizationMode =
diff --git a/src/mono/wasm/runtime/types.ts b/src/mono/wasm/runtime/types/internal.ts
similarity index 74%
rename from src/mono/wasm/runtime/types.ts
rename to src/mono/wasm/runtime/types/internal.ts
index 3f1c811dceccb..f9a16235228ca 100644
--- a/src/mono/wasm/runtime/types.ts
+++ b/src/mono/wasm/runtime/types/internal.ts
@@ -1,8 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { AssetEntry, DotnetModuleConfig, LoadingResource, MonoConfig, RuntimeAPI, WebAssemblyStartOptions } from "./types-api";
-import { CharPtr, EmscriptenModule, ManagedPointer, NativePointer, VoidPtr, Int32Ptr } from "./types/emscripten";
+import type { AssetBehaviours, AssetEntry, DotnetModuleConfig, LoadingResource, MonoConfig, ResourceRequest, RuntimeAPI, WebAssemblyStartOptions } from ".";
+import type { CharPtr, EmscriptenModule, ManagedPointer, NativePointer, VoidPtr, Int32Ptr } from "./emscripten";
export type GCHandle = {
__brand: "GCHandle"
@@ -92,18 +92,50 @@ export interface AssetEntryInternal extends AssetEntry {
pendingDownloadInternal?: LoadingResource
}
-export type AssetBehaviours =
- "resource" // load asset as a managed resource assembly
- | "assembly" // load asset as a managed assembly
- | "pdb" // load asset as a managed debugging information
- | "heap" // store asset into the native heap
- | "icu" // load asset as an ICU data archive
- | "vfs" // load asset into the virtual filesystem (for fopen, File.Open, etc)
- | "dotnetwasm" // the binary of the dotnet runtime
- | "js-module-threads" // the javascript module for threads
- | "symbols" // the symbols for the wasm native code
+export type LoaderHelpers = {
+ config: MonoConfigInternal;
+ diagnosticTracing: boolean;
+
+ maxParallelDownloads: number;
+ enableDownloadRetry: boolean;
+
+ loadedFiles: string[],
+ _loaded_files: { url: string, file: string }[];
+ scriptDirectory: string
+ scriptUrl: string
+ assetUniqueQuery?: string
+ preferredIcuAsset: string | null,
+ invariantMode: boolean,
+ actual_downloaded_assets_count: number,
+ actual_instantiated_assets_count: number,
+ expected_downloaded_assets_count: number,
+ expected_instantiated_assets_count: number,
+
+ afterConfigLoaded: PromiseAndController,
+ allDownloadsQueued: PromiseAndController,
+ wasmDownloadPromise: PromiseAndController,
+ runtimeModuleLoaded: PromiseAndController,
+
+ abort_startup: (reason: any, should_exit: boolean) => void,
+ mono_exit: (exit_code: number, reason?: any) => void,
+ createPromiseController: (afterResolve?: () => void, afterReject?: () => void) => PromiseAndController,
+ getPromiseController: (promise: ControllablePromise) => PromiseController,
+ assertIsControllablePromise: (promise: Promise) => asserts promise is ControllablePromise,
+ mono_download_assets: () => Promise,
+ resolve_asset_path: (behavior: AssetBehaviours) => AssetEntryInternal,
+ setup_proxy_console: (id: string, console: Console, origin: string) => void
+ fetch_like: (url: string, init?: RequestInit) => Promise;
+ locateFile: (path: string, prefix?: string) => string,
+ downloadResource?: (request: ResourceRequest) => LoadingResource | undefined
+ out(message: string): void;
+ err(message: string): void;
+ getApplicationEnvironment?: (bootConfigResponse: Response) => string | null;
+}
export type RuntimeHelpers = {
+ config: MonoConfigInternal;
+ diagnosticTracing: boolean;
+
runtime_interop_module: MonoAssembly;
runtime_interop_namespace: string;
runtime_interop_exports_classname: string;
@@ -113,29 +145,36 @@ export type RuntimeHelpers = {
mono_wasm_runtime_is_ready: boolean;
mono_wasm_bindings_is_ready: boolean;
- loaded_files: string[];
- maxParallelDownloads: number;
- enableDownloadRetry: boolean;
- config: MonoConfigInternal;
- diagnosticTracing: boolean;
+ loadedMemorySnapshot: boolean,
enablePerfMeasure: boolean;
waitForDebugger?: number;
- fetch_like: (url: string, init?: RequestInit) => Promise;
- scriptDirectory: string
- requirePromise: Promise
ExitStatus: ExitStatusError;
quit: Function,
- locateFile: (path: string, prefix?: string) => string,
javaScriptExports: JavaScriptExports,
- loadedFiles: string[],
- loadedMemorySnapshot: boolean,
storeMemorySnapshotPending: boolean,
memorySnapshotCacheKey: string,
subtle: SubtleCrypto | null,
- preferredIcuAsset: string | null,
- invariantMode: boolean,
updateMemoryViews: () => void
runtimeReady: boolean,
+
+ runtimeModuleUrl: string
+ nativeModuleUrl: string
+ allAssetsInMemory: PromiseAndController,
+ dotnetReady: PromiseAndController,
+ memorySnapshotSkippedOrDone: PromiseAndController,
+ afterInstantiateWasm: PromiseAndController,
+ beforePreInit: PromiseAndController,
+ afterPreInit: PromiseAndController,
+ afterPreRun: PromiseAndController,
+ beforeOnRuntimeInitialized: PromiseAndController,
+ afterOnRuntimeInitialized: PromiseAndController,
+ afterPostRun: PromiseAndController,
+
+ //core
+ stringify_as_error_with_stack?: (error: any) => string,
+ instantiate_asset: (asset: AssetEntry, url: string, bytes: Uint8Array) => void,
+ instantiate_symbols_asset: (pendingAsset: AssetEntryInternal) => Promise,
+ jiterpreter_dump_stats?: (x: boolean) => string,
}
export type AOTProfilerOptions = {
@@ -150,38 +189,6 @@ export type BrowserProfilerOptions = {
export type DotnetModule = EmscriptenModule & DotnetModuleConfig;
export type DotnetModuleInternal = EmscriptenModule & DotnetModuleConfig & EmscriptenModuleInternal;
-
-export type DotnetModuleConfigImports = {
- require?: (name: string) => any;
- fetch?: (url: string, options: any | undefined) => Promise;
- fs?: {
- promises?: {
- readFile?: (path: string) => Promise,
- }
- readFileSync?: (path: string, options: any | undefined) => string,
- };
- crypto?: {
- randomBytes?: (size: number) => Buffer
- };
- ws?: WebSocket & { Server: any };
- path?: {
- normalize?: (path: string) => string,
- dirname?: (path: string) => string,
- };
- url?: any;
-}
-
-// see src\mono\wasm\runtime\rollup.config.js
-// inline this, because the lambda could allocate closure on hot path otherwise
-export function mono_assert(condition: unknown, messageFactory: string | (() => string)): asserts condition {
- if (!condition) {
- const message = typeof messageFactory === "string"
- ? messageFactory
- : messageFactory();
- throw new Error(`Assert failed: ${message}`);
- }
-}
-
// see src/mono/wasm/driver.c MARSHAL_TYPE_xxx and Runtime.cs MarshalType
export const enum MarshalType {
NULL = 0,
@@ -233,30 +240,26 @@ export function is_nullish(value: T | null | undefined): value is null | unde
}
export type EmscriptenInternals = {
- isWorker: boolean,
- isShell: boolean,
isPThread: boolean,
disableLegacyJsInterop: boolean,
quit_: Function,
ExitStatus: ExitStatusError,
- requirePromise: Promise
};
export type GlobalObjects = {
mono: any,
binding: any,
internal: any,
module: DotnetModuleInternal,
- helpers: RuntimeHelpers,
+ loaderHelpers: LoaderHelpers,
+ runtimeHelpers: RuntimeHelpers,
api: RuntimeAPI,
};
export type EmscriptenReplacements = {
fetch: any,
require: any,
- requirePromise: Promise,
updateMemoryViews: Function,
pthreadReplacements: PThreadReplacements | undefined | null
scriptDirectory: string;
- scriptUrl: string
noExitRuntime?: boolean;
}
export interface ExitStatusError {
@@ -401,6 +404,7 @@ export declare interface EmscriptenModuleInternal {
__locateFile?: (path: string, prefix?: string) => string;
locateFile?: (path: string, prefix?: string) => string;
mainScriptUrlOrBlob?: string;
+ ENVIRONMENT_IS_PTHREAD?: boolean;
wasmModule: WebAssembly.Instance | null;
ready: Promise;
asm: { memory?: WebAssembly.Memory };
@@ -410,3 +414,45 @@ export declare interface EmscriptenModuleInternal {
addRunDependency(id: string): void;
onConfigLoaded?: (config: MonoConfig, api: RuntimeAPI) => void | Promise;
}
+
+/// A PromiseController encapsulates a Promise together with easy access to its resolve and reject functions.
+/// It's a bit like a TaskCompletionSource in .NET
+export interface PromiseController {
+ isDone: boolean;
+ readonly promise: Promise;
+ resolve: (value: T | PromiseLike) => void;
+ reject: (reason?: any) => void;
+}
+
+
+/// A Promise with a controller attached
+export interface ControllablePromise extends Promise {
+ __brand: "ControllablePromise"
+}
+
+/// Just a pair of a promise and its controller
+export interface PromiseAndController {
+ promise: ControllablePromise;
+ promise_control: PromiseController;
+}
+
+export type passEmscriptenInternalsType = (internals: EmscriptenInternals) => void;
+export type setGlobalObjectsType = (globalObjects: GlobalObjects) => void;
+export type initializeExportsType = (globalObjects: GlobalObjects) => RuntimeAPI;
+export type initializeReplacementsType = (replacements: EmscriptenReplacements) => void;
+export type configureEmscriptenStartupType = (module: DotnetModuleInternal) => void;
+export type configureWorkerStartupType = (module: DotnetModuleInternal) => Promise
+
+
+export type RuntimeModuleExportsInternal = {
+ setRuntimeGlobals: setGlobalObjectsType,
+ initializeExports: initializeExportsType,
+ initializeReplacements: initializeReplacementsType,
+ configureEmscriptenStartup: configureEmscriptenStartupType,
+ configureWorkerStartup: configureWorkerStartupType,
+ passEmscriptenInternals: passEmscriptenInternalsType,
+}
+
+export type NativeModuleExportsInternal = {
+ default: (unificator: Function) => EmscriptenModuleInternal
+}
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/web-socket.ts b/src/mono/wasm/runtime/web-socket.ts
index 9b2e1042cb4c0..e28477b6efe96 100644
--- a/src/mono/wasm/runtime/web-socket.ts
+++ b/src/mono/wasm/runtime/web-socket.ts
@@ -3,11 +3,10 @@
import { prevent_timer_throttling } from "./scheduling";
import { Queue } from "./queue";
-import { PromiseController, createPromiseController } from "./promise-controller";
-import { mono_assert } from "./types";
-import { Module } from "./globals";
+import { Module, createPromiseController } from "./globals";
import { setI32 } from "./memory";
import { VoidPtr } from "./types/emscripten";
+import { PromiseController } from "./types/internal";
const wasm_ws_pending_send_buffer = Symbol.for("wasm ws_pending_send_buffer");
const wasm_ws_pending_send_buffer_offset = Symbol.for("wasm ws_pending_send_buffer_offset");
diff --git a/src/mono/wasm/runtime/workers/README.md b/src/mono/wasm/runtime/workers/README.md
index b6347fe1d33c3..0939b05204d3c 100644
--- a/src/mono/wasm/runtime/workers/README.md
+++ b/src/mono/wasm/runtime/workers/README.md
@@ -13,7 +13,7 @@ To add a new web worker, add a definition here and modify the
## Caveats: a note about pthreads
-The workers in this directory are completely standalone from the Emscripten pthreads! they do not have access to the shared instance memory, and do not load the Emscripten `dotnet.js`. As a result, the workers in this directory cannot use any of pthread APIs or otherwise interact with the runtime in any way, except through message passing, or by having something in the runtime set up their own shared array buffer (which would be inaccessible from wasm).
+The workers in this directory are completely standalone from the Emscripten pthreads! they do not have access to the shared instance memory, and do not load the Emscripten `dotnet.native.js`. As a result, the workers in this directory cannot use any of pthread APIs or otherwise interact with the runtime in any way, except through message passing, or by having something in the runtime set up their own shared array buffer (which would be inaccessible from wasm).
On the other hand, the workers in this directory also do not depend on a .NET runtime compiled with `-s USE_PTHREADS` and are thus usable on sufficiently new browser using the single-threaded builds of .NET for WebAssembly.
diff --git a/src/mono/wasm/symbolicator/Program.cs b/src/mono/wasm/symbolicator/Program.cs
index ee293863187f2..668f1ed06593d 100644
--- a/src/mono/wasm/symbolicator/Program.cs
+++ b/src/mono/wasm/symbolicator/Program.cs
@@ -72,4 +72,4 @@
return 0;
-static void ShowUsage() => Console.WriteLine($"Usage: symbolicator [] [-|]");
+static void ShowUsage() => Console.WriteLine($"Usage: symbolicator [] [-|]");
diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js
index 63dc5d143f7af..90371a45707e3 100644
--- a/src/mono/wasm/test-main.js
+++ b/src/mono/wasm/test-main.js
@@ -305,6 +305,7 @@ async function dry_run(runArgs) {
appendElementOnExit: false,
logExitCode: false,
pthreadPoolSize: 0,
+ assetUniqueQuery: "?dry_run=true",
// this just means to not continue startup after the snapshot is taken.
// If there was previously a matching snapshot, it will be used.
exitAfterSnapshot: true
diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj
index 5bb5fb38c0ec0..a63ceb8adae6b 100644
--- a/src/mono/wasm/wasm.proj
+++ b/src/mono/wasm/wasm.proj
@@ -459,19 +459,21 @@
-
-
diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs
index 46bc35c0325ef..41722523d284d 100644
--- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs
+++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/AssetsComputingHelper.cs
@@ -19,6 +19,13 @@ public class AssetsComputingHelper
"Microsoft.NETCore.App.Runtime.Mono.perftrace.browser-wasm",
};
+ private static readonly string[] dotnetJsSingleThreadNames = new[]
+ {
+ "dotnet",
+ "dotnet.native",
+ "dotnet.runtime"
+ };
+
public static bool ShouldFilterCandidate(
ITaskItem candidate,
bool timezoneSupport,
@@ -50,7 +57,7 @@ public static bool ShouldFilterCandidate(
".json" when fromMonoPackage && (fileName == "emcc-props" || fileName == "package") => $"{fileName}{extension} is not used by Blazor",
".ts" when fromMonoPackage && fileName == "dotnet.d" => "dotnet type definition is not used by Blazor",
".ts" when fromMonoPackage && fileName == "dotnet-legacy.d" => "dotnet type definition is not used by Blazor",
- ".js" when assetType == "native" && !(fileName == "dotnet" || enableThreads && fileName == "dotnet.worker") => $"{fileName}{extension} is not used by Blazor",
+ ".js" when assetType == "native" && !(dotnetJsSingleThreadNames.Contains(fileName) || enableThreads && fileName == "dotnet.native.worker") => $"{fileName}{extension} is not used by Blazor",
".pdb" when !copySymbols => "copying symbols is disabled",
".symbols" when fromMonoPackage => "extension .symbols is not required.",
_ => null
diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs
index 97caad5a38574..d8fe399652dc7 100644
--- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs
+++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs
@@ -107,11 +107,11 @@ public override bool Execute()
}
string candidateFileName = candidate.GetMetadata("FileName");
- if ((candidateFileName == "dotnet" || candidateFileName == "dotnet.worker") && candidate.GetMetadata("Extension") == ".js")
+ if (candidateFileName.StartsWith("dotnet") && candidate.GetMetadata("Extension") == ".js")
{
string newDotnetJSFileName = null;
string newDotNetJSFullPath = null;
- if (FingerprintDotNetJs)
+ if (candidateFileName != "dotnet" || FingerprintDotNetJs)
{
var itemHash = FileHasher.GetFileHash(candidate.ItemSpec);
newDotnetJSFileName = $"{candidateFileName}.{candidate.GetMetadata("NuGetPackageVersion")}.{itemHash}.js";
diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs
index 0eddaf4d4aed9..87467d8ef53f9 100644
--- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs
+++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs
@@ -165,11 +165,10 @@ private List ProcessNativeAssets(
{
var key = kvp.Key;
var asset = kvp.Value;
- var isDotNetJs = IsDotNetJs(key);
- var isDotNetWorkerJs = IsDotNetWorkerJs(key);
+ var isDotNetJs = IsAnyDotNetJs(key);
var isDotNetWasm = IsDotNetWasm(key);
- if (!isDotNetJs && !isDotNetWasm && !isDotNetWorkerJs)
+ if (!isDotNetJs && !isDotNetWasm)
{
if (resolvedNativeAssetToPublish.TryGetValue(Path.GetFileName(asset.GetMetadata("OriginalItemSpec")), out var existing))
{
@@ -198,9 +197,17 @@ private List ProcessNativeAssets(
continue;
}
- if (isDotNetJs || isDotNetWorkerJs)
+ if (isDotNetJs)
{
- var baseName = isDotNetWorkerJs ? "dotnet.worker" : "dotnet";
+ var baseName = Path.GetFileNameWithoutExtension(key);
+ if (baseName.StartsWith("dotnet.native"))
+ baseName = "dotnet.native";
+ else if (baseName.StartsWith("dotnet.runtime"))
+ baseName = "dotnet.runtime";
+ else if (baseName.StartsWith("dotnet.worker"))
+ baseName = "dotnet.worker";
+ else if (baseName.StartsWith("dotnet"))
+ baseName = "dotnet";
var aotDotNetJs = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == $"{baseName}.js");
ITaskItem newDotNetJs = null;
@@ -235,7 +242,10 @@ private List ProcessNativeAssets(
if (isDotNetWasm)
{
- var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}" == "dotnet.wasm");
+ var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => {
+ var name= $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}";
+ return name == "dotnet.native.wasm" || name == "dotnet.wasm";
+ });
ITaskItem newDotNetWasm = null;
if (aotDotNetWasm != null)
{
@@ -252,10 +262,14 @@ private List ProcessNativeAssets(
ApplyPublishProperties(newDotNetWasm);
nativeStaticWebAssets.Add(newDotNetWasm);
- if (resolvedNativeAssetToPublish.TryGetValue("dotnet.wasm", out var resolved))
+ if (resolvedNativeAssetToPublish.TryGetValue("dotnet.native.wasm", out var resolved))
{
filesToRemove.Add(resolved);
}
+ else if (resolvedNativeAssetToPublish.TryGetValue("dotnet.wasm", out var resolved2))
+ {
+ filesToRemove.Add(resolved2);
+ }
continue;
}
}
@@ -268,19 +282,18 @@ private List ProcessNativeAssets(
return nativeStaticWebAssets;
- static bool IsDotNetJs(string key)
+ static bool IsAnyDotNetJs(string key)
{
var fileName = Path.GetFileName(key);
- return fileName.StartsWith("dotnet.", StringComparison.Ordinal) && fileName.EndsWith(".js", StringComparison.Ordinal) && !fileName.Contains("worker");
+ return fileName.StartsWith("dotnet.", StringComparison.Ordinal) && fileName.EndsWith(".js", StringComparison.Ordinal);
}
- static bool IsDotNetWorkerJs(string key)
+ static bool IsDotNetWasm(string key)
{
- var fileName = Path.GetFileName(key);
- return fileName.StartsWith("dotnet.worker.", StringComparison.Ordinal) && fileName.EndsWith(".js", StringComparison.Ordinal);
+ var name = Path.GetFileName(key);
+ return string.Equals("dotnet.native.wasm", name, StringComparison.Ordinal)
+ || string.Equals("dotnet.wasm", name, StringComparison.Ordinal);
}
-
- static bool IsDotNetWasm(string key) => string.Equals("dotnet.wasm", Path.GetFileName(key), StringComparison.Ordinal);
}
private List ProcessSymbolAssets(
diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs
index 31ed093e9a202..0e8dc24e3e23a 100644
--- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs
+++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs
@@ -196,8 +196,7 @@ public void WriteBootJson(Stream output, string entryAssemblyName)
string.Equals(assetTraitValue, "native", StringComparison.OrdinalIgnoreCase))
{
Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as a native application resource.", resource.ItemSpec);
- if (string.Equals(fileName, "dotnet", StringComparison.OrdinalIgnoreCase) &&
- string.Equals(fileExtension, ".wasm", StringComparison.OrdinalIgnoreCase))
+ if (fileName.StartsWith("dotnet", StringComparison.OrdinalIgnoreCase) && string.Equals(fileExtension, ".wasm", StringComparison.OrdinalIgnoreCase))
{
behavior = "dotnetwasm";
}
@@ -286,7 +285,7 @@ public void WriteBootJson(Stream output, string entryAssemblyName)
UseSimpleDictionaryFormat = true
});
- result.extensions = new Dictionary> ();
+ result.extensions = new Dictionary>();
foreach (var configExtension in Extensions)
{
var key = configExtension.GetMetadata("key");
diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
index 439ebf64e7ed5..7370e93939f74 100644
--- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
+++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
@@ -78,6 +78,21 @@ private sealed class WasmEntry : AssetEntry
public WasmEntry(string name, string hash) : base(name, hash, "dotnetwasm") { }
}
+ private sealed class LoaderJsEntry : AssetEntry
+ {
+ public LoaderJsEntry(string name, string hash) : base(name, hash, "js-module-dotnet") { }
+ }
+
+ private sealed class NativeJsEntry : AssetEntry
+ {
+ public NativeJsEntry(string name, string hash) : base(name, hash, "js-module-native") { }
+ }
+
+ private sealed class RuntimeJsEntry : AssetEntry
+ {
+ public RuntimeJsEntry(string name, string hash) : base(name, hash, "js-module-runtime") { }
+ }
+
private sealed class ThreadsWorkerEntry : AssetEntry
{
public ThreadsWorkerEntry(string name, string hash) : base(name, hash, "js-module-threads") { }
@@ -198,15 +213,27 @@ protected override bool ExecuteInternal()
var dest = Path.Combine(AppDir!, name);
if (!FileCopyChecked(item.ItemSpec, dest, "NativeAssets"))
return false;
- if (name == "dotnet.wasm")
+ if (name == "dotnet.js")
+ {
+ config.Assets.Add(new LoaderJsEntry (name, Utils.ComputeIntegrity(item.ItemSpec)) );
+ }
+ else if (name == "dotnet.native.wasm")
{
config.Assets.Add(new WasmEntry (name, Utils.ComputeIntegrity(item.ItemSpec)) );
}
- else if (IncludeThreadsWorker && name == "dotnet.worker.js")
+ else if (name == "dotnet.native.js")
+ {
+ config.Assets.Add(new NativeJsEntry (name, Utils.ComputeIntegrity(item.ItemSpec)) );
+ }
+ else if (name == "dotnet.runtime.js")
+ {
+ config.Assets.Add(new RuntimeJsEntry (name, Utils.ComputeIntegrity(item.ItemSpec)) );
+ }
+ else if (IncludeThreadsWorker && name == "dotnet.native.worker.js")
{
config.Assets.Add(new ThreadsWorkerEntry (name, Utils.ComputeIntegrity(item.ItemSpec)));
}
- else if(name == "dotnet.js.symbols")
+ else if(name == "dotnet.native.js.symbols")
{
config.Assets.Add(new SymbolsData(name, Utils.ComputeIntegrity(item.ItemSpec)));
}
diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilderBaseTask.cs b/src/tasks/WasmAppBuilder/WasmAppBuilderBaseTask.cs
index a552adfbb1927..b5a6539e2cb87 100644
--- a/src/tasks/WasmAppBuilder/WasmAppBuilderBaseTask.cs
+++ b/src/tasks/WasmAppBuilder/WasmAppBuilderBaseTask.cs
@@ -22,7 +22,7 @@ public abstract class WasmAppBuilderBaseTask : Task
[Required]
public string[] Assemblies { get; set; } = Array.Empty();
- // files like dotnet.wasm, icudt.dat etc
+ // files like dotnet.native.wasm, icudt.dat etc
[NotNull]
[Required]
public ITaskItem[] NativeAssets { get; set; } = Array.Empty();