Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions eng/native.wasm.targets
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,46 @@
<EmccExportedFunction Include="___coreclr_wasm_rtlrestorecontext_tag" />
<EmccExportedFunction Include="___async_continuation" />
</ItemGroup>

<!-- Emscripten's default INCOMING_MODULE_JS_API, kept explicit so a Module property we don't declare aborts a debug build early. -->
<ItemGroup>
<_EmccIncomingModuleJSAPI Include="ENVIRONMENT" />
<_EmccIncomingModuleJSAPI Include="arguments" />
<_EmccIncomingModuleJSAPI Include="canvas" />
<_EmccIncomingModuleJSAPI Include="dynamicLibraries" />
<_EmccIncomingModuleJSAPI Include="elementPointerLock" />
<_EmccIncomingModuleJSAPI Include="instantiateWasm" />
<_EmccIncomingModuleJSAPI Include="locateFile" />
<_EmccIncomingModuleJSAPI Include="monitorRunDependencies" />
<_EmccIncomingModuleJSAPI Include="noExitRuntime" />
<_EmccIncomingModuleJSAPI Include="noInitialRun" />
<_EmccIncomingModuleJSAPI Include="onAbort" />
<_EmccIncomingModuleJSAPI Include="onExit" />
<_EmccIncomingModuleJSAPI Include="onRuntimeInitialized" />
<_EmccIncomingModuleJSAPI Include="postRun" />
<_EmccIncomingModuleJSAPI Include="preInit" />
<_EmccIncomingModuleJSAPI Include="preRun" />
<_EmccIncomingModuleJSAPI Include="print" />
<_EmccIncomingModuleJSAPI Include="printErr" />
<_EmccIncomingModuleJSAPI Include="setStatus" />
<_EmccIncomingModuleJSAPI Include="statusMessage" />
<_EmccIncomingModuleJSAPI Include="stderr" />
<_EmccIncomingModuleJSAPI Include="stdin" />
<_EmccIncomingModuleJSAPI Include="stdout" />
<_EmccIncomingModuleJSAPI Include="thisProgram" />
<_EmccIncomingModuleJSAPI Include="wasm" />
<_EmccIncomingModuleJSAPI Include="websocket" />
</ItemGroup>
<PropertyGroup>
<_EmccExportedRuntimeMethods>@(EmccExportedRuntimeMethod -> '%(Identity)',',')</_EmccExportedRuntimeMethods>
<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')</_EmccExportedFunctions>
<_EmccIncomingModuleJSAPIs>@(_EmccIncomingModuleJSAPI -> '%(Identity)',',')</_EmccIncomingModuleJSAPIs>
</PropertyGroup>

<ItemGroup>
<NativeCMakeArg Condition="'$(TargetsBrowser)' == 'true'" Include="-cmakeargs &quot;-DCMAKE_EMCC_EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)&quot;" />
<NativeCMakeArg Condition="'$(TargetsBrowser)' == 'true'" Include="-cmakeargs &quot;-DCMAKE_EMCC_EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)&quot;" />
<NativeCMakeArg Condition="'$(TargetsBrowser)' == 'true'" Include="-cmakeargs &quot;-DCMAKE_EMCC_INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPIs)&quot;" />
</ItemGroup>

