diff --git a/src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj b/src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj
index 11eac88f6dca6..9379e718d57cd 100644
--- a/src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj
+++ b/src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj
@@ -4,6 +4,9 @@
true
true
true
+ true
+ true
+ web
-s USE_CLOSURE_COMPILER=1 -s LEGACY_GL_EMULATION=1 -lGL -lSDL -lidbfs.js
diff --git a/src/mono/wasi/build/WasiApp.Native.targets b/src/mono/wasi/build/WasiApp.Native.targets
index 95cd07c61d04f..03a62b781b739 100644
--- a/src/mono/wasi/build/WasiApp.Native.targets
+++ b/src/mono/wasi/build/WasiApp.Native.targets
@@ -291,8 +291,6 @@
-
-
diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets
index d0837e1ec5569..7aa3cb71b29ca 100644
--- a/src/mono/wasm/build/WasmApp.Native.targets
+++ b/src/mono/wasm/build/WasmApp.Native.targets
@@ -170,7 +170,6 @@
<_WasmDevel Condition="'$(_WasmDevel)' == '' and '$(WasmBuildNative)' == 'true' and '$(Configuration)' == 'Debug'">true
- <_EmccAssertionLevelDefault Condition="'$(_EmccAssertionLevelDefault)' == ''">0
<_EmccOptimizationFlagDefault Condition="'$(_WasmDevel)' == 'true'">-O0
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(Configuration)' == 'Debug' and '$(WasmBuildingForNestedPublish)' != 'true'">-O1
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == ''">-Oz
@@ -209,7 +208,6 @@
<_EmccCFlags Include="$(EmccCompileOptimizationFlag)" />
- <_EmccCFlags Include="-s ASSERTIONS=$(_EmccAssertionLevelDefault)" Condition="'$(_WasmDevel)' == 'true'" />
<_EmccCFlags Include="@(_EmccCommonFlags)" />
<_EmccCFlags Include="-DDISABLE_PERFTRACING_LISTEN_PORTS=1" />
@@ -227,7 +225,6 @@
<_EmccLDFlags Include="$(EmccLinkOptimizationFlag)" />
- <_EmccLDFlags Include="-s ASSERTIONS=$(_EmccAssertionLevelDefault)" Condition="'$(_WasmDevel)' == 'true'" />
<_EmccLDFlags Include="@(_EmccCommonFlags)" />
<_DriverCDependencies Include="$(_WasmPInvokeHPath);$(_WasmICallTablePath)" />
@@ -416,14 +413,18 @@
<_WasmEHLib Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-js.a
<_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' == 'true'">libmono-wasm-eh-js.a
<_WasmEHLibToExclude Condition="'$(WasmEnableExceptionHandling)' != 'true'">libmono-wasm-eh-wasm.a
+ <_EmccExportedLibraryFunction>"[@(EmccExportedLibraryFunction -> '%27%(Identity)%27', ',')]"
<_EmccExportedRuntimeMethods>"[@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]"
<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')
+
<_EmccLDSFlags Include="-s INITIAL_MEMORY=$(EmccInitialHeapSize)" />
<_EmccLDSFlags Include="-s STACK_SIZE=$(EmccStackSize)" />
<_EmccLDSFlags Include="-s WASM_BIGINT=1" />
+ <_EmccLDSFlags Condition="'$(EmccEnvironment)' != ''" Include="-s ENVIRONMENT="$(EmccEnvironment)"" />
+ <_EmccLDSFlags Condition="'$(EmccEnableAssertions)' == 'true'" Include="-s ASSERTIONS=1" />
<_WasmNativeFileForLinking Include="%(_BitcodeFile.ObjectFile)" />
<_WasmNativeFileForLinking Include="%(_WasmSourceFileToCompile.ObjectFile)" />
@@ -449,6 +450,7 @@
<_EmccLinkStepArgs Include="-o "$(_WasmIntermediateOutputPath)dotnet.js"" />
<_WasmLinkDependencies Include="$(_EmccLinkRsp)" />
+ <_EmccLinkStepArgs Include="-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$(_EmccExportedLibraryFunction)" Condition="'$(_EmccExportedLibraryFunction)' != ''" />
<_EmccLinkStepArgs Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" />
<_EmccLinkStepArgs Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" />
diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets
index b5ab71e762566..796a22378de0a 100644
--- a/src/mono/wasm/build/WasmApp.targets
+++ b/src/mono/wasm/build/WasmApp.targets
@@ -49,6 +49,8 @@
- $(EmccFlags) - Emcc flags used for both compiling native files, and linking
- $(EmccExtraLDFlags) - Extra emcc flags for linking
- $(EmccExtraCFlags) - Extra emcc flags for compiling native files
+ - $(EmccEnableAssertions) - Corresponds to `ASSERTIONS` arg for emcc. Default false.
+ - $(EmccEnvironment) - Corresponds to `ENVIRONMENT` arg for emcc. Default is `web,webview,worker,node,shell`.
- $(EmccInitialHeapSize) - Initial heap size specified with `emcc`. Default value: 16777216 or size of the DLLs, whichever is larger.
Corresponds to `-s INITIAL_MEMORY=...` emcc arg.
(previously named EmccTotalMemory, which is still kept as an alias)
@@ -90,6 +92,7 @@
- @(EmccExportedRuntimeMethod) - Extra method for emcc flag EXPORTED_RUNTIME_METHODS
+ - @(EmccExportedLibraryFunction) - Extra method for emcc flag DEFAULT_LIBRARY_FUNCS_TO_INCLUDE
- @(EmccExportedFunction) - Extra function for emcc flag EXPORTED_FUNCTIONS
-->
@@ -341,7 +344,6 @@
Condition="'$(WasmEmitSymbolMap)' == 'true' and
'$(_HasDotnetJsSymbols)' != 'true' and
Exists('$(MicrosoftNetCoreAppRuntimePackRidNativeDir)dotnet.js.symbols')" />
-
diff --git a/src/mono/wasm/runtime/assets.ts b/src/mono/wasm/runtime/assets.ts
index 2852e1f4d463b..b829f03bd32d9 100644
--- a/src/mono/wasm/runtime/assets.ts
+++ b/src/mono/wasm/runtime/assets.ts
@@ -4,6 +4,7 @@
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 "./imports";
+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";
@@ -36,6 +37,7 @@ const skipBufferByAssetTypes: {
[k: string]: boolean
} = {
"dotnetwasm": true,
+ "symbols": true,
};
const containedInSnapshotByAssetTypes: {
@@ -57,6 +59,7 @@ const skipInstantiateByAssetTypes: {
} = {
"js-module-threads": true,
"dotnetwasm": true,
+ "symbols": true,
};
export function shouldLoadIcuAsset(asset: AssetEntryInternal): boolean {
@@ -119,9 +122,7 @@ export async function mono_download_assets(): Promise {
countAndStartDownload(asset);
} else {
// Otherwise cleanup in case we were given pending download. It would be even better if we could abort the download.
- asset.pendingDownloadInternal = null as any; // GC
- asset.pendingDownload = null as any; // GC
- asset.buffer = null as any; // GC
+ cleanupAsset(asset);
// tell the debugger it is loaded
if (asset.behavior == "resource" || asset.behavior == "assembly" || asset.behavior == "pdb") {
const url = resolve_path(asset, "");
@@ -144,15 +145,17 @@ export async function mono_download_assets(): Promise {
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!);
- asset.pendingDownloadInternal = null as any; // GC
- asset.pendingDownload = null as any; // GC
- asset.buffer = null as any; // GC
+ 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) {
@@ -415,6 +418,7 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) {
switch (asset.behavior) {
case "dotnetwasm":
case "js-module-threads":
+ case "symbols":
// do nothing
break;
case "resource":
@@ -516,6 +520,18 @@ export async function instantiate_wasm_asset(
successCallback(compiledInstance, compiledModule);
}
+export async function instantiate_symbols_asset(
+ pendingAsset: AssetEntryInternal,
+): Promise {
+ try {
+ const response = await pendingAsset.pendingDownloadInternal!.response;
+ const text = await response.text();
+ parseSymbolMapFile(text);
+ } catch (error: any) {
+ console.log(`MONO_WASM: Error loading symbol file ${pendingAsset.name}: ${JSON.stringify(error)}`);
+ }
+}
+
// used from Blazor
export function mono_wasm_load_data_archive(data: Uint8Array, prefix: string): boolean {
if (data.length < 8)
@@ -580,3 +596,10 @@ export async function wait_for_all_assets() {
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
+}
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts
index d80c3a4fb72c5..f31503173e710 100644
--- a/src/mono/wasm/runtime/dotnet.d.ts
+++ b/src/mono/wasm/runtime/dotnet.d.ts
@@ -59,7 +59,6 @@ declare interface EmscriptenModule {
UTF8ArrayToString(u8Array: Uint8Array, idx?: number, maxBytesToRead?: number): string;
FS_createPath(parent: string, path: string, canRead?: boolean, canWrite?: boolean): string;
FS_createDataFile(parent: string, name: string, data: TypedArray, canRead: boolean, canWrite: boolean, canOwn?: boolean): string;
- FS_readFile(filename: string, opts: any): any;
addFunction(fn: Function, signature: string): number;
stackSave(): VoidPtr;
stackRestore(stack: VoidPtr): void;
@@ -178,7 +177,7 @@ interface AssetEntry extends ResourceRequest {
*/
pendingDownload?: LoadingResource;
}
-type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-threads";
+type AssetBehaviours = "resource" | "assembly" | "pdb" | "heap" | "icu" | "vfs" | "dotnetwasm" | "js-module-threads" | "symbols";
type GlobalizationMode = "icu" | // load ICU globalization data from any runtime assets with behavior "icu".
"invariant" | // operate in invariant globalization mode.
"auto";
diff --git a/src/mono/wasm/runtime/jiterpreter-jit-call.ts b/src/mono/wasm/runtime/jiterpreter-jit-call.ts
index e84fc620da4ff..8cc2d23d45c74 100644
--- a/src/mono/wasm/runtime/jiterpreter-jit-call.ts
+++ b/src/mono/wasm/runtime/jiterpreter-jit-call.ts
@@ -156,6 +156,9 @@ class TrampolineInfo {
}
}
+// this is cached replacements for Module.getWasmTableEntry();
+// we could add and
+// if we need to export the original
function getWasmTableEntry (index: number) {
let result = fnCache[index];
if (!result) {
@@ -172,8 +175,6 @@ function getWasmTableEntry (index: number) {
export function mono_interp_invoke_wasm_jit_call_trampoline (
thunkIndex: number, ret_sp: number, sp: number, ftndesc: number, thrown: NativePointer
) {
- // FIXME: It's impossible to get emscripten to export this for some reason
- // const thunk = Module.getWasmTableEntry(thunkIndex);
const thunk = getWasmTableEntry(thunkIndex);
try {
thunk(ret_sp, sp, ftndesc, thrown);
diff --git a/src/mono/wasm/runtime/logging.ts b/src/mono/wasm/runtime/logging.ts
index fb8cb01f52975..a4420b01f57f5 100644
--- a/src/mono/wasm/runtime/logging.ts
+++ b/src/mono/wasm/runtime/logging.ts
@@ -1,11 +1,10 @@
// 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 { INTERNAL, Module, runtimeHelpers } from "./imports";
import { CharPtr, VoidPtr } from "./types/emscripten";
-const wasm_func_map = new Map();
+export const wasm_func_map = new Map();
const regexes: any[] = [];
// V8
@@ -183,31 +182,15 @@ export function setup_proxy_console(id: string, console: Console, origin: string
anyConsole[m] = proxyConsoleMethod(`console.${m}`, send, true);
}
-export function readSymbolMapFile(filename: string): void {
- if (runtimeHelpers.mono_wasm_symbols_are_ready) return;
- runtimeHelpers.mono_wasm_symbols_are_ready = true;
- try {
- const res = Module.FS_readFile(filename, { flags: "r", encoding: "utf8" });
- res.split(/[\r\n]/).forEach((line: string) => {
- const parts: string[] = line.split(/:/);
- if (parts.length < 2)
- return;
-
- parts[1] = parts.splice(1).join(":");
- wasm_func_map.set(Number(parts[0]), parts[1]);
- });
- if (BuildConfiguration === "Debug") {
- console.debug(`MONO_WASM: Loaded ${wasm_func_map.size} symbols`);
- }
- } catch (error: any) {
- if (error.errno == 44) {// NOENT
- if (BuildConfiguration === "Debug") {
- console.debug(`MONO_WASM: Could not find symbols file ${filename}. Ignoring.`);
- }
- }
- else {
- console.log(`MONO_WASM: Error loading symbol file ${filename}: ${JSON.stringify(error)}`);
- }
- return;
- }
-}
+export function parseSymbolMapFile(text: string) {
+ text.split(/[\r\n]/).forEach((line: string) => {
+ const parts: string[] = line.split(/:/);
+ if (parts.length < 2)
+ return;
+
+ parts[1] = parts.splice(1).join(":");
+ wasm_func_map.set(Number(parts[0]), parts[1]);
+ });
+
+ if (runtimeHelpers.diagnosticTracing) console.debug(`MONO_WASM: Loaded ${wasm_func_map.size} symbols`);
+}
\ No newline at end of file
diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts
index 970a8408f3eea..fc795d9437137 100644
--- a/src/mono/wasm/runtime/startup.ts
+++ b/src/mono/wasm/runtime/startup.ts
@@ -21,7 +21,6 @@ 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 { readSymbolMapFile } from "./logging";
import { mono_wasm_init_diagnostics } from "./diagnostics";
import { preAllocatePThreadWorkerPool, instantiateWasmPThreadWorkerPool } from "./pthreads/browser";
import { export_linker } from "./exports-linker";
@@ -267,7 +266,6 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) {
bindings_init();
if (!runtimeHelpers.mono_wasm_runtime_is_ready) mono_wasm_runtime_ready();
- if (!runtimeHelpers.mono_wasm_symbols_are_ready) readSymbolMapFile("dotnet.js.symbols");
setTimeout(() => {
// when there are free CPU cycles
diff --git a/src/mono/wasm/runtime/types.ts b/src/mono/wasm/runtime/types.ts
index cd8b63dbe9ff0..a1be576921549 100644
--- a/src/mono/wasm/runtime/types.ts
+++ b/src/mono/wasm/runtime/types.ts
@@ -206,6 +206,7 @@ export type AssetBehaviours =
| "vfs" // load asset into the virtual filesystem (for fopen, File.Open, etc)
| "dotnetwasm" // the binary of the dotnet runtime
| "js-module-threads" // the javascript module for threads
+ | "symbols" // the symbols for the wasm native code
export type RuntimeHelpers = {
runtime_interop_module: MonoAssembly;
@@ -216,7 +217,6 @@ export type RuntimeHelpers = {
_i52_error_scratch_buffer: Int32Ptr;
mono_wasm_runtime_is_ready: boolean;
mono_wasm_bindings_is_ready: boolean;
- mono_wasm_symbols_are_ready: boolean;
loaded_files: string[];
maxParallelDownloads: number;
diff --git a/src/mono/wasm/runtime/types/emscripten.ts b/src/mono/wasm/runtime/types/emscripten.ts
index cc8ac6462125e..7c508458a3e1e 100644
--- a/src/mono/wasm/runtime/types/emscripten.ts
+++ b/src/mono/wasm/runtime/types/emscripten.ts
@@ -50,7 +50,6 @@ export declare interface EmscriptenModule {
UTF8ArrayToString(u8Array: Uint8Array, idx?: number, maxBytesToRead?: number): string;
FS_createPath(parent: string, path: string, canRead?: boolean, canWrite?: boolean): string;
FS_createDataFile(parent: string, name: string, data: TypedArray, canRead: boolean, canWrite: boolean, canOwn?: boolean): string;
- FS_readFile(filename: string, opts: any): any;
addFunction(fn: Function, signature: string): number;
stackSave(): VoidPtr;
stackRestore(stack: VoidPtr): void;
diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj
index 76cab4d84ce84..9755e405afed4 100644
--- a/src/mono/wasm/wasm.proj
+++ b/src/mono/wasm/wasm.proj
@@ -197,9 +197,7 @@
-
-
@@ -272,6 +270,7 @@
+ <_EmccExportedLibraryFunction>"[@(EmccExportedLibraryFunction -> '%27%(Identity)%27', ',')]"
<_EmccExportedRuntimeMethods>"[@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]"
<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')
16777216
@@ -290,6 +289,7 @@
<_EmccLinkFlags Include="-s ALLOW_TABLE_GROWTH=1" />
<_EmccLinkFlags Include="-s NO_EXIT_RUNTIME=1" />
<_EmccLinkFlags Include="-s FORCE_FILESYSTEM=1" />
+ <_EmccLinkFlags Condition="'$(_EmccExportedLibraryFunction)' != ''" Include="-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$(_EmccExportedLibraryFunction)" />
<_EmccLinkFlags Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" />
<_EmccLinkFlags Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" />
<_EmccLinkFlags Include="--source-map-base http://example.com" />
@@ -375,7 +375,7 @@
-g -Os -s -DDEBUG=1 -DENABLE_AOT_PROFILER=1 -DENABLE_BROWSER_PROFILER=1
-Oz -DENABLE_BROWSER_PROFILER=1
- $(CMakeConfigurationEmccFlags)
+ $(CMakeConfigurationEmccFlags) -s ASSERTIONS=1
-O2
$(CMakeConfigurationLinkFlags) -s EXPORT_ES6=1
diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
index c74b5816a26bf..7d9b47cc1ad33 100644
--- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
+++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs
@@ -116,6 +116,11 @@ public IcuData(string name, string hash) : base(name, hash, "icu") {}
public bool LoadRemote { get; set; }
}
+ private sealed class SymbolsData : AssetEntry
+ {
+ public SymbolsData(string name, string hash) : base(name, hash, "symbols") {}
+ }
+
protected override bool ValidateArguments()
{
if (!base.ValidateArguments())
@@ -198,6 +203,10 @@ protected override bool ExecuteInternal()
{
config.Assets.Add(new ThreadsWorkerEntry (name, Utils.ComputeIntegrity(item.ItemSpec)));
}
+ else if(name == "dotnet.js.symbols")
+ {
+ config.Assets.Add(new SymbolsData(name, Utils.ComputeIntegrity(item.ItemSpec)));
+ }
}
string packageJsonPath = Path.Combine(AppDir, "package.json");