diff --git a/eng/native.wasm.targets b/eng/native.wasm.targets index c72c24ff6df2d1..734349ba2f1d34 100644 --- a/eng/native.wasm.targets +++ b/eng/native.wasm.targets @@ -147,14 +147,46 @@ + + + + <_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" /> + <_EmccExportedRuntimeMethods>@(EmccExportedRuntimeMethod -> '%(Identity)',',') <_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',') + <_EmccIncomingModuleJSAPIs>@(_EmccIncomingModuleJSAPI -> '%(Identity)',',') + diff --git a/src/mono/browser/browser.proj b/src/mono/browser/browser.proj index 710a36801a553b..87f40c18f6ec01 100644 --- a/src/mono/browser/browser.proj +++ b/src/mono/browser/browser.proj @@ -208,9 +208,43 @@ + + + <_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" /> + + + + <_EmccIncomingModuleJSAPI Include="wasmMemory" /> + <_EmccExportedLibraryFunction>"[@(EmccExportedLibraryFunction -> '%27%(Identity)%27', ',')]" <_EmccExportedRuntimeMethods>"[@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]" + <_EmccIncomingModuleJSAPIs>"[@(_EmccIncomingModuleJSAPI -> '%27%(Identity)%27', ',')]" <_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',') 33554432 @@ -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)" /> + + <_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" /> @@ -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)" }, diff --git a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets index 9d4dc3b1394726..d586baabf9d99b 100644 --- a/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets +++ b/src/mono/browser/build/BrowserWasmApp.CoreCLR.targets @@ -112,65 +112,15 @@ TaskFactory="TaskHostFactory" Condition="'$(WasmAppBuilderTasksAssemblyPath)' != ''" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -856,6 +806,7 @@ <_EmccExportedRuntimeMethods>"[BROWSER_HOST,@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]" + <_EmccIncomingModuleJSAPIs>"[@(_EmccIncomingModuleJSAPI -> '%27%(Identity)%27', ',')]" <_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',') @@ -935,6 +886,8 @@ <_EmccLinkStepArgs Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" /> + + <_EmccLinkStepArgs Condition="'$(Configuration)' == 'Debug'" Include="-s INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPIs)" /> <_EmccLinkStepArgs Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" /> diff --git a/src/mono/browser/build/BrowserWasmApp.targets b/src/mono/browser/build/BrowserWasmApp.targets index 4afa05842060c2..f4b70c287b7d7c 100644 --- a/src/mono/browser/build/BrowserWasmApp.targets +++ b/src/mono/browser/build/BrowserWasmApp.targets @@ -313,6 +313,8 @@ + <_WasmEHLib Condition="'$(WasmEnableExceptionHandling)' == 'true'">libmono-wasm-eh-wasm.a @@ -325,6 +327,7 @@ <_WasmSIMDLibToExclude Condition="'$(WasmEnableSIMD)' == 'true'">libmono-wasm-nosimd.a <_EmccExportedLibraryFunction>"[@(EmccExportedLibraryFunction -> '%27%(Identity)%27', ',')]" <_EmccExportedRuntimeMethods>"[@(EmccExportedRuntimeMethod -> '%27%(Identity)%27', ',')]" + <_EmccIncomingModuleJSAPIs>"[@(_EmccIncomingModuleJSAPI -> '%27%(Identity)%27', ',')]" <_EmccExportedFunctions>@(EmccExportedFunction -> '%(Identity)',',') @@ -373,6 +376,8 @@ <_EmccLinkStepArgs Include="-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$(_EmccExportedLibraryFunction)" Condition="'$(_EmccExportedLibraryFunction)' != ''" /> <_EmccLinkStepArgs Include="-s EXPORTED_RUNTIME_METHODS=$(_EmccExportedRuntimeMethods)" /> + + <_EmccLinkStepArgs Condition="'$(Configuration)' == 'Debug'" Include="-s INCOMING_MODULE_JS_API=$(_EmccIncomingModuleJSAPIs)" /> <_EmccLinkStepArgs Include="-s EXPORTED_FUNCTIONS=$(_EmccExportedFunctions)" /> <_EmccLinkStepArgs Include="$(EmccExtraLDFlags)" /> diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index 9874cb3934e8c3..8151170e0216b2 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -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 g_assert (*stsize != (size_t)-1); #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 diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index d592ec19a2a55e..8ba6b8e8302743 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -399,6 +399,7 @@ + @@ -408,6 +409,7 @@ + diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index 49876ab799114d..00403d00d3e517 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -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 () diff --git a/src/native/libs/Common/JavaScript/types/internal.ts b/src/native/libs/Common/JavaScript/types/internal.ts index 7307d336ee6772..cdf67e75aca812 100644 --- a/src/native/libs/Common/JavaScript/types/internal.ts +++ b/src/native/libs/Common/JavaScript/types/internal.ts @@ -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 { diff --git a/src/native/libs/System.Native.Browser/native/index.ts b/src/native/libs/System.Native.Browser/native/index.ts index 60347ab790c727..c85fa44fc286f8 100644 --- a/src/native/libs/System.Native.Browser/native/index.ts +++ b/src/native/libs/System.Native.Browser/native/index.ts @@ -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) { @@ -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 = [() => { @@ -82,6 +87,6 @@ export function dotnetInitializeModule(internals: InternalExchange): void { // silently ignore any error during shutdown } }; - }, ...(_ems_.Module.preRun || [])]; + }, ...asCallbackArray(_ems_.Module.preRun)]; } } diff --git a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts index 6e64216e031534..cc2ed758ba9e02 100644 --- a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts @@ -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 { - return controller.responsePromise!.then(() => new Promise(() => { }), (err) => { throw err; }); + return controller.responsePromise!.then(() => new Promise(() => { }), (err) => { + throw err; + }); } export function httpTransformStreamWrite(controller: HttpController, bufferPtr: VoidPtr, bufferLength: number): ControllablePromise {