</Target>
Expand Down
37 changes: 37 additions & 0 deletions src/mono/browser/browser.proj
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,43 @@
<ItemGroup Condition="'$(WasmEnableThreads)' == 'true'">
<EmccExportedFunction Include="_emscripten_main_runtime_thread_id" />
</ItemGroup>
<!-- Emscripten's default INCOMING_MODULE_JS_API, kept explicit so a Module property we don't declare aborts a debug build early. -->
<ItemGroup>
<_EmccIncomingModuleJSAPI Include="ENVIRONMENT" />
<_EmccIncomingModuleJSAPI Include="arguments" />
<_EmccIncomingModuleJSAPI Include="canvas" />
<_EmccIncomingModuleJSAPI Include="dynamicLibraries" />
<_EmccIncomingModuleJSAPI Include="elementPointerLock" />
<_EmccIncomingModuleJSAPI Include="instantiateWasm" />
<_EmccIncomingModuleJSAPI Include="locateFile" />
<_EmccIncomingModuleJSAPI Include="monitorRunDependencies" />
<_EmccIncomingModuleJSAPI Include="noExitRuntime" />
<_EmccIncomingModuleJSAPI Include="noInitialRun" />
<_EmccIncomingModuleJSAPI Include="onAbort" />
<_EmccIncomingModuleJSAPI Include="onExit" />
<_EmccIncomingModuleJSAPI Include="onRuntimeInitialized" />
<_EmccIncomingModuleJSAPI Include="postRun" />
<_EmccIncomingModuleJSAPI Include="preInit" />
<_EmccIncomingModuleJSAPI Include="preRun" />
<_EmccIncomingModuleJSAPI Include="print" />
<_EmccIncomingModuleJSAPI Include="printErr" />
<_EmccIncomingModuleJSAPI Include="setStatus" />
<_EmccIncomingModuleJSAPI Include="statusMessage" />
<_EmccIncomingModuleJSAPI Include="stderr" />
<_EmccIncomingModuleJSAPI Include="stdin" />
<_EmccIncomingModuleJSAPI Include="stdout" />
<_EmccIncomingModuleJSAPI Include="thisProgram" />
<_EmccIncomingModuleJSAPI Include="wasm" />
<_EmccIncomingModuleJSAPI Include="websocket" />
</ItemGroup>
<ItemGroup Condition="'$(WasmEnableThreads)' == 'true'">
<!-- not an emscripten default; set on the worker from the message which starts a pthread -->
<_EmccIncomingModuleJSAPI Include="wasmMemory" />
</ItemGroup>
<PropertyGroup>
<_EmccExportedLibraryFunction>"[@(EmccExportedLibraryFunction -> '%27%(Identity)%27', ',')]"</_EmccExportedLibraryFunction>
<_EmccExportedRuntimeMethods>"[@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]"</_EmccExportedRuntimeMethods>
<_EmccIncomingModuleJSAPIs>"[@(_EmccIncomingModuleJSAPI -> '%27%(Identity)%27', ',')]"</_EmccIncomingModuleJSAPIs>
<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')</_EmccExportedFunctions>
<!-- reserve at least enough space to complete initializing sgen without growing the heap -->
<EmccInitialHeapSize>33554432</EmccInitialHeapSize>
Expand All @@ -232,6 +266,8 @@
<_EmccLinkFlags Include="-s FORCE_FILESYSTEM=1" />
<_EmccLinkFlags Condition="'$(_EmccExportedLibraryFunction)' != ''" Include="-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$(_EmccExportedLibraryFunction)" />
<_EmccLinkFlags Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" />
<!-- INCOMING_MODULE_JS_API only matters with emscripten assertions (Debug); in Release let emscripten use its default list. -->
<_EmccLinkFlags Condition="'$(Configuration)' == 'Debug'" Include="-s INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPIs)" />
<_EmccLinkFlags Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" />
<_EmccLinkFlags Include="--source-map-base http://example.com" />
<_EmccLinkFlags Include="-s WASM_BIGINT=1" />
Expand Down Expand Up @@ -271,6 +307,7 @@
"WasmOptConfigurationFlags": [@(WasmOptConfigurationFlags -> '%22%(Identity)%22', ',')],
"EmccDefaultExportedFunctions": [@(EmccExportedFunction -> '%22%(Identity)%22', ',')],
"EmccDefaultExportedRuntimeMethods": [@(EmccExportedRuntimeMethod -> '%22%(Identity)%22', ',')],
"EmccDefaultIncomingModuleJSAPI": [@(_EmccIncomingModuleJSAPI -> '%22%(Identity)%22', ',')],
"PropertiesThatTriggerRelinking": [
{ "identity": "InvariantTimezone", "defaultValueInRuntimePack": "$(InvariantTimezone)" },
{ "identity": "InvariantGlobalization", "defaultValueInRuntimePack": "$(InvariantGlobalization)" },
Expand Down
65 changes: 9 additions & 56 deletions src/mono/browser/build/BrowserWasmApp.CoreCLR.targets
Original file line number Diff line number Diff line change
Expand Up @@ -112,65 +112,15 @@
TaskFactory="TaskHostFactory"
Condition="'$(WasmAppBuilderTasksAssemblyPath)' != ''" />

<!-- Fallback exported runtime methods and functions for the emcc link step.
Used when the workload path is active and native.wasm.targets is not available.
TODO-WASM https://github.com/dotnet/runtime/issues/126100#issuecomment-4925516500: Keep this list in sync with eng/native.wasm.targets.
When building in-tree, native.wasm.targets is imported AFTER this target (below)
and its GenerateEmccExports definition wins (MSBuild last-definition-wins). -->
<Target Name="GenerateEmccExports"
Condition="'$(TargetsBrowser)' == 'true'">
<ItemGroup>
<EmccExportedRuntimeMethod Include="FS" />
<EmccExportedRuntimeMethod Include="HEAP8" />
<EmccExportedRuntimeMethod Include="HEAP16" />
<EmccExportedRuntimeMethod Include="HEAPU8" />
<EmccExportedRuntimeMethod Include="HEAPU16" />
<EmccExportedRuntimeMethod Include="HEAP32" />
<EmccExportedRuntimeMethod Include="HEAPU32" />
<EmccExportedRuntimeMethod Include="HEAPF32" />
<EmccExportedRuntimeMethod Include="HEAPF64" />
<EmccExportedRuntimeMethod Include="HEAP64" />
<EmccExportedRuntimeMethod Include="HEAPU64" />
<EmccExportedRuntimeMethod Include="out" />
<EmccExportedRuntimeMethod Include="err" />
<EmccExportedRuntimeMethod Include="ccall" />
<EmccExportedRuntimeMethod Include="cwrap" />
<EmccExportedRuntimeMethod Include="setValue" />
<EmccExportedRuntimeMethod Include="getValue" />
<EmccExportedRuntimeMethod Include="UTF8ToString" />
<EmccExportedRuntimeMethod Include="UTF8ArrayToString" />
<EmccExportedRuntimeMethod Include="lengthBytesUTF8" />
<EmccExportedRuntimeMethod Include="stringToUTF8Array" />
<EmccExportedRuntimeMethod Include="safeSetTimeout" />
<EmccExportedRuntimeMethod Include="runtimeKeepalivePush" />
<EmccExportedRuntimeMethod Include="runtimeKeepalivePop" />
<EmccExportedRuntimeMethod Include="abort" />

<EmccExportedFunction Include="_free" />
<EmccExportedFunction Include="_htons" />
<EmccExportedFunction Include="_malloc" />
<EmccExportedFunction Include="_sbrk" />
<EmccExportedFunction Include="_memalign" />
<EmccExportedFunction Include="_posix_memalign" />
<EmccExportedFunction Include="_memset" />
<EmccExportedFunction Include="_ntohs" />
<EmccExportedFunction Include="stackAlloc" />
<EmccExportedFunction Include="stackRestore" />
<EmccExportedFunction Include="stackSave" />
<EmccExportedFunction Include="___stack_pointer" />
<EmccExportedFunction Include="___coreclr_wasm_rtlrestorecontext_tag" />
<EmccExportedFunction Include="___async_continuation" />
</ItemGroup>
</Target>

<!-- Import shared native.wasm.targets for Emscripten SDK, ICU, exported functions/methods.
Only available in-tree (RepositoryEngineeringDir is set by the build system).
When present its GenerateEmccExports target overrides the fallback above
(MSBuild last-definition-wins), so the in-tree list is always authoritative. -->
<!-- Import shared native.wasm.targets, which defines GenerateEmccExports (exported functions/methods
and the INCOMING_MODULE_JS_API allowlist) plus the Emscripten SDK, ICU, and the relink registry.
In-tree it is imported from the engineering dir below; in the workload it ships next to this file
in the Sdk pack (Microsoft.NET.Runtime.WebAssembly.Sdk.pkgproj). Exactly one of the two imports
fires, so GenerateEmccExports is always defined without a duplicated copy in this file. -->
<Import Project="$(RepositoryEngineeringDir)native.wasm.targets"
Condition="'$(RepositoryEngineeringDir)' != '' and Exists('$(RepositoryEngineeringDir)native.wasm.targets')" />

<!-- Import the static runtime-pack settings and relink registry. -->
<!-- In the workload/pack layout native.wasm.targets sits next to this file; in-tree this path does not exist. -->
<Import Project="$(MSBuildThisFileDirectory)native.wasm.targets"
Condition="Exists('$(MSBuildThisFileDirectory)native.wasm.targets')" />

Expand Down Expand Up @@ -856,6 +806,7 @@

<PropertyGroup>
<_EmccExportedRuntimeMethods>"[BROWSER_HOST,@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]"</_EmccExportedRuntimeMethods>
<_EmccIncomingModuleJSAPIs>"[@(_EmccIncomingModuleJSAPI -> '%27%(Identity)%27', ',')]"</_EmccIncomingModuleJSAPIs>
<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')</_EmccExportedFunctions>
</PropertyGroup>

Expand Down Expand Up @@ -935,6 +886,8 @@

<!-- Exported functions and runtime methods -->
<_EmccLinkStepArgs Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" />
<!-- INCOMING_MODULE_JS_API only matters with emscripten assertions (Debug); in Release let emscripten use its default list. -->
<_EmccLinkStepArgs Condition="'$(Configuration)' == 'Debug'" Include="-s INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPIs)" />
<_EmccLinkStepArgs Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" />

<!-- JS library files -->
Expand Down
5 changes: 5 additions & 0 deletions src/mono/browser/build/BrowserWasmApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@
<Target Name="_BrowserWasmWriteRspForLinking" BeforeTargets="_WasmWriteRspForLinking">
<ItemGroup>
<EmccExportedRuntimeMethod Include="PThread" Condition="'$(WasmEnableThreads)' == 'true'" />
<!-- _EmccIncomingModuleJSAPI defaults (incl. wasmMemory when threads are enabled) come from wasm-props.json
via _ReadWasmProps, written by src/mono/browser/browser.proj. -->
</ItemGroup>
<PropertyGroup>
<_WasmEHLib Condition="'$(WasmEnableExceptionHandling)' == 'true'">libmono-wasm-eh-wasm.a</_WasmEHLib>
Expand All @@ -325,6 +327,7 @@
<_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-nosimd.a</_WasmSIMDLibToExclude>
<_EmccExportedLibraryFunction>"[@(EmccExportedLibraryFunction -> '%27%(Identity)%27', ',')]"</_EmccExportedLibraryFunction>
<_EmccExportedRuntimeMethods>"[@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]"</_EmccExportedRuntimeMethods>
<_EmccIncomingModuleJSAPIs>"[@(_EmccIncomingModuleJSAPI -> '%27%(Identity)%27', ',')]"</_EmccIncomingModuleJSAPIs>
<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')</_EmccExportedFunctions>
</PropertyGroup>

Expand Down Expand Up @@ -373,6 +376,8 @@

<_EmccLinkStepArgs Include="-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$(_EmccExportedLibraryFunction)" Condition="'$(_EmccExportedLibraryFunction)' != ''" />
<_EmccLinkStepArgs Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" />
<!-- INCOMING_MODULE_JS_API only matters with emscripten assertions (Debug); in Release let emscripten use its default list. -->
<_EmccLinkStepArgs Condition="'$(Configuration)' == 'Debug'" Include="-s INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPIs)" />
<_EmccLinkStepArgs Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" />

<_EmccLinkStepArgs Include="$(EmccExtraLDFlags)" />
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/utils/mono-threads-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize)
if (G_UNLIKELY (res != 0))
g_error ("%s: pthread_attr_destroy failed with \"%s\" (%d)", __func__, g_strerror (res), res);

