<LibrariesRuntimeFiles Condition="'$(TargetOS)' == 'browser'"
Include="
$(LibrariesNativeArtifactsPath)dotnet.js;
+ $(LibrariesNativeArtifactsPath)dotnet.native.js;
+ $(LibrariesNativeArtifactsPath)dotnet.runtime.js;
$(LibrariesNativeArtifactsPath)dotnet.d.ts;
$(LibrariesNativeArtifactsPath)dotnet-legacy.d.ts;
$(LibrariesNativeArtifactsPath)package.json;
- $(LibrariesNativeArtifactsPath)dotnet.wasm;
- $(LibrariesNativeArtifactsPath)dotnet.js.symbols;
+ $(LibrariesNativeArtifactsPath)dotnet.native.wasm;
+ $(LibrariesNativeArtifactsPath)dotnet.native.js.symbols;
$(LibrariesNativeArtifactsPath)*.dat;"
IsNative="true" />
<!-- for threaded wasm -->
<_XHarnessArgs Condition="'$(IsFunctionalTest)' == 'true'" >$(_XHarnessArgs) --expected-exit-code=$(ExpectedExitCode)</_XHarnessArgs>
<_XHarnessArgs Condition="'$(WasmXHarnessArgs)' != ''" >$(_XHarnessArgs) $(WasmXHarnessArgs)</_XHarnessArgs>
<_XHarnessArgs Condition="('$(WasmEnableThreads)' == 'true' or '$(WasmEnablePerfTracing)' == 'true') and '$(_XHarnessArs.Contains("--web-server-use-cop")' != 'true'">$(_XHarnessArgs) --web-server-use-cop</_XHarnessArgs>
- <_XHarnessArgs >$(_XHarnessArgs) -s dotnet.js.symbols</_XHarnessArgs>
+ <_XHarnessArgs >$(_XHarnessArgs) -s dotnet.native.js.symbols</_XHarnessArgs>
<_XHarnessArgs Condition="'$(_UseWasmSymbolicator)' == 'true'" >$(_XHarnessArgs) --symbol-patterns wasm-symbol-patterns.txt</_XHarnessArgs>
<_XHarnessArgs Condition="'$(_UseWasmSymbolicator)' == 'true'" >$(_XHarnessArgs) --symbolicator WasmSymbolicator.dll,Microsoft.WebAssembly.Internal.SymbolicatorWrapperForXHarness</_XHarnessArgs>
<_XHarnessArgs Condition="'$(_WasmBrowserPathForTests)' != ''" >$(_XHarnessArgs) "--browser-path=$(_WasmBrowserPathForTests)"</_XHarnessArgs>
<PlatformManifestFileEntry Include="libmono-wasm-eh-wasm.a" IsNative="true" />
<PlatformManifestFileEntry Include="wasm-bundled-timezones.a" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.js" IsNative="true" />
- <PlatformManifestFileEntry Include="dotnet.worker.js" IsNative="true" />
- <PlatformManifestFileEntry Include="dotnet.js.symbols" IsNative="true" />
+ <PlatformManifestFileEntry Include="dotnet.runtime.js" IsNative="true" />
+ <PlatformManifestFileEntry Include="dotnet.native.js" IsNative="true" />
+ <PlatformManifestFileEntry Include="dotnet.native.worker.js" IsNative="true" />
+ <PlatformManifestFileEntry Include="dotnet.native.js.symbols" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.d.ts" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet-legacy.d.ts" IsNative="true" />
- <PlatformManifestFileEntry Include="dotnet.wasm" IsNative="true" />
+ <PlatformManifestFileEntry Include="dotnet.native.wasm" IsNative="true" />
<PlatformManifestFileEntry Include="icudt.dat" IsNative="true" />
<PlatformManifestFileEntry Include="icudt_no_CJK.dat" IsNative="true" />
<PlatformManifestFileEntry Include="icudt_CJK.dat" IsNative="true" />
<PlatformManifestFileEntry Include="icudt_optimal_no_CJK.dat" IsNative="true" />
<PlatformManifestFileEntry Include="package.json" IsNative="true" />
<PlatformManifestFileEntry Include="pal_random.lib.js" IsNative="true" />
- <PlatformManifestFileEntry Include="runtime.es6.iffe.js" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.es6.pre.js" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.es6.lib.js" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.es6.extpost.js" IsNative="true" />
<PlatformManifestFileEntry Include="driver.h" IsNative="true" />
<PlatformManifestFileEntry Include="stubs.c" IsNative="true" />
<PlatformManifestFileEntry Include="synthetic-pthread.c" IsNative="true" />
+ <PlatformManifestFileEntry Include="dotnet.wasm" IsNative="true" />
<!-- ICU-specific files -->
<PlatformManifestFileEntry Include="libicudata.a" IsNative="true" />
<PlatformManifestFileEntry Include="libicui18n.a" IsNative="true" />
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);
<!-- Remove dotnet.js/wasm from runtime pack, in favor of the relinked ones in @(WasmNativeAsset) -->
<ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)"
- Condition="@(WasmNativeAsset->Count()) > 0 and '%(FileName)' == 'dotnet' and ('%(Extension)' == '.wasm' or '%(Extension)' == '.js')" />
+ Condition="@(WasmNativeAsset->Count()) > 0 and ( '%(FileName)' == 'dotnet' or '%(FileName)' == 'dotnet.native' ) and ('%(Extension)' == '.wasm' or '%(Extension)' == '.js')" />
</ItemGroup>
<ComputeWasmBuildAssets
$(TargetFileName)
"
Outputs="
- bin/$(Configuration)/AppBundle/dotnet.wasm;
+ bin/$(Configuration)/AppBundle/dotnet.native.wasm;
+ bin/$(Configuration)/AppBundle/dotnet.native.js;
bin/$(Configuration)/AppBundle/$(_WasmMainJSFileName);
">
<PropertyGroup>
<script type='module' src="./main.js"></script>
<script type='module' src="./dotnet.js"></script>
<link rel="preload" href="./mono-config.json" as="fetch" crossorigin="anonymous">
- <link rel="prefetch" href="./dotnet.wasm" as="fetch" crossorigin="anonymous">
+ <link rel="prefetch" href="./dotnet.native.js" as="fetch" crossorigin="anonymous">
+ <link rel="prefetch" href="./dotnet.runtime.js" as="fetch" crossorigin="anonymous">
+ <link rel="prefetch" href="./dotnet.native.wasm" as="fetch" crossorigin="anonymous">
<!-- users should consider if they optimize for the first load or subsequent load from memory snapshot -->
<link rel="prefetch" href="./icudt.dat" as="fetch" crossorigin="anonymous">
<link rel="prefetch" href="./managed/System.Private.CoreLib.webcil" as="fetch" crossorigin="anonymous">
<script type="module" src="./frame-main.js"></script>
<script type='module' src="./dotnet.js"></script>
<link rel="preload" href="./mono-config.json" as="fetch" crossorigin="anonymous">
- <link rel="prefetch" href="./dotnet.wasm" as="fetch" crossorigin="anonymous">
+ <link rel="prefetch" href="./dotnet.native.js" as="fetch" crossorigin="anonymous">
+ <link rel="prefetch" href="./dotnet.runtime.js" as="fetch" crossorigin="anonymous">
+ <link rel="prefetch" href="./dotnet.native.wasm" as="fetch" crossorigin="anonymous">
<!-- users should consider if they optimize for the first load or subsequent load from memory snapshot -->
<link rel="prefetch" href="./managed/System.Private.CoreLib.dll" as="fetch" crossorigin="anonymous">
</head>
<Target Name="CopyRelinkedPackage" AfterTargets="WasmBuildApp" DependsOnTargets="Build" Inputs="$(WasmAppDir)/dotnet.js;
- $(WasmAppDir)/dotnet.wasm;
+ $(WasmAppDir)/dotnet.runtime.js;
+ $(WasmAppDir)/dotnet.native.js;
+ $(WasmAppDir)/dotnet.native.wasm;
$(MicrosoftNetCoreAppRuntimePackNativeDir)/dotnet.d.ts;
$(MicrosoftNetCoreAppRuntimePackNativeDir)/dotnet-legacy.d.ts;
$(MicrosoftNetCoreAppRuntimePackNativeDir)/package.json;" Outputs="bin/dotnet-runtime/.npm-stamp">
<ItemGroup>
<NpmPackageFiles Include="$(WasmAppDir)/dotnet.js"/>
- <NpmPackageFiles Include="$(WasmAppDir)/dotnet.wasm"/>
+ <NpmPackageFiles Include="$(WasmAppDir)/dotnet.runtime.js"/>
+ <NpmPackageFiles Include="$(WasmAppDir)/dotnet.native.js"/>
+ <NpmPackageFiles Include="$(WasmAppDir)/dotnet.native.wasm"/>
<NpmPackageFiles Include="$(MicrosoftNetCoreAppRuntimePackNativeDir)/dotnet.d.ts"/>
<NpmPackageFiles Include="$(MicrosoftNetCoreAppRuntimePackNativeDir)/dotnet-legacy.d.ts"/>
<NpmPackageFiles Include="$(MicrosoftNetCoreAppRuntimePackNativeDir)/package.json"/>
</PropertyGroup>
<Target Name="CopyRelinkedPackage" AfterTargets="WasmBuildApp" DependsOnTargets="Build" Inputs="$(WasmAppDir)/dotnet.js;
- $(WasmAppDir)/dotnet.wasm;
+ $(WasmAppDir)/dotnet.runtime.js;
+ $(WasmAppDir)/dotnet.native.js;
+ $(WasmAppDir)/dotnet.native.wasm;
$(MicrosoftNetCoreAppRuntimePackNativeDir)/dotnet.d.ts;
$(MicrosoftNetCoreAppRuntimePackNativeDir)/dotnet-legacy.d.ts;
$(MicrosoftNetCoreAppRuntimePackNativeDir)/package.json;" Outputs="bin/dotnet-runtime/.npm-stamp">
<ItemGroup>
<NpmPackageFiles Include="$(WasmAppDir)/dotnet.js"/>
- <NpmPackageFiles Include="$(WasmAppDir)/dotnet.wasm"/>
+ <NpmPackageFiles Include="$(WasmAppDir)/dotnet.runtime.js"/>
+ <NpmPackageFiles Include="$(WasmAppDir)/dotnet.native.js"/>
+ <NpmPackageFiles Include="$(WasmAppDir)/dotnet.native.wasm"/>
<NpmPackageFiles Include="$(MicrosoftNetCoreAppRuntimePackNativeDir)/dotnet.d.ts"/>
<NpmPackageFiles Include="$(MicrosoftNetCoreAppRuntimePackNativeDir)/dotnet-legacy.d.ts"/>
<NpmPackageFiles Include="$(MicrosoftNetCoreAppRuntimePackNativeDir)/package.json"/>
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
// 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]
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
}
_ => 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);
}
}
var filesToExist = new List<string>()
{
mainJS,
- "dotnet.wasm",
+ "dotnet.native.wasm",
"mono-config.json",
- "dotnet.js"
+ "dotnet.js",
+ "dotnet.native.js",
+ "dotnet.runtime.js"
};
if (isBrowserProject)
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)
{
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);
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}");
(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));
Path.Combine(paths.ObjWasmDir, "pinvoke-table.h"),
Path.Combine(paths.ObjWasmDir, "driver-gen.c"),
- Path.Combine(paths.BundleDir, "dotnet.wasm"),
- Path.Combine(paths.BundleDir, "dotnet.js")
+ Path.Combine(paths.BundleDir, "dotnet.native.wasm"),
+ Path.Combine(paths.BundleDir, "dotnet.native.js"),
};
if (buildArgs.AOT)
foreach (var file in files)
dict[Path.GetFileName(file)] = (file, unchanged);
+ // those files do not change on re-link
+ dict["dotnet.js"]=(Path.Combine(paths.BundleDir, "dotnet.js"), true);
+ dict["dotnet.runtime.js"]=(Path.Combine(paths.BundleDir, "dotnet.runtime.js"), true);
+
return dict;
}
}
var pathsDict = GetFilesTable(true, objDir);
pathsDict.Remove("runtime-icall-table.h");
- pathsDict.UpdateTo(unchanged: false, "dotnet.wasm", "dotnet.js", "emcc-link.rsp");
+ pathsDict.UpdateTo(unchanged: false, "dotnet.native.wasm", "dotnet.native.js", "emcc-link.rsp");
var originalStat = StatFiles(pathsDict.Select(kvp => kvp.Value.fullPath));
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");
}
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}";
<_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)' != ''" />
<Target Name="_WasmLinkDotNet"
Inputs="@(_WasmLinkDependencies);$(_EmccDefaultFlagsRsp);$(_EmccDefaultLinkFlagsRsp);$(_EmccLinkRsp)"
- Outputs="$(_WasmIntermediateOutputPath)dotnet.js;$(_WasmIntermediateOutputPath)dotnet.wasm"
+ Outputs="$(_WasmIntermediateOutputPath)dotnet.native.js;$(_WasmIntermediateOutputPath)dotnet.native.wasm"
DependsOnTargets="_CheckEmccIsExpectedVersion;_WasmSelectRuntimeComponentsForLinking;_WasmCompileAssemblyBitCodeFilesForAOT;_WasmWriteRspFilesForLinking"
Returns="@(FileWrites)" >
<Output TaskParameter="ExitCode" PropertyName="_EmccLinkStepExitCode" />
</Exec>
<ItemGroup>
- <FileWrites Include="$(_WasmIntermediateOutputPath)dotnet.wasm" />
- <FileWrites Include="$(_WasmIntermediateOutputPath)dotnet.js" />
- <FileWrites Include="$(_WasmIntermediateOutputPath)dotnet.js.symbols" Condition="'$(WasmEmitSymbolMap)' == 'true'" />
+ <FileWrites Include="$(_WasmIntermediateOutputPath)dotnet.native.wasm" />
+ <FileWrites Include="$(_WasmIntermediateOutputPath)dotnet.native.js" />
+ <FileWrites Include="$(_WasmIntermediateOutputPath)dotnet.native.js.symbols" Condition="'$(WasmEmitSymbolMap)' == 'true'" />
</ItemGroup>
<ItemGroup>
<WasmOptConfigurationFlags Condition="'$(WasmOptConfigurationFlags)' != ''" Include="$(WasmOptConfigurationFlags)" />
</ItemGroup>
- <Message Text="Stripping symbols from dotnet.wasm ..." Importance="High" Condition="'$(WasmNativeStrip)' == 'true'" />
- <Exec Command="wasm-opt$(_ExeExt) --enable-simd --enable-exception-handling @(WasmOptConfigurationFlags, ' ') --strip-dwarf "$(_WasmIntermediateOutputPath)dotnet.wasm" -o "$(_WasmIntermediateOutputPath)dotnet.wasm""
+ <Message Text="Stripping symbols from dotnet.native.wasm ..." Importance="High" Condition="'$(WasmNativeStrip)' == 'true'" />
+ <Exec Command="wasm-opt$(_ExeExt) --enable-simd --enable-exception-handling @(WasmOptConfigurationFlags, ' ') --strip-dwarf "$(_WasmIntermediateOutputPath)dotnet.native.wasm" -o "$(_WasmIntermediateOutputPath)dotnet.native.wasm""
Condition="'$(WasmNativeStrip)' == 'true'"
IgnoreStandardErrorWarningFormat="true"
EnvironmentVariables="@(EmscriptenEnvVars)" />
<Target Name="_CompleteWasmBuildNative">
<ItemGroup>
- <WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.wasm" />
- <WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.js" />
- <WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.worker.js" Condition="Exists('$(_WasmIntermediateOutputPath)dotnet.worker.js')" />
- <WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.js.symbols" Condition="'$(WasmEmitSymbolMap)' == 'true' and Exists('$(_WasmIntermediateOutputPath)dotnet.js.symbols')" />
+ <WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.native.wasm" />
+ <WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.native.js" />
+ <WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.native.worker.js" Condition="Exists('$(_WasmIntermediateOutputPath)dotnet.worker.js')" />
+ <WasmNativeAsset Include="$(_WasmIntermediateOutputPath)dotnet.native.js.symbols" Condition="'$(WasmEmitSymbolMap)' == 'true' and Exists('$(_WasmIntermediateOutputPath)dotnet.native.js.symbols')" />
<_WasmAssembliesInternal Remove="$(_WasmDedupAssembly)"/>
</ItemGroup>
</Target>
- $(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
<Warning Condition="'$(InvariantGlobalization)' == 'true' and '$(HybridGlobalization)' == 'true'" Text="%24(HybridGlobalization) has no effect when %24(InvariantGlobalization) is set to true." />
<PropertyGroup>
<HybridGlobalization Condition="'$(InvariantGlobalization)' == 'true'">false</HybridGlobalization>
- <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.wasm'">true</_HasDotnetWasm>
- <_HasDotnetJsWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.worker.js'">true</_HasDotnetJsWorker>
- <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.js.symbols'">true</_HasDotnetJsSymbols>
- <_HasDotnetJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.js'">true</_HasDotnetJs>
+ <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.wasm'">true</_HasDotnetWasm>
+ <_HasDotnetJsWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.worker.js'">true</_HasDotnetJsWorker>
+ <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js.symbols'">true</_HasDotnetJsSymbols>
+ <_HasDotnetNativeJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js'">true</_HasDotnetNativeJs>
<_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and Exists('$(WasmIcuDataFileName)')">$(WasmIcuDataFileName)</_WasmIcuDataFileName>
<_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and !Exists('$(WasmIcuDataFileName)')">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(WasmIcuDataFileName)</_WasmIcuDataFileName>
</PropertyGroup>
<ItemGroup>
<!-- If dotnet.{wasm,js} weren't added already (eg. AOT can add them), then add the default ones -->
- <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.wasm" Condition="'$(_HasDotnetWasm)' != 'true'" />
- <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.js" Condition="'$(_HasDotnetJs)' != 'true'" />
- <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.worker.js" Condition="'$(_HasDotnetJsWorker)' != 'true' and Exists('$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.worker.js')" />
- <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.js.symbols"
+ <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.js" />
+ <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.runtime.js" />
+ <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.native.wasm" Condition="'$(_HasDotnetWasm)' != 'true'" />
+ <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.native.js" Condition="'$(_HasDotnetNativeJs)' != 'true'" />
+ <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.native.worker.js" Condition="'$(_HasDotnetJsWorker)' != 'true' and Exists('$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.native.worker.js')" />
+ <WasmNativeAsset Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.native.js.symbols"
Condition="'$(WasmEmitSymbolMap)' == 'true' and
'$(_HasDotnetJsSymbols)' != 'true' and
- Exists('$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.js.symbols')" />
+ Exists('$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.native.js.symbols')" />
</ItemGroup>
<ItemGroup Condition="'$(InvariantGlobalization)' != 'true'">
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
${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}")
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)
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<void>();
-const allDownloadsQueued = createPromiseController<void>();
-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<void> | 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<void> {
- 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<AssetEntryInternal>[] = [];
-
- 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<void>[] = [];
- 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<AssetEntryInternal> {
- 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<AssetEntryInternal> {
- // 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<void>();
- }
-
- 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<Response | undefined> {
- // 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 = <Response><any>{
- 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();
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":
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") {
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(
wasmModuleImports: WebAssembly.Imports,
successCallback: InstantiateWasmSuccessCallback,
): Promise<void> {
- 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;
successCallback(compiledInstance, compiledModule);
}
-export async function instantiate_symbols_asset(
- pendingAsset: AssetEntryInternal,
-): Promise<void> {
+export async function instantiate_symbols_asset(pendingAsset: AssetEntryInternal): Promise<void> {
try {
const response = await pendingAsset.pendingDownloadInternal!.response;
const text = await response.text();
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
// 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");
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");
}
-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<string, MonoAssembly>();
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);
+++ /dev/null
-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
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";
//! This is not considered public API with backward compatibility guarantees.
-declare const promise_control_symbol: unique symbol;
interface PromiseController<T = any> {
isDone: boolean;
readonly promise: Promise<T>;
reject: (reason?: any) => void;
}
interface ControllablePromise<T = any> extends Promise<T> {
- [promise_control_symbol]: PromiseController<T>;
+ __brand: "ControllablePromise";
}
interface PromiseAndController<T> {
promise: ControllablePromise<T>;
-90231971bda6e6a32b2c5239c60176b9126469d29478f572b8a15ab7476cd791
\ No newline at end of file
+6d0ff454946223f77abe8e6c1e377489c33b2914da86120f6b2952b739ebec20
\ No newline at end of file
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";
// 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 {
postMessageToBrowser,
addEventListenerFromBrowser,
createPromiseController,
- delay,
+ delay: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)),
command,
reply,
expectAdvertise
export type {
PromiseAndController,
-} from "../../promise-controller";
+} from "../../types/internal";
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<T extends keyof WebSocketEventMap>(type: T, listener: (this: MockRemoteSocket, ev: WebSocketEventMap[T]) => any, options?: boolean | AddEventListenerOptions): void;
// 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,
/// <reference lib="webworker" />
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";
import { importAndInstantiateMock } from "./mock-remote";
import type { Mock, MockRemoteSocket } from "../mock";
-import { PromiseAndController, createPromiseController } from "../../promise-controller";
import {
isEventPipeCommand,
isProcessCommand,
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);
// 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<Mock> {
if (monoDiagnosticsMock) {
} 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;
// 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";
*/
mono_wasm_load_data_archive: (data: Uint8Array, prefix: string) => boolean;
/**
- * @deprecated Please use configSrc instead
- */
- mono_wasm_load_config: (configFilePath: string) => Promise<void>;
- /**
* @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead.
*/
mono_wasm_new_root_buffer: (capacity: number, name?: string) => WasmRootBuffer;
* application environment
*/
applicationEnvironment?: string;
+ /**
+ * query string to be used for asset loading
+ */
+ assetUniqueQuery?: string;
};
interface ResourceRequest {
name: string;
*/
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
};
type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise<RuntimeAPI>;
+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;
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;
}
-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;
function setup(disableLegacyJsInterop) {
const pthreadReplacements = {};
const dotnet_replacements = {
- scriptUrl: import.meta.url,
fetch: globalThis.fetch,
require,
updateMemoryViews,
#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
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;
-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
// 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 = {
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) {
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,
}
// 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
// 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";
/// <reference path="./types/v8.d.ts" />
/// <reference path="./types/node.d.ts" />
-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<void>(),
+ dotnetReady: createPromiseController<any>(),
+ memorySnapshotSkippedOrDone: createPromiseController<void>(),
+ afterInstantiateWasm: createPromiseController<void>(),
+ beforePreInit: createPromiseController<void>(),
+ afterPreInit: createPromiseController<void>(),
+ afterPreRun: createPromiseController<void>(),
+ beforeOnRuntimeInitialized: createPromiseController<void>(),
+ afterOnRuntimeInitialized: createPromiseController<void>(),
+ afterPostRun: createPromiseController<void>(),
});
+
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<RuntimeHelpers>);
}
+
+export function createPromiseController<T>(afterResolve?: () => void, afterReject?: () => void): PromiseAndController<T> {
+ return loaderHelpers.createPromiseController<T>(afterResolve, afterReject);
+}
\ No newline at end of file
// 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 {
}
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;
});
if (!res.__headerNames) {
res.__headerNames = [];
res.__headerValues = [];
- const entries: Iterable<string[]> = (<any>res.headers).entries();
+ if (res.headers && (<any>res.headers).entries) {
+ const entries: Iterable<string[]> = (<any>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]);
+ }
}
}
}
// 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(<any>src, <any>(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(<any>src, <any>(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
const cultureName = conv_string_root(cultureRoot);
if (!cultureName)
throw new Error("Cannot change case, the culture name is null.");
- const input = string_decoder.decode(<any>src, <any>(src + 2*srcLength));
+ const input = string_decoder.decode(<any>src, <any>(src + 2 * srcLength));
let result = toUpper ? input.toLocaleUpperCase(cultureName) : input.toLocaleLowerCase(cultureName);
if (result.length > destLength)
result = input;
// 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.
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 <WasmIcuDataFileName> user can define what ICU source file they want to load.
- // There is no need to check application's culture when <WasmIcuDataFileName> 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;
-}
} 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";
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";
// 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 {
// 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 {
// 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";
// 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 {
/*
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 {
}
// 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(<any>ip + (2 * indexPlusOne));
}
-function getArgI16 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgI16(ip: MintOpcodePtr, indexPlusOne: number) {
return getI16(<any>ip + (2 * indexPlusOne));
}
-function getArgI32 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgI32(ip: MintOpcodePtr, indexPlusOne: number) {
const src = <any>ip + (2 * indexPlusOne);
return getI32_unaligned(src);
}
-function getArgU32 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgU32(ip: MintOpcodePtr, indexPlusOne: number) {
const src = <any>ip + (2 * indexPlusOne);
return getU32_unaligned(src);
}
-function getArgF32 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgF32(ip: MintOpcodePtr, indexPlusOne: number) {
const src = <any>ip + (2 * indexPlusOne);
return getF32_unaligned(src);
}
-function getArgF64 (ip: MintOpcodePtr, indexPlusOne: number) {
+function getArgF64(ip: MintOpcodePtr, indexPlusOne: number) {
const src = <any>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(<any>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
) {
const knownConstantValues = new Map<number, number>();
-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 = <MintOpcodePtr><any>0;
let isFirstInstruction = true, isConditionallyExecuted = false,
firstOpcodeInBlock = true, containsSimd = false,
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
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
return result;
}
-const notNullSince : Map<number, number> = new Map();
+const notNullSince: Map<number, number> = 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) {
// 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.
// 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
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
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))
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(<any>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);
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) {
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:
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
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),
}
}
-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)),
// 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,
};
// 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],
[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,
[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]: <any>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]: <any>JiterpSpecialOpcode.CGE_UN_R4,
- [MintOpcode.MINT_BLE_R4_S]: MintOpcode.MINT_CLE_R4,
- [MintOpcode.MINT_BLE_UN_R4_S]: <any>JiterpSpecialOpcode.CLE_UN_R4,
-
- [MintOpcode.MINT_BEQ_R8_S]: MintOpcode.MINT_CEQ_R8,
- [MintOpcode.MINT_BNE_UN_R8_S]: <any>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]: <any>JiterpSpecialOpcode.CGE_UN_R8,
- [MintOpcode.MINT_BLE_R8_S]: MintOpcode.MINT_CLE_R8,
- [MintOpcode.MINT_BLE_UN_R8_S]: <any>JiterpSpecialOpcode.CLE_UN_R8,
+ [MintOpcode.MINT_BEQ_R4_S]: MintOpcode.MINT_CEQ_R4,
+ [MintOpcode.MINT_BNE_UN_R4_S]: <any>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]: <any>JiterpSpecialOpcode.CGE_UN_R4,
+ [MintOpcode.MINT_BLE_R4_S]: MintOpcode.MINT_CLE_R4,
+ [MintOpcode.MINT_BLE_UN_R4_S]: <any>JiterpSpecialOpcode.CLE_UN_R4,
+
+ [MintOpcode.MINT_BEQ_R8_S]: MintOpcode.MINT_CEQ_R8,
+ [MintOpcode.MINT_BNE_UN_R8_S]: <any>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]: <any>JiterpSpecialOpcode.CGE_UN_R8,
+ [MintOpcode.MINT_BLE_R8_S]: MintOpcode.MINT_CLE_R8,
+ [MintOpcode.MINT_BLE_UN_R8_S]: <any>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];
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[<any>opcode];
if (!info)
return true;
}
-function append_call_handler_store_ret_ip (
+function append_call_handler_store_ret_ip(
builder: WasmBuilder, ip: MintOpcodePtr,
frame: NativePointer, opcode: MintOpcode
) {
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();
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;
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);
}
}
-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 = (
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;
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:
return true;
}
-function append_getelema1 (
+function append_getelema1(
builder: WasmBuilder, ip: MintOpcodePtr,
objectOffset: number, indexOffset: number, elementSize: number
) {
// 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);
const vec128Test =
"0061736d0100000001040160000003020100070801047465737400000a090107004100fd111a0b";
-let wasmSimdSupported : boolean | undefined;
+let wasmSimdSupported: boolean | undefined;
-function getIsWasmSimdSupported () : boolean {
+function getIsWasmSimdSupported(): boolean {
if (wasmSimdSupported !== undefined)
return wasmSimdSupported;
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);
[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()) {
}
}
-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);
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 = <WasmSimdOpcode>cwraps.mono_jiterp_get_simd_opcode(1, index);
if (simple) {
append_simd_2_load(builder, ip);
}
}
-function emit_simd_3 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic3) : boolean {
+function emit_simd_3(builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic3): boolean {
const simple = <WasmSimdOpcode>cwraps.mono_jiterp_get_simd_opcode(2, index);
if (simple) {
const isShift = simdShiftTable.has(index);
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 = <WasmSimdOpcode>cwraps.mono_jiterp_get_simd_opcode(3, index);
if (simple) {
append_simd_4_load(builder, ip);
}
}
-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);
// 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 {
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 {
--- /dev/null
+// 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<void> | 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<void> {
+ 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<AssetEntryInternal>[] = [];
+
+ 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<void>[] = [];
+ 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<void> {
+ 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<AssetEntryInternal> {
+ 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<AssetEntryInternal> {
+ // 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<void>();
+ }
+
+ 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<Response | undefined> {
+ // 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 = <Response><any>{
+ 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
// 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<Response> | null | undefined;
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");
}
}
-// 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
-}
// 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 {
-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[] = [];
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;
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 = {
behavior: "assembly",
};
assets.push(asset);
- downloadResource(asset);
}
if (hasDebuggingEnabled(resourceLoader.bootConfig) && resources.pdb) {
for (const name in resources.pdb) {
behavior: "pdb",
};
assets.push(asset);
- downloadResource(asset);
}
}
const applicationCulture = resourceLoader.startOptions.applicationCulture || (navigator.languages && navigator.languages[0]);
} 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,
};
if (resourceLoader.bootConfig.runtimeOptions) {
moduleConfig.runtimeOptions = [...(moduleConfig.runtimeOptions || []), ...(resourceLoader.bootConfig.runtimeOptions || [])];
}
-
- return moduleConfig;
}
function getICUResourceName(bootConfig: BootJsonData, culture: string | undefined): string {
return "icudt_CJK.dat";
}
return "icudt_no_CJK.dat";
-}
\ No newline at end of file
+}
+
-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 {
--- /dev/null
+// 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<void> {
+ 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 = <any>{ message: errMessage, error: err, isError: true };
+ loaderHelpers.abort_startup(errMessage, true);
+ throw err;
+ }
+}
\ No newline at end of file
--- /dev/null
+// 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<void>((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);
+ }
+ }
+}
--- /dev/null
+// 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<MonoConfig>(),
+ allDownloadsQueued: createPromiseController<void>(),
+ wasmDownloadPromise: createPromiseController<AssetEntryInternal>(),
+ runtimeModuleLoaded: createPromiseController<void>(),
+
+ abort_startup,
+ mono_exit,
+ createPromiseController,
+ getPromiseController,
+ assertIsControllablePromise,
+ mono_download_assets,
+ resolve_asset_path,
+ setup_proxy_console,
+
+ } as Partial<LoaderHelpers>);
+}
--- /dev/null
+// 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 <WasmIcuDataFileName> user can define what ICU source file they want to load.
+ // There is no need to check application's culture when <WasmIcuDataFileName> 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;
+}
--- /dev/null
+// 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;
--- /dev/null
+// 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);
+}
--- /dev/null
+
+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<void> {
+
+ 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<Response> {
+ 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 <Response><any>{
+ 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 Stra<unicode char - Latin Small Letter Sharp S>e.xml
+ // https://bugs.chromium.org/p/v8/issues/detail?id=12541
+ return <Response><any>{
+ ok: true,
+ url,
+ arrayBuffer: () => {
+ return new Uint8Array(read(url, "binary"));
+ },
+ json: () => {
+ return JSON.parse(read(url, "utf8"));
+ }
+ };
+ }
+ }
+ catch (e: any) {
+ return <Response><any>{
+ 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);
+}
// 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<T = any> {
- isDone: boolean;
- readonly promise: Promise<T>;
- resolve: (value: T | PromiseLike<T>) => void;
- reject: (reason?: any) => void;
-}
-
-/// A Promise<T> with a controller attached
-export interface ControllablePromise<T = any> extends Promise<T> {
- [promise_control_symbol]: PromiseController<T>;
-}
-
-/// Just a pair of a promise and its controller
-export interface PromiseAndController<T> {
- promise: ControllablePromise<T>;
- promise_control: PromiseController<T>;
-}
-
/// 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<T>(afterResolve?: () => void, afterReject?: () => void): PromiseAndController<T> {
});
(<any>promise_control).promise = promise;
const controllablePromise = promise as ControllablePromise<T>;
- controllablePromise[promise_control_symbol] = promise_control;
+ (controllablePromise as any)[promise_control_symbol] = promise_control;
return { promise: controllablePromise, promise_control: promise_control };
}
export function getPromiseController<T>(promise: ControllablePromise<T>): PromiseController<T>;
export function getPromiseController<T>(promise: Promise<T>): PromiseController<T> | undefined {
- return (promise as ControllablePromise<T>)[promise_control_symbol];
+ return (promise as any)[promise_control_symbol];
}
export function isControllablePromise<T>(promise: Promise<T>): promise is ControllablePromise<T> {
- return (promise as ControllablePromise<T>)[promise_control_symbol] !== undefined;
+ return (promise as any)[promise_control_symbol] !== undefined;
}
export function assertIsControllablePromise<T>(promise: Promise<T>): asserts promise is ControllablePromise<T> {
// 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;
}
}
-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<RuntimeAPI | EmscriptenModuleInternal> {
+ // extract ModuleConfig
if (typeof moduleFactory === "function") {
const extension = moduleFactory(globalObjectsRoot.api) as any;
if (extension.ready) {
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<RuntimeAPI> {
+ 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<EmscriptenModuleInternal> {
+ await init_polyfills(module);
+
+ setupPreloadChannelToMainThread();
+
+ await loaderHelpers.afterConfigLoaded.promise;
+
+ const promises = importModules();
+ const es6Modules = await Promise.all(promises);
+ initializeModules(es6Modules as any);
+
return module;
}
--- /dev/null
+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<TPort>(port: TPort): any {
+ return {
+ [monoSymbol]: {
+ mono_cmd: WorkerMonoCommandType.preload,
+ port
+ }
+ };
+}
+
+const enum WorkerMonoCommandType {
+ channel_created = "channel_created",
+ preload = "preload",
+}
}
}
-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) => {
// 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";
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";
// 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,
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";
}
const promise = mono_wasm_get_jsobj_from_js_handle(js_handle);
mono_assert(!!promise, () => `ERR28: promise not found for js_handle: ${js_handle} `);
- assertIsControllablePromise<any>(promise);
- const promise_control = getPromiseController(promise);
+ loaderHelpers.assertIsControllablePromise<any>(promise);
+ const promise_control = loaderHelpers.getPromiseController(promise);
const orig_resolve = promise_control.resolve;
promise_control.resolve = (argInner: JSMarshalerArgument) => {
// 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);
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<MarshalerType, MarshalerToJs>();
// 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";
# 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`.
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";
// 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*/];
// 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");
// 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";
/**
*/
mono_wasm_load_data_archive: (data: Uint8Array, prefix: string) => boolean;
/**
- * @deprecated Please use configSrc instead
- */
- mono_wasm_load_config: (configFilePath: string) => Promise<void>;
- /**
* @deprecated Please use [JSImportAttribute] or [JSExportAttribute] for interop instead.
*/
mono_wasm_new_root_buffer: (capacity: number, name?: string) => WasmRootBuffer;
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";
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 {
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,
// 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";
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";
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";
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";
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<void> {
// v8 shell doesn't have Event and EventTarget
if (MonoWasmThreads && typeof globalThis.Event === "undefined") {
globalThis.Event = class Event {
}
};
}
-}
-
-export function initializeReplacements(replacements: EmscriptenReplacements): void {
- // require replacement
- const imports = Module.imports = (Module.imports || {}) as DotnetModuleConfigImports;
- const requireWrapper = (wrappedRequire: Function) => (name: string) => {
- const resolved = (<any>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<void> {
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;
runtimeHelpers.subtle = globalThis.crypto?.subtle;
}
-const dummyPerformance = {
- now: function () {
- return Date.now();
- }
-};
-export async function fetch_like(url: string, init?: RequestInit): Promise<Response> {
- 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 <Response><any>{
- 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 Stra<unicode char - Latin Small Letter Sharp S>e.xml
- // https://bugs.chromium.org/p/v8/issues/detail?id=12541
- const arrayBuffer = new Uint8Array(read(url, "binary"));
- return <Response><any>{
- ok: true,
- url,
- arrayBuffer: () => arrayBuffer,
- json: () => JSON.parse(Module.UTF8ArrayToString(arrayBuffer, 0, arrayBuffer.length))
- };
- }
- }
- catch (e: any) {
- return <Response><any>{
- 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);
-}
// 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.
+++ /dev/null
-// 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<void> {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-
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<pthread_ptr, Thread> = new Map();
// 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
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);
// 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 {
};
}
-export function makePreloadMonoMessage<TPort>(port: TPort): MonoWorkerMessagePreload<TPort> {
- return {
- [monoSymbol]: {
- mono_cmd: WorkerMonoCommandType.preload,
- port
- }
- };
-}
-
export function isMonoWorkerMessage(message: unknown): message is MonoWorkerMessage<any> {
return message !== undefined && typeof message === "object" && message !== null && monoSymbol in message;
}
/// <reference lib="webworker" />
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,
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 {
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);
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.
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,
{
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 {
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",
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: [
const workerConfigs = findWebWorkerInputs("./workers").map((workerInput) => makeWorkerConfig(workerInput.workerName, workerInput.path));
const allConfigs = [
- iffeConfig,
+ loaderConfig,
+ runtimeConfig,
typesConfig,
legacyConfig,
].concat(workerConfigs)
.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;
}
};
- 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) {
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;
// 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
export async function mono_run_main_and_exit(main_assembly_name: string, args: string[]): Promise<number> {
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;
}
}
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<void>((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
- ;
- }
-}
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";
// 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
delete inputs.maxParallelDownloads;
delete inputs.enableDownloadRetry;
delete inputs.exitAfterSnapshot;
+ delete inputs.assetUniqueQuery;
inputs.GitHash = GitHash;
inputs.ProductVersion = ProductVersion;
// 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<any>();
-export const afterConfigLoaded = createPromiseController<MonoConfig>();
-export const memorySnapshotSkippedOrDone = createPromiseController<void>();
-export const afterInstantiateWasm = createPromiseController<void>();
-export const beforePreInit = createPromiseController<void>();
-export const afterPreInit = createPromiseController<void>();
-export const afterPreRun = createPromiseController<void>();
-export const beforeOnRuntimeInitialized = createPromiseController<void>();
-export const afterOnRuntimeInitialized = createPromiseController<void>();
-export const afterPostRun = createPromiseController<void>();
+
// default size if MonoConfig.pthreadPoolSize is undefined
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) {
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.
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)];
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);
+ };
}
}
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;
successCallback: InstantiateWasmSuccessCallback
): Promise<void> {
// 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.
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.
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");
})();
}
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;
}
}
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
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();
}
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();
}
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();
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)
}
// 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)
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");
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");
}
// 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
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");
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);
const mark = startMeasure();
if (debugLevel == undefined) {
debugLevel = 0;
- if (config && config.debugLevel) {
+ if (runtimeHelpers.config.debugLevel) {
debugLevel = 0 + debugLevel;
}
}
} catch (err: any) {
_print_error("MONO_WASM: mono_wasm_load_runtime () failed", err);
- abort_startup(err, false);
+ loaderHelpers.abort_startup(err, false);
}
}
}
}
-/**
- * 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<void> {
- 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 = <any>{ 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
/// 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<void> {
- 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)
// these are the only events which are called on worker
module.preInit = [() => preInitWorkerAsync()];
module.instantiateWasm = instantiateWasmWorker;
- await afterPreInit.promise;
+ await runtimeHelpers.afterPreInit.promise;
}
// 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";
--- /dev/null
+// 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
+}
export default constant;
}
-declare function createEmscripten(module: any): Promise<void>;
+// 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;
// 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
-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
/**
* application environment
*/
- applicationEnvironment?: string
+ applicationEnvironment?: string,
+ /**
+ * query string to be used for asset loading
+ */
+ assetUniqueQuery?: string,
};
export interface ResourceRequest {
| "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 =
// 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"
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<MonoConfig>,
+ allDownloadsQueued: PromiseAndController<void>,
+ wasmDownloadPromise: PromiseAndController<AssetEntryInternal>,
+ runtimeModuleLoaded: PromiseAndController<void>,
+
+ abort_startup: (reason: any, should_exit: boolean) => void,
+ mono_exit: (exit_code: number, reason?: any) => void,
+ createPromiseController: <T>(afterResolve?: () => void, afterReject?: () => void) => PromiseAndController<T>,
+ getPromiseController: <T>(promise: ControllablePromise<T>) => PromiseController<T>,
+ assertIsControllablePromise: <T>(promise: Promise<T>) => asserts promise is ControllablePromise<T>,
+ mono_download_assets: () => Promise<void>,
+ resolve_asset_path: (behavior: AssetBehaviours) => AssetEntryInternal,
+ setup_proxy_console: (id: string, console: Console, origin: string) => void
+ fetch_like: (url: string, init?: RequestInit) => Promise<Response>;
+ 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;
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<Response>;
- scriptDirectory: string
- requirePromise: Promise<Function>
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<void>,
+ dotnetReady: PromiseAndController<any>,
+ memorySnapshotSkippedOrDone: PromiseAndController<void>,
+ afterInstantiateWasm: PromiseAndController<void>,
+ beforePreInit: PromiseAndController<void>,
+ afterPreInit: PromiseAndController<void>,
+ afterPreRun: PromiseAndController<void>,
+ beforeOnRuntimeInitialized: PromiseAndController<void>,
+ afterOnRuntimeInitialized: PromiseAndController<void>,
+ afterPostRun: PromiseAndController<void>,
+
+ //core
+ stringify_as_error_with_stack?: (error: any) => string,
+ instantiate_asset: (asset: AssetEntry, url: string, bytes: Uint8Array) => void,
+ instantiate_symbols_asset: (pendingAsset: AssetEntryInternal) => Promise<void>,
+ jiterpreter_dump_stats?: (x: boolean) => string,
}
export type AOTProfilerOptions = {
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<Response>;
- fs?: {
- promises?: {
- readFile?: (path: string) => Promise<string | Buffer>,
- }
- 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,
}
export type EmscriptenInternals = {
- isWorker: boolean,
- isShell: boolean,
isPThread: boolean,
disableLegacyJsInterop: boolean,
quit_: Function,
ExitStatus: ExitStatusError,
- requirePromise: Promise<Function>
};
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<Function>,
updateMemoryViews: Function,
pthreadReplacements: PThreadReplacements | undefined | null
scriptDirectory: string;
- scriptUrl: string
noExitRuntime?: boolean;
}
export interface ExitStatusError {
__locateFile?: (path: string, prefix?: string) => string;
locateFile?: (path: string, prefix?: string) => string;
mainScriptUrlOrBlob?: string;
+ ENVIRONMENT_IS_PTHREAD?: boolean;
wasmModule: WebAssembly.Instance | null;
ready: Promise<unknown>;
asm: { memory?: WebAssembly.Memory };
addRunDependency(id: string): void;
onConfigLoaded?: (config: MonoConfig, api: RuntimeAPI) => void | Promise<void>;
}
+
+/// 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<T = any> {
+ isDone: boolean;
+ readonly promise: Promise<T>;
+ resolve: (value: T | PromiseLike<T>) => void;
+ reject: (reason?: any) => void;
+}
+
+
+/// A Promise<T> with a controller attached
+export interface ControllablePromise<T = any> extends Promise<T> {
+ __brand: "ControllablePromise"
+}
+
+/// Just a pair of a promise and its controller
+export interface PromiseAndController<T> {
+ promise: ControllablePromise<T>;
+ promise_control: PromiseController<T>;
+}
+
+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<void>
+
+
+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
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");
## 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.
return 0;
-static void ShowUsage() => Console.WriteLine($"Usage: symbolicator <path/to/dotnet.js.symbols> [</path/to/patterns-file>] [-|<file-with-traces>]");
+static void ShowUsage() => Console.WriteLine($"Usage: symbolicator <path/to/dotnet.native.js.symbols> [</path/to/patterns-file>] [-|<file-with-traces>]");
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
</ItemGroup>
<Copy SourceFiles="$(NativeBinDir)dotnet.js;
+ $(NativeBinDir)dotnet.runtime.js;
+ $(NativeBinDir)dotnet.native.js;
$(NativeBinDir)dotnet.d.ts;
$(NativeBinDir)dotnet-legacy.d.ts;
$(NativeBinDir)package.json;
- $(NativeBinDir)dotnet.wasm"
+ $(NativeBinDir)dotnet.native.wasm"
DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
SkipUnchangedFiles="true" />
- <Copy SourceFiles="$(NativeBinDir)dotnet.worker.js"
+ <Copy SourceFiles="$(NativeBinDir)dotnet.native.worker.js"
DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
- Condition="Exists('$(NativeBinDir)dotnet.worker.js')"
+ Condition="Exists('$(NativeBinDir)dotnet.native.worker.js')"
SkipUnchangedFiles="true" />
- <Copy SourceFiles="$(NativeBinDir)dotnet.js.symbols"
+ <Copy SourceFiles="$(NativeBinDir)dotnet.native.js.symbols"
DestinationFolder="$(MicrosoftNetCoreAppRuntimePackNativeDir)"
SkipUnchangedFiles="true" />
"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,
".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
}
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";
{
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))
{
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;
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)
{
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;
}
}
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<ITaskItem> ProcessSymbolAssets(
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";
}
UseSimpleDictionaryFormat = true
});
- result.extensions = new Dictionary<string, Dictionary<string, object>> ();
+ result.extensions = new Dictionary<string, Dictionary<string, object>>();
foreach (var configExtension in Extensions)
{
var key = configExtension.GetMetadata("key");
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") { }
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)));
}
[Required]
public string[] Assemblies { get; set; } = Array.Empty<string>();
- // files like dotnet.wasm, icudt.dat etc
+ // files like dotnet.native.wasm, icudt.dat etc
[NotNull]
[Required]
public ITaskItem[] NativeAssets { get; set; } = Array.Empty<ITaskItem>();