Skip to content
Open
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>
<_EmccIncomingModuleJSAPI>@(EmccIncomingModuleJSAPI -> '%(Identity)',',')</_EmccIncomingModuleJSAPI>
</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=$(_EmccIncomingModuleJSAPI)&quot;" />
</ItemGroup>

</Target>
Expand Down
36 changes: 36 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>
<_EmccIncomingModuleJSAPI>"[@(EmccIncomingModuleJSAPI -> '%27%(Identity)%27', ',')]"</_EmccIncomingModuleJSAPI>
<_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,7 @@
<_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 INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPI)" />
<_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 +306,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
32 changes: 32 additions & 0 deletions src/mono/browser/build/BrowserWasmApp.CoreCLR.targets
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,36 @@
<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>
</Target>

<!-- Import shared native.wasm.targets for Emscripten SDK, ICU, exported functions/methods.
Expand Down Expand Up @@ -856,6 +886,7 @@

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Structurally addressed: the items now come from the GenerateEmccExports dependency, so the ItemGroup-before-PropertyGroup ordering hazard this flags is gone. The CoreCLR in-tree browserhost link was rebuilt and its checkIncomingModuleAPI is unchanged (rejects wasmMemory/wasmBinary, accepts the 26 defaults). A full Wasm.Build.Tests/xharness Debug startup run is still pending, so I'm leaving this open until that runs.

Note: written with GitHub Copilot.

<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')</_EmccExportedFunctions>
</PropertyGroup>

Expand Down Expand Up @@ -935,6 +966,7 @@

<!-- Exported functions and runtime methods -->
<_EmccLinkStepArgs Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" />
<_EmccLinkStepArgs Include="-s INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPI)" />
<_EmccLinkStepArgs Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" />

<!-- JS library files -->
Expand Down
4 changes: 4 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>
<_EmccIncomingModuleJSAPI>"[@(EmccIncomingModuleJSAPI -> '%27%(Identity)%27', ',')]"</_EmccIncomingModuleJSAPI>
<_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',')</_EmccExportedFunctions>
</PropertyGroup>

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

<_EmccLinkStepArgs Include="-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$(_EmccExportedLibraryFunction)" Condition="'$(_EmccExportedLibraryFunction)' != ''" />
<_EmccLinkStepArgs Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" />
<_EmccLinkStepArgs Include="-s INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPI)" />
<_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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probably backport this to 11.0 (we could argue it's a test-only change since it happens in Debug only) since it will get lost in main soon

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nobody in the world ever builds mono+MT+wasm+debug. And I'm not going to do it any time soon again.

g_assert (*stsize != (size_t)-1);
Comment on lines +201 to 202
#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
2 changes: 2 additions & 0 deletions src/native/corehost/browserhost/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ target_link_options(browserhost PRIVATE
-sEXIT_RUNTIME=1
-sALLOW_TABLE_GROWTH=1
-sEXPORTED_RUNTIME_METHODS=BROWSER_HOST,${CMAKE_EMCC_EXPORTED_RUNTIME_METHODS}
# Emscripten's default INCOMING_MODULE_JS_API, kept explicit so a Module property we don't declare aborts a debug build early. Value comes from GenerateEmccExports in eng/native.wasm.targets.
-sINCOMING_MODULE_JS_API=${CMAKE_EMCC_INCOMING_MODULE_JS_API}
-sEXPORTED_FUNCTIONS=${CMAKE_EMCC_EXPORTED_FUNCTIONS}
-sEXPORT_NAME=createDotnetRuntime
-sENVIRONMENT=web,webview,worker,node,shell
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,14 +54,19 @@ 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) {
const virtualWorkingDirectory = _ems_.dotnetApi.getConfig().virtualWorkingDirectory;
_ems_.FS.createPath("/", virtualWorkingDirectory!, true, true);
_ems_.FS.chdir(virtualWorkingDirectory!);
}
}, ...(_ems_.Module.preInit || [])];
}, ...asCallbackArray(_ems_.Module.preInit)];

// preInit runs before Emscripten assigns the native WASM exports.
_ems_.Module.preRun = [() => {
Expand All @@ -80,6 +85,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