g_assert (*staddr != NULL);
// emscripten links with --stack-first at -O0, which puts the stack at the start of the linear memory, so staddr can legitimately be NULL
Comment thread
pavelsavara marked this conversation as resolved.
g_assert (*stsize != (size_t)-1);
Comment thread
pavelsavara marked this conversation as resolved.
#elif defined(HOST_WASI) && !defined(DISABLE_THREADS)
// TODO: this will need changes for WASI multithreading as the stack will be allocated per thread at different addresses
Expand Down
2 changes: 2 additions & 0 deletions src/mono/wasm/build/WasmApp.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@
<WasmOptConfigurationFlags ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="false" Output="true" />
<EmccDefaultExportedFunctions ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="false" Output="true" />
<EmccDefaultExportedRuntimeMethods ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="false" Output="true" />
<EmccDefaultIncomingModuleJSAPI ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="false" Output="true" />
<PropertiesThatTriggerRelinking ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="false" Output="true" />
</ParameterGroup>
</UsingTask>
Expand All @@ -408,6 +409,7 @@
<Output TaskParameter="EmccProperties" ItemName="_EmccPropItems" />
<Output TaskParameter="EmccDefaultExportedFunctions" ItemName="EmccExportedFunction" />
<Output TaskParameter="EmccDefaultExportedRuntimeMethods" ItemName="EmccExportedRuntimeMethod" />
<Output TaskParameter="EmccDefaultIncomingModuleJSAPI" ItemName="_EmccIncomingModuleJSAPI" />

<!-- shared by browser/wasi -->
<Output TaskParameter="WasmOptConfigurationFlags" ItemName="_DefaulWasmOptConfigurationFlags" />
Expand Down
4 changes: 4 additions & 0 deletions src/native/corehost/browserhost/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG)
-sASSERTIONS=1
-sLLD_REPORT_UNDEFINED
-sERROR_ON_UNDEFINED_SYMBOLS=1
# Emscripten's default INCOMING_MODULE_JS_API, kept explicit so a Module property we don't declare
# aborts the build early. This is only meaningful with ASSERTIONS=1, so it is Debug-only. The value
# comes from GenerateEmccExports in eng/native.wasm.targets.
-sINCOMING_MODULE_JS_API=${CMAKE_EMCC_INCOMING_MODULE_JS_API}
)
endif ()

Expand Down
6 changes: 3 additions & 3 deletions src/native/libs/Common/JavaScript/types/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ export type EmscriptenModuleInternal = EmscriptenModule & DotnetModuleConfig & {
instantiateWasm?: InstantiateWasmCallBack;
onAbort?: (reason: any, extraJson?: string) => void;
onExit?: (code: number) => void;
preInit?: (() => any)[];
preRun?: (() => any)[];
postRun?: (() => any)[];
preInit?: (() => any)[] | (() => any);
preRun?: (() => any)[] | (() => any);
postRun?: (() => any)[] | (() => any);
}

export interface AssetEntryInternal extends AssetEntry {
Expand Down
9 changes: 7 additions & 2 deletions src/native/libs/System.Native.Browser/native/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ export function dotnetInitializeModule(internals: InternalExchange): void {
return _ems_.wasmTable;
}

function asCallbackArray(callbacks: undefined | (() => any) | (() => any)[]): (() => any)[] {
if (!callbacks) return [];
return typeof callbacks === "function" ? [callbacks] : callbacks;
}

function setupEmscripten() {
_ems_.Module.preInit = [() => {
if (_ems_.dotnetApi.getConfig) {
Expand All @@ -63,7 +68,7 @@ export function dotnetInitializeModule(internals: InternalExchange): void {
}
// SpecialFolder.CommonApplicationData maps to /usr/share
_ems_.FS.createPath("/", "usr/share", true, true);
}, ...(_ems_.Module.preInit || [])];
}, ...asCallbackArray(_ems_.Module.preInit)];

// preInit runs before Emscripten assigns the native WASM exports.
_ems_.Module.preRun = [() => {
Expand All @@ -82,6 +87,6 @@ export function dotnetInitializeModule(internals: InternalExchange): void {
// silently ignore any error during shutdown
}
};
}, ...(_ems_.Module.preRun || [])];
}, ...asCallbackArray(_ems_.Module.preRun)];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ export function httpAbort(controller: HttpController): void {
// Never resolves; rejects as soon as the fetch does. A failed fetch abandons the readable end of the
// TransformStream, which leaves an in-flight write() pending forever, so writes race against this.
function rejectWhenFetchFails(controller: HttpController): Promise<never> {
return controller.responsePromise!.then(() => new Promise<never>(() => { }), (err) => { throw err; });
return controller.responsePromise!.then(() => new Promise<never>(() => { }), (err) => {
throw err;
});
}

export function httpTransformStreamWrite(controller: HttpController, bufferPtr: VoidPtr, bufferLength: number): ControllablePromise<void> {
Expand Down
Loading