From 55edc8b1c950ecbf43bf84aab333eb30cbcfa2e4 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 26 Apr 2023 17:31:57 +0200 Subject: [PATCH 1/4] wip --- .../Directory.Build.props | 1 - .../tests/debugger-test/debugger-main.js | 33 ++- src/mono/wasm/runtime/CMakeLists.txt | 4 +- src/mono/wasm/runtime/assets.ts | 5 +- src/mono/wasm/runtime/blazor/BootConfig.ts | 2 +- .../blazor/WebAssemblyResourceLoader.ts | 2 +- .../runtime/blazor/WebAssemblyStartOptions.ts | 30 --- src/mono/wasm/runtime/blazor/_Integration.ts | 4 +- src/mono/wasm/runtime/config.ts | 28 ++ src/mono/wasm/runtime/dotnet.d.ts | 136 +++++----- .../wasm/runtime/es6/dotnet.es6.extpost.js | 15 +- src/mono/wasm/runtime/es6/dotnet.es6.lib.js | 136 +++++----- src/mono/wasm/runtime/es6/dotnet.es6.post.js | 1 - src/mono/wasm/runtime/es6/dotnet.es6.pre.js | 21 +- src/mono/wasm/runtime/export-api.ts | 14 +- src/mono/wasm/runtime/export-types.ts | 15 +- src/mono/wasm/runtime/exports.ts | 78 ++---- src/mono/wasm/runtime/http.ts | 7 +- src/mono/wasm/runtime/icu.ts | 2 +- src/mono/wasm/runtime/imports.ts | 67 ++--- src/mono/wasm/runtime/invoke-js.ts | 4 +- src/mono/wasm/runtime/modularize-dotnet.md | 35 +-- .../wasm/runtime/net6-legacy/export-types.ts | 4 +- .../runtime/net6-legacy/method-binding.ts | 14 +- src/mono/wasm/runtime/polyfills.ts | 12 +- .../wasm/runtime/pthreads/browser/index.ts | 3 +- .../wasm/runtime/pthreads/shared/index.ts | 2 +- .../wasm/runtime/pthreads/worker/index.ts | 3 +- src/mono/wasm/runtime/run-outer.ts | 164 +++++++----- src/mono/wasm/runtime/run.ts | 6 +- src/mono/wasm/runtime/snapshot.ts | 2 +- src/mono/wasm/runtime/startup.ts | 85 +++--- src/mono/wasm/runtime/types-api.ts | 245 ++++++++++++++++++ src/mono/wasm/runtime/types.ts | 223 ++-------------- src/mono/wasm/runtime/types/consts.d.ts | 5 +- src/mono/wasm/runtime/types/emscripten.ts | 14 - src/mono/wasm/test-main.js | 14 +- src/mono/wasm/wasm.proj | 1 - 38 files changed, 731 insertions(+), 706 deletions(-) delete mode 100644 src/mono/wasm/runtime/blazor/WebAssemblyStartOptions.ts create mode 100644 src/mono/wasm/runtime/config.ts delete mode 100644 src/mono/wasm/runtime/es6/dotnet.es6.post.js create mode 100644 src/mono/wasm/runtime/types-api.ts diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index bac17f28db4828..5760758d70ecb5 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -253,7 +253,6 @@ - diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-main.js b/src/mono/wasm/debugger/tests/debugger-test/debugger-main.js index eb86874b2144e3..6f39603f1dcffe 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-main.js +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-main.js @@ -3,26 +3,23 @@ "use strict"; -import createDotnetRuntime from './dotnet.js' +import { dotnet, exit } from './dotnet.js' try { - const runtime = await createDotnetRuntime(({ INTERNAL }) => ({ - configSrc: "./mono-config.json", - onConfigLoaded: (config) => { - config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug"; - /* For custom logging patch the functions below - config.diagnosticTracing = true; - config.environmentVariables["MONO_LOG_LEVEL"] = "debug"; - config.environmentVariables["MONO_LOG_MASK"] = "all"; - INTERNAL.logging = { - trace: (domain, log_level, message, isFatal, dataPtr) => console.log({ domain, log_level, message, isFatal, dataPtr }), - debugger: (level, message) => console.log({ level, message }), - }; - */ - }, - })); + const runtime = await dotnet + .withEnvironmentVariable("DOTNET_MODIFIABLE_ASSEMBLIES", "debug") + // For custom logging patch the functions below + //.withDiagnosticTracing(true) + //.withEnvironmentVariable("MONO_LOG_LEVEL", "debug") + //.withEnvironmentVariable("MONO_LOG_MASK", "all") + .create(); + /*runtime.INTERNAL.logging = { + trace: (domain, log_level, message, isFatal, dataPtr) => console.log({ domain, log_level, message, isFatal, dataPtr }), + debugger: (level, message) => console.log({ level, message }), + };*/ App.runtime = runtime; await App.init(); -} catch (err) { - console.log(`WASM ERROR ${err}`); } +catch (err) { + exit(2, err); +} \ No newline at end of file diff --git a/src/mono/wasm/runtime/CMakeLists.txt b/src/mono/wasm/runtime/CMakeLists.txt index 81b17cf63f6acd..4d3781bb924f68 100644 --- a/src/mono/wasm/runtime/CMakeLists.txt +++ b/src/mono/wasm/runtime/CMakeLists.txt @@ -34,8 +34,8 @@ target_link_libraries(dotnet ${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.post.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 --post-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.post.js --extern-post-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js " + 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 " RUNTIME_OUTPUT_DIRECTORY "${NATIVE_BIN_DIR}") set(ignoreMeWasmOptFlags "${CONFIGURATION_WASM_OPT_FLAGS}") diff --git a/src/mono/wasm/runtime/assets.ts b/src/mono/wasm/runtime/assets.ts index b829f03bd32d97..172818415f0e19 100644 --- a/src/mono/wasm/runtime/assets.ts +++ b/src/mono/wasm/runtime/assets.ts @@ -10,7 +10,8 @@ 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 { AssetBehaviours, AssetEntry, AssetEntryInternal, LoadingResource, mono_assert, ResourceRequest } from "./types"; +import { AssetEntryInternal, mono_assert } from "./types"; +import { AssetBehaviours, AssetEntry, LoadingResource, ResourceRequest } from "./types-api"; import { InstantiateWasmSuccessCallback, VoidPtr } from "./types/emscripten"; const allAssetsInMemory = createPromiseController(); @@ -314,7 +315,7 @@ async function start_asset_download_sources(asset: AssetEntryInternal): Promise< const loadingResource = download_resource(asset); asset.pendingDownloadInternal = loadingResource; response = await loadingResource.response; - if (!response.ok) { + if (!response || !response.ok) { continue;// next source } return response; diff --git a/src/mono/wasm/runtime/blazor/BootConfig.ts b/src/mono/wasm/runtime/blazor/BootConfig.ts index 5100603f64c928..e3316250da681d 100644 --- a/src/mono/wasm/runtime/blazor/BootConfig.ts +++ b/src/mono/wasm/runtime/blazor/BootConfig.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import { Module } from "../imports"; -import { WebAssemblyBootResourceType } from "./WebAssemblyStartOptions"; +import { WebAssemblyBootResourceType } from "../types-api"; type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise | null | undefined; diff --git a/src/mono/wasm/runtime/blazor/WebAssemblyResourceLoader.ts b/src/mono/wasm/runtime/blazor/WebAssemblyResourceLoader.ts index 73e363693cd7e7..c0840f6edb1ad9 100644 --- a/src/mono/wasm/runtime/blazor/WebAssemblyResourceLoader.ts +++ b/src/mono/wasm/runtime/blazor/WebAssemblyResourceLoader.ts @@ -1,9 +1,9 @@ // 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 { toAbsoluteUri } from "./_Polyfill"; import { BootJsonData, ResourceList } from "./BootConfig"; -import { WebAssemblyStartOptions, WebAssemblyBootResourceType } from "./WebAssemblyStartOptions"; const networkFetchCacheMode = "no-cache"; export class WebAssemblyResourceLoader { diff --git a/src/mono/wasm/runtime/blazor/WebAssemblyStartOptions.ts b/src/mono/wasm/runtime/blazor/WebAssemblyStartOptions.ts deleted file mode 100644 index 3f8c0fc4b811fa..00000000000000 --- a/src/mono/wasm/runtime/blazor/WebAssemblyStartOptions.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -export interface WebAssemblyStartOptions { - /** - * Overrides the built-in boot resource loading mechanism so that boot resources can be fetched - * from a custom source, such as an external CDN. - * @param type The type of the resource to be loaded. - * @param name The name of the resource to be loaded. - * @param defaultUri The URI from which the framework would fetch the resource by default. The URI may be relative or absolute. - * @param integrity The integrity string representing the expected content in the response. - * @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior. - */ - loadBootResource(type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string): string | Promise | null | undefined; - - /** - * Override built-in environment setting on start. - */ - environment?: string; - - /** - * Gets the application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47 - */ - applicationCulture?: string; -} - -// This type doesn't have to align with anything in BootConfig. -// Instead, this represents the public API through which certain aspects -// of boot resource loading can be customized. -export type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration"; diff --git a/src/mono/wasm/runtime/blazor/_Integration.ts b/src/mono/wasm/runtime/blazor/_Integration.ts index 7518796505091c..7f2fc7060b5f7a 100644 --- a/src/mono/wasm/runtime/blazor/_Integration.ts +++ b/src/mono/wasm/runtime/blazor/_Integration.ts @@ -1,8 +1,8 @@ import { INTERNAL, Module } from "../imports"; -import { AssetEntry, LoadingResource, MonoConfigInternal } from "../types"; +import { MonoConfigInternal } from "../types"; +import { AssetEntry, LoadingResource, WebAssemblyBootResourceType } from "../types-api"; import { BootConfigResult, BootJsonData, ICUDataMode } from "./BootConfig"; import { WebAssemblyResourceLoader } from "./WebAssemblyResourceLoader"; -import { WebAssemblyBootResourceType } from "./WebAssemblyStartOptions"; import { hasDebuggingEnabled } from "./_Polyfill"; export async function loadBootConfig(config: MonoConfigInternal,) { diff --git a/src/mono/wasm/runtime/config.ts b/src/mono/wasm/runtime/config.ts new file mode 100644 index 00000000000000..34e92f032cbaa2 --- /dev/null +++ b/src/mono/wasm/runtime/config.ts @@ -0,0 +1,28 @@ +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 diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts index 111491048da668..8b8f2e9d4d01e6 100644 --- a/src/mono/wasm/runtime/dotnet.d.ts +++ b/src/mono/wasm/runtime/dotnet.d.ts @@ -5,69 +5,6 @@ //! This is not considered public API with backward compatibility guarantees. -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; - modifiableAssemblies: string | null; - aspnetCoreBrowserTools: string | null; -} -type BootJsonDataExtension = { - [extensionName: string]: ResourceList; -}; -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; -} -type ResourceList = { - [name: string]: string; -}; -type ExtendedResourceList = { - [name: string]: { - hash: string; - behavior: string; - }; -}; -declare enum ICUDataMode { - Sharded = 0, - All = 1, - Invariant = 2, - Custom = 3 -} - -interface DotnetHostBuilder { - withConfig(config: MonoConfig): DotnetHostBuilder; - withConfigSrc(configSrc: string): DotnetHostBuilder; - withApplicationArguments(...args: string[]): DotnetHostBuilder; - withEnvironmentVariable(name: string, value: string): DotnetHostBuilder; - withEnvironmentVariables(variables: { - [i: string]: string; - }): DotnetHostBuilder; - withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder; - withDiagnosticTracing(enabled: boolean): DotnetHostBuilder; - withDebugging(level: number): DotnetHostBuilder; - withMainAssembly(mainAssemblyName: string): DotnetHostBuilder; - withApplicationArgumentsFromQuery(): DotnetHostBuilder; - withStartupMemoryCache(value: boolean): DotnetHostBuilder; - create(): Promise; - run(): Promise; -} - declare interface NativePointer { __brandNativePointer: "NativePointer"; } @@ -121,6 +58,22 @@ type InstantiateWasmSuccessCallback = (instance: WebAssembly.Instance, module: W type InstantiateWasmCallBack = (imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback) => any; declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; +interface DotnetHostBuilder { + withConfig(config: MonoConfig): DotnetHostBuilder; + withConfigSrc(configSrc: string): DotnetHostBuilder; + withApplicationArguments(...args: string[]): DotnetHostBuilder; + withEnvironmentVariable(name: string, value: string): DotnetHostBuilder; + withEnvironmentVariables(variables: { + [i: string]: string; + }): DotnetHostBuilder; + withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder; + withDiagnosticTracing(enabled: boolean): DotnetHostBuilder; + withDebugging(level: number): DotnetHostBuilder; + withMainAssembly(mainAssemblyName: string): DotnetHostBuilder; + withApplicationArgumentsFromQuery(): DotnetHostBuilder; + create(): Promise; + run(): Promise; +} type MonoConfig = { /** * The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script. @@ -297,8 +250,52 @@ type ModuleAPI = { dotnet: DotnetHostBuilder; exit: (code: number, reason?: any) => void; }; -declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise; -type CreateDotnetRuntimeType = typeof createDotnetRuntime; +type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise; + +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; + modifiableAssemblies: string | null; + aspnetCoreBrowserTools: string | null; +} +type BootJsonDataExtension = { + [extensionName: string]: ResourceList; +}; +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; +} +type ResourceList = { + [name: string]: string; +}; +type ExtendedResourceList = { + [name: string]: { + hash: string; + behavior: string; + }; +}; +declare enum ICUDataMode { + Sharded = 0, + All = 1, + Invariant = 2, + Custom = 3 +} interface IDisposable { dispose(): void; @@ -324,11 +321,14 @@ interface IMemoryView extends IDisposable { 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; } - -declare const dotnet: ModuleAPI["dotnet"]; -declare const exit: ModuleAPI["exit"]; +declare const createDotnetRuntime: CreateDotnetRuntimeType; export { AssetEntry, BootJsonData, CreateDotnetRuntimeType, DotnetModuleConfig, EmscriptenModule, ICUDataMode, IMemoryView, ModuleAPI, MonoConfig, ResourceRequest, RuntimeAPI, createDotnetRuntime as default, dotnet, exit }; diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js b/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js index f852ad05419b2c..27437d8f3a868c 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js @@ -1,10 +1,7 @@ -const ENVIRONMENT_IS_WEB = typeof window == "object"; -const ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string"; -const MONO = {}, BINDING = {}, INTERNAL = {}, IMPORTS = {}; + var fetch = fetch || undefined; var require = require || undefined; var __dirname = __dirname || ''; -__dotnet_runtime.__setEmscriptenEntrypoint(createDotnetRuntime); -const __initializeImportsAndExports = __dotnet_runtime.__initializeImportsAndExports; -const __requirePromise = ENVIRONMENT_IS_NODE ? import(/* webpackIgnore: true */'module').then(mod => mod.createRequire(import.meta.url)) : undefined; -const dotnet = __dotnet_runtime.moduleExports.dotnet; -const exit = __dotnet_runtime.moduleExports.exit; -export { dotnet, exit, INTERNAL }; +var createEmscripten = createDotnetRuntime; +var unifyModuleConfig = __dotnet_runtime.unifyModuleConfig; +var earlyExports = __dotnet_runtime.earlyExports; +export const dotnet = __dotnet_runtime.dotnet; +export const exit = __dotnet_runtime.exit; \ No newline at end of file diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js index 326f539b612ae0..f581e14ff4fb55 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js @@ -4,58 +4,78 @@ "use strict"; -// USE_PTHREADS is emscripten's define symbol, which is passed to acorn optimizer, so we could use it here -#if USE_PTHREADS -const monoWasmThreads = true; -const isPThread = `ENVIRONMENT_IS_PTHREAD`; -#else -const monoWasmThreads = false; -const isPThread = "false"; -#endif // because we can't pass custom define symbols to acorn optimizer, we use environment variables to pass other build options const DISABLE_LEGACY_JS_INTEROP = process.env.DISABLE_LEGACY_JS_INTEROP === "1"; -const disableLegacyJsInterop = DISABLE_LEGACY_JS_INTEROP ? "true" : "false"; -const DotnetSupportLib = { - $DOTNET: {}, - // this line will be placed early on emscripten runtime creation, passing import and export objects into __dotnet_runtime IIFE - // Emscripten uses require function for nodeJS even in ES6 module. We need https://nodejs.org/api/module.html#modulecreaterequirefilename - // We use dynamic import because there is no "module" module in the browser. - // This is async init of it, note it would become available only after first tick. - // Also fix of scriptDirectory would be delayed - // Emscripten's getBinaryPromise is not async for NodeJs, but we would like to have it async, so we replace it. - // We also replace implementation of fetch - $DOTNET__postset: ` -let __dotnet_replacement_PThread = ${monoWasmThreads} ? {} : undefined; -${monoWasmThreads ? ` -__dotnet_replacement_PThread.loadWasmModuleToWorker = PThread.loadWasmModuleToWorker; -__dotnet_replacement_PThread.threadInitTLS = PThread.threadInitTLS; -__dotnet_replacement_PThread.allocateUnusedWorker = PThread.allocateUnusedWorker; -` : ''} -let __dotnet_replacements = {scriptUrl: import.meta.url, fetch: globalThis.fetch, require, updateMemoryViews, pthreadReplacements: __dotnet_replacement_PThread}; -if (ENVIRONMENT_IS_NODE) { - __dotnet_replacements.requirePromise = __requirePromise; -} -let __dotnet_exportedAPI = __initializeImportsAndExports( - { isGlobal:false, isNode:ENVIRONMENT_IS_NODE, isWorker:ENVIRONMENT_IS_WORKER, isShell:ENVIRONMENT_IS_SHELL, isWeb:ENVIRONMENT_IS_WEB, isPThread:${isPThread}, disableLegacyJsInterop:${disableLegacyJsInterop}, quit_, ExitStatus, requirePromise:__dotnet_replacements.requirePromise }, - { mono:MONO, binding:BINDING, internal:INTERNAL, module:Module, marshaled_imports: IMPORTS }, - __dotnet_replacements, __callbackAPI); -updateMemoryViews = __dotnet_replacements.updateMemoryViews; -fetch = __dotnet_replacements.fetch; -_scriptDir = __dirname = scriptDirectory = __dotnet_replacements.scriptDirectory; -if (ENVIRONMENT_IS_NODE) { - __dotnet_replacements.requirePromise.then(someRequire => { - require = someRequire; +function setup(disableLegacyJsInterop) { + const pthreadReplacements = {}; + const dotnet_replacements = { + scriptUrl: import.meta.url, + fetch: globalThis.fetch, + require, + updateMemoryViews, + pthreadReplacements, + scriptDirectory, + noExitRuntime + }; + // USE_PTHREADS is emscripten's define symbol, which is passed to acorn optimizer, so we could use it here + #if USE_PTHREADS + pthreadReplacements.loadWasmModuleToWorker = PThread.loadWasmModuleToWorker; + pthreadReplacements.threadInitTLS = PThread.threadInitTLS; + pthreadReplacements.allocateUnusedWorker = PThread.allocateUnusedWorker; + #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.initializeImports({ + isNode: ENVIRONMENT_IS_NODE, + isWorker: ENVIRONMENT_IS_WORKER, + isShell: ENVIRONMENT_IS_SHELL, + isWeb: ENVIRONMENT_IS_WEB, + isPThread: ENVIRONMENT_IS_PTHREAD, + disableLegacyJsInterop, + quit_, ExitStatus }); + + #if USE_PTHREADS + if (ENVIRONMENT_IS_PTHREAD) { + Module.config = {}; + earlyExports.module = Module; + __dotnet_runtime.initializeReplacements(dotnet_replacements); + __dotnet_runtime.configureWorkerStartup(Module); + } else { + #endif + __dotnet_runtime.initializeReplacements(dotnet_replacements); + __dotnet_runtime.configureEmscriptenStartup(Module); + #if USE_PTHREADS + } + #endif + + updateMemoryViews = dotnet_replacements.updateMemoryViews; + noExitRuntime = dotnet_replacements.noExitRuntime; + fetch = dotnet_replacements.fetch; + _scriptDir = __dirname = scriptDirectory = dotnet_replacements.scriptDirectory; + #if USE_PTHREADS + PThread.loadWasmModuleToWorker = pthreadReplacements.loadWasmModuleToWorker; + PThread.threadInitTLS = pthreadReplacements.threadInitTLS; + PThread.allocateUnusedWorker = pthreadReplacements.allocateUnusedWorker; + #endif } -var noExitRuntime = __dotnet_replacements.noExitRuntime; -${monoWasmThreads ? ` -PThread.loadWasmModuleToWorker = __dotnet_replacements.pthreadReplacements.loadWasmModuleToWorker; -PThread.threadInitTLS = __dotnet_replacements.pthreadReplacements.threadInitTLS; -PThread.allocateUnusedWorker = __dotnet_replacements.pthreadReplacements.allocateUnusedWorker; -` : ''} -`, + +const postset = ` + DOTNET.setup(${DISABLE_LEGACY_JS_INTEROP ? "true" : "false"}); +`; + +const DotnetSupportLib = { + $DOTNET: { setup }, + $DOTNET__postset: postset }; // the methods would be visible to EMCC linker @@ -107,18 +127,18 @@ let linked_functions = [ "icudt68_dat", ]; -if (monoWasmThreads) { - linked_functions = [...linked_functions, - /// mono-threads-wasm.c - "mono_wasm_pthread_on_pthread_attached", - // threads.c - "mono_wasm_eventloop_has_unsettled_interop_promises", - // diagnostics_server.c - "mono_wasm_diagnostic_server_on_server_thread_created", - "mono_wasm_diagnostic_server_on_runtime_server_init", - "mono_wasm_diagnostic_server_stream_signal_work_available", - ] -} +#if USE_PTHREADS +linked_functions = [...linked_functions, + /// mono-threads-wasm.c + "mono_wasm_pthread_on_pthread_attached", + // threads.c + "mono_wasm_eventloop_has_unsettled_interop_promises", + // diagnostics_server.c + "mono_wasm_diagnostic_server_on_server_thread_created", + "mono_wasm_diagnostic_server_on_runtime_server_init", + "mono_wasm_diagnostic_server_stream_signal_work_available", +] +#endif if (!DISABLE_LEGACY_JS_INTEROP) { linked_functions = [...linked_functions, "mono_wasm_invoke_js_with_args_ref", diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.post.js b/src/mono/wasm/runtime/es6/dotnet.es6.post.js deleted file mode 100644 index f39dd3f847f80f..00000000000000 --- a/src/mono/wasm/runtime/es6/dotnet.es6.post.js +++ /dev/null @@ -1 +0,0 @@ -createDotnetRuntime.ready = createDotnetRuntime.ready.then(() => { return __dotnet_exportedAPI; }); \ No newline at end of file diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.pre.js b/src/mono/wasm/runtime/es6/dotnet.es6.pre.js index 67102e3458d41f..3ecc1bcdc9be79 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.pre.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.pre.js @@ -1,20 +1 @@ -var __callbackAPI = { MONO, BINDING, INTERNAL, IMPORTS }; -if (typeof createDotnetRuntime === "function") { - __callbackAPI.Module = Module = { ready: Module.ready }; - const extension = createDotnetRuntime(__callbackAPI) - if (extension.ready) { - throw new Error("MONO_WASM: Module.ready couldn't be redefined.") - } - Object.assign(Module, extension); - createDotnetRuntime = Module; - if (!createDotnetRuntime.locateFile) createDotnetRuntime.locateFile = createDotnetRuntime.__locateFile = (path) => scriptDirectory + path; -} -else if (typeof createDotnetRuntime === "object") { - __callbackAPI.Module = Module = { ready: Module.ready, __undefinedConfig: Object.keys(createDotnetRuntime).length === 1 }; - Object.assign(Module, createDotnetRuntime); - createDotnetRuntime = Module; - if (!createDotnetRuntime.locateFile) createDotnetRuntime.locateFile = createDotnetRuntime.__locateFile = (path) => scriptDirectory + path; -} -else { - throw new Error("MONO_WASM: Can't use moduleFactory callback of createDotnetRuntime function.") -} \ No newline at end of file +createDotnetRuntime = Module = unifyModuleConfig(Module, createDotnetRuntime); \ No newline at end of file diff --git a/src/mono/wasm/runtime/export-api.ts b/src/mono/wasm/runtime/export-api.ts index 63d081087380e0..debc4815024a4c 100644 --- a/src/mono/wasm/runtime/export-api.ts +++ b/src/mono/wasm/runtime/export-api.ts @@ -1,14 +1,14 @@ // 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 { runtimeHelpers } from "./imports"; 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, mono_exit } from "./run"; -import { dotnet } from "./run-outer"; +import { mono_run_main, mono_run_main_and_exit } from "./run"; import { mono_wasm_setenv } from "./startup"; -import { APIType, ModuleAPI, MonoConfig } from "./types"; export function export_api(): any { const api: APIType = { @@ -47,11 +47,3 @@ export function export_api(): any { }; return api; } - -export function export_module(): ModuleAPI { - const exports: ModuleAPI = { - dotnet, - exit: mono_exit - }; - return exports; -} \ No newline at end of file diff --git a/src/mono/wasm/runtime/export-types.ts b/src/mono/wasm/runtime/export-types.ts index 1221d3f2fc0bba..f81661e365e1f7 100644 --- a/src/mono/wasm/runtime/export-types.ts +++ b/src/mono/wasm/runtime/export-types.ts @@ -1,25 +1,24 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { BootJsonData, ICUDataMode } from "./blazor/BootConfig"; -import { IMemoryView } from "./marshal"; -import { createDotnetRuntime, CreateDotnetRuntimeType, DotnetModuleConfig, RuntimeAPI, MonoConfig, ModuleAPI, AssetEntry, ResourceRequest } from "./types"; -import { EmscriptenModule } from "./types/emscripten"; +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"; // ----------------------------------------------------------- // this files has all public exports from the dotnet.js module // ----------------------------------------------------------- - // Here, declare things that go in the global namespace, or augment existing declarations in the global namespace declare global { function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; } -export default createDotnetRuntime; +declare const createDotnetRuntime: CreateDotnetRuntimeType; -declare const dotnet: ModuleAPI["dotnet"]; -declare const exit: ModuleAPI["exit"]; +export default createDotnetRuntime; export { EmscriptenModule, diff --git a/src/mono/wasm/runtime/exports.ts b/src/mono/wasm/runtime/exports.ts index 02641068889c15..4115f730f0ebae 100644 --- a/src/mono/wasm/runtime/exports.ts +++ b/src/mono/wasm/runtime/exports.ts @@ -3,49 +3,39 @@ import ProductVersion from "consts:productVersion"; import GitHash from "consts:gitHash"; -import MonoWasmThreads from "consts:monoWasmThreads"; import BuildConfiguration from "consts:configuration"; import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop"; +import type { DotnetHostBuilder, RuntimeAPI } from "./types-api"; +import type { EarlyExports, DotnetModuleInternal } from "./types"; -import { ENVIRONMENT_IS_PTHREAD, exportedRuntimeAPI, disableLegacyJsInterop, moduleExports, set_emscripten_entrypoint, set_imports_exports } from "./imports"; -import { is_nullish, EarlyImports, EarlyExports, EarlyReplacements, RuntimeAPI, CreateDotnetRuntimeType, DotnetModuleInternal } from "./types"; -import { configure_emscripten_startup, mono_wasm_pthread_worker_init } from "./startup"; +import { disableLegacyJsInterop, exportedRuntimeAPI, initializeImports, set_exports } from "./imports"; +import { is_nullish } from "./types"; +import { configureEmscriptenStartup, configureWorkerStartup } from "./startup"; import { create_weak_ref } from "./weak-ref"; import { export_internal } from "./exports-internal"; -import { export_linker } from "./exports-linker"; -import { init_polyfills } from "./polyfills"; -import { export_api, export_module } from "./export-api"; +import { export_api } from "./export-api"; +import { mono_exit } from "./run"; +import { earlyExports, unifyModuleConfig } from "./run-outer"; +import { HostBuilder } from "./run-outer"; +import { initializeReplacements, init_polyfills } 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 { set_legacy_exports } from "./net6-legacy/imports"; -const __initializeImportsAndExports: any = initializeImportsAndExports; // don't want to export the type -const __setEmscriptenEntrypoint: any = setEmscriptenEntrypoint; // don't want to export the type -let __linker_exports: any = null; - - -// this is executed early during load of emscripten runtime -// it exports methods to global objects MONO, BINDING and Module in backward compatible way -// At runtime this will be referred to as 'createDotnetRuntime' -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -function initializeImportsAndExports( - imports: EarlyImports, +function initializeExports( exports: EarlyExports, - replacements: EarlyReplacements, - callbackAPI: any ): RuntimeAPI { + set_exports(exports); const module = exports.module as DotnetModuleInternal; const globalThisAny = globalThis as any; - // we want to have same instance of MONO, BINDING and Module in dotnet iife - set_imports_exports(imports, exports); if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) { set_legacy_exports(exports); } - init_polyfills(replacements); + init_polyfills(); // here we merge methods from the local objects into exported objects if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) { @@ -55,10 +45,8 @@ function initializeImportsAndExports( } Object.assign(exports.internal, export_internal()); const API = export_api(); - __linker_exports = export_linker(); Object.assign(exportedRuntimeAPI, { INTERNAL: exports.internal, - IMPORTS: exports.marshaled_imports, Module: module, runtimeBuildInfo: { productVersion: ProductVersion, @@ -74,24 +62,11 @@ function initializeImportsAndExports( }); } - Object.assign(callbackAPI, API); - if (exports.module.__undefinedConfig) { - module.disableDotnet6Compatibility = true; - module.configSrc = "./mono-config.json"; - } - - if (!module.out) { - module.out = console.log.bind(console); - } - if (!module.err) { - module.err = console.error.bind(console); - } - if (typeof module.disableDotnet6Compatibility === "undefined") { module.disableDotnet6Compatibility = true; } // here we expose objects global namespace for tests and backward compatibility - if (imports.isGlobal || !module.disableDotnet6Compatibility) { + if (!module.disableDotnet6Compatibility) { Object.assign(module, exportedRuntimeAPI); if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) { @@ -125,9 +100,7 @@ function initializeImportsAndExports( globalThisAny.MONO = exports.mono; globalThisAny.BINDING = exports.binding; globalThisAny.INTERNAL = exports.internal; - if (!imports.isGlobal) { - globalThisAny.Module = module; - } + globalThisAny.Module = module; // Blazor back compat warnWrap("cwrap", () => module.cwrap); @@ -146,16 +119,9 @@ function initializeImportsAndExports( } list.registerRuntime(exportedRuntimeAPI); - if (MonoWasmThreads && ENVIRONMENT_IS_PTHREAD) { - return mono_wasm_pthread_worker_init(module, exportedRuntimeAPI); - } - - configure_emscripten_startup(module, exportedRuntimeAPI); - return exportedRuntimeAPI; } - class RuntimeList { private list: { [runtimeId: number]: WeakRef } = {}; @@ -171,10 +137,10 @@ class RuntimeList { } } -function setEmscriptenEntrypoint(emscriptenEntrypoint: CreateDotnetRuntimeType) { - Object.assign(moduleExports, export_module()); - set_emscripten_entrypoint(emscriptenEntrypoint); -} - -export { __initializeImportsAndExports, __setEmscriptenEntrypoint, __linker_exports, moduleExports }; - +// export external API +const dotnet: DotnetHostBuilder = new HostBuilder(); +const exit = mono_exit; +export { + dotnet, exit, + earlyExports, initializeImports, initializeExports, initializeReplacements, unifyModuleConfig, configureEmscriptenStartup, configureWorkerStartup +}; \ No newline at end of file diff --git a/src/mono/wasm/runtime/http.ts b/src/mono/wasm/runtime/http.ts index 62a1f4b61cc2c6..1ba00c0cd6a891 100644 --- a/src/mono/wasm/runtime/http.ts +++ b/src/mono/wasm/runtime/http.ts @@ -2,11 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. import { wrap_as_cancelable_promise } from "./cancelable-promise"; -import { Module } from "./imports"; +import { Module, runtimeHelpers } from "./imports"; import { MemoryViewType, Span } from "./marshal"; -import { fetch_like } from "./polyfills"; import { mono_assert } from "./types"; -import { VoidPtr } from "./types/emscripten"; +import type { VoidPtr } from "./types/emscripten"; export function http_wasm_supports_streaming_response(): boolean { return typeof Response !== "undefined" && "body" in Response.prototype && typeof ReadableStream === "function"; @@ -57,7 +56,7 @@ export function http_wasm_fetch(url: string, header_names: string[], header_valu } return wrap_as_cancelable_promise(async () => { - const res = await fetch_like(url, options) as ResponseExtension; + const res = await runtimeHelpers.fetch_like(url, options) as ResponseExtension; res.__abort_controller = abort_controller; return res; }); diff --git a/src/mono/wasm/runtime/icu.ts b/src/mono/wasm/runtime/icu.ts index dfed61e8b475ad..687732d252ce58 100644 --- a/src/mono/wasm/runtime/icu.ts +++ b/src/mono/wasm/runtime/icu.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import cwraps from "./cwraps"; -import { Module, runtimeHelpers } from "./imports"; +import { ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./imports"; import { VoidPtr } from "./types/emscripten"; // @offset must be the address of an ICU data archive in the native heap. diff --git a/src/mono/wasm/runtime/imports.ts b/src/mono/wasm/runtime/imports.ts index cab9189477d356..ee02cfaf732d68 100644 --- a/src/mono/wasm/runtime/imports.ts +++ b/src/mono/wasm/runtime/imports.ts @@ -5,13 +5,13 @@ /// /// -import type { CreateDotnetRuntimeType, DotnetModule, RuntimeAPI, EarlyExports, EarlyImports, ModuleAPI, RuntimeHelpers } from "./types"; -import type { EmscriptenModule, EmscriptenModuleInternal } from "./types/emscripten"; +import { RuntimeAPI } from "./types-api"; +import type { DotnetModule, EarlyExports, EarlyImports, EmscriptenModuleInternal, RuntimeHelpers } from "./types"; +import type { EmscriptenModule } from "./types/emscripten"; // these are our public API (except internal) export let Module: EmscriptenModule & DotnetModule & EmscriptenModuleInternal; export let INTERNAL: any; -export let IMPORTS: any; // these are imported and re-exported from emscripten internals export let ENVIRONMENT_IS_NODE: boolean; @@ -19,22 +19,15 @@ export let ENVIRONMENT_IS_SHELL: boolean; export let ENVIRONMENT_IS_WEB: boolean; export let ENVIRONMENT_IS_WORKER: boolean; export let ENVIRONMENT_IS_PTHREAD: boolean; -export const exportedRuntimeAPI: RuntimeAPI = {} as any; -export const moduleExports: ModuleAPI = {} as any; -export let emscriptenEntrypoint: CreateDotnetRuntimeType; - +export let exportedRuntimeAPI: RuntimeAPI = null as any; +export let runtimeHelpers: RuntimeHelpers = null as any; // this is when we link with workload tools. The consts:WasmEnableLegacyJsInterop is when we compile with rollup. export let disableLegacyJsInterop = false; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function set_imports_exports( +export function initializeImports( imports: EarlyImports, - exports: EarlyExports, ): void { - INTERNAL = exports.internal; - IMPORTS = exports.marshaled_imports; - Module = exports.module; - ENVIRONMENT_IS_NODE = imports.isNode; ENVIRONMENT_IS_SHELL = imports.isShell; ENVIRONMENT_IS_WEB = imports.isWeb; @@ -43,27 +36,37 @@ export function set_imports_exports( disableLegacyJsInterop = imports.disableLegacyJsInterop; runtimeHelpers.quit = imports.quit_; runtimeHelpers.ExitStatus = imports.ExitStatus; - runtimeHelpers.requirePromise = imports.requirePromise; } -export function set_emscripten_entrypoint( - entrypoint: CreateDotnetRuntimeType +export function set_exports( + exports: EarlyExports, ): void { - emscriptenEntrypoint = entrypoint; -} + INTERNAL = exports.internal; + Module = exports.module; + runtimeHelpers = exports.helpers; + exportedRuntimeAPI = exports.api; + if (!exports.module.config.environmentVariables) { + exports.module.config.environmentVariables = {}; + } + Object.assign(runtimeHelpers, { + javaScriptExports: {} as any, + mono_wasm_bindings_is_ready: false, + maxParallelDownloads: 16, + enableDownloadRetry: true, + config: exports.module.config, + diagnosticTracing: false, + enablePerfMeasure: true, + loadedFiles: [] + } as Partial); +} -const initialRuntimeHelpers: Partial = -{ - javaScriptExports: {} as any, - mono_wasm_bindings_is_ready: false, - maxParallelDownloads: 16, - enableDownloadRetry: true, - config: { - environmentVariables: {}, - }, - diagnosticTracing: false, - enablePerfMeasure: true, - loadedFiles: [] -}; -export const runtimeHelpers: RuntimeHelpers = initialRuntimeHelpers as any; +export function set_module_and_helpers( + module: EmscriptenModule & DotnetModule & EmscriptenModuleInternal, + helpers: RuntimeHelpers, + internal: any +) { + Module = module; + INTERNAL = internal; + runtimeHelpers = helpers; +} diff --git a/src/mono/wasm/runtime/invoke-js.ts b/src/mono/wasm/runtime/invoke-js.ts index 53882278e4aba8..2ae40414ac31d8 100644 --- a/src/mono/wasm/runtime/invoke-js.ts +++ b/src/mono/wasm/runtime/invoke-js.ts @@ -7,7 +7,7 @@ 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 { Int32Ptr } from "./types/emscripten"; -import { IMPORTS, INTERNAL, Module, runtimeHelpers } from "./imports"; +import { INTERNAL, Module, runtimeHelpers } from "./imports"; import { bind_arg_marshal_to_js } from "./marshal-to-js"; import { mono_wasm_new_external_root } from "./roots"; import { mono_wasm_symbolicate_string } from "./logging"; @@ -256,7 +256,7 @@ export function mono_wasm_set_module_imports(module_name: string, moduleImports: function mono_wasm_lookup_function(function_name: string, js_module_name: string): Function { mono_assert(function_name && typeof function_name === "string", "function_name must be string"); - let scope: any = IMPORTS; + let scope: any = {}; const parts = function_name.split("."); if (js_module_name) { scope = importedModules.get(js_module_name); diff --git a/src/mono/wasm/runtime/modularize-dotnet.md b/src/mono/wasm/runtime/modularize-dotnet.md index cbf5233773c102..63f4122f4e7fa0 100644 --- a/src/mono/wasm/runtime/modularize-dotnet.md +++ b/src/mono/wasm/runtime/modularize-dotnet.md @@ -5,37 +5,4 @@ See https://emscripten.org/docs/tools_reference/emcc.html#emcc-pre-js There are `-extern-pre-js`,`-pre-js`, `-post-js`, `-extern-post-js`. In `src\mono\wasm\build\WasmApp.Native.targets` we apply them by file naming convention as: `*.extpre.js`,`*.pre.js`, `*.post.js`, `*.extpost.js` -In `src\mono\wasm\runtime\CMakeLists.txt` which links only in-tree, we use same mapping explicitly. Right now CommonJS is default. - -# dotnet.es6.pre.js -- Executed second (2) -- Applied only when linking ES6 -- Will check that it was passed `moduleFactory` callback. Because of emscripten reasons it has confusing `createDotnetRuntime` name here. -- Will validate `Module.ready` is left un-overridden. - -# runtime.*.iffe.js -- Executed third (3) -- this is produced from `*.ts` files in this directory by rollupJS. - -# dotnet.*.post.js -- Executed last (4) -- When `onRuntimeInitialized` is overridden it would wait for emscriptens `Module.ready` -- Otherwise it would wait for MonoVM to load all assets and assemblies. -- It would pass on the API exports - -# About new API -The signature is -``` -function createDotnetRuntime(module: DotnetModuleConfig): Promise -``` - -Simplest intended usage looks like this in ES6: -``` -import createDotnetRuntime from './dotnet.js' - -await createDotnetRuntime({ - configSrc: "./mono-config.json", -}); -``` - -For more complex scenario with using APIs see `src\mono\sample\wasm` +In `src\mono\wasm\runtime\CMakeLists.txt` which links only in-tree, we use same mapping explicitly. diff --git a/src/mono/wasm/runtime/net6-legacy/export-types.ts b/src/mono/wasm/runtime/net6-legacy/export-types.ts index 2253784ae8b65a..921689525e34a7 100644 --- a/src/mono/wasm/runtime/net6-legacy/export-types.ts +++ b/src/mono/wasm/runtime/net6-legacy/export-types.ts @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { MemOffset, MonoArray, MonoObject, MonoObjectRef, MonoString, NumberOrPointer, WasmRoot, WasmRootBuffer } from "../types"; -import { VoidPtr } from "../types/emscripten"; +import type { MemOffset, MonoArray, MonoObject, MonoObjectRef, MonoString, NumberOrPointer, WasmRoot, WasmRootBuffer } from "../types"; +import type { VoidPtr } from "../types/emscripten"; /** * @deprecated Please use methods in top level API object instead diff --git a/src/mono/wasm/runtime/net6-legacy/method-binding.ts b/src/mono/wasm/runtime/net6-legacy/method-binding.ts index a5614e2e82dc7b..cf330c8af1000a 100644 --- a/src/mono/wasm/runtime/net6-legacy/method-binding.ts +++ b/src/mono/wasm/runtime/net6-legacy/method-binding.ts @@ -12,7 +12,7 @@ import { MonoMethod, MonoObject, MonoType, MonoClass, mono_assert, VoidPtrNull, 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 { BINDING, legacyHelpers } from "./imports"; +import { legacyHelpers } from "./imports"; import { js_to_mono_obj_root, _js_to_mono_uri_root, js_to_mono_enum } from "./js-to-cs"; import { _teardown_after_call } from "./method-calls"; @@ -99,18 +99,18 @@ export function _create_rebindable_named_function(name: string, argumentNames: s export function _create_primitive_converters(): void { const result = primitiveConverters; result.set("m", { steps: [{}], size: 0 }); - result.set("s", { steps: [{ convert_root: js_string_to_mono_string_root.bind(BINDING) }], size: 0, needs_root: true }); - result.set("S", { steps: [{ convert_root: js_string_to_mono_string_interned_root.bind(BINDING) }], size: 0, needs_root: true }); + result.set("s", { steps: [{ convert_root: js_string_to_mono_string_root.bind(Module) }], size: 0, needs_root: true }); + result.set("S", { steps: [{ convert_root: js_string_to_mono_string_interned_root.bind(Module) }], size: 0, needs_root: true }); // note we also bind first argument to false for both _js_to_mono_obj and _js_to_mono_uri, // because we will root the reference, so we don't need in-flight reference // also as those are callback arguments and we don't have platform code which would release the in-flight reference on C# end - result.set("o", { steps: [{ convert_root: js_to_mono_obj_root.bind(BINDING) }], size: 0, needs_root: true }); - result.set("u", { steps: [{ convert_root: _js_to_mono_uri_root.bind(BINDING, false) }], size: 0, needs_root: true }); + result.set("o", { steps: [{ convert_root: js_to_mono_obj_root.bind(Module) }], size: 0, needs_root: true }); + result.set("u", { steps: [{ convert_root: _js_to_mono_uri_root.bind(Module, false) }], size: 0, needs_root: true }); // ref object aka T&& - result.set("R", { steps: [{ convert_root: js_to_mono_obj_root.bind(BINDING), byref: true }], size: 0, needs_root: true }); + result.set("R", { steps: [{ convert_root: js_to_mono_obj_root.bind(Module), byref: true }], size: 0, needs_root: true }); // result.set ('k', { steps: [{ convert: js_to_mono_enum.bind (this), indirect: 'i64'}], size: 8}); - result.set("j", { steps: [{ convert: js_to_mono_enum.bind(BINDING), indirect: "i32" }], size: 8 }); + result.set("j", { steps: [{ convert: js_to_mono_enum.bind(Module), indirect: "i32" }], size: 8 }); result.set("b", { steps: [{ indirect: "bool" }], size: 8 }); result.set("i", { steps: [{ indirect: "i32" }], size: 8 }); diff --git a/src/mono/wasm/runtime/polyfills.ts b/src/mono/wasm/runtime/polyfills.ts index edbc423123d9b0..cbccad539165f4 100644 --- a/src/mono/wasm/runtime/polyfills.ts +++ b/src/mono/wasm/runtime/polyfills.ts @@ -3,15 +3,15 @@ import BuildConfiguration from "consts:configuration"; import MonoWasmThreads from "consts:monoWasmThreads"; -import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WEB, ENVIRONMENT_IS_WORKER, INTERNAL, Module, runtimeHelpers } from "./imports"; +import type { DotnetModuleConfigImports, EarlyReplacements } from "./types"; +import type { TypedArray } from "./types/emscripten"; +import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WORKER, ENVIRONMENT_IS_WEB, INTERNAL, Module, runtimeHelpers } from "./imports"; import { replaceEmscriptenPThreadLibrary } from "./pthreads/shared/emscripten-replacements"; -import { DotnetModuleConfigImports, EarlyReplacements } from "./types"; -import { TypedArray } from "./types/emscripten"; let node_fs: any | undefined = undefined; let node_url: any | undefined = undefined; -export function init_polyfills(replacements: EarlyReplacements): void { +export function init_polyfills(): void { // performance.now() is used by emscripten and doesn't work in JSC if (typeof globalThis.performance === "undefined") { @@ -119,7 +119,9 @@ export function init_polyfills(replacements: EarlyReplacements): void { } }; } +} +export function initializeReplacements(replacements: EarlyReplacements): void { // require replacement const imports = Module.imports = (Module.imports || {}) as DotnetModuleConfigImports; const requireWrapper = (wrappedRequire: Function) => (name: string) => { @@ -150,7 +152,7 @@ export function init_polyfills(replacements: EarlyReplacements): void { console.debug(`MONO_WASM: starting in ${runtimeHelpers.scriptDirectory}`); } if (Module.__locateFile === Module.locateFile) { - // above it's our early version from dotnet.es6.pre.js, we could replace it with better + // 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; diff --git a/src/mono/wasm/runtime/pthreads/browser/index.ts b/src/mono/wasm/runtime/pthreads/browser/index.ts index 16a61cf54adfcd..9a41aa5d824a7c 100644 --- a/src/mono/wasm/runtime/pthreads/browser/index.ts +++ b/src/mono/wasm/runtime/pthreads/browser/index.ts @@ -5,9 +5,10 @@ import { isMonoWorkerMessageChannelCreated, monoSymbol, makeMonoThreadMessageApp import { pthread_ptr } from "../shared/types"; import { MonoThreadMessage } from "../shared"; import { PromiseController, createPromiseController } from "../../promise-controller"; -import { MonoConfig, mono_assert } from "../../types"; +import { mono_assert } from "../../types"; import Internals from "../shared/emscripten-internals"; import { runtimeHelpers } from "../../imports"; +import { MonoConfig } from "../../types-api"; const threads: Map = new Map(); diff --git a/src/mono/wasm/runtime/pthreads/shared/index.ts b/src/mono/wasm/runtime/pthreads/shared/index.ts index 774dbc76ec8af4..1d387bb9cd36c6 100644 --- a/src/mono/wasm/runtime/pthreads/shared/index.ts +++ b/src/mono/wasm/runtime/pthreads/shared/index.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import { Module } from "../../imports"; -import { MonoConfig } from "../../types"; +import { MonoConfig } from "../../types-api"; import { pthread_ptr } from "./types"; export interface PThreadInfo { diff --git a/src/mono/wasm/runtime/pthreads/worker/index.ts b/src/mono/wasm/runtime/pthreads/worker/index.ts index da4c780804c55b..715620521cbcd3 100644 --- a/src/mono/wasm/runtime/pthreads/worker/index.ts +++ b/src/mono/wasm/runtime/pthreads/worker/index.ts @@ -7,7 +7,7 @@ import MonoWasmThreads from "consts:monoWasmThreads"; import { Module, ENVIRONMENT_IS_PTHREAD, runtimeHelpers, ENVIRONMENT_IS_WEB } from "../../imports"; import { makeChannelCreatedMonoMessage, makePreloadMonoMessage } from "../shared"; import type { pthread_ptr } from "../shared/types"; -import { mono_assert, is_nullish, MonoConfig, MonoConfigInternal } from "../../types"; +import { is_nullish, MonoConfigInternal, mono_assert } from "../../types"; import type { MonoThreadMessage } from "../shared"; import { PThreadSelf, @@ -18,6 +18,7 @@ import { } from "./events"; import { setup_proxy_console } from "../../logging"; import { afterConfigLoaded, preRunWorker } from "../../startup"; +import { MonoConfig } from "../../types-api"; // re-export some of the events types export { diff --git a/src/mono/wasm/runtime/run-outer.ts b/src/mono/wasm/runtime/run-outer.ts index 8785c0e2c639d2..dd2d0e612f6f2a 100644 --- a/src/mono/wasm/runtime/run-outer.ts +++ b/src/mono/wasm/runtime/run-outer.ts @@ -2,42 +2,47 @@ // 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 { WebAssemblyStartOptions } from "./blazor/WebAssemblyStartOptions"; -import { emscriptenEntrypoint, runtimeHelpers } from "./imports"; -import { setup_proxy_console } from "./logging"; + +import type { MonoConfig, DotnetHostBuilder, DotnetModuleConfig, RuntimeAPI, WebAssemblyStartOptions } from "./types-api"; +import type { MonoConfigInternal, RuntimeHelpers, EarlyExports, DotnetModuleInternal, EmscriptenModuleInternal } from "./types"; + +import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WEB, set_module_and_helpers } from "./imports"; import { mono_exit } from "./run"; -import { DotnetModuleConfig, MonoConfig, MonoConfigInternal, mono_assert, RuntimeAPI } from "./types"; - -export interface DotnetHostBuilder { - withConfig(config: MonoConfig): DotnetHostBuilder - withConfigSrc(configSrc: string): DotnetHostBuilder - withApplicationArguments(...args: string[]): DotnetHostBuilder - withEnvironmentVariable(name: string, value: string): DotnetHostBuilder - withEnvironmentVariables(variables: { [i: string]: string; }): DotnetHostBuilder - withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder - withDiagnosticTracing(enabled: boolean): DotnetHostBuilder - withDebugging(level: number): DotnetHostBuilder - withMainAssembly(mainAssemblyName: string): DotnetHostBuilder - withApplicationArgumentsFromQuery(): DotnetHostBuilder - withStartupMemoryCache(value: boolean): DotnetHostBuilder - create(): Promise - run(): Promise -} +import { mono_assert } from "./types"; +import { setup_proxy_console } from "./logging"; +import { deep_merge_config, deep_merge_module } from "./config"; +import { initializeExports } from "./exports"; + +export const earlyExports: EarlyExports = { + mono: {}, + binding: {}, + internal: {}, + module: {}, + helpers: {}, + api: {} +} as any; +const module: DotnetModuleInternal = Object.assign(earlyExports.module, { + disableDotnet6Compatibility: true, + config: {} +}); +const monoConfig: MonoConfigInternal = Object.assign(module.config!, {}) as any; +const helpers: RuntimeHelpers = earlyExports.helpers; +const api: RuntimeAPI = Object.assign(earlyExports.api, { Module: module, ...module }); +Object.assign(api, { + INTERNAL: earlyExports.internal, +}); + +set_module_and_helpers(module, helpers, earlyExports.internal); -class HostBuilder implements DotnetHostBuilder { +export class HostBuilder implements DotnetHostBuilder { private instance?: RuntimeAPI; private applicationArguments?: string[]; private virtualWorkingDirectory?: string; - private moduleConfig: DotnetModuleConfig = { - disableDotnet6Compatibility: true, - configSrc: "./mono-config.json", - config: runtimeHelpers.config, - }; // internal withModuleConfig(moduleConfig: DotnetModuleConfig): DotnetHostBuilder { try { - Object.assign(this.moduleConfig!, moduleConfig); + deep_merge_module(module, moduleConfig); return this; } catch (err) { mono_exit(1, err); @@ -48,10 +53,9 @@ class HostBuilder implements DotnetHostBuilder { // internal withConsoleForwarding(): DotnetHostBuilder { try { - const configInternal: MonoConfigInternal = { + deep_merge_config(monoConfig, { forwardConsoleLogsToWS: true - }; - Object.assign(this.moduleConfig.config!, configInternal); + }); return this; } catch (err) { mono_exit(1, err); @@ -85,10 +89,9 @@ class HostBuilder implements DotnetHostBuilder { // internal withAsyncFlushOnExit(): DotnetHostBuilder { try { - const configInternal: MonoConfigInternal = { + deep_merge_config(monoConfig, { asyncFlushOnExit: true - }; - Object.assign(this.moduleConfig.config!, configInternal); + }); return this; } catch (err) { mono_exit(1, err); @@ -99,10 +102,9 @@ class HostBuilder implements DotnetHostBuilder { // internal withExitCodeLogging(): DotnetHostBuilder { try { - const configInternal: MonoConfigInternal = { + deep_merge_config(monoConfig, { logExitCode: true - }; - Object.assign(this.moduleConfig.config!, configInternal); + }); return this; } catch (err) { mono_exit(1, err); @@ -113,10 +115,9 @@ class HostBuilder implements DotnetHostBuilder { // internal withElementOnExit(): DotnetHostBuilder { try { - const configInternal: MonoConfigInternal = { + deep_merge_config(monoConfig, { appendElementOnExit: true - }; - Object.assign(this.moduleConfig.config!, configInternal); + }); return this; } catch (err) { mono_exit(1, err); @@ -128,10 +129,9 @@ class HostBuilder implements DotnetHostBuilder { // todo fallback later by debugLevel withWaitingForDebugger(level: number): DotnetHostBuilder { try { - const configInternal: MonoConfigInternal = { + deep_merge_config(monoConfig, { waitForDebugger: level - }; - Object.assign(this.moduleConfig.config!, configInternal); + }); return this; } catch (err) { mono_exit(1, err); @@ -141,10 +141,9 @@ class HostBuilder implements DotnetHostBuilder { withStartupMemoryCache(value: boolean): DotnetHostBuilder { try { - const configInternal: MonoConfigInternal = { + deep_merge_config(monoConfig, { startupMemoryCache: value - }; - Object.assign(this.moduleConfig.config!, configInternal); + }); return this; } catch (err) { mono_exit(1, err); @@ -154,10 +153,7 @@ class HostBuilder implements DotnetHostBuilder { withConfig(config: MonoConfig): DotnetHostBuilder { try { - const providedConfig = { ...config }; - providedConfig.assets = [...(this.moduleConfig.config!.assets || []), ...(providedConfig.assets || [])]; - providedConfig.environmentVariables = { ...(this.moduleConfig.config!.environmentVariables || {}), ...(providedConfig.environmentVariables || {}) }; - Object.assign(this.moduleConfig.config!, providedConfig); + deep_merge_config(monoConfig, config); return this; } catch (err) { mono_exit(1, err); @@ -168,7 +164,7 @@ class HostBuilder implements DotnetHostBuilder { withConfigSrc(configSrc: string): DotnetHostBuilder { try { mono_assert(configSrc && typeof configSrc === "string", "must be file path or URL"); - Object.assign(this.moduleConfig, { configSrc }); + deep_merge_module(module, { configSrc }); return this; } catch (err) { mono_exit(1, err); @@ -189,7 +185,11 @@ class HostBuilder implements DotnetHostBuilder { withEnvironmentVariable(name: string, value: string): DotnetHostBuilder { try { - this.moduleConfig.config!.environmentVariables![name] = value; + const environmentVariables: { [key: string]: string } = {}; + environmentVariables[name] = value; + deep_merge_config(monoConfig, { + environmentVariables + }); return this; } catch (err) { mono_exit(1, err); @@ -200,7 +200,9 @@ class HostBuilder implements DotnetHostBuilder { withEnvironmentVariables(variables: { [i: string]: string; }): DotnetHostBuilder { try { mono_assert(variables && typeof variables === "object", "must be dictionary object"); - Object.assign(this.moduleConfig.config!.environmentVariables!, variables); + deep_merge_config(monoConfig, { + environmentVariables: variables + }); return this; } catch (err) { mono_exit(1, err); @@ -211,7 +213,9 @@ class HostBuilder implements DotnetHostBuilder { withDiagnosticTracing(enabled: boolean): DotnetHostBuilder { try { mono_assert(typeof enabled === "boolean", "must be boolean"); - this.moduleConfig.config!.diagnosticTracing = enabled; + deep_merge_config(monoConfig, { + diagnosticTracing: enabled + }); return this; } catch (err) { mono_exit(1, err); @@ -222,7 +226,9 @@ class HostBuilder implements DotnetHostBuilder { withDebugging(level: number): DotnetHostBuilder { try { mono_assert(level && typeof level === "number", "must be number"); - this.moduleConfig.config!.debugLevel = level; + deep_merge_config(monoConfig, { + debugLevel: level + }); return this; } catch (err) { mono_exit(1, err); @@ -244,8 +250,9 @@ class HostBuilder implements DotnetHostBuilder { withRuntimeOptions(runtimeOptions: string[]): DotnetHostBuilder { try { mono_assert(runtimeOptions && Array.isArray(runtimeOptions), "must be array of strings"); - const configInternal = this.moduleConfig.config as MonoConfigInternal; - configInternal.runtimeOptions = [...(configInternal.runtimeOptions || []), ...(runtimeOptions || [])]; + deep_merge_config(monoConfig, { + runtimeOptions + }); return this; } catch (err) { mono_exit(1, err); @@ -255,7 +262,9 @@ class HostBuilder implements DotnetHostBuilder { withMainAssembly(mainAssemblyName: string): DotnetHostBuilder { try { - this.moduleConfig.config!.mainAssemblyName = mainAssemblyName; + deep_merge_config(monoConfig, { + mainAssemblyName + }); return this; } catch (err) { mono_exit(1, err); @@ -283,15 +292,16 @@ class HostBuilder implements DotnetHostBuilder { } withStartupOptions(startupOptions: Partial): DotnetHostBuilder { - const configInternal = this.moduleConfig.config as MonoConfigInternal; - configInternal.startupOptions = startupOptions; + deep_merge_config(monoConfig, { + startupOptions + }); return this.withConfigSrc("blazor.boot.json"); } async create(): Promise { try { if (!this.instance) { - if (ENVIRONMENT_IS_WEB && (this.moduleConfig.config! as MonoConfigInternal).forwardConsoleLogsToWS && typeof globalThis.WebSocket != "undefined") { + if (ENVIRONMENT_IS_WEB && (module.config! as MonoConfigInternal).forwardConsoleLogsToWS && typeof globalThis.WebSocket != "undefined") { setup_proxy_console("main", globalThis.console, globalThis.location.origin); } if (ENVIRONMENT_IS_NODE) { @@ -302,9 +312,10 @@ class HostBuilder implements DotnetHostBuilder { throw new Error(`NodeJS at '${process.execPath}' has too low version '${process.versions.node}'`); } } - mono_assert(this.moduleConfig, "Null moduleConfig"); - mono_assert(this.moduleConfig.config, "Null moduleConfig.config"); - this.instance = await emscriptenEntrypoint(this.moduleConfig); + mono_assert(module, "Null moduleConfig"); + mono_assert(module.config, "Null moduleConfig.config"); + await createEmscripten(module); + this.instance = api; } if (this.virtualWorkingDirectory) { const FS = (this.instance!.Module as any).FS; @@ -321,11 +332,11 @@ class HostBuilder implements DotnetHostBuilder { async run(): Promise { try { - mono_assert(this.moduleConfig.config, "Null moduleConfig.config"); + mono_assert(module.config, "Null moduleConfig.config"); if (!this.instance) { await this.create(); } - mono_assert(this.moduleConfig.config.mainAssemblyName, "Null moduleConfig.config.mainAssemblyName"); + mono_assert(module.config.mainAssemblyName, "Null moduleConfig.config.mainAssemblyName"); if (!this.applicationArguments) { if (ENVIRONMENT_IS_NODE) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -336,7 +347,7 @@ class HostBuilder implements DotnetHostBuilder { this.applicationArguments = []; } } - return this.instance!.runMainAndExit(this.moduleConfig.config.mainAssemblyName, this.applicationArguments!); + return this.instance!.runMainAndExit(module.config.mainAssemblyName, this.applicationArguments!); } catch (err) { mono_exit(1, err); throw err; @@ -344,4 +355,23 @@ class HostBuilder implements DotnetHostBuilder { } } -export const dotnet: DotnetHostBuilder = new HostBuilder(); +export function unifyModuleConfig(originalModule: EmscriptenModuleInternal, moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): DotnetModuleConfig { + initializeExports(earlyExports); + Object.assign(module, { ready: originalModule.ready }); + if (typeof moduleFactory === "function") { + const extension = moduleFactory(api) as any; + if (extension.ready) { + throw new Error("MONO_WASM: Module.ready couldn't be redefined."); + } + Object.assign(module, extension); + deep_merge_module(module, extension); + } + else if (typeof moduleFactory === "object") { + deep_merge_module(module, moduleFactory); + } + else { + throw new Error("MONO_WASM: Can't use moduleFactory callback of createDotnetRuntime function."); + } + + return module; +} diff --git a/src/mono/wasm/runtime/run.ts b/src/mono/wasm/runtime/run.ts index 27d1a65fd6fb60..e5d1136828a09e 100644 --- a/src/mono/wasm/runtime/run.ts +++ b/src/mono/wasm/runtime/run.ts @@ -64,7 +64,7 @@ export function mono_on_abort(error: any): void { // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function mono_exit(exit_code: number, reason?: any): void { - if (runtimeHelpers.config.asyncFlushOnExit && exit_code === 0) { + if (runtimeHelpers.config && runtimeHelpers.config.asyncFlushOnExit && exit_code === 0) { // this would NOT call Node's exit() immediately, it's a hanging promise (async () => { try { @@ -136,7 +136,7 @@ function set_exit_code_and_quit_now(exit_code: number, reason?: any): void { } function appendElementOnExit(exit_code: number) { - if (ENVIRONMENT_IS_WEB && runtimeHelpers.config.appendElementOnExit) { + 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"; @@ -147,7 +147,7 @@ function appendElementOnExit(exit_code: number) { } function logErrorOnExit(exit_code: number, reason?: any) { - if (runtimeHelpers.config.logExitCode) { + 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)); diff --git a/src/mono/wasm/runtime/snapshot.ts b/src/mono/wasm/runtime/snapshot.ts index eb96dec46c5611..e3f2c24997bdc3 100644 --- a/src/mono/wasm/runtime/snapshot.ts +++ b/src/mono/wasm/runtime/snapshot.ts @@ -4,7 +4,7 @@ import ProductVersion from "consts:productVersion"; import GitHash from "consts:gitHash"; import MonoWasmThreads from "consts:monoWasmThreads"; -import { runtimeHelpers } from "./imports"; +import { ENVIRONMENT_IS_WEB, runtimeHelpers } from "./imports"; const memoryPrefix = "https://dotnet.generated.invalid/wasm-memory"; diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index 92c644c64a182b..eb31d66f7e52d9 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -4,8 +4,11 @@ import BuildConfiguration from "consts:configuration"; import MonoWasmThreads from "consts:monoWasmThreads"; import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop"; -import { CharPtrNull, DotnetModule, RuntimeAPI, MonoConfig, MonoConfigInternal, DotnetModuleInternal, mono_assert } from "./types"; -import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, disableLegacyJsInterop, INTERNAL, Module, runtimeHelpers } from "./imports"; +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 "./imports"; import cwraps, { init_c_exports } from "./cwraps"; import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug"; import { toBase64StringImpl } from "./base64"; @@ -52,8 +55,27 @@ const MONO_PTHREAD_POOL_SIZE = 4; // we are making emscripten startup async friendly // emscripten is executing the events without awaiting it and so we need to block progress via PromiseControllers above -export function configure_emscripten_startup(module: DotnetModuleInternal, exportedAPI: RuntimeAPI): void { +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"]) { + // this is dummy plug so that wasmBinaryFile doesn't try to use URL class + module["locateFile"] = module["__locateFile"] = (path) => runtimeHelpers.scriptDirectory + path; + } + + if (!module.out) { + module.out = console.log.bind(console); + } + + if (!module.err) { + module.err = console.error.bind(console); + } + // 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 userInstantiateWasm: undefined | ((imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback) => any) = module.instantiateWasm; @@ -83,7 +105,7 @@ export function configure_emscripten_startup(module: DotnetModuleInternal, expor endMeasure(mark, MeasuredBlock.emscriptenStartup); // - here we resolve the promise returned by createDotnetRuntime export // - any code after createDotnetRuntime is executed now - dotnetReady.promise_control.resolve(exportedAPI); + dotnetReady.promise_control.resolve(exportedRuntimeAPI); }).catch(err => { dotnetReady.promise_control.reject(err); }); @@ -94,7 +116,6 @@ export function configure_emscripten_startup(module: DotnetModuleInternal, expor } } - function instantiateWasm( imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback, @@ -210,11 +231,11 @@ export function preRunWorker() { async function preRunAsync(userPreRun: (() => void)[]) { Module.addRunDependency("mono_pre_run_async"); // wait for previous stages - await afterInstantiateWasm.promise; - await afterPreInit.promise; - if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: preRunAsync"); - const mark = startMeasure(); try { + await afterInstantiateWasm.promise; + await afterPreInit.promise; + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: preRunAsync"); + const mark = startMeasure(); // all user Module.preRun callbacks userPreRun.map(fn => fn()); endMeasure(mark, MeasuredBlock.preRun); @@ -229,13 +250,14 @@ async function preRunAsync(userPreRun: (() => void)[]) { } async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) { - // wait for previous stage - await 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(); try { + // wait for previous stage + await 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(); + await wait_for_all_assets(); // Diagnostics early are not supported with memory snapshot. See below how we enable them later. @@ -302,9 +324,9 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) { async function postRunAsync(userpostRun: (() => void)[]) { // wait for previous stage - await afterOnRuntimeInitialized.promise; - if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: postRunAsync"); try { + await afterOnRuntimeInitialized.promise; + if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: postRunAsync"); const mark = startMeasure(); // create /usr/share folder which is SpecialFolder.CommonApplicationData @@ -335,8 +357,15 @@ export function abort_startup(reason: any, should_exit: boolean): void { beforeOnRuntimeInitialized.promise_control.reject(reason); afterOnRuntimeInitialized.promise_control.reject(reason); afterPostRun.promise_control.reject(reason); - if (should_exit && (typeof reason !== "object" || reason.silent !== true)) { - mono_exit(1, 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; } } @@ -346,7 +375,6 @@ function mono_wasm_pre_init_essential(isWorker: boolean): void { if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_wasm_pre_init_essential"); - // init_polyfills() is already called from export.ts init_c_exports(); cwraps_internal(INTERNAL); if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) { @@ -595,13 +623,7 @@ export function mono_wasm_load_runtime(unused?: string, debugLevel?: number): vo } catch (err: any) { _print_error("MONO_WASM: mono_wasm_load_runtime () failed", err); - abort_startup(err, false); - if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) { - const wasm_exit = cwraps.mono_wasm_exit; - wasm_exit(1); - } - throw err; } } @@ -667,7 +689,7 @@ export async function mono_wasm_load_config(configFilePath?: string): Promiseconfig); + await Module.onConfigLoaded(config, exportedRuntimeAPI); normalizeConfig(); } catch (err: any) { @@ -678,11 +700,10 @@ export async function mono_wasm_load_config(configFilePath?: string): Promise{ message: errMessage, error: err, isError: true }; + abort_startup(errMessage, true); throw err; } - } function normalizeConfig() { @@ -757,17 +778,15 @@ export function mono_wasm_set_main_args(name: string, allRuntimeArguments: strin /// 1. Emscripten skips a lot of initialization on the pthread workers, Module may not have everything you expect. /// 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 mono_wasm_pthread_worker_init(module: DotnetModule, exportedAPI: RuntimeAPI): Promise { +export async function configureWorkerStartup(module: DotnetModuleInternal): Promise { 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) => { console.debug("MONO_WASM: pthread created", ev.pthread_self.pthread_id); }); - // this is the only event which is called on worker + // these are the only events which are called on worker module.preInit = [() => preInitWorkerAsync()]; module.instantiateWasm = instantiateWasmWorker; - await afterPreInit.promise; - return exportedAPI.Module; } diff --git a/src/mono/wasm/runtime/types-api.ts b/src/mono/wasm/runtime/types-api.ts new file mode 100644 index 00000000000000..3fd1c327e0c1d7 --- /dev/null +++ b/src/mono/wasm/runtime/types-api.ts @@ -0,0 +1,245 @@ +import type { EmscriptenModule, NativePointer } from "./types/emscripten"; + +export interface DotnetHostBuilder { + withConfig(config: MonoConfig): DotnetHostBuilder + withConfigSrc(configSrc: string): DotnetHostBuilder + withApplicationArguments(...args: string[]): DotnetHostBuilder + withEnvironmentVariable(name: string, value: string): DotnetHostBuilder + withEnvironmentVariables(variables: { [i: string]: string; }): DotnetHostBuilder + withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder + withDiagnosticTracing(enabled: boolean): DotnetHostBuilder + withDebugging(level: number): DotnetHostBuilder + withMainAssembly(mainAssemblyName: string): DotnetHostBuilder + withApplicationArgumentsFromQuery(): DotnetHostBuilder + create(): Promise + run(): Promise +} + +export type MonoConfig = { + /** + * The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script. + */ + assemblyRootFolder?: string, + /** + * A list of assets to load along with the runtime. + */ + assets?: AssetEntry[], + /** + * Additional search locations for assets. + */ + remoteSources?: string[], // Sources will be checked in sequential order until the asset is found. The string "./" indicates to load from the application directory (as with the files in assembly_list), and a fully-qualified URL like "https://example.com/" indicates that asset loads can be attempted from a remote server. Sources must end with a "/". + /** + * It will not fail the startup is .pdb files can't be downloaded + */ + ignorePdbLoadErrors?: boolean, + /** + * We are throttling parallel downloads in order to avoid net::ERR_INSUFFICIENT_RESOURCES on chrome. The default value is 16. + */ + maxParallelDownloads?: number, + /** + * We are making up to 2 more delayed attempts to download same asset. Default true. + */ + enableDownloadRetry?: boolean, + /** + * Name of the assembly with main entrypoint + */ + mainAssemblyName?: string, + /** + * Configures the runtime's globalization mode + */ + globalizationMode?: GlobalizationMode, + /** + * debugLevel > 0 enables debugging and sets the debug log level to debugLevel + * debugLevel == 0 disables debugging and enables interpreter optimizations + * debugLevel < 0 enabled debugging and disables debug logging. + */ + debugLevel?: number, + /** + * Enables diagnostic log messages during startup + */ + diagnosticTracing?: boolean + /** + * Dictionary-style Object containing environment variables + */ + environmentVariables?: { + [i: string]: string; + }, + /** + * initial number of workers to add to the emscripten pthread pool + */ + pthreadPoolSize?: number, + /** + * If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false. + */ + startupMemoryCache?: boolean, + /** + * hash of assets + */ + assetsHash?: string, + /** + * application environment + */ + applicationEnvironment?: string +}; + +export interface ResourceRequest { + name: string, // the name of the asset, including extension. + behavior: AssetBehaviours, // determines how the asset will be handled once loaded + resolvedUrl?: string; + hash?: string; +} + +export interface LoadingResource { + name: string; + url: string; + response: Promise; +} + +// Types of assets that can be in the mono-config.js/mono-config.json file (taken from /src/tasks/WasmAppBuilder/WasmAppBuilder.cs) +export interface AssetEntry extends ResourceRequest { + /** + * If specified, overrides the path of the asset in the virtual filesystem and similar data structures once downloaded. + */ + virtualPath?: string, + /** + * Culture code + */ + culture?: string, + /** + * If true, an attempt will be made to load the asset from each location in MonoConfig.remoteSources. + */ + loadRemote?: boolean, // + /** + * If true, the runtime startup would not fail if the asset download was not successful. + */ + isOptional?: boolean + /** + * If provided, runtime doesn't have to fetch the data. + * Runtime would set the buffer to null after instantiation to free the memory. + */ + buffer?: ArrayBuffer + /** + * It's metadata + fetch-like Promise + * If provided, the runtime doesn't have to initiate the download. It would just await the response. + */ + pendingDownload?: 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 javascript module for threads + +export 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 + "auto" // (default): if "icu" behavior assets are present, use ICU, otherwise invariant. + +export type DotnetModuleConfig = { + disableDotnet6Compatibility?: boolean, + + config?: MonoConfig, + configSrc?: string, + onConfigLoaded?: (config: MonoConfig) => void | Promise; + onDotnetReady?: () => void | Promise; + onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void; + getApplicationEnvironment?: (bootConfigResponse: Response) => string | null; + + imports?: any; + exports?: string[]; + downloadResource?: (request: ResourceRequest) => LoadingResource | undefined +} & Partial + +export type APIType = { + runMain: (mainAssemblyName: string, args: string[]) => Promise, + runMainAndExit: (mainAssemblyName: string, args: string[]) => Promise, + setEnvironmentVariable: (name: string, value: string) => void, + getAssemblyExports(assemblyName: string): Promise, + setModuleImports(moduleName: string, moduleImports: any): void, + getConfig: () => MonoConfig, + setHeapB32: (offset: NativePointer, value: number | boolean) => void, + setHeapU8: (offset: NativePointer, value: number) => void, + setHeapU16: (offset: NativePointer, value: number) => void, + setHeapU32: (offset: NativePointer, value: NativePointer | number) => void, + setHeapI8: (offset: NativePointer, value: number) => void, + setHeapI16: (offset: NativePointer, value: number) => void, + setHeapI32: (offset: NativePointer, value: number) => void, + setHeapI52: (offset: NativePointer, value: number) => void, + setHeapU52: (offset: NativePointer, value: number) => void, + setHeapI64Big: (offset: NativePointer, value: bigint) => void, + setHeapF32: (offset: NativePointer, value: number) => void, + setHeapF64: (offset: NativePointer, value: number) => void, + getHeapB32: (offset: NativePointer) => boolean, + getHeapU8: (offset: NativePointer) => number, + getHeapU16: (offset: NativePointer) => number, + getHeapU32: (offset: NativePointer) => number, + getHeapI8: (offset: NativePointer) => number, + getHeapI16: (offset: NativePointer) => number, + getHeapI32: (offset: NativePointer) => number, + getHeapI52: (offset: NativePointer) => number, + getHeapU52: (offset: NativePointer) => number, + getHeapI64Big: (offset: NativePointer) => bigint, + getHeapF32: (offset: NativePointer) => number, + getHeapF64: (offset: NativePointer) => number, +} + +export type RuntimeAPI = { + /** + * @deprecated Please use API object instead. See also MONOType in dotnet-legacy.d.ts + */ + MONO: any, + /** + * @deprecated Please use API object instead. See also BINDINGType in dotnet-legacy.d.ts + */ + BINDING: any, + INTERNAL: any, + Module: EmscriptenModule, + runtimeId: number, + runtimeBuildInfo: { + productVersion: string, + gitHash: string, + buildConfiguration: string, + } +} & APIType + +export type ModuleAPI = { + dotnet: DotnetHostBuilder; + exit: (code: number, reason?: any) => void +} + +export type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise; + +export interface WebAssemblyStartOptions { + /** + * Overrides the built-in boot resource loading mechanism so that boot resources can be fetched + * from a custom source, such as an external CDN. + * @param type The type of the resource to be loaded. + * @param name The name of the resource to be loaded. + * @param defaultUri The URI from which the framework would fetch the resource by default. The URI may be relative or absolute. + * @param integrity The integrity string representing the expected content in the response. + * @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior. + */ + loadBootResource(type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string): string | Promise | null | undefined; + + /** + * Override built-in environment setting on start. + */ + environment?: string; + + /** + * Gets the application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47 + */ + applicationCulture?: string; +} + +// This type doesn't have to align with anything in BootConfig. +// Instead, this represents the public API through which certain aspects +// of boot resource loading can be customized. +export type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration"; \ No newline at end of file diff --git a/src/mono/wasm/runtime/types.ts b/src/mono/wasm/runtime/types.ts index 98c14d0fd33af5..f4762513c83cd4 100644 --- a/src/mono/wasm/runtime/types.ts +++ b/src/mono/wasm/runtime/types.ts @@ -1,9 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { WebAssemblyStartOptions } from "./blazor/WebAssemblyStartOptions"; -import { DotnetHostBuilder } from "./run-outer"; -import { CharPtr, EmscriptenModule, ManagedPointer, NativePointer, VoidPtr, Int32Ptr, EmscriptenModuleInternal } from "./types/emscripten"; +import { AssetEntry, DotnetModuleConfig, LoadingResource, MonoConfig, RuntimeAPI, WebAssemblyStartOptions } from "./types-api"; +import { CharPtr, EmscriptenModule, ManagedPointer, NativePointer, VoidPtr, Int32Ptr } from "./types/emscripten"; export type GCHandle = { __brand: "GCHandle" @@ -67,74 +66,6 @@ export function coerceNull(ptr: T | nu return ptr as T; } -export type MonoConfig = { - /** - * The subfolder containing managed assemblies and pdbs. This is relative to dotnet.js script. - */ - assemblyRootFolder?: string, - /** - * A list of assets to load along with the runtime. - */ - assets?: AssetEntry[], - /** - * Additional search locations for assets. - */ - remoteSources?: string[], // Sources will be checked in sequential order until the asset is found. The string "./" indicates to load from the application directory (as with the files in assembly_list), and a fully-qualified URL like "https://example.com/" indicates that asset loads can be attempted from a remote server. Sources must end with a "/". - /** - * It will not fail the startup is .pdb files can't be downloaded - */ - ignorePdbLoadErrors?: boolean, - /** - * We are throttling parallel downloads in order to avoid net::ERR_INSUFFICIENT_RESOURCES on chrome. The default value is 16. - */ - maxParallelDownloads?: number, - /** - * We are making up to 2 more delayed attempts to download same asset. Default true. - */ - enableDownloadRetry?: boolean, - /** - * Name of the assembly with main entrypoint - */ - mainAssemblyName?: string, - /** - * Configures the runtime's globalization mode - */ - globalizationMode?: GlobalizationMode, - /** - * debugLevel > 0 enables debugging and sets the debug log level to debugLevel - * debugLevel == 0 disables debugging and enables interpreter optimizations - * debugLevel < 0 enabled debugging and disables debug logging. - */ - debugLevel?: number, - /** - * Enables diagnostic log messages during startup - */ - diagnosticTracing?: boolean - /** - * Dictionary-style Object containing environment variables - */ - environmentVariables?: { - [i: string]: string; - }, - /** - * initial number of workers to add to the emscripten pthread pool - */ - pthreadPoolSize?: number, - /** - * If true, the snapshot of runtime's memory will be stored in the browser and used for faster startup next time. Default is false. - */ - startupMemoryCache?: boolean, - /** - * hash of assets - */ - assetsHash?: string, - - /** - * application environment - */ - applicationEnvironment?: string -}; - export type MonoConfigInternal = MonoConfig & { runtimeOptions?: string[], // array of runtime options as strings aotProfilerOptions?: AOTProfilerOptions, // dictionary-style Object. If omitted, aot profiler will not be initialized. @@ -156,49 +87,6 @@ export type RunArguments = { diagnosticTracing?: boolean, } -export interface ResourceRequest { - name: string, // the name of the asset, including extension. - behavior: AssetBehaviours, // determines how the asset will be handled once loaded - resolvedUrl?: string; - hash?: string; -} - -export interface LoadingResource { - name: string; - url: string; - response: Promise; -} - -// Types of assets that can be in the mono-config.js/mono-config.json file (taken from /src/tasks/WasmAppBuilder/WasmAppBuilder.cs) -export interface AssetEntry extends ResourceRequest { - /** - * If specified, overrides the path of the asset in the virtual filesystem and similar data structures once downloaded. - */ - virtualPath?: string, - /** - * Culture code - */ - culture?: string, - /** - * If true, an attempt will be made to load the asset from each location in MonoConfig.remoteSources. - */ - loadRemote?: boolean, // - /** - * If true, the runtime startup would not fail if the asset download was not successful. - */ - isOptional?: boolean - /** - * If provided, runtime doesn't have to fetch the data. - * Runtime would set the buffer to null after instantiation to free the memory. - */ - buffer?: ArrayBuffer - /** - * It's metadata + fetch-like Promise - * If provided, the runtime doesn't have to initiate the download. It would just await the response. - */ - pendingDownload?: LoadingResource -} - export interface AssetEntryInternal extends AssetEntry { // this is almost the same as pendingDownload, but it could have multiple values in time, because of re-try download logic pendingDownloadInternal?: LoadingResource @@ -249,13 +137,6 @@ export type RuntimeHelpers = { updateMemoryViews: () => void } -export 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 - "auto" // (default): if "icu" behavior assets are present, use ICU, otherwise invariant. - - export type AOTProfilerOptions = { writeAt?: string, // should be in the format ::, default: 'WebAssembly.Runtime::StopProfile' sendTo?: string // should be in the format ::, default: 'WebAssembly.Runtime::DumpAotProfileData' (DumpAotProfileData stores the data into INTERNAL.aotProfileData.) @@ -268,20 +149,6 @@ export type BrowserProfilerOptions = { export type DotnetModule = EmscriptenModule & DotnetModuleConfig; export type DotnetModuleInternal = EmscriptenModule & DotnetModuleConfig & EmscriptenModuleInternal; -export type DotnetModuleConfig = { - disableDotnet6Compatibility?: boolean, - - config?: MonoConfig, - configSrc?: string, - onConfigLoaded?: (config: MonoConfig) => void | Promise; - onDotnetReady?: () => void | Promise; - onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void; - getApplicationEnvironment?: (bootConfigResponse: Response) => string | null; - - imports?: any; - exports?: string[]; - downloadResource?: (request: ResourceRequest) => LoadingResource | undefined -} & Partial export type DotnetModuleConfigImports = { require?: (name: string) => any; @@ -365,7 +232,6 @@ export function is_nullish(value: T | null | undefined): value is null | unde } export type EarlyImports = { - isGlobal: boolean, isNode: boolean, isWorker: boolean, isShell: boolean, @@ -381,17 +247,18 @@ export type EarlyExports = { binding: any, internal: any, module: any, - marshaled_imports: any, + helpers: any, + api: any, }; export type EarlyReplacements = { fetch: any, require: any, requirePromise: Promise, - noExitRuntime: boolean, updateMemoryViews: Function, pthreadReplacements: PThreadReplacements | undefined | null scriptDirectory: string; scriptUrl: string + noExitRuntime?: boolean; } export interface ExitStatusError { new(status: number): any; @@ -531,64 +398,26 @@ export interface WasmRootBuffer { toString(): string; } -export type APIType = { - runMain: (mainAssemblyName: string, args: string[]) => Promise, - runMainAndExit: (mainAssemblyName: string, args: string[]) => Promise, - setEnvironmentVariable: (name: string, value: string) => void, - getAssemblyExports(assemblyName: string): Promise, - setModuleImports(moduleName: string, moduleImports: any): void, - getConfig: () => MonoConfig, - setHeapB32: (offset: NativePointer, value: number | boolean) => void, - setHeapU8: (offset: NativePointer, value: number) => void, - setHeapU16: (offset: NativePointer, value: number) => void, - setHeapU32: (offset: NativePointer, value: NativePointer | number) => void, - setHeapI8: (offset: NativePointer, value: number) => void, - setHeapI16: (offset: NativePointer, value: number) => void, - setHeapI32: (offset: NativePointer, value: number) => void, - setHeapI52: (offset: NativePointer, value: number) => void, - setHeapU52: (offset: NativePointer, value: number) => void, - setHeapI64Big: (offset: NativePointer, value: bigint) => void, - setHeapF32: (offset: NativePointer, value: number) => void, - setHeapF64: (offset: NativePointer, value: number) => void, - getHeapB32: (offset: NativePointer) => boolean, - getHeapU8: (offset: NativePointer) => number, - getHeapU16: (offset: NativePointer) => number, - getHeapU32: (offset: NativePointer) => number, - getHeapI8: (offset: NativePointer) => number, - getHeapI16: (offset: NativePointer) => number, - getHeapI32: (offset: NativePointer) => number, - getHeapI52: (offset: NativePointer) => number, - getHeapU52: (offset: NativePointer) => number, - getHeapI64Big: (offset: NativePointer) => bigint, - getHeapF32: (offset: NativePointer) => number, - getHeapF64: (offset: NativePointer) => number, -} - -// this represents visibility in the javascript -// like https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web.JS/src/Platform/Mono/MonoTypes.ts -export type RuntimeAPI = { - /** - * @deprecated Please use API object instead. See also MONOType in dotnet-legacy.d.ts - */ - MONO: any, - /** - * @deprecated Please use API object instead. See also BINDINGType in dotnet-legacy.d.ts - */ - BINDING: any, - INTERNAL: any, - Module: EmscriptenModule, - runtimeId: number, - runtimeBuildInfo: { - productVersion: string, - gitHash: string, - buildConfiguration: string, - } -} & APIType - -export type ModuleAPI = { - dotnet: DotnetHostBuilder; - exit: (code: number, reason?: any) => void +export declare interface EmscriptenModuleInternal { + __locateFile?: (path: string, prefix?: string) => string; + locateFile?: (path: string, prefix?: string) => string; + mainScriptUrlOrBlob?: string; + wasmModule: WebAssembly.Instance | null; + ready: Promise; + asm: { memory?: WebAssembly.Memory }; + wasmMemory?: WebAssembly.Memory; + getWasmTableEntry(index: number): any; + removeRunDependency(id: string): void; + addRunDependency(id: string): void; + initializeImportsAndExports: (imports: EarlyImports, replacements: EarlyReplacements) => void; + onConfigLoaded?: (config: MonoConfig, api: RuntimeAPI) => void | Promise; } -export declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise; -export type CreateDotnetRuntimeType = typeof createDotnetRuntime; +export declare function initializeImportsAndExports( + imports: EarlyImports, + exports: EarlyExports, +): RuntimeAPI; + +export type RuntimeModuleAPI = { + initializeImportsAndExports: typeof initializeImportsAndExports; +} diff --git a/src/mono/wasm/runtime/types/consts.d.ts b/src/mono/wasm/runtime/types/consts.d.ts index f286d28da3b045..58c96f36e9af33 100644 --- a/src/mono/wasm/runtime/types/consts.d.ts +++ b/src/mono/wasm/runtime/types/consts.d.ts @@ -18,6 +18,5 @@ declare module "consts:monoDiagnosticsMock" { export default constant; } -// these constants from dotnet.es6.extpost.js duplicate detection inside emscripten internals, but happen earlier -declare const ENVIRONMENT_IS_NODE: boolean; -declare const ENVIRONMENT_IS_WEB: boolean; \ No newline at end of file +declare function createEmscripten(module: any): Promise; +declare const earlyExports: any; diff --git a/src/mono/wasm/runtime/types/emscripten.ts b/src/mono/wasm/runtime/types/emscripten.ts index 7c508458a3e1e9..bcefbbbb40b9b6 100644 --- a/src/mono/wasm/runtime/types/emscripten.ts +++ b/src/mono/wasm/runtime/types/emscripten.ts @@ -64,20 +64,6 @@ export declare interface EmscriptenModule { onAbort?: { (error: any): void }; } -export declare interface EmscriptenModuleInternal { - __locateFile?: (path: string, prefix?: string) => string; - locateFile?: (path: string, prefix?: string) => string; - mainScriptUrlOrBlob?: string; - wasmModule: WebAssembly.Instance | null; - ready: Promise; - asm: { memory?: WebAssembly.Memory }; - wasmMemory?: WebAssembly.Memory; - getWasmTableEntry(index: number): any; - removeRunDependency(id: string): void; - addRunDependency(id: string): void; -} - - export type InstantiateWasmSuccessCallback = (instance: WebAssembly.Instance, module: WebAssembly.Module | undefined) => void; export type InstantiateWasmCallBack = (imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback) => any; diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 475163ecfe5c0a..6dcf03a8ab48cc 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -204,10 +204,6 @@ let mono_exit = (code, reason) => { console.log(`test-main failed early ${code} ${reason}`); }; -async function loadDotnet(file) { - return await import(file); -} - const App = { /** Runs a particular test in legacy interop tests * @type {(method_name: string, args: any[]=, signature: any=) => return number} @@ -255,7 +251,7 @@ const App = { }; globalThis.App = App; // Necessary as System.Runtime.InteropServices.JavaScript.Tests.MarshalTests (among others) call the App.call_test_method directly -function configureRuntime(dotnet, runArgs, INTERNAL) { +function configureRuntime(dotnet, runArgs) { dotnet .withVirtualWorkingDirectory(runArgs.workingDirectory) .withEnvironmentVariables(runArgs.environmentVariables) @@ -272,7 +268,7 @@ function configureRuntime(dotnet, runArgs, INTERNAL) { const modulesToLoad = runArgs.environmentVariables["NPM_MODULES"]; if (modulesToLoad) { dotnet.withModuleConfig({ - onConfigLoaded: (config) => { + onConfigLoaded: (config, { INTERNAL }) => { loadNodeModules(config, INTERNAL.require, modulesToLoad) } }) @@ -300,9 +296,9 @@ async function dry_run(runArgs) { try { console.log("Silently starting separate runtime instance as another ES6 module to populate caches..."); // this separate instance of the ES6 module, in which we just populate the caches - const { dotnet, exit, INTERNAL } = await loadDotnet('./dotnet.js?dry_run=true'); + const { dotnet, exit } = await import('./dotnet.js?dry_run=true'); mono_exit = exit; - configureRuntime(dotnet, runArgs, INTERNAL); + configureRuntime(dotnet, runArgs); // silent minimal startup await dotnet.withConfig({ forwardConsoleLogsToWS: false, @@ -338,7 +334,7 @@ async function run() { // this is subsequent run with the actual tests. It will use whatever was cached in the previous run. // This way, we are testing that the cached version works. - const { dotnet, exit, INTERNAL } = await loadDotnet('./dotnet.js'); + const { dotnet, exit, INTERNAL } = await import('./dotnet.js'); mono_exit = exit; if (runArgs.applicationArguments.length == 0) { diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 971ee55a3baa72..cb76cb0d19e025 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -427,7 +427,6 @@ From 57d9b116b684bb1da67bce8ede268af559625fbb Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Thu, 27 Apr 2023 13:43:42 +0200 Subject: [PATCH 2/4] fix early environment --- src/mono/wasm/runtime/imports.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/runtime/imports.ts b/src/mono/wasm/runtime/imports.ts index ee02cfaf732d68..90e5a637ce83bb 100644 --- a/src/mono/wasm/runtime/imports.ts +++ b/src/mono/wasm/runtime/imports.ts @@ -14,9 +14,9 @@ export let Module: EmscriptenModule & DotnetModule & EmscriptenModuleInternal; export let INTERNAL: any; // these are imported and re-exported from emscripten internals -export let ENVIRONMENT_IS_NODE: boolean; +export let ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string"; export let ENVIRONMENT_IS_SHELL: boolean; -export let ENVIRONMENT_IS_WEB: boolean; +export let ENVIRONMENT_IS_WEB = typeof window == "object"; export let ENVIRONMENT_IS_WORKER: boolean; export let ENVIRONMENT_IS_PTHREAD: boolean; export let exportedRuntimeAPI: RuntimeAPI = null as any; From 192ed547e8e4d7d651fa2167080134df3a4ce63f Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Thu, 27 Apr 2023 14:41:58 +0200 Subject: [PATCH 3/4] module earlyExports --- src/mono/wasm/runtime/es6/dotnet.es6.extpost.js | 1 - src/mono/wasm/runtime/es6/dotnet.es6.lib.js | 1 - src/mono/wasm/runtime/types/consts.d.ts | 1 - 3 files changed, 3 deletions(-) diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js b/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js index 27437d8f3a868c..7c42d93dd9c138 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.extpost.js @@ -2,6 +2,5 @@ var fetch = fetch || undefined; var require = require || undefined; var __dirname = __dirname || ''; var createEmscripten = createDotnetRuntime; var unifyModuleConfig = __dotnet_runtime.unifyModuleConfig; -var earlyExports = __dotnet_runtime.earlyExports; export const dotnet = __dotnet_runtime.dotnet; export const exit = __dotnet_runtime.exit; \ No newline at end of file diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js index f581e14ff4fb55..418cbee72552f3 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js @@ -47,7 +47,6 @@ function setup(disableLegacyJsInterop) { #if USE_PTHREADS if (ENVIRONMENT_IS_PTHREAD) { Module.config = {}; - earlyExports.module = Module; __dotnet_runtime.initializeReplacements(dotnet_replacements); __dotnet_runtime.configureWorkerStartup(Module); } else { diff --git a/src/mono/wasm/runtime/types/consts.d.ts b/src/mono/wasm/runtime/types/consts.d.ts index 58c96f36e9af33..11a7e5439e3110 100644 --- a/src/mono/wasm/runtime/types/consts.d.ts +++ b/src/mono/wasm/runtime/types/consts.d.ts @@ -19,4 +19,3 @@ declare module "consts:monoDiagnosticsMock" { } declare function createEmscripten(module: any): Promise; -declare const earlyExports: any; From 8dad84d1689827fd91406a8f51db75d9489cb04e Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 28 Apr 2023 14:41:23 +0200 Subject: [PATCH 4/4] - maraf's feedback - renamed imports.ts to globals.ts - formatted jiterp code --- src/mono/wasm/runtime/assets.ts | 2 +- src/mono/wasm/runtime/blazor/BootConfig.ts | 2 +- src/mono/wasm/runtime/blazor/_Integration.ts | 2 +- src/mono/wasm/runtime/cwraps.ts | 2 +- src/mono/wasm/runtime/debug.ts | 2 +- .../runtime/diagnostics/browser/controller.ts | 2 +- .../diagnostics/server_pthread/index.ts | 2 +- .../diagnostics/server_pthread/mock-remote.ts | 2 +- .../server_pthread/socket-connection.ts | 2 +- src/mono/wasm/runtime/es6/dotnet.es6.lib.js | 4 +- src/mono/wasm/runtime/export-api.ts | 2 +- src/mono/wasm/runtime/exports-internal.ts | 2 +- src/mono/wasm/runtime/exports.ts | 39 +-- src/mono/wasm/runtime/gc-handles.ts | 2 +- src/mono/wasm/runtime/gc-lock.ts | 2 +- src/mono/wasm/runtime/globals.ts | 70 ++++ src/mono/wasm/runtime/http.ts | 2 +- src/mono/wasm/runtime/hybrid-globalization.ts | 46 ++- src/mono/wasm/runtime/icu.ts | 2 +- src/mono/wasm/runtime/imports.ts | 72 ---- src/mono/wasm/runtime/invoke-cs.ts | 2 +- src/mono/wasm/runtime/invoke-js.ts | 2 +- .../wasm/runtime/jiterpreter-interp-entry.ts | 96 ++--- src/mono/wasm/runtime/jiterpreter-jit-call.ts | 167 ++++----- src/mono/wasm/runtime/jiterpreter-support.ts | 224 ++++++------ src/mono/wasm/runtime/jiterpreter.ts | 329 +++++++++++------- src/mono/wasm/runtime/logging.ts | 2 +- src/mono/wasm/runtime/managed-exports.ts | 2 +- src/mono/wasm/runtime/marshal-to-cs.ts | 2 +- src/mono/wasm/runtime/marshal-to-js.ts | 2 +- src/mono/wasm/runtime/marshal.ts | 2 +- src/mono/wasm/runtime/memory.ts | 2 +- src/mono/wasm/runtime/net6-legacy/buffers.ts | 2 +- .../wasm/runtime/net6-legacy/corebindings.ts | 4 +- src/mono/wasm/runtime/net6-legacy/cs-to-js.ts | 2 +- .../runtime/net6-legacy/exports-legacy.ts | 2 +- .../net6-legacy/{imports.ts => globals.ts} | 10 +- src/mono/wasm/runtime/net6-legacy/js-to-cs.ts | 4 +- .../runtime/net6-legacy/method-binding.ts | 4 +- .../wasm/runtime/net6-legacy/method-calls.ts | 2 +- src/mono/wasm/runtime/polyfills.ts | 8 +- src/mono/wasm/runtime/profiler.ts | 2 +- .../wasm/runtime/pthreads/browser/index.ts | 2 +- .../pthreads/shared/emscripten-internals.ts | 2 +- .../shared/emscripten-replacements.ts | 2 +- .../wasm/runtime/pthreads/shared/index.ts | 2 +- .../wasm/runtime/pthreads/worker/index.ts | 2 +- src/mono/wasm/runtime/roots.ts | 2 +- src/mono/wasm/runtime/run-outer.ts | 28 +- src/mono/wasm/runtime/run.ts | 2 +- src/mono/wasm/runtime/snapshot.ts | 2 +- src/mono/wasm/runtime/startup.ts | 4 +- src/mono/wasm/runtime/strings.ts | 2 +- src/mono/wasm/runtime/types.ts | 24 +- src/mono/wasm/runtime/web-socket.ts | 2 +- 55 files changed, 634 insertions(+), 575 deletions(-) create mode 100644 src/mono/wasm/runtime/globals.ts delete mode 100644 src/mono/wasm/runtime/imports.ts rename src/mono/wasm/runtime/net6-legacy/{imports.ts => globals.ts} (82%) diff --git a/src/mono/wasm/runtime/assets.ts b/src/mono/wasm/runtime/assets.ts index 172818415f0e19..fa9366d1bb60af 100644 --- a/src/mono/wasm/runtime/assets.ts +++ b/src/mono/wasm/runtime/assets.ts @@ -3,7 +3,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 { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./globals"; import { parseSymbolMapFile } from "./logging"; import { mono_wasm_load_bytes_into_heap } from "./memory"; import { endMeasure, MeasuredBlock, startMeasure } from "./profiler"; diff --git a/src/mono/wasm/runtime/blazor/BootConfig.ts b/src/mono/wasm/runtime/blazor/BootConfig.ts index e3316250da681d..48c033b7368b38 100644 --- a/src/mono/wasm/runtime/blazor/BootConfig.ts +++ b/src/mono/wasm/runtime/blazor/BootConfig.ts @@ -1,7 +1,7 @@ // 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 "../imports"; +import { Module } from "../globals"; import { WebAssemblyBootResourceType } from "../types-api"; type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) => string | Promise | null | undefined; diff --git a/src/mono/wasm/runtime/blazor/_Integration.ts b/src/mono/wasm/runtime/blazor/_Integration.ts index 7f2fc7060b5f7a..64896bfaa013c8 100644 --- a/src/mono/wasm/runtime/blazor/_Integration.ts +++ b/src/mono/wasm/runtime/blazor/_Integration.ts @@ -1,4 +1,4 @@ -import { INTERNAL, Module } from "../imports"; +import { INTERNAL, Module } from "../globals"; import { MonoConfigInternal } from "../types"; import { AssetEntry, LoadingResource, WebAssemblyBootResourceType } from "../types-api"; import { BootConfigResult, BootJsonData, ICUDataMode } from "./BootConfig"; diff --git a/src/mono/wasm/runtime/cwraps.ts b/src/mono/wasm/runtime/cwraps.ts index c7f73b34db5282..6c6912fd6b6c99 100644 --- a/src/mono/wasm/runtime/cwraps.ts +++ b/src/mono/wasm/runtime/cwraps.ts @@ -8,7 +8,7 @@ import type { } from "./types"; import type { VoidPtr, CharPtrPtr, Int32Ptr, CharPtr, ManagedPointer } from "./types/emscripten"; import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop"; -import { disableLegacyJsInterop, Module } from "./imports"; +import { disableLegacyJsInterop, Module } from "./globals"; type SigLine = [lazy: boolean, name: string, returnType: string | null, argTypes?: string[], opts?: any]; diff --git a/src/mono/wasm/runtime/debug.ts b/src/mono/wasm/runtime/debug.ts index bb856bf45aa33b..7dcc132ff4518d 100644 --- a/src/mono/wasm/runtime/debug.ts +++ b/src/mono/wasm/runtime/debug.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import BuildConfiguration from "consts:configuration"; -import { INTERNAL, Module, runtimeHelpers } from "./imports"; +import { INTERNAL, Module, runtimeHelpers } from "./globals"; import { toBase64StringImpl } from "./base64"; import cwraps from "./cwraps"; import { VoidPtr, CharPtr } from "./types/emscripten"; diff --git a/src/mono/wasm/runtime/diagnostics/browser/controller.ts b/src/mono/wasm/runtime/diagnostics/browser/controller.ts index 35ccb1d64207d4..9eedcdd80aaeff 100644 --- a/src/mono/wasm/runtime/diagnostics/browser/controller.ts +++ b/src/mono/wasm/runtime/diagnostics/browser/controller.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import cwraps from "../../cwraps"; -import { INTERNAL } from "../../imports"; +import { INTERNAL } from "../../globals"; import { withStackAlloc, getI32 } from "../../memory"; import { Thread, waitForThread } from "../../pthreads/browser"; import { isDiagnosticMessage, makeDiagnosticServerControlCommand } from "../shared/controller-commands"; diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/index.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/index.ts index 4f757d092970c6..9d55897033a652 100644 --- a/src/mono/wasm/runtime/diagnostics/server_pthread/index.ts +++ b/src/mono/wasm/runtime/diagnostics/server_pthread/index.ts @@ -6,7 +6,7 @@ import monoDiagnosticsMock from "consts:monoDiagnosticsMock"; import { assertNever } from "../../types"; import { pthread_self } from "../../pthreads/worker"; -import { Module } from "../../imports"; +import { Module } from "../../globals"; import cwraps from "../../cwraps"; import { EventPipeSessionIDImpl } from "../shared/types"; import { CharPtr } from "../../types/emscripten"; diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/mock-remote.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/mock-remote.ts index 47e98e29b36b57..f30b99175de857 100644 --- a/src/mono/wasm/runtime/diagnostics/server_pthread/mock-remote.ts +++ b/src/mono/wasm/runtime/diagnostics/server_pthread/mock-remote.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import monoDiagnosticsMock from "consts:monoDiagnosticsMock"; -import { runtimeHelpers } from "../../imports"; +import { runtimeHelpers } from "../../globals"; import type { Mock } from "../mock"; import { mock } from "../mock"; diff --git a/src/mono/wasm/runtime/diagnostics/server_pthread/socket-connection.ts b/src/mono/wasm/runtime/diagnostics/server_pthread/socket-connection.ts index 47e216f1a7060c..cc3a8d838524dc 100644 --- a/src/mono/wasm/runtime/diagnostics/server_pthread/socket-connection.ts +++ b/src/mono/wasm/runtime/diagnostics/server_pthread/socket-connection.ts @@ -3,7 +3,7 @@ import { assertNever } from "../../types"; import { VoidPtr } from "../../types/emscripten"; -import { Module } from "../../imports"; +import { Module } from "../../globals"; import type { CommonSocket } from "./common-socket"; enum ListenerState { Sending, diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js index 418cbee72552f3..b23d1981049550 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js @@ -34,11 +34,9 @@ function setup(disableLegacyJsInterop) { }); } - __dotnet_runtime.initializeImports({ - isNode: ENVIRONMENT_IS_NODE, + __dotnet_runtime.passEmscriptenInternals({ isWorker: ENVIRONMENT_IS_WORKER, isShell: ENVIRONMENT_IS_SHELL, - isWeb: ENVIRONMENT_IS_WEB, isPThread: ENVIRONMENT_IS_PTHREAD, disableLegacyJsInterop, quit_, ExitStatus diff --git a/src/mono/wasm/runtime/export-api.ts b/src/mono/wasm/runtime/export-api.ts index debc4815024a4c..e258beaa3801bc 100644 --- a/src/mono/wasm/runtime/export-api.ts +++ b/src/mono/wasm/runtime/export-api.ts @@ -3,7 +3,7 @@ import type { MonoConfig, APIType } from "./types-api"; -import { runtimeHelpers } from "./imports"; +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"; diff --git a/src/mono/wasm/runtime/exports-internal.ts b/src/mono/wasm/runtime/exports-internal.ts index fdd68c0f830a01..14f5709555576d 100644 --- a/src/mono/wasm/runtime/exports-internal.ts +++ b/src/mono/wasm/runtime/exports-internal.ts @@ -5,7 +5,7 @@ import { mono_wasm_cancel_promise } from "./cancelable-promise"; import cwraps from "./cwraps"; import { mono_wasm_send_dbg_command_with_parms, mono_wasm_send_dbg_command, mono_wasm_get_dbg_command_info, mono_wasm_get_details, mono_wasm_release_object, mono_wasm_call_function_on, mono_wasm_debugger_resume, mono_wasm_detach_debugger, mono_wasm_raise_debug_event, mono_wasm_change_debugger_log_level, mono_wasm_debugger_attached } from "./debug"; import { http_wasm_supports_streaming_response, http_wasm_create_abort_controler, http_wasm_abort_request, http_wasm_abort_response, http_wasm_fetch, http_wasm_fetch_bytes, http_wasm_get_response_header_names, http_wasm_get_response_header_values, http_wasm_get_response_bytes, http_wasm_get_response_length, http_wasm_get_streamed_response_bytes } from "./http"; -import { exportedRuntimeAPI, Module, runtimeHelpers } from "./imports"; +import { exportedRuntimeAPI, Module, runtimeHelpers } from "./globals"; import { get_property, set_property, has_property, get_typeof_property, get_global_this, dynamic_import } from "./invoke-js"; import { mono_intern_string } from "./strings"; import { mono_wasm_stringify_as_error_with_stack } from "./logging"; diff --git a/src/mono/wasm/runtime/exports.ts b/src/mono/wasm/runtime/exports.ts index 4115f730f0ebae..c7ea64155b8e54 100644 --- a/src/mono/wasm/runtime/exports.ts +++ b/src/mono/wasm/runtime/exports.ts @@ -6,9 +6,8 @@ import GitHash from "consts:gitHash"; import BuildConfiguration from "consts:configuration"; import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop"; import type { DotnetHostBuilder, RuntimeAPI } from "./types-api"; -import type { EarlyExports, DotnetModuleInternal } from "./types"; -import { disableLegacyJsInterop, exportedRuntimeAPI, initializeImports, set_exports } from "./imports"; +import { Module, disableLegacyJsInterop, exportedRuntimeAPI, passEmscriptenInternals, } from "./globals"; import { is_nullish } from "./types"; import { configureEmscriptenStartup, configureWorkerStartup } from "./startup"; @@ -16,37 +15,35 @@ 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 { earlyExports, unifyModuleConfig } from "./run-outer"; +import { globalObjectsRoot, unifyModuleConfig } from "./run-outer"; import { HostBuilder } from "./run-outer"; import { initializeReplacements, init_polyfills } 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 { set_legacy_exports } from "./net6-legacy/imports"; +import { initializeLegacyExports } from "./net6-legacy/globals"; -function initializeExports( - exports: EarlyExports, -): RuntimeAPI { - set_exports(exports); - const module = exports.module as DotnetModuleInternal; +function initializeExports(): RuntimeAPI { + const module = Module; + const globals = globalObjectsRoot; const globalThisAny = globalThis as any; if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) { - set_legacy_exports(exports); + initializeLegacyExports(globals); } init_polyfills(); // here we merge methods from the local objects into exported objects if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) { - Object.assign(exports.mono, export_mono_api()); - Object.assign(exports.binding, export_binding_api()); - Object.assign(exports.internal, export_internal_api()); + Object.assign(globals.mono, export_mono_api()); + Object.assign(globals.binding, export_binding_api()); + Object.assign(globals.internal, export_internal_api()); } - Object.assign(exports.internal, export_internal()); + Object.assign(globals.internal, export_internal()); const API = export_api(); Object.assign(exportedRuntimeAPI, { - INTERNAL: exports.internal, + INTERNAL: globals.internal, Module: module, runtimeBuildInfo: { productVersion: ProductVersion, @@ -57,8 +54,8 @@ function initializeExports( }); if (WasmEnableLegacyJsInterop && !disableLegacyJsInterop) { Object.assign(exportedRuntimeAPI, { - MONO: exports.mono, - BINDING: exports.binding, + MONO: globals.mono, + BINDING: globals.binding, }); } @@ -97,9 +94,9 @@ function initializeExports( } }); }; - globalThisAny.MONO = exports.mono; - globalThisAny.BINDING = exports.binding; - globalThisAny.INTERNAL = exports.internal; + globalThisAny.MONO = globals.mono; + globalThisAny.BINDING = globals.binding; + globalThisAny.INTERNAL = globals.internal; globalThisAny.Module = module; // Blazor back compat @@ -142,5 +139,5 @@ const dotnet: DotnetHostBuilder = new HostBuilder(); const exit = mono_exit; export { dotnet, exit, - earlyExports, initializeImports, initializeExports, initializeReplacements, unifyModuleConfig, configureEmscriptenStartup, configureWorkerStartup + globalObjectsRoot as earlyExports, passEmscriptenInternals, initializeExports, initializeReplacements, unifyModuleConfig, configureEmscriptenStartup, configureWorkerStartup }; \ No newline at end of file diff --git a/src/mono/wasm/runtime/gc-handles.ts b/src/mono/wasm/runtime/gc-handles.ts index ce83039e4e3669..b1bc580d931b36 100644 --- a/src/mono/wasm/runtime/gc-handles.ts +++ b/src/mono/wasm/runtime/gc-handles.ts @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { runtimeHelpers } from "./imports"; +import { runtimeHelpers } from "./globals"; import { GCHandle, GCHandleNull, JSHandle, JSHandleDisposed, JSHandleNull, mono_assert } from "./types"; import { create_weak_ref } from "./weak-ref"; diff --git a/src/mono/wasm/runtime/gc-lock.ts b/src/mono/wasm/runtime/gc-lock.ts index 35c6be03b7ca6f..31b2db200c5b39 100644 --- a/src/mono/wasm/runtime/gc-lock.ts +++ b/src/mono/wasm/runtime/gc-lock.ts @@ -1,5 +1,5 @@ import MonoWasmThreads from "consts:monoWasmThreads"; -import { ENVIRONMENT_IS_PTHREAD } from "./imports"; +import { ENVIRONMENT_IS_PTHREAD } from "./globals"; import cwraps from "./cwraps"; let locked = false; diff --git a/src/mono/wasm/runtime/globals.ts b/src/mono/wasm/runtime/globals.ts new file mode 100644 index 00000000000000..1f032e37c966ab --- /dev/null +++ b/src/mono/wasm/runtime/globals.ts @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/* eslint-disable @typescript-eslint/triple-slash-reference */ +/// +/// + +import { RuntimeAPI } from "./types-api"; +import type { DotnetModule, GlobalObjects, EmscriptenInternals, EmscriptenModuleInternal, RuntimeHelpers } from "./types"; +import type { EmscriptenModule } from "./types/emscripten"; + +// these are our public API (except internal) +export let Module: EmscriptenModule & DotnetModule & EmscriptenModuleInternal; +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 let ENVIRONMENT_IS_PTHREAD: boolean; +export let exportedRuntimeAPI: RuntimeAPI = null as any; +export let runtimeHelpers: RuntimeHelpers = 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; + +// 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; + ENVIRONMENT_IS_PTHREAD = internals.isPThread; + disableLegacyJsInterop = internals.disableLegacyJsInterop; + runtimeHelpers.quit = internals.quit_; + runtimeHelpers.ExitStatus = internals.ExitStatus; +} + +export function setGlobalObjects( + globalObjects: GlobalObjects, +) { + earlyExports = globalObjects; + Module = globalObjects.module; + INTERNAL = globalObjects.internal; + runtimeHelpers = globalObjects.helpers; + exportedRuntimeAPI = globalObjects.api; + + Object.assign(globalObjects.module, { + disableDotnet6Compatibility: true, + config: { environmentVariables: {} } + }); + Object.assign(globalObjects.module.config!, {}) as any; + Object.assign(earlyExports.api, { + Module: globalObjects.module, ...globalObjects.module + }); + Object.assign(earlyExports.api, { + INTERNAL: earlyExports.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); +} diff --git a/src/mono/wasm/runtime/http.ts b/src/mono/wasm/runtime/http.ts index 1ba00c0cd6a891..a3d676e91a90dc 100644 --- a/src/mono/wasm/runtime/http.ts +++ b/src/mono/wasm/runtime/http.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import { wrap_as_cancelable_promise } from "./cancelable-promise"; -import { Module, runtimeHelpers } from "./imports"; +import { Module, runtimeHelpers } from "./globals"; import { MemoryViewType, Span } from "./marshal"; import { mono_assert } from "./types"; import type { VoidPtr } from "./types/emscripten"; diff --git a/src/mono/wasm/runtime/hybrid-globalization.ts b/src/mono/wasm/runtime/hybrid-globalization.ts index 494b873407de6d..62ecac2949ec4b 100644 --- a/src/mono/wasm/runtime/hybrid-globalization.ts +++ b/src/mono/wasm/runtime/hybrid-globalization.ts @@ -1,15 +1,15 @@ // 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 "./imports"; +import { Module } from "./globals"; import { mono_wasm_new_external_root } from "./roots"; -import {MonoString, MonoStringRef } from "./types"; +import { MonoString, MonoStringRef } from "./types"; import { Int32Ptr } from "./types/emscripten"; import { conv_string_root, js_string_to_mono_string_root, string_decoder } from "./strings"; import { setU16 } from "./memory"; -export function mono_wasm_change_case_invariant(exceptionMessage: Int32Ptr, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number) : void{ - try{ +export function mono_wasm_change_case_invariant(exceptionMessage: Int32Ptr, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number): void { + try { const input = get_utf16_string(src, srcLength); let result = toUpper ? input.toUpperCase() : input.toLowerCase(); // Unicode defines some codepoints which expand into multiple codepoints, @@ -18,16 +18,16 @@ export function mono_wasm_change_case_invariant(exceptionMessage: Int32Ptr, src: result = input; for (let i = 0; i < result.length; i++) - setU16(dst + i*2, result.charCodeAt(i)); + setU16(dst + i * 2, result.charCodeAt(i)); } catch (ex: any) { pass_exception_details(ex, exceptionMessage); } } -export function mono_wasm_change_case(exceptionMessage: Int32Ptr, culture: MonoStringRef, src: number, srcLength: number, dst: number, destLength: number, toUpper: number) : void{ +export function mono_wasm_change_case(exceptionMessage: Int32Ptr, culture: MonoStringRef, src: number, srcLength: number, dst: number, destLength: number, toUpper: number): void { const cultureRoot = mono_wasm_new_external_root(culture); - try{ + try { const cultureName = conv_string_root(cultureRoot); if (!cultureName) throw new Error("Cannot change case, the culture name is null."); @@ -37,7 +37,7 @@ export function mono_wasm_change_case(exceptionMessage: Int32Ptr, culture: MonoS result = input; for (let i = 0; i < destLength; i++) - setU16(dst + i*2, result.charCodeAt(i)); + setU16(dst + i * 2, result.charCodeAt(i)); } catch (ex: any) { pass_exception_details(ex, exceptionMessage); @@ -47,7 +47,7 @@ export function mono_wasm_change_case(exceptionMessage: Int32Ptr, culture: MonoS } } -function get_utf16_string(ptr: number, length: number): string{ +function get_utf16_string(ptr: number, length: number): string { const view = new Uint16Array(Module.HEAPU16.buffer, ptr, length); let string = ""; for (let i = 0; i < length; i++) @@ -55,12 +55,12 @@ function get_utf16_string(ptr: number, length: number): string{ return string; } -export function mono_wasm_compare_string(exceptionMessage: Int32Ptr, culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number) : number{ +export function mono_wasm_compare_string(exceptionMessage: Int32Ptr, culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number): number { const cultureRoot = mono_wasm_new_external_root(culture); - try{ + try { const cultureName = conv_string_root(cultureRoot); - const string1 = string_decoder.decode(str1, (str1 + 2*str1Length)); - const string2 = string_decoder.decode(str2, (str2 + 2*str2Length)); + const string1 = string_decoder.decode(str1, (str1 + 2 * str1Length)); + const string2 = string_decoder.decode(str2, (str2 + 2 * str2Length)); const casePicker = (options & 0x1f); const locale = cultureName ? cultureName : undefined; const result = compare_strings(string1, string2, locale, casePicker); @@ -77,16 +77,16 @@ export function mono_wasm_compare_string(exceptionMessage: Int32Ptr, culture: Mo } } -function pass_exception_details(ex: any, exceptionMessage: Int32Ptr){ +function pass_exception_details(ex: any, exceptionMessage: Int32Ptr) { const exceptionJsString = ex.message + "\n" + ex.stack; const exceptionRoot = mono_wasm_new_external_root(exceptionMessage); js_string_to_mono_string_root(exceptionJsString, exceptionRoot); exceptionRoot.release(); } -export function mono_wasm_starts_with(exceptionMessage: Int32Ptr, culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number): number{ +export function mono_wasm_starts_with(exceptionMessage: Int32Ptr, culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number): number { const cultureRoot = mono_wasm_new_external_root(culture); - try{ + try { const cultureName = conv_string_root(cultureRoot); const prefix = get_clean_string(str2, str2Length); // no need to look for an empty string @@ -114,9 +114,9 @@ export function mono_wasm_starts_with(exceptionMessage: Int32Ptr, culture: MonoS } } -export function mono_wasm_ends_with(exceptionMessage: Int32Ptr, culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number): number{ +export function mono_wasm_ends_with(exceptionMessage: Int32Ptr, culture: MonoStringRef, str1: number, str1Length: number, str2: number, str2Length: number, options: number): number { const cultureRoot = mono_wasm_new_external_root(culture); - try{ + try { const cultureName = conv_string_root(cultureRoot); const suffix = get_clean_string(str2, str2Length); if (suffix.length == 0) @@ -144,16 +144,14 @@ export function mono_wasm_ends_with(exceptionMessage: Int32Ptr, culture: MonoStr } } -function get_clean_string(strPtr: number, strLen: number) -{ - const str = string_decoder.decode(strPtr, (strPtr + 2*strLen)); +function get_clean_string(strPtr: number, strLen: number) { + const str = string_decoder.decode(strPtr, (strPtr + 2 * strLen)); const nStr = str.normalize(); return nStr.replace(/[\u200B-\u200D\uFEFF\0]/g, ""); } -export function compare_strings(string1: string, string2: string, locale: string | undefined, casePicker: number) : number{ - switch (casePicker) - { +export function compare_strings(string1: string, string2: string, locale: string | undefined, casePicker: number): number { + switch (casePicker) { case 0: // 0: None - default algorithm for the platform OR // StringSort - since .Net 5 StringSort gives the same result as None, even for hyphen etc. diff --git a/src/mono/wasm/runtime/icu.ts b/src/mono/wasm/runtime/icu.ts index 687732d252ce58..f3b5b4586b164e 100644 --- a/src/mono/wasm/runtime/icu.ts +++ b/src/mono/wasm/runtime/icu.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import cwraps from "./cwraps"; -import { ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./imports"; +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. diff --git a/src/mono/wasm/runtime/imports.ts b/src/mono/wasm/runtime/imports.ts deleted file mode 100644 index 90e5a637ce83bb..00000000000000 --- a/src/mono/wasm/runtime/imports.ts +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/* eslint-disable @typescript-eslint/triple-slash-reference */ -/// -/// - -import { RuntimeAPI } from "./types-api"; -import type { DotnetModule, EarlyExports, EarlyImports, EmscriptenModuleInternal, RuntimeHelpers } from "./types"; -import type { EmscriptenModule } from "./types/emscripten"; - -// these are our public API (except internal) -export let Module: EmscriptenModule & DotnetModule & EmscriptenModuleInternal; -export let INTERNAL: any; - -// these are imported and re-exported from emscripten internals -export let ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string"; -export let ENVIRONMENT_IS_SHELL: boolean; -export let ENVIRONMENT_IS_WEB = typeof window == "object"; -export let ENVIRONMENT_IS_WORKER: boolean; -export let ENVIRONMENT_IS_PTHREAD: boolean; -export let exportedRuntimeAPI: RuntimeAPI = null as any; -export let runtimeHelpers: RuntimeHelpers = null as any; -// this is when we link with workload tools. The consts:WasmEnableLegacyJsInterop is when we compile with rollup. -export let disableLegacyJsInterop = false; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function initializeImports( - imports: EarlyImports, -): void { - ENVIRONMENT_IS_NODE = imports.isNode; - ENVIRONMENT_IS_SHELL = imports.isShell; - ENVIRONMENT_IS_WEB = imports.isWeb; - ENVIRONMENT_IS_WORKER = imports.isWorker; - ENVIRONMENT_IS_PTHREAD = imports.isPThread; - disableLegacyJsInterop = imports.disableLegacyJsInterop; - runtimeHelpers.quit = imports.quit_; - runtimeHelpers.ExitStatus = imports.ExitStatus; -} - -export function set_exports( - exports: EarlyExports, -): void { - INTERNAL = exports.internal; - Module = exports.module; - runtimeHelpers = exports.helpers; - exportedRuntimeAPI = exports.api; - - if (!exports.module.config.environmentVariables) { - exports.module.config.environmentVariables = {}; - } - Object.assign(runtimeHelpers, { - javaScriptExports: {} as any, - mono_wasm_bindings_is_ready: false, - maxParallelDownloads: 16, - enableDownloadRetry: true, - config: exports.module.config, - diagnosticTracing: false, - enablePerfMeasure: true, - loadedFiles: [] - } as Partial); -} - -export function set_module_and_helpers( - module: EmscriptenModule & DotnetModule & EmscriptenModuleInternal, - helpers: RuntimeHelpers, - internal: any -) { - Module = module; - INTERNAL = internal; - runtimeHelpers = helpers; -} diff --git a/src/mono/wasm/runtime/invoke-cs.ts b/src/mono/wasm/runtime/invoke-cs.ts index f55810af6eab23..340b3afa414052 100644 --- a/src/mono/wasm/runtime/invoke-cs.ts +++ b/src/mono/wasm/runtime/invoke-cs.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import MonoWasmThreads from "consts:monoWasmThreads"; -import { Module, runtimeHelpers } from "./imports"; +import { Module, runtimeHelpers } from "./globals"; import { bind_arg_marshal_to_cs } from "./marshal-to-cs"; import { marshal_exception_to_js, bind_arg_marshal_to_js } from "./marshal-to-js"; import { diff --git a/src/mono/wasm/runtime/invoke-js.ts b/src/mono/wasm/runtime/invoke-js.ts index 2ae40414ac31d8..6cb566f024aa15 100644 --- a/src/mono/wasm/runtime/invoke-js.ts +++ b/src/mono/wasm/runtime/invoke-js.ts @@ -7,7 +7,7 @@ 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 { Int32Ptr } from "./types/emscripten"; -import { INTERNAL, Module, runtimeHelpers } from "./imports"; +import { INTERNAL, Module, runtimeHelpers } from "./globals"; import { bind_arg_marshal_to_js } from "./marshal-to-js"; import { mono_wasm_new_external_root } from "./roots"; import { mono_wasm_symbolicate_string } from "./logging"; diff --git a/src/mono/wasm/runtime/jiterpreter-interp-entry.ts b/src/mono/wasm/runtime/jiterpreter-interp-entry.ts index 964bd1316d202d..aad65e7ad4841c 100644 --- a/src/mono/wasm/runtime/jiterpreter-interp-entry.ts +++ b/src/mono/wasm/runtime/jiterpreter-interp-entry.ts @@ -3,7 +3,7 @@ import { mono_assert, MonoMethod, MonoType } from "./types"; import { NativePointer } from "./types/emscripten"; -import { Module } from "./imports"; +import { Module } from "./globals"; import { getU32_unaligned, _zero_region } from "./memory"; @@ -24,18 +24,18 @@ const /* typedef struct { - InterpMethod *rmethod; - gpointer this_arg; - gpointer res; - gpointer args [16]; - gpointer *many_args; + InterpMethod *rmethod; + gpointer this_arg; + gpointer res; + gpointer args [16]; + gpointer *many_args; } InterpEntryData; typedef struct { - InterpMethod *rmethod; // 0 - ThreadContext *context; // 4 - gpointer orig_domain; // 8 - gpointer attach_cookie; // 12 + InterpMethod *rmethod; // 0 + ThreadContext *context; // 4 + gpointer orig_domain; // 8 + gpointer attach_cookie; // 12 } JiterpEntryDataHeader; */ @@ -47,12 +47,12 @@ const const maxJitQueueLength = 4, queueFlushDelayMs = 10; -let trampBuilder : WasmBuilder; -let trampImports : Array<[string, string, Function]> | undefined; -let fnTable : WebAssembly.Table; +let trampBuilder: WasmBuilder; +let trampImports: Array<[string, string, Function]> | undefined; +let fnTable: WebAssembly.Table; let jitQueueTimeout = 0; -const jitQueue : TrampolineInfo[] = []; -const infoTable : { [ptr: number] : TrampolineInfo } = {}; +const jitQueue: TrampolineInfo[] = []; +const infoTable: { [ptr: number]: TrampolineInfo } = {}; /* const enum WasmReftype { @@ -61,7 +61,7 @@ const enum WasmReftype { } */ -function getTrampImports () { +function getTrampImports() { if (trampImports) return trampImports; @@ -91,7 +91,7 @@ class TrampolineInfo { result: number; hitCount: number; - constructor ( + constructor( imethod: number, method: MonoMethod, argumentCount: number, pParamTypes: NativePointer, unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, name: string, defaultImplementation: number @@ -125,9 +125,9 @@ class TrampolineInfo { } } -let mostRecentOptions : JiterpreterOptions | undefined = undefined; +let mostRecentOptions: JiterpreterOptions | undefined = undefined; -export function mono_interp_record_interp_entry (imethod: number) { +export function mono_interp_record_interp_entry(imethod: number) { // clear the unbox bit imethod = imethod & ~0x1; @@ -153,11 +153,11 @@ export function mono_interp_record_interp_entry (imethod: number) { } // returns function pointer -export function mono_interp_jit_wasm_entry_trampoline ( +export function mono_interp_jit_wasm_entry_trampoline( imethod: number, method: MonoMethod, argumentCount: number, pParamTypes: NativePointer, unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, name: NativePointer, defaultImplementation: number -) : number { +): number { // HACK if (argumentCount > maxInlineArgs) return 0; @@ -182,7 +182,7 @@ export function mono_interp_jit_wasm_entry_trampoline ( return info.result; } -function ensure_jit_is_scheduled () { +function ensure_jit_is_scheduled() { if (jitQueueTimeout > 0) return; @@ -201,7 +201,7 @@ function ensure_jit_is_scheduled () { }, queueFlushDelayMs); } -function flush_wasm_entry_trampoline_jit_queue () { +function flush_wasm_entry_trampoline_jit_queue() { if (jitQueue.length <= 0) return; @@ -213,29 +213,37 @@ function flush_wasm_entry_trampoline_jit_queue () { trampBuilder = builder = new WasmBuilder(constantSlots); builder.defineType( - "unbox", { + "unbox", + { "pMonoObject": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "interp_entry_prologue", { + "interp_entry_prologue", + { "pData": WasmValtype.i32, "this_arg": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "interp_entry", { + "interp_entry", + { "pData": WasmValtype.i32, "sp_args": WasmValtype.i32, "res": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "stackval_from_data", { + "stackval_from_data", + { "type": WasmValtype.i32, "result": WasmValtype.i32, "value": WasmValtype.i32 - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); } else builder.clear(constantSlots); @@ -257,7 +265,7 @@ function flush_wasm_entry_trampoline_jit_queue () { for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; - const sig : any = {}; + const sig: any = {}; if (info.hasThisReference) sig["this_arg"] = WasmValtype.i32; if (info.hasReturnValue) @@ -405,7 +413,7 @@ function flush_wasm_entry_trampoline_jit_queue () { } } -function append_stackval_from_data ( +function append_stackval_from_data( builder: WasmBuilder, type: MonoType, valueName: string ) { const stackvalSize = cwraps.mono_jiterp_get_size_of_stackval(); @@ -486,9 +494,9 @@ function append_stackval_from_data ( builder.local("sp_args", WasmOpcode.set_local); } -function generate_wasm_body ( +function generate_wasm_body( builder: WasmBuilder, info: TrampolineInfo -) : boolean { +): boolean { // FIXME: This is not thread-safe, but the alternative of alloca makes the trampoline // more expensive // The solution is likely to put the address of the scratch buffer in a global that we provide @@ -558,15 +566,15 @@ function generate_wasm_body ( } /* - for (i = 0; i < sig->param_count; ++i) { - if (m_type_is_byref (sig->params [i])) { - sp_args->data.p = params [i]; - sp_args++; - } else { - int size = stackval_from_data (sig->params [i], sp_args, params [i], FALSE); - sp_args = STACK_ADD_BYTES (sp_args, size); - } - } + for (i = 0; i < sig->param_count; ++i) { + if (m_type_is_byref (sig->params [i])) { + sp_args->data.p = params [i]; + sp_args++; + } else { + int size = stackval_from_data (sig->params [i], sp_args, params [i], FALSE); + sp_args = STACK_ADD_BYTES (sp_args, size); + } + } */ for (let i = 0; i < info.paramTypes.length; i++) { diff --git a/src/mono/wasm/runtime/jiterpreter-jit-call.ts b/src/mono/wasm/runtime/jiterpreter-jit-call.ts index b5734380b360b1..3f016adc005108 100644 --- a/src/mono/wasm/runtime/jiterpreter-jit-call.ts +++ b/src/mono/wasm/runtime/jiterpreter-jit-call.ts @@ -3,7 +3,7 @@ import { mono_assert, MonoType, MonoMethod } from "./types"; import { NativePointer, Int32Ptr, VoidPtr } from "./types/emscripten"; -import { Module, runtimeHelpers } from "./imports"; +import { Module, runtimeHelpers } from "./globals"; import { getU8, getI32_unaligned, getU32_unaligned, setU32_unchecked } from "./memory"; @@ -26,17 +26,17 @@ const /* struct _JitCallInfo { - gpointer addr; // 0 - gpointer extra_arg; // 4 - gpointer wrapper; // 8 - MonoMethodSignature *sig; // 12 - guint8 *arginfo; // 16 - gint32 res_size; // 20 - int ret_mt; // 24 - gboolean no_wrapper; // 28 + gpointer addr; // 0 + gpointer extra_arg; // 4 + gpointer wrapper; // 8 + MonoMethodSignature *sig; // 12 + guint8 *arginfo; // 16 + gint32 res_size; // 20 + int ret_mt; // 24 + gboolean no_wrapper; // 28 #if HOST_BROWSER - int hit_count; - WasmJitCallThunk jiterp_thunk; + int hit_count; + WasmJitCallThunk jiterp_thunk; #endif }; */ @@ -52,15 +52,15 @@ const offsetOfAddr = 0, const maxJitQueueLength = 6, maxSharedQueueLength = 12; - // sizeOfStackval = 8; +// sizeOfStackval = 8; -let trampBuilder : WasmBuilder; -let fnTable : WebAssembly.Table; -let wasmEhSupported : boolean | undefined = undefined; +let trampBuilder: WasmBuilder; +let fnTable: WebAssembly.Table; +let wasmEhSupported: boolean | undefined = undefined; let nextDisambiguateIndex = 0; -const fnCache : Array = []; -const targetCache : { [target: number] : TrampolineInfo } = {}; -const jitQueue : TrampolineInfo[] = []; +const fnCache: Array = []; +const targetCache: { [target: number]: TrampolineInfo } = {}; +const jitQueue: TrampolineInfo[] = []; class TrampolineInfo { method: MonoMethod; @@ -90,7 +90,7 @@ class TrampolineInfo { wasmNativeSignature: WasmValtype[]; enableDirect: boolean; - constructor ( + constructor( method: MonoMethod, rmethod: VoidPtr, cinfo: VoidPtr, arg_offsets: VoidPtr, catch_exceptions: boolean ) { @@ -159,7 +159,7 @@ class TrampolineInfo { // this is cached replacements for Module.getWasmTableEntry(); // we could add and // if we need to export the original -function getWasmTableEntry (index: number) { +function getWasmTableEntry(index: number) { let result = fnCache[index]; if (!result) { if (index >= fnCache.length) @@ -172,7 +172,7 @@ function getWasmTableEntry (index: number) { return result; } -export function mono_interp_invoke_wasm_jit_call_trampoline ( +export function mono_interp_invoke_wasm_jit_call_trampoline( thunkIndex: number, ret_sp: number, sp: number, ftndesc: number, thrown: NativePointer ) { const thunk = getWasmTableEntry(thunkIndex); @@ -183,10 +183,10 @@ export function mono_interp_invoke_wasm_jit_call_trampoline ( } } -export function mono_interp_jit_wasm_jit_call_trampoline ( +export function mono_interp_jit_wasm_jit_call_trampoline( method: MonoMethod, rmethod: VoidPtr, cinfo: VoidPtr, arg_offsets: VoidPtr, catch_exceptions: number -) : void { +): void { // multiple cinfos can share the same target function, so for that scenario we want to // use the same TrampolineInfo for all of them. if that info has already been jitted // we want to immediately store its pointer into the cinfo, otherwise we add it to @@ -227,9 +227,9 @@ export function mono_interp_jit_wasm_jit_call_trampoline ( // pure wasm implementation of do_jit_call_indirect (using wasm EH). see do-jit-call.wat / do-jit-call.wasm const doJitCall16 = "0061736d01000000010b0260017f0060037f7f7f00021d020169066d656d6f727902000001690b6a69745f63616c6c5f636200000302010107180114646f5f6a69745f63616c6c5f696e64697265637400010a1301110006402001100019200241013602000b0b"; -let doJitCallModule : WebAssembly.Module | undefined = undefined; +let doJitCallModule: WebAssembly.Module | undefined = undefined; -function getIsWasmEhSupported () : boolean { +function getIsWasmEhSupported(): boolean { if (wasmEhSupported !== undefined) return wasmEhSupported; @@ -254,9 +254,9 @@ function getIsWasmEhSupported () : boolean { // this is the generic entry point for do_jit_call that is registered by default at runtime startup. // its job is to do initialization for the optimized do_jit_call path, which will either use a jitted // wasm trampoline or will use a specialized JS function. -export function mono_jiterp_do_jit_call_indirect ( +export function mono_jiterp_do_jit_call_indirect( jit_call_cb: number, cb_data: VoidPtr, thrown: Int32Ptr -) : void { +): void { mono_assert(!runtimeHelpers.storeMemorySnapshotPending, "Attempting to set function into table during creation of memory snapshot"); const table = getWasmFunctionTable(); const jitCallCb = table.get(jit_call_cb); @@ -311,7 +311,7 @@ export function mono_jiterp_do_jit_call_indirect ( do_jit_call_indirect_js(jit_call_cb, cb_data, thrown); } -export function mono_interp_flush_jitcall_queue () : void { +export function mono_interp_flush_jitcall_queue(): void { if (jitQueue.length === 0) return; @@ -320,7 +320,8 @@ export function mono_interp_flush_jitcall_queue () : void { trampBuilder = builder = new WasmBuilder(0); // Function type for compiled trampolines builder.defineType( - "trampoline", { + "trampoline", + { "ret_sp": WasmValtype.i32, "sp": WasmValtype.i32, "ftndesc": WasmValtype.i32, @@ -338,7 +339,7 @@ export function mono_interp_flush_jitcall_queue () : void { if (builder.options.enableWasmEh) { if (!getIsWasmEhSupported()) { // The user requested to enable wasm EH but it's not supported, so turn the option back off - applyOptions({enableWasmEh: false}); + applyOptions({ enableWasmEh: false }); builder.options.enableWasmEh = false; } } @@ -347,7 +348,7 @@ export function mono_interp_flush_jitcall_queue () : void { let compileStarted = 0; let rejected = true, threw = false; - const trampImports : Array<[string, string, Function | number]> = [ + const trampImports: Array<[string, string, Function | number]> = [ ]; try { @@ -361,7 +362,7 @@ export function mono_interp_flush_jitcall_queue () : void { for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; - const sig : any = {}; + const sig: any = {}; if (info.enableDirect) { if (info.hasThisReference) @@ -425,7 +426,7 @@ export function mono_interp_flush_jitcall_queue () : void { builder.appendULeb(jitQueue.length); for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; - builder.beginFunction("trampoline", {"old_sp": WasmValtype.i32}); + builder.beginFunction("trampoline", { "old_sp": WasmValtype.i32 }); const ok = generate_wasm_body(builder, info); // FIXME @@ -572,66 +573,66 @@ const enum CilOpcodes { const wasmTypeFromCilOpcode = { [CilOpcodes.DUMMY_BYREF]: WasmValtype.i32, - [CilOpcodes.LDIND_I1]: WasmValtype.i32, - [CilOpcodes.LDIND_U1]: WasmValtype.i32, - [CilOpcodes.LDIND_I2]: WasmValtype.i32, - [CilOpcodes.LDIND_U2]: WasmValtype.i32, - [CilOpcodes.LDIND_I4]: WasmValtype.i32, - [CilOpcodes.LDIND_U4]: WasmValtype.i32, - [CilOpcodes.LDIND_I8]: WasmValtype.i64, - [CilOpcodes.LDIND_I]: WasmValtype.i32, - [CilOpcodes.LDIND_R4]: WasmValtype.f32, - [CilOpcodes.LDIND_R8]: WasmValtype.f64, + [CilOpcodes.LDIND_I1]: WasmValtype.i32, + [CilOpcodes.LDIND_U1]: WasmValtype.i32, + [CilOpcodes.LDIND_I2]: WasmValtype.i32, + [CilOpcodes.LDIND_U2]: WasmValtype.i32, + [CilOpcodes.LDIND_I4]: WasmValtype.i32, + [CilOpcodes.LDIND_U4]: WasmValtype.i32, + [CilOpcodes.LDIND_I8]: WasmValtype.i64, + [CilOpcodes.LDIND_I]: WasmValtype.i32, + [CilOpcodes.LDIND_R4]: WasmValtype.f32, + [CilOpcodes.LDIND_R8]: WasmValtype.f64, [CilOpcodes.LDIND_REF]: WasmValtype.i32, [CilOpcodes.STIND_REF]: WasmValtype.i32, - [CilOpcodes.STIND_I1]: WasmValtype.i32, - [CilOpcodes.STIND_I2]: WasmValtype.i32, - [CilOpcodes.STIND_I4]: WasmValtype.i32, - [CilOpcodes.STIND_I8]: WasmValtype.i64, - [CilOpcodes.STIND_R4]: WasmValtype.f32, - [CilOpcodes.STIND_R8]: WasmValtype.f64, - [CilOpcodes.STIND_I]: WasmValtype.i32, + [CilOpcodes.STIND_I1]: WasmValtype.i32, + [CilOpcodes.STIND_I2]: WasmValtype.i32, + [CilOpcodes.STIND_I4]: WasmValtype.i32, + [CilOpcodes.STIND_I8]: WasmValtype.i64, + [CilOpcodes.STIND_R4]: WasmValtype.f32, + [CilOpcodes.STIND_R8]: WasmValtype.f64, + [CilOpcodes.STIND_I]: WasmValtype.i32, }; // Maps a CIL ld/st opcode to the wasm opcode to perform it, if any const wasmOpcodeFromCilOpcode = { - [CilOpcodes.LDIND_I1]: WasmOpcode.i32_load8_s, - [CilOpcodes.LDIND_U1]: WasmOpcode.i32_load8_u, - [CilOpcodes.LDIND_I2]: WasmOpcode.i32_load16_s, - [CilOpcodes.LDIND_U2]: WasmOpcode.i32_load16_u, - [CilOpcodes.LDIND_I4]: WasmOpcode.i32_load, - [CilOpcodes.LDIND_U4]: WasmOpcode.i32_load, - [CilOpcodes.LDIND_I8]: WasmOpcode.i64_load, - [CilOpcodes.LDIND_I]: WasmOpcode.i32_load, - [CilOpcodes.LDIND_R4]: WasmOpcode.f32_load, - [CilOpcodes.LDIND_R8]: WasmOpcode.f64_load, + [CilOpcodes.LDIND_I1]: WasmOpcode.i32_load8_s, + [CilOpcodes.LDIND_U1]: WasmOpcode.i32_load8_u, + [CilOpcodes.LDIND_I2]: WasmOpcode.i32_load16_s, + [CilOpcodes.LDIND_U2]: WasmOpcode.i32_load16_u, + [CilOpcodes.LDIND_I4]: WasmOpcode.i32_load, + [CilOpcodes.LDIND_U4]: WasmOpcode.i32_load, + [CilOpcodes.LDIND_I8]: WasmOpcode.i64_load, + [CilOpcodes.LDIND_I]: WasmOpcode.i32_load, + [CilOpcodes.LDIND_R4]: WasmOpcode.f32_load, + [CilOpcodes.LDIND_R8]: WasmOpcode.f64_load, [CilOpcodes.LDIND_REF]: WasmOpcode.i32_load, // TODO: Memory barrier? [CilOpcodes.STIND_REF]: WasmOpcode.i32_store, // Memory barrier not needed - [CilOpcodes.STIND_I1]: WasmOpcode.i32_store8, - [CilOpcodes.STIND_I2]: WasmOpcode.i32_store16, - [CilOpcodes.STIND_I4]: WasmOpcode.i32_store, - [CilOpcodes.STIND_I8]: WasmOpcode.i64_store, - [CilOpcodes.STIND_R4]: WasmOpcode.f32_store, - [CilOpcodes.STIND_R8]: WasmOpcode.f64_store, - [CilOpcodes.STIND_I]: WasmOpcode.i32_store, + [CilOpcodes.STIND_I1]: WasmOpcode.i32_store8, + [CilOpcodes.STIND_I2]: WasmOpcode.i32_store16, + [CilOpcodes.STIND_I4]: WasmOpcode.i32_store, + [CilOpcodes.STIND_I8]: WasmOpcode.i64_store, + [CilOpcodes.STIND_R4]: WasmOpcode.f32_store, + [CilOpcodes.STIND_R8]: WasmOpcode.f64_store, + [CilOpcodes.STIND_I]: WasmOpcode.i32_store, }; -function append_ldloc (builder: WasmBuilder, offsetBytes: number, opcode: WasmOpcode) { +function append_ldloc(builder: WasmBuilder, offsetBytes: number, opcode: WasmOpcode) { builder.local("sp"); builder.appendU8(opcode); builder.appendMemarg(offsetBytes, 0); } -function append_ldloca (builder: WasmBuilder, offsetBytes: number) { +function append_ldloca(builder: WasmBuilder, offsetBytes: number) { builder.local("sp"); builder.i32_const(offsetBytes); builder.appendU8(WasmOpcode.i32_add); } -function generate_wasm_body ( +function generate_wasm_body( builder: WasmBuilder, info: TrampolineInfo -) : boolean { +): boolean { let stack_index = 0; // If wasm EH is enabled we will perform the call inside a catch-all block and set a flag @@ -744,18 +745,18 @@ function generate_wasm_body ( builder.callImport(info.name); /* - if (sig->ret->type != MONO_TYPE_VOID) { - // Store return value - stind_op = mono_type_to_stind (sig->ret); - // FIXME: - if (stind_op == CEE_STOBJ) - mono_mb_emit_op (mb, CEE_STOBJ, mono_class_from_mono_type_internal (sig->ret)); - else if (stind_op == CEE_STIND_REF) - // Avoid write barriers, the vret arg points to the stack - mono_mb_emit_byte (mb, CEE_STIND_I); - else - mono_mb_emit_byte (mb, stind_op); - } + if (sig->ret->type != MONO_TYPE_VOID) { + // Store return value + stind_op = mono_type_to_stind (sig->ret); + // FIXME: + if (stind_op == CEE_STOBJ) + mono_mb_emit_op (mb, CEE_STOBJ, mono_class_from_mono_type_internal (sig->ret)); + else if (stind_op == CEE_STIND_REF) + // Avoid write barriers, the vret arg points to the stack + mono_mb_emit_byte (mb, CEE_STIND_I); + else + mono_mb_emit_byte (mb, stind_op); + } */ // The stack should now contain [ret_sp, retval], so write retval through the return address diff --git a/src/mono/wasm/runtime/jiterpreter-support.ts b/src/mono/wasm/runtime/jiterpreter-support.ts index 9c4fdc3de0d22b..010e67496b19b5 100644 --- a/src/mono/wasm/runtime/jiterpreter-support.ts +++ b/src/mono/wasm/runtime/jiterpreter-support.ts @@ -3,7 +3,7 @@ import { mono_assert } from "./types"; import { NativePointer, ManagedPointer, VoidPtr } from "./types/emscripten"; -import { Module, runtimeHelpers } from "./imports"; +import { Module, runtimeHelpers } from "./globals"; import { WasmOpcode } from "./jiterpreter-opcodes"; import { MintOpcode } from "./mintops"; import cwraps from "./cwraps"; @@ -122,7 +122,7 @@ type ImportedFunctionInfo = { func: Function; } -const compressedNameCache : { [number: number] : string } = {}; +const compressedNameCache: { [number: number]: string } = {}; export class WasmBuilder { cfg: Cfg; @@ -134,20 +134,20 @@ export class WasmBuilder { locals = new Map(); permanentFunctionTypeCount = 0; - permanentFunctionTypes: { [name: string] : FunctionType } = {}; - permanentFunctionTypesByShape: { [shape: string] : FunctionTypeIndex } = {}; - permanentFunctionTypesByIndex: { [index: number] : FunctionTypeByIndex } = {}; + permanentFunctionTypes: { [name: string]: FunctionType } = {}; + permanentFunctionTypesByShape: { [shape: string]: FunctionTypeIndex } = {}; + permanentFunctionTypesByIndex: { [index: number]: FunctionTypeByIndex } = {}; functionTypeCount!: number; - functionTypes!: { [name: string] : FunctionType }; - functionTypesByShape!: { [shape: string] : FunctionTypeIndex }; - functionTypesByIndex: { [index: number] : FunctionTypeByIndex } = {}; + functionTypes!: { [name: string]: FunctionType }; + functionTypesByShape!: { [shape: string]: FunctionTypeIndex }; + functionTypesByIndex: { [index: number]: FunctionTypeByIndex } = {}; permanentImportedFunctionCount = 0; - permanentImportedFunctions: { [name: string] : ImportedFunctionInfo } = {}; + permanentImportedFunctions: { [name: string]: ImportedFunctionInfo } = {}; importedFunctionCount!: number; - importedFunctions!: { [name: string] : ImportedFunctionInfo }; + importedFunctions!: { [name: string]: ImportedFunctionInfo }; nextImportIndex = 0; functions: Array = []; @@ -167,13 +167,13 @@ export class WasmBuilder { compressImportNames = false; - constructor (constantSlotCount: number) { + constructor(constantSlotCount: number) { this.stack = [new BlobBuilder()]; this.clear(constantSlotCount); this.cfg = new Cfg(this); } - clear (constantSlotCount: number) { + clear(constantSlotCount: number) { this.options = getOptions(); this.stackSize = 1; this.inSection = false; @@ -213,14 +213,14 @@ export class WasmBuilder { this.allowNullCheckOptimization = this.options.eliminateNullChecks; } - _push () { + _push() { this.stackSize++; if (this.stackSize >= this.stack.length) this.stack.push(new BlobBuilder()); this.current.clear(); } - _pop (writeToOutput: boolean) { + _pop(writeToOutput: boolean) { if (this.stackSize <= 1) throw new Error("Stack empty"); @@ -238,7 +238,7 @@ export class WasmBuilder { // HACK: Approximate amount of space we need to generate the full module at present // FIXME: This does not take into account any other functions already generated if they weren't // emitted into the module immediately - get bytesGeneratedSoFar () { + get bytesGeneratedSoFar() { return this.stack[0].size + // HACK: A random constant for section headers and padding 32 + @@ -258,59 +258,59 @@ export class WasmBuilder { return this.current.size; } - appendU8 (value: number | WasmOpcode) { + appendU8(value: number | WasmOpcode) { if ((value != value >>> 0) || (value > 255)) throw new Error(`Byte out of range: ${value}`); return this.current.appendU8(value); } - appendU32 (value: number) { + appendU32(value: number) { return this.current.appendU32(value); } - appendF32 (value: number) { + appendF32(value: number) { return this.current.appendF32(value); } - appendF64 (value: number) { + appendF64(value: number) { return this.current.appendF64(value); } - appendBoundaryValue (bits: number, sign: number) { + appendBoundaryValue(bits: number, sign: number) { return this.current.appendBoundaryValue(bits, sign); } - appendULeb (value: number | MintOpcodePtr) { + appendULeb(value: number | MintOpcodePtr) { return this.current.appendULeb(value); } - appendLeb (value: number) { + appendLeb(value: number) { return this.current.appendLeb(value); } - appendLebRef (sourceAddress: VoidPtr, signed: boolean) { + appendLebRef(sourceAddress: VoidPtr, signed: boolean) { return this.current.appendLebRef(sourceAddress, signed); } - appendBytes (bytes: Uint8Array) { + appendBytes(bytes: Uint8Array) { return this.current.appendBytes(bytes); } - appendName (text: string) { + appendName(text: string) { return this.current.appendName(text); } - ret (ip: MintOpcodePtr) { + ret(ip: MintOpcodePtr) { this.ip_const(ip); this.appendU8(WasmOpcode.return_); } - i32_const (value: number | ManagedPointer | NativePointer) { + i32_const(value: number | ManagedPointer | NativePointer) { this.appendU8(WasmOpcode.i32_const); this.appendLeb(value); } - ptr_const (pointer: number | ManagedPointer | NativePointer) { + ptr_const(pointer: number | ManagedPointer | NativePointer) { let idx = this.options.useConstants ? this.constantSlots.indexOf(pointer) : -1; if ( this.options.useConstants && @@ -329,17 +329,17 @@ export class WasmBuilder { } } - ip_const (value: MintOpcodePtr) { + ip_const(value: MintOpcodePtr) { this.appendU8(WasmOpcode.i32_const); this.appendLeb(value - this.base); } - i52_const (value: number) { + i52_const(value: number) { this.appendU8(WasmOpcode.i64_const); this.appendLeb(value); } - defineType ( + defineType( name: string, parameters: { [name: string]: WasmValtype }, returnType: WasmValtype, permanent: boolean ) { @@ -376,7 +376,7 @@ export class WasmBuilder { } } - const tup : FunctionType = [ + const tup: FunctionType = [ index, parameters, returnType, `(${JSON.stringify(parameters)}) -> ${returnType}`, permanent ]; @@ -388,7 +388,7 @@ export class WasmBuilder { return index; } - generateTypeSection () { + generateTypeSection() { this.beginSection(1); this.appendULeb(this.functionTypeCount); /* @@ -414,8 +414,8 @@ export class WasmBuilder { this.endSection(); } - getImportedFunctionTable () : any { - const imports : any = {}; + getImportedFunctionTable(): any { + const imports: any = {}; for (const k in this.importedFunctions) { const f = this.importedFunctions[k]; const name = this.getCompressedName(f); @@ -424,8 +424,8 @@ export class WasmBuilder { return imports; } - getCompressedName (ifi: ImportedFunctionInfo) { - if (!this.compressImportNames || typeof(ifi.index) !== "number") + getCompressedName(ifi: ImportedFunctionInfo) { + if (!this.compressImportNames || typeof (ifi.index) !== "number") return ifi.name; let result = compressedNameCache[ifi.index!]; @@ -434,7 +434,7 @@ export class WasmBuilder { return result; } - _generateImportSection () { + _generateImportSection() { const importsToEmit = []; for (const k in this.importedFunctions) { const f = this.importedFunctions[k]; @@ -474,10 +474,10 @@ export class WasmBuilder { this.appendULeb(0x01); } - defineImportedFunction ( + defineImportedFunction( module: string, name: string, functionTypeName: string, assumeUsed: boolean, permanent: boolean, func: Function | number - ) : ImportedFunctionInfo { + ): ImportedFunctionInfo { if (permanent && (this.importedFunctionCount > this.permanentImportedFunctionCount)) throw new Error("New permanent imports cannot be defined after non-permanent ones"); const type = this.functionTypes[functionTypeName]; @@ -509,7 +509,7 @@ export class WasmBuilder { return result; } - defineFunction ( + defineFunction( options: { type: string, name: string, @@ -517,7 +517,7 @@ export class WasmBuilder { locals: { [name: string]: WasmValtype }, }, generator: Function ) { - const rec : FunctionInfo = { + const rec: FunctionInfo = { index: this.functions.length, name: options.name, typeName: options.type, @@ -534,7 +534,7 @@ export class WasmBuilder { return rec; } - emitImportsAndFunctions () { + emitImportsAndFunctions() { let exportCount = 0; for (let i = 0; i < this.functions.length; i++) { const func = this.functions[i]; @@ -581,7 +581,7 @@ export class WasmBuilder { this.endSection(); } - callImport (name: string) { + callImport(name: string) { const func = this.importedFunctions[name]; if (!func) throw new Error("No imported function named " + name); @@ -591,7 +591,7 @@ export class WasmBuilder { this.appendULeb(func.index); } - beginSection (type: number) { + beginSection(type: number) { if (this.inSection) this._pop(true); this.appendU8(type); @@ -599,7 +599,7 @@ export class WasmBuilder { this.inSection = true; } - endSection () { + endSection() { if (!this.inSection) throw new Error("Not in section"); if (this.inFunction) @@ -608,7 +608,7 @@ export class WasmBuilder { this.inSection = false; } - _assignParameterIndices = (parms: {[name: string] : WasmValtype}) => { + _assignParameterIndices = (parms: { [name: string]: WasmValtype }) => { let result = 0; for (const k in parms) { this.locals.set(k, result); @@ -618,8 +618,8 @@ export class WasmBuilder { return result; }; - _assignLocalIndices ( - counts: any, locals: {[name: string] : WasmValtype}, + _assignLocalIndices( + counts: any, locals: { [name: string]: WasmValtype }, base: number, localGroupCount: number ) { counts[WasmValtype.i32] = 0; @@ -671,9 +671,9 @@ export class WasmBuilder { return localGroupCount; } - beginFunction ( + beginFunction( type: string, - locals?: {[name: string]: WasmValtype} + locals?: { [name: string]: WasmValtype } ) { if (this.inFunction) throw new Error("Already in function"); @@ -715,7 +715,7 @@ export class WasmBuilder { this.inFunction = true; } - endFunction (writeToOutput: boolean) { + endFunction(writeToOutput: boolean) { if (!this.inFunction) throw new Error("Not in function"); if (this.activeBlocks > 0) @@ -725,7 +725,7 @@ export class WasmBuilder { return result; } - block (type?: WasmValtype, opcode?: WasmOpcode) { + block(type?: WasmValtype, opcode?: WasmOpcode) { const result = this.appendU8(opcode || WasmOpcode.block); if (type) this.appendU8(type); @@ -735,15 +735,15 @@ export class WasmBuilder { return result; } - endBlock () { + endBlock() { if (this.activeBlocks <= 0) throw new Error("No blocks active"); this.activeBlocks--; this.appendU8(WasmOpcode.end); } - arg (name: string | number, opcode?: WasmOpcode) { - const index = typeof(name) === "string" + arg(name: string | number, opcode?: WasmOpcode) { + const index = typeof (name) === "string" ? (this.locals.has(name) ? this.locals.get(name)! : undefined) : name; if (typeof (index) !== "number") @@ -753,8 +753,8 @@ export class WasmBuilder { this.appendULeb(index); } - local (name: string | number, opcode?: WasmOpcode) { - const index = typeof(name) === "string" + local(name: string | number, opcode?: WasmOpcode) { + const index = typeof (name) === "string" ? (this.locals.has(name) ? this.locals.get(name)! : undefined) : name + this.argumentCount; if (typeof (index) !== "number") @@ -766,7 +766,7 @@ export class WasmBuilder { this.appendULeb(index); } - appendMemarg (offset: number, alignPower: number) { + appendMemarg(offset: number, alignPower: number) { this.appendULeb(alignPower); this.appendULeb(offset); } @@ -774,7 +774,7 @@ export class WasmBuilder { /* generates either (u32)get_local(ptr) + offset or (u32)ptr1 + offset */ - lea (ptr1: string | number, offset: number) { + lea(ptr1: string | number, offset: number) { if (typeof (ptr1) === "string") this.local(ptr1); else @@ -785,14 +785,14 @@ export class WasmBuilder { this.appendU8(WasmOpcode.i32_add); } - getArrayView (fullCapacity?: boolean) { + getArrayView(fullCapacity?: boolean) { if (this.stackSize > 1) throw new Error("Jiterpreter block stack not empty"); return this.stack[0].getArrayView(fullCapacity); } - getConstants () { - const result : { [key: string]: number } = {}; + getConstants() { + const result: { [key: string]: number } = {}; for (let i = 0; i < this.constantSlots.length; i++) result[i.toString(shortNameBase)] = this.constantSlots[i]; return result; @@ -806,7 +806,7 @@ export class BlobBuilder { encoder?: TextEncoder; textBuf = new Uint8Array(1024); - constructor () { + constructor() { this.capacity = 16 * 1024; this.buffer = Module._malloc(this.capacity); Module.HEAPU8.fill(0, this.buffer, this.buffer + this.capacity); @@ -816,11 +816,11 @@ export class BlobBuilder { this.encoder = new TextEncoder(); } - clear () { + clear() { this.size = 0; } - appendU8 (value: number | WasmOpcode) { + appendU8(value: number | WasmOpcode) { if (this.size >= this.capacity) throw new Error("Buffer full"); @@ -829,35 +829,35 @@ export class BlobBuilder { return result; } - appendU32 (value: number) { + appendU32(value: number) { const result = this.size; cwraps.mono_jiterp_write_number_unaligned(this.buffer + this.size, value, JiterpNumberMode.U32); this.size += 4; return result; } - appendI32 (value: number) { + appendI32(value: number) { const result = this.size; cwraps.mono_jiterp_write_number_unaligned(this.buffer + this.size, value, JiterpNumberMode.I32); this.size += 4; return result; } - appendF32 (value: number) { + appendF32(value: number) { const result = this.size; cwraps.mono_jiterp_write_number_unaligned(this.buffer + this.size, value, JiterpNumberMode.F32); this.size += 4; return result; } - appendF64 (value: number) { + appendF64(value: number) { const result = this.size; cwraps.mono_jiterp_write_number_unaligned(this.buffer + this.size, value, JiterpNumberMode.F64); this.size += 8; return result; } - appendBoundaryValue (bits: number, sign: number) { + appendBoundaryValue(bits: number, sign: number) { if (this.size + 8 >= this.capacity) throw new Error("Buffer full"); @@ -868,7 +868,7 @@ export class BlobBuilder { return bytesWritten; } - appendULeb (value: number) { + appendULeb(value: number) { mono_assert(value >= 0, "cannot pass negative value to appendULeb"); if (value < 0x7F) { if (this.size + 1 >= this.capacity) @@ -888,7 +888,7 @@ export class BlobBuilder { return bytesWritten; } - appendLeb (value: number) { + appendLeb(value: number) { if (this.size + 8 >= this.capacity) throw new Error("Buffer full"); @@ -899,7 +899,7 @@ export class BlobBuilder { return bytesWritten; } - appendLebRef (sourceAddress: VoidPtr, signed: boolean) { + appendLebRef(sourceAddress: VoidPtr, signed: boolean) { if (this.size + 8 >= this.capacity) throw new Error("Buffer full"); @@ -910,7 +910,7 @@ export class BlobBuilder { return bytesWritten; } - copyTo (destination: BlobBuilder, count?: number) { + copyTo(destination: BlobBuilder, count?: number) { if (typeof (count) !== "number") count = this.size; @@ -918,7 +918,7 @@ export class BlobBuilder { destination.size += count; } - appendBytes (bytes: Uint8Array, count?: number) { + appendBytes(bytes: Uint8Array, count?: number) { const result = this.size; if (bytes.buffer === Module.HEAPU8.buffer) { if (typeof (count) !== "number") @@ -937,7 +937,7 @@ export class BlobBuilder { return result; } - appendName (text: string) { + appendName(text: string) { let count = text.length; // TextEncoder overhead is significant for short strings, and lots of our strings // are single-character import names, so add a fast path for single characters @@ -972,7 +972,7 @@ export class BlobBuilder { this.appendBytes(this.textBuf, count); } - getArrayView (fullCapacity?: boolean) { + getArrayView(fullCapacity?: boolean) { return new Uint8Array(Module.HEAPU8.buffer, this.buffer, fullCapacity ? this.capacity : this.size); } } @@ -1019,11 +1019,11 @@ class Cfg { observedBranchTargets = new Set(); trace = 0; - constructor (builder: WasmBuilder) { + constructor(builder: WasmBuilder) { this.builder = builder; } - initialize (startOfBody: MintOpcodePtr, backBranchTargets: Uint16Array | null, trace: number) { + initialize(startOfBody: MintOpcodePtr, backBranchTargets: Uint16Array | null, trace: number) { this.segments.length = 0; this.blockStack.length = 0; this.startOfBody = startOfBody; @@ -1039,7 +1039,7 @@ class Cfg { } // We have a header containing the table of locals and we need to preserve it - entry (ip: MintOpcodePtr) { + entry(ip: MintOpcodePtr) { this.entryIp = ip; this.appendBlob(); mono_assert(this.segments.length === 1, "expected 1 segment"); @@ -1053,7 +1053,7 @@ class Cfg { } } - appendBlob () { + appendBlob() { if (this.builder.current.size === this.lastSegmentEnd) return; @@ -1069,7 +1069,7 @@ class Cfg { this.overheadBytes += 2; } - startBranchBlock (ip: MintOpcodePtr, isBackBranchTarget: boolean) { + startBranchBlock(ip: MintOpcodePtr, isBackBranchTarget: boolean) { this.appendBlob(); this.segments.push({ type: "branch-block-header", @@ -1079,7 +1079,7 @@ class Cfg { this.overheadBytes += 1; // each branch block just costs us an end } - branch (target: MintOpcodePtr, isBackward: boolean, isConditional: boolean) { + branch(target: MintOpcodePtr, isBackward: boolean, isConditional: boolean) { this.observedBranchTargets.add(target); this.appendBlob(); this.segments.push({ @@ -1102,13 +1102,13 @@ class Cfg { } } - emitBlob (segment: CfgBlob, source: Uint8Array) { + emitBlob(segment: CfgBlob, source: Uint8Array) { // console.log(`segment @${(segment.ip).toString(16)} ${segment.start}-${segment.start + segment.length}`); const view = source.subarray(segment.start, segment.start + segment.length); this.builder.appendBytes(view); } - generate (): Uint8Array { + generate(): Uint8Array { // HACK: Make sure any remaining bytes are inserted into a trailing segment this.appendBlob(); @@ -1316,7 +1316,7 @@ export const enum WasmValtype { f64 = 0x7C, } -let wasmTable : WebAssembly.Table | undefined; +let wasmTable: WebAssembly.Table | undefined; let wasmNextFunctionIndex = -1, wasmFunctionIndicesFree = 0; // eslint-disable-next-line prefer-const @@ -1342,9 +1342,9 @@ export const _now = (globalThis.performance && globalThis.performance.now) ? globalThis.performance.now.bind(globalThis.performance) : Date.now; -let scratchBuffer : NativePointer = 0; +let scratchBuffer: NativePointer = 0; -export function append_bailout (builder: WasmBuilder, ip: MintOpcodePtr, reason: BailoutReason) { +export function append_bailout(builder: WasmBuilder, ip: MintOpcodePtr, reason: BailoutReason) { builder.ip_const(ip); if (builder.options.countBailouts) { builder.i32_const(builder.base); @@ -1355,7 +1355,7 @@ export function append_bailout (builder: WasmBuilder, ip: MintOpcodePtr, reason: } // generate a bailout that is recorded for the monitoring phase as a possible early exit. -export function append_exit (builder: WasmBuilder, ip: MintOpcodePtr, opcodeCounter: number, reason: BailoutReason) { +export function append_exit(builder: WasmBuilder, ip: MintOpcodePtr, opcodeCounter: number, reason: BailoutReason) { if (opcodeCounter <= (builder.options.monitoringLongDistance + 2)) { builder.local("cinfo"); builder.i32_const(opcodeCounter); @@ -1379,7 +1379,7 @@ export function append_exit (builder: WasmBuilder, ip: MintOpcodePtr, opcodeCoun builder.appendU8(WasmOpcode.return_); } -export function copyIntoScratchBuffer (src: NativePointer, size: number) : NativePointer { +export function copyIntoScratchBuffer(src: NativePointer, size: number): NativePointer { if (!scratchBuffer) scratchBuffer = Module._malloc(64); if (size > 64) @@ -1389,7 +1389,7 @@ export function copyIntoScratchBuffer (src: NativePointer, size: number) : Nativ return scratchBuffer; } -export function getWasmFunctionTable () { +export function getWasmFunctionTable() { if (!wasmTable) wasmTable = (Module)["asm"]["__indirect_function_table"]; if (!wasmTable) @@ -1397,8 +1397,8 @@ export function getWasmFunctionTable () { return wasmTable; } -export function addWasmFunctionPointer (f: Function) { - mono_assert(f,"Attempting to set null function into table"); +export function addWasmFunctionPointer(f: Function) { + mono_assert(f, "Attempting to set null function into table"); mono_assert(!runtimeHelpers.storeMemorySnapshotPending, "Attempting to set function into table during creation of memory snapshot"); const table = getWasmFunctionTable(); @@ -1414,7 +1414,7 @@ export function addWasmFunctionPointer (f: Function) { return index; } -export function try_append_memset_fast (builder: WasmBuilder, localOffset: number, value: number, count: number, destOnStack: boolean) { +export function try_append_memset_fast(builder: WasmBuilder, localOffset: number, value: number, count: number, destOnStack: boolean) { if (count <= 0) { if (destOnStack) builder.appendU8(WasmOpcode.drop); @@ -1468,7 +1468,7 @@ export function try_append_memset_fast (builder: WasmBuilder, localOffset: numbe return true; } -export function append_memset_dest (builder: WasmBuilder, value: number, count: number) { +export function append_memset_dest(builder: WasmBuilder, value: number, count: number) { // spec: pop n, pop val, pop d, fill from d[0] to d[n] with value val if (try_append_memset_fast(builder, 0, value, count, true)) return; @@ -1480,7 +1480,7 @@ export function append_memset_dest (builder: WasmBuilder, value: number, count: builder.appendU8(0); } -export function try_append_memmove_fast ( +export function try_append_memmove_fast( builder: WasmBuilder, destLocalOffset: number, srcLocalOffset: number, count: number, addressesOnStack: boolean, destLocal?: string, srcLocal?: string ) { @@ -1524,7 +1524,7 @@ export function try_append_memmove_fast ( // Then copy the remaining 0-7 bytes while (count >= 1) { - let loadOp : WasmOpcode, storeOp : WasmOpcode; + let loadOp: WasmOpcode, storeOp: WasmOpcode; let localCount = count % 4; switch (localCount) { case 0: @@ -1564,7 +1564,7 @@ export function try_append_memmove_fast ( } // expects dest then source to have been pushed onto wasm stack -export function append_memmove_dest_src (builder: WasmBuilder, count: number) { +export function append_memmove_dest_src(builder: WasmBuilder, count: number) { if (try_append_memmove_fast(builder, 0, 0, count, true)) return true; @@ -1578,7 +1578,7 @@ export function append_memmove_dest_src (builder: WasmBuilder, count: number) { return true; } -export function recordFailure () : void { +export function recordFailure(): void { counters.failures++; if (counters.failures >= maxFailures) { console.log(`MONO_WASM: Disabling jiterpreter after ${counters.failures} failures`); @@ -1606,9 +1606,9 @@ export const enum JiterpMember { ClauseDataOffsets = 12, } -const memberOffsets : { [index: number] : number } = {}; +const memberOffsets: { [index: number]: number } = {}; -export function getMemberOffset (member: JiterpMember) { +export function getMemberOffset(member: JiterpMember) { const cached = memberOffsets[member]; if (cached === undefined) return memberOffsets[member] = cwraps.mono_jiterp_get_member_offset(member); @@ -1616,23 +1616,23 @@ export function getMemberOffset (member: JiterpMember) { return cached; } -export function getRawCwrap (name: string): Function { +export function getRawCwrap(name: string): Function { const result = (Module)["asm"][name]; if (typeof (result) !== "function") throw new Error(`raw cwrap ${name} not found`); return result; } -const opcodeTableCache : { [opcode: number] : number } = {}; +const opcodeTableCache: { [opcode: number]: number } = {}; -export function getOpcodeTableValue (opcode: MintOpcode) { +export function getOpcodeTableValue(opcode: MintOpcode) { let result = opcodeTableCache[opcode]; if (typeof (result) !== "number") result = opcodeTableCache[opcode] = cwraps.mono_jiterp_get_opcode_value_table_entry(opcode); return result; } -export function importDef (name: string, fn: Function): [string, string, Function] { +export function importDef(name: string, fn: Function): [string, string, Function] { return [name, name, fn]; } @@ -1678,7 +1678,7 @@ export type JiterpreterOptions = { wasmBytesLimit: number; } -const optionNames : { [jsName: string] : string } = { +const optionNames: { [jsName: string]: string } = { "enableTraces": "jiterpreter-traces-enabled", "enableInterpEntry": "jiterpreter-interp-entry-enabled", "enableJitCall": "jiterpreter-jit-call-enabled", @@ -1709,10 +1709,10 @@ const optionNames : { [jsName: string] : string } = { }; let optionsVersion = -1; -let optionTable : JiterpreterOptions = {}; +let optionTable: JiterpreterOptions = {}; // applies one or more jiterpreter options to change the current jiterpreter configuration. -export function applyOptions (options: JiterpreterOptions) { +export function applyOptions(options: JiterpreterOptions) { for (const k in options) { const info = optionNames[k]; if (!info) { @@ -1726,12 +1726,12 @@ export function applyOptions (options: JiterpreterOptions) { else if (typeof (v) === "number") cwraps.mono_jiterp_parse_option(`--${info}=${v}`); else - console.error(`Jiterpreter option must be a boolean or a number but was ${typeof(v)} '${v}'`); + console.error(`Jiterpreter option must be a boolean or a number but was ${typeof (v)} '${v}'`); } } // returns the current jiterpreter configuration. do not mutate the return value! -export function getOptions () { +export function getOptions() { const currentVersion = cwraps.mono_jiterp_get_options_version(); if (currentVersion !== optionsVersion) { updateOptions(); @@ -1740,7 +1740,7 @@ export function getOptions () { return optionTable; } -function updateOptions () { +function updateOptions() { const pJson = cwraps.mono_jiterp_get_options_as_json(); const json = Module.UTF8ToString(pJson); Module._free(pJson); diff --git a/src/mono/wasm/runtime/jiterpreter.ts b/src/mono/wasm/runtime/jiterpreter.ts index 004befc179cf29..30759e547a0e6d 100644 --- a/src/mono/wasm/runtime/jiterpreter.ts +++ b/src/mono/wasm/runtime/jiterpreter.ts @@ -3,7 +3,7 @@ import { mono_assert, MonoMethod } from "./types"; import { NativePointer } from "./types/emscripten"; -import { Module, runtimeHelpers } from "./imports"; +import { Module, runtimeHelpers } from "./globals"; import { getU16, getU32_unaligned } from "./memory"; @@ -81,21 +81,21 @@ export const // Web browsers limit synchronous module compiles to 4KB maxModuleSize = 4080; -export const callTargetCounts : { [method: number] : number } = {}; +export const callTargetCounts: { [method: number]: number } = {}; -export let mostRecentTrace : InstrumentedTraceState | undefined; -export let mostRecentOptions : JiterpreterOptions | undefined = undefined; +export let mostRecentTrace: InstrumentedTraceState | undefined; +export let mostRecentOptions: JiterpreterOptions | undefined = undefined; // You can disable an opcode for debugging purposes by adding it to this list, // instead of aborting the trace it will insert a bailout instead. This means that you will // have trace code generated as if the opcode were otherwise enabled -export const disabledOpcodes : Array = [ +export const disabledOpcodes: Array = [ ]; // Detailed output and/or instrumentation will happen when a trace is jitted if the method fullname has a match // Having any items in this list will add some overhead to the jitting of *all* traces // These names can be substrings and instrumentation will happen if the substring is found in the full name -export const instrumentedMethodNames : Array = [ +export const instrumentedMethodNames: Array = [ ]; export class InstrumentedTraceState { @@ -104,7 +104,7 @@ export class InstrumentedTraceState { operand1: number | undefined; operand2: number | undefined; - constructor (name: string) { + constructor(name: string) { this.name = name; this.eip = 0; } @@ -116,24 +116,24 @@ export class TraceInfo { name: string | undefined; abortReason: string | undefined; fnPtr: number | undefined; - bailoutCounts: { [code: number] : number } | undefined; + bailoutCounts: { [code: number]: number } | undefined; bailoutCount: number | undefined; - constructor (ip: MintOpcodePtr, index: number) { + constructor(ip: MintOpcodePtr, index: number) { this.ip = ip; this.index = index; } - get hitCount () { + get hitCount() { return cwraps.mono_jiterp_get_trace_hit_count(this.index); } } -export const instrumentedTraces : { [key: number]: InstrumentedTraceState } = {}; +export const instrumentedTraces: { [key: number]: InstrumentedTraceState } = {}; export let nextInstrumentedTraceId = 1; export let countLimitedPrintCounter = 10; -export const abortCounts : { [key: string] : number } = {}; -export const traceInfo : { [key: string] : TraceInfo } = {}; +export const abortCounts: { [key: string]: number } = {}; +export const traceInfo: { [key: string]: TraceInfo } = {}; export const sizeOfDataItem = 4, @@ -144,25 +144,25 @@ export const /* 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 { @@ -177,12 +177,13 @@ struct InterpMethod { void **data_items; */ -export let traceBuilder : WasmBuilder; -export let traceImports : Array<[string, string, Function]> | undefined; +export let traceBuilder: WasmBuilder; +export let traceImports: Array<[string, string, Function]> | undefined; export let _wrap_trace_function: Function; -const mathOps1d = [ +const mathOps1d = + [ "asin", "acos", "atan", @@ -228,7 +229,7 @@ const mathOps1d = [ "powf", ]; -function recordBailout (ip: number, base: MintOpcodePtr, reason: BailoutReason) { +function recordBailout(ip: number, base: MintOpcodePtr, reason: BailoutReason) { cwraps.mono_jiterp_trace_bailout(reason); // Counting these is not meaningful and messes up the end of run statistics if (reason === BailoutReason.Return) @@ -254,7 +255,7 @@ function recordBailout (ip: number, base: MintOpcodePtr, reason: BailoutReason) return ip; } -function getTraceImports () { +function getTraceImports() { if (traceImports) return traceImports; @@ -315,7 +316,7 @@ function getTraceImports () { return traceImports; } -function wrap_trace_function ( +function wrap_trace_function( f: Function, name: string, traceBuf: any, base: MintOpcodePtr, instrumentedTraceId: number ) { @@ -354,265 +355,343 @@ function wrap_trace_function ( ); } -function initialize_builder (builder: WasmBuilder) { +function initialize_builder(builder: WasmBuilder) { // Function type for compiled traces builder.defineType( - "trace", { + "trace", + { "frame": WasmValtype.i32, "pLocals": WasmValtype.i32, "cinfo": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "bailout", { + "bailout", + { "retval": WasmValtype.i32, "base": WasmValtype.i32, "reason": WasmValtype.i32 - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "copy_pointer", { + "copy_pointer", + { "dest": WasmValtype.i32, "src": WasmValtype.i32 - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "value_copy", { + "value_copy", + { "dest": WasmValtype.i32, "src": WasmValtype.i32, "klass": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "entry", { + "entry", + { "imethod": WasmValtype.i32 - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "strlen", { + "strlen", + { "ppString": WasmValtype.i32, "pResult": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "getchr", { + "getchr", + { "ppString": WasmValtype.i32, "pIndex": WasmValtype.i32, "pResult": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "getspan", { + "getspan", + { "destination": WasmValtype.i32, "span": WasmValtype.i32, "index": WasmValtype.i32, "element_size": WasmValtype.i32 - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "overflow_check_i4", { + "overflow_check_i4", + { "lhs": WasmValtype.i32, "rhs": WasmValtype.i32, "opcode": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "mathop_d_d", { + "mathop_d_d", + { "value": WasmValtype.f64, - }, WasmValtype.f64, true + }, + WasmValtype.f64, true ); builder.defineType( - "mathop_dd_d", { + "mathop_dd_d", + { "lhs": WasmValtype.f64, "rhs": WasmValtype.f64, - }, WasmValtype.f64, true + }, + WasmValtype.f64, true ); builder.defineType( - "mathop_f_f", { + "mathop_f_f", + { "value": WasmValtype.f32, - }, WasmValtype.f32, true + }, + WasmValtype.f32, true ); builder.defineType( - "mathop_ff_f", { + "mathop_ff_f", + { "lhs": WasmValtype.f32, "rhs": WasmValtype.f32, - }, WasmValtype.f32, true + }, + WasmValtype.f32, true ); builder.defineType( - "fmaf", { + "fmaf", + { "x": WasmValtype.f32, "y": WasmValtype.f32, "z": WasmValtype.f32, - }, WasmValtype.f32, true + }, + WasmValtype.f32, true ); builder.defineType( - "fma", { + "fma", + { "x": WasmValtype.f64, "y": WasmValtype.f64, "z": WasmValtype.f64, - }, WasmValtype.f64, true + }, + WasmValtype.f64, true ); builder.defineType( - "trace_eip", { + "trace_eip", + { "traceId": WasmValtype.i32, "eip": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "newobj_i", { + "newobj_i", + { "ppDestination": WasmValtype.i32, "vtable": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "newstr", { + "newstr", + { "ppDestination": WasmValtype.i32, "length": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "localloc", { + "localloc", + { "destination": WasmValtype.i32, "len": WasmValtype.i32, "frame": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "ld_del_ptr", { + "ld_del_ptr", + { "ppDestination": WasmValtype.i32, "ppSource": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "ldtsflda", { + "ldtsflda", + { "ppDestination": WasmValtype.i32, "offset": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "gettype", { + "gettype", + { "destination": WasmValtype.i32, "source": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "cast", { + "cast", + { "destination": WasmValtype.i32, "source": WasmValtype.i32, "klass": WasmValtype.i32, "opcode": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "try_unbox", { + "try_unbox", + { "klass": WasmValtype.i32, "destination": WasmValtype.i32, "source": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "box", { + "box", + { "vtable": WasmValtype.i32, "destination": WasmValtype.i32, "source": WasmValtype.i32, "vt": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "conv", { + "conv", + { "destination": WasmValtype.i32, "source": WasmValtype.i32, "opcode": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "relop_fp", { + "relop_fp", + { "lhs": WasmValtype.f64, "rhs": WasmValtype.f64, "opcode": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "safepoint", { + "safepoint", + { "frame": WasmValtype.i32, "ip": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "hashcode", { + "hashcode", + { "ppObj": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "try_hash", { + "try_hash", + { "ppObj": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "hascsize", { + "hascsize", + { "ppObj": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "hasflag", { + "hasflag", + { "klass": WasmValtype.i32, "dest": WasmValtype.i32, "sp1": WasmValtype.i32, "sp2": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "array_rank", { + "array_rank", + { "destination": WasmValtype.i32, "source": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "stfld_o", { + "stfld_o", + { "locals": WasmValtype.i32, "fieldOffsetBytes": WasmValtype.i32, "targetLocalOffsetBytes": WasmValtype.i32, "sourceLocalOffsetBytes": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "notnull", { + "notnull", + { "ptr": WasmValtype.i32, "expected": WasmValtype.i32, "traceIp": WasmValtype.i32, "ip": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "cmpxchg_i32", { + "cmpxchg_i32", + { "dest": WasmValtype.i32, "newVal": WasmValtype.i32, "expected": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "cmpxchg_i64", { + "cmpxchg_i64", + { "dest": WasmValtype.i32, "newVal": WasmValtype.i32, "expected": WasmValtype.i32, "oldVal": WasmValtype.i32, - }, WasmValtype.void, true + }, + WasmValtype.void, true ); builder.defineType( - "transfer", { + "transfer", + { "displacement": WasmValtype.i32, "trace": WasmValtype.i32, "frame": WasmValtype.i32, "locals": WasmValtype.i32, "cinfo": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); builder.defineType( - "stelem_ref", { + "stelem_ref", + { "o": WasmValtype.i32, "aindex": WasmValtype.i32, "ref": WasmValtype.i32, - }, WasmValtype.i32, true + }, + WasmValtype.i32, true ); const traceImports = getTraceImports(); @@ -624,7 +703,7 @@ function initialize_builder (builder: WasmBuilder) { } } -function assert_not_null ( +function assert_not_null( value: number, expectedValue: number, traceIp: MintOpcodePtr, ip: MintOpcodePtr ) { if (value && (value === expectedValue)) @@ -634,11 +713,11 @@ function assert_not_null ( } // returns function id -function generate_wasm ( +function generate_wasm( frame: NativePointer, methodName: string, ip: MintOpcodePtr, startOfBody: MintOpcodePtr, sizeOfBody: MintOpcodePtr, methodFullName: string | undefined, backwardBranchTable: Uint16Array | null -) : number { +): number { // Pre-allocate a decent number of constant slots - this adds fixed size bloat // to the trace but will make the actual pointer constants in the trace smaller // If we run out of constant slots it will transparently fall back to i32_const @@ -862,7 +941,7 @@ function generate_wasm ( } } -export function trace_current_ip (traceId: number, eip: MintOpcodePtr) { +export function trace_current_ip(traceId: number, eip: MintOpcodePtr) { const tup = instrumentedTraces[traceId]; if (!tup) throw new Error(`Unrecognized instrumented trace id ${traceId}`); @@ -870,14 +949,14 @@ export function trace_current_ip (traceId: number, eip: MintOpcodePtr) { mostRecentTrace = tup; } -export function trace_operands (a: number, b: number) { +export function trace_operands(a: number, b: number) { if (!mostRecentTrace) throw new Error("No trace active"); mostRecentTrace.operand1 = a >>> 0; mostRecentTrace.operand2 = b >>> 0; } -export function record_abort (traceIp: MintOpcodePtr, ip: MintOpcodePtr, traceName: string, reason: string | MintOpcode) { +export function record_abort(traceIp: MintOpcodePtr, ip: MintOpcodePtr, traceName: string, reason: string | MintOpcode) { if (typeof (reason) === "number") { cwraps.mono_jiterp_adjust_abort_count(reason, 1); reason = OpcodeInfo[reason][0]; @@ -900,10 +979,10 @@ export function record_abort (traceIp: MintOpcodePtr, ip: MintOpcodePtr, traceNa const JITERPRETER_TRAINING = 0; const JITERPRETER_NOT_JITTED = 1; -export function mono_interp_tier_prepare_jiterpreter ( +export function mono_interp_tier_prepare_jiterpreter( frame: NativePointer, method: MonoMethod, ip: MintOpcodePtr, index: number, startOfBody: MintOpcodePtr, sizeOfBody: MintOpcodePtr -) : number { +): number { mono_assert(ip, "expected instruction pointer"); if (!mostRecentOptions) mostRecentOptions = getOptions(); @@ -969,7 +1048,7 @@ export function mono_interp_tier_prepare_jiterpreter ( } } -export function jiterpreter_dump_stats (b?: boolean, concise?: boolean) { +export function jiterpreter_dump_stats(b?: boolean, concise?: boolean) { if (!mostRecentOptions || (b !== undefined)) mostRecentOptions = getOptions(); @@ -1004,7 +1083,7 @@ export function jiterpreter_dump_stats (b?: boolean, concise?: boolean) { } if (mostRecentOptions.estimateHeat) { - const counts : { [key: string] : number } = {}; + const counts: { [key: string]: number } = {}; const traces = Object.values(traceInfo); for (let i = 0; i < traces.length; i++) { @@ -1087,7 +1166,7 @@ export function jiterpreter_dump_stats (b?: boolean, concise?: boolean) { console.log(`${traces[i].name} @${traces[i].ip} (${traces[i].hitCount} hits) ${traces[i].abortReason}`); } - const tuples : Array<[string, number]> = []; + const tuples: Array<[string, number]> = []; for (const k in counts) tuples.push([k, counts[k]]); @@ -1112,7 +1191,7 @@ export function jiterpreter_dump_stats (b?: boolean, concise?: boolean) { console.log(`// ${keys[i]}: ${abortCounts[keys[i]]} abort(s)`); } - if ((typeof(globalThis.setTimeout) === "function") && (b !== undefined)) + if ((typeof (globalThis.setTimeout) === "function") && (b !== undefined)) setTimeout( () => jiterpreter_dump_stats(b), 15000 diff --git a/src/mono/wasm/runtime/logging.ts b/src/mono/wasm/runtime/logging.ts index 9e3bef14fa4792..5f3910e30499f1 100644 --- a/src/mono/wasm/runtime/logging.ts +++ b/src/mono/wasm/runtime/logging.ts @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { INTERNAL, Module, runtimeHelpers } from "./imports"; +import { INTERNAL, Module, runtimeHelpers } from "./globals"; import { CharPtr, VoidPtr } from "./types/emscripten"; export const wasm_func_map = new Map(); diff --git a/src/mono/wasm/runtime/managed-exports.ts b/src/mono/wasm/runtime/managed-exports.ts index f4af331a516ce5..4892052af57202 100644 --- a/src/mono/wasm/runtime/managed-exports.ts +++ b/src/mono/wasm/runtime/managed-exports.ts @@ -3,7 +3,7 @@ import { GCHandle, MarshalerToCs, MarshalerToJs, MarshalerType, MonoMethod, mono_assert } from "./types"; import cwraps from "./cwraps"; -import { runtimeHelpers, ENVIRONMENT_IS_PTHREAD, Module } from "./imports"; +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 { invoke_method_and_handle_exception } from "./invoke-cs"; import { marshal_array_to_cs_impl, marshal_exception_to_cs, marshal_intptr_to_cs } from "./marshal-to-cs"; diff --git a/src/mono/wasm/runtime/marshal-to-cs.ts b/src/mono/wasm/runtime/marshal-to-cs.ts index 2e1ff002741a24..cc596738cd07f2 100644 --- a/src/mono/wasm/runtime/marshal-to-cs.ts +++ b/src/mono/wasm/runtime/marshal-to-cs.ts @@ -5,7 +5,7 @@ import monoWasmThreads from "consts:monoWasmThreads"; import { isThenable } from "./cancelable-promise"; import cwraps from "./cwraps"; import { assert_not_disposed, cs_owned_js_handle_symbol, js_owned_gc_handle_symbol, mono_wasm_get_js_handle, setup_managed_proxy, teardown_managed_proxy } from "./gc-handles"; -import { Module, runtimeHelpers } from "./imports"; +import { Module, runtimeHelpers } from "./globals"; import { ManagedError, set_gc_handle, set_js_handle, set_arg_type, set_arg_i32, set_arg_f64, set_arg_i52, set_arg_f32, set_arg_i16, set_arg_u8, set_arg_b8, set_arg_date, diff --git a/src/mono/wasm/runtime/marshal-to-js.ts b/src/mono/wasm/runtime/marshal-to-js.ts index 36f1dcd6bcd1fe..6590bacd12cefe 100644 --- a/src/mono/wasm/runtime/marshal-to-js.ts +++ b/src/mono/wasm/runtime/marshal-to-js.ts @@ -4,7 +4,7 @@ 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 "./imports"; +import { Module, 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, diff --git a/src/mono/wasm/runtime/marshal.ts b/src/mono/wasm/runtime/marshal.ts index 51032095d1414d..5cc7a9eab5cad7 100644 --- a/src/mono/wasm/runtime/marshal.ts +++ b/src/mono/wasm/runtime/marshal.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import { js_owned_gc_handle_symbol, teardown_managed_proxy } from "./gc-handles"; -import { Module, runtimeHelpers } from "./imports"; +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"; diff --git a/src/mono/wasm/runtime/memory.ts b/src/mono/wasm/runtime/memory.ts index 2a5cf9592921b5..dc3c43357856e2 100644 --- a/src/mono/wasm/runtime/memory.ts +++ b/src/mono/wasm/runtime/memory.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import monoWasmThreads from "consts:monoWasmThreads"; -import { Module, runtimeHelpers } from "./imports"; +import { Module, runtimeHelpers } from "./globals"; import { mono_assert, MemOffset, NumberOrPointer } from "./types"; import { VoidPtr, CharPtr } from "./types/emscripten"; import cwraps, { I52Error } from "./cwraps"; diff --git a/src/mono/wasm/runtime/net6-legacy/buffers.ts b/src/mono/wasm/runtime/net6-legacy/buffers.ts index b82e36a5b69ff4..0a33b6991b0bdc 100644 --- a/src/mono/wasm/runtime/net6-legacy/buffers.ts +++ b/src/mono/wasm/runtime/net6-legacy/buffers.ts @@ -1,7 +1,7 @@ // 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 "../imports"; +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"; diff --git a/src/mono/wasm/runtime/net6-legacy/corebindings.ts b/src/mono/wasm/runtime/net6-legacy/corebindings.ts index 97f660910a5c23..489df81ece89af 100644 --- a/src/mono/wasm/runtime/net6-legacy/corebindings.ts +++ b/src/mono/wasm/runtime/net6-legacy/corebindings.ts @@ -4,10 +4,10 @@ import { JSHandle, GCHandle, MonoObjectRef, MonoMethod, MonoObject, WasmRoot } from "../types"; import { mono_bind_method, _create_primitive_converters } from "./method-binding"; import { mono_wasm_new_root } from "../roots"; -import { Module, runtimeHelpers } from "../imports"; +import { Module, runtimeHelpers } from "../globals"; import cwraps from "../cwraps"; import { PromiseController } from "../promise-controller"; -import { legacyHelpers, wasm_type_symbol } from "./imports"; +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*/]; const fn_signatures: SigLine[] = [ diff --git a/src/mono/wasm/runtime/net6-legacy/cs-to-js.ts b/src/mono/wasm/runtime/net6-legacy/cs-to-js.ts index c19744f11c3507..2aefab4afb7a72 100644 --- a/src/mono/wasm/runtime/net6-legacy/cs-to-js.ts +++ b/src/mono/wasm/runtime/net6-legacy/cs-to-js.ts @@ -13,7 +13,7 @@ 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 "./imports"; +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"; diff --git a/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts b/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts index 3e93287282e8a2..0c45c2749357ab 100644 --- a/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts +++ b/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts @@ -4,7 +4,7 @@ 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 "../imports"; +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"; diff --git a/src/mono/wasm/runtime/net6-legacy/imports.ts b/src/mono/wasm/runtime/net6-legacy/globals.ts similarity index 82% rename from src/mono/wasm/runtime/net6-legacy/imports.ts rename to src/mono/wasm/runtime/net6-legacy/globals.ts index d62ebf7806e7d1..cf69addeaee4ac 100644 --- a/src/mono/wasm/runtime/net6-legacy/imports.ts +++ b/src/mono/wasm/runtime/net6-legacy/globals.ts @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import type { EarlyExports, MonoClass } from "../types"; +import type { GlobalObjects, MonoClass } from "../types"; import type { VoidPtr } from "../types/emscripten"; import type { BINDINGType, MONOType } from "./export-types"; @@ -11,11 +11,11 @@ export let BINDING: BINDINGType; export const legacyHelpers: LegacyHelpers = { }; -export function set_legacy_exports( - exports: EarlyExports, +export function initializeLegacyExports( + globals: GlobalObjects, ): void { - MONO = exports.mono; - BINDING = exports.binding; + MONO = globals.mono; + BINDING = globals.binding; } export type LegacyHelpers = { diff --git a/src/mono/wasm/runtime/net6-legacy/js-to-cs.ts b/src/mono/wasm/runtime/net6-legacy/js-to-cs.ts index 2ccf51d09759ba..f4f81ef5615d7e 100644 --- a/src/mono/wasm/runtime/net6-legacy/js-to-cs.ts +++ b/src/mono/wasm/runtime/net6-legacy/js-to-cs.ts @@ -4,7 +4,7 @@ import { isThenable } from "../cancelable-promise"; import { legacy_c_functions as cwraps } from "../cwraps"; import { js_owned_gc_handle_symbol, assert_not_disposed, cs_owned_js_handle_symbol, mono_wasm_get_js_handle, setup_managed_proxy, mono_wasm_release_cs_owned_object, teardown_managed_proxy, mono_wasm_get_jsobj_from_js_handle } from "../gc-handles"; -import { Module } from "../imports"; +import { Module } from "../globals"; import { wrap_error_root, wrap_no_error_root } from "../invoke-js"; 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"; @@ -14,7 +14,7 @@ import { TypedArray, Int32Ptr } from "../types/emscripten"; import { has_backing_array_buffer } from "./buffers"; import { legacyManagedExports } from "./corebindings"; import { get_js_owned_object_by_gc_handle_ref } from "./cs-to-js"; -import { legacyHelpers, wasm_type_symbol } from "./imports"; +import { legacyHelpers, wasm_type_symbol } from "./globals"; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function _js_to_mono_uri_root(should_add_in_flight: boolean, js_obj: any, result: WasmRoot): void { diff --git a/src/mono/wasm/runtime/net6-legacy/method-binding.ts b/src/mono/wasm/runtime/net6-legacy/method-binding.ts index cf330c8af1000a..780301959061f6 100644 --- a/src/mono/wasm/runtime/net6-legacy/method-binding.ts +++ b/src/mono/wasm/runtime/net6-legacy/method-binding.ts @@ -3,7 +3,7 @@ import MonoWasmThreads from "consts:monoWasmThreads"; import { legacy_c_functions as cwraps } from "../cwraps"; -import { ENVIRONMENT_IS_PTHREAD, Module } from "../imports"; +import { ENVIRONMENT_IS_PTHREAD, Module } from "../globals"; import { parseFQN } from "../invoke-cs"; 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"; @@ -12,7 +12,7 @@ import { MonoMethod, MonoObject, MonoType, MonoClass, mono_assert, VoidPtrNull, 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 { legacyHelpers } from "./imports"; +import { legacyHelpers } from "./globals"; import { js_to_mono_obj_root, _js_to_mono_uri_root, js_to_mono_enum } from "./js-to-cs"; import { _teardown_after_call } from "./method-calls"; diff --git a/src/mono/wasm/runtime/net6-legacy/method-calls.ts b/src/mono/wasm/runtime/net6-legacy/method-calls.ts index fa50cb01d42416..cf9fee9430ebd1 100644 --- a/src/mono/wasm/runtime/net6-legacy/method-calls.ts +++ b/src/mono/wasm/runtime/net6-legacy/method-calls.ts @@ -3,7 +3,7 @@ import MonoWasmThreads from "consts:monoWasmThreads"; import { get_js_obj, mono_wasm_get_jsobj_from_js_handle } from "../gc-handles"; -import { Module, runtimeHelpers, INTERNAL, ENVIRONMENT_IS_PTHREAD } from "../imports"; +import { Module, runtimeHelpers, INTERNAL, ENVIRONMENT_IS_PTHREAD } from "../globals"; import { wrap_error_root, wrap_no_error_root } from "../invoke-js"; import { _release_temp_frame } from "../memory"; import { mono_wasm_new_external_root, mono_wasm_new_root } from "../roots"; diff --git a/src/mono/wasm/runtime/polyfills.ts b/src/mono/wasm/runtime/polyfills.ts index cbccad539165f4..7185f3579c7152 100644 --- a/src/mono/wasm/runtime/polyfills.ts +++ b/src/mono/wasm/runtime/polyfills.ts @@ -3,9 +3,9 @@ import BuildConfiguration from "consts:configuration"; import MonoWasmThreads from "consts:monoWasmThreads"; -import type { DotnetModuleConfigImports, EarlyReplacements } from "./types"; +import type { DotnetModuleConfigImports, EmscriptenReplacements } from "./types"; import type { TypedArray } from "./types/emscripten"; -import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WORKER, ENVIRONMENT_IS_WEB, INTERNAL, Module, runtimeHelpers } from "./imports"; +import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, ENVIRONMENT_IS_WORKER, ENVIRONMENT_IS_WEB, INTERNAL, Module, runtimeHelpers } from "./globals"; import { replaceEmscriptenPThreadLibrary } from "./pthreads/shared/emscripten-replacements"; let node_fs: any | undefined = undefined; @@ -121,7 +121,7 @@ export function init_polyfills(): void { } } -export function initializeReplacements(replacements: EarlyReplacements): void { +export function initializeReplacements(replacements: EmscriptenReplacements): void { // require replacement const imports = Module.imports = (Module.imports || {}) as DotnetModuleConfigImports; const requireWrapper = (wrappedRequire: Function) => (name: string) => { @@ -294,7 +294,7 @@ function normalizeDirectoryUrl(dir: string) { return dir.slice(0, dir.lastIndexOf("/")) + "/"; } -export function detectScriptDirectory(replacements: EarlyReplacements): string { +export function detectScriptDirectory(replacements: EmscriptenReplacements): string { if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled replacements.scriptUrl = self.location.href; diff --git a/src/mono/wasm/runtime/profiler.ts b/src/mono/wasm/runtime/profiler.ts index 489cd4ff86856c..fbaa646d903bb7 100644 --- a/src/mono/wasm/runtime/profiler.ts +++ b/src/mono/wasm/runtime/profiler.ts @@ -1,7 +1,7 @@ // 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, Module, runtimeHelpers } from "./imports"; +import { ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./globals"; import { AOTProfilerOptions, BrowserProfilerOptions } from "./types"; import cwraps from "./cwraps"; import { MonoMethod } from "./types"; diff --git a/src/mono/wasm/runtime/pthreads/browser/index.ts b/src/mono/wasm/runtime/pthreads/browser/index.ts index 9a41aa5d824a7c..9910fcea2daea4 100644 --- a/src/mono/wasm/runtime/pthreads/browser/index.ts +++ b/src/mono/wasm/runtime/pthreads/browser/index.ts @@ -7,7 +7,7 @@ import { MonoThreadMessage } from "../shared"; import { PromiseController, createPromiseController } from "../../promise-controller"; import { mono_assert } from "../../types"; import Internals from "../shared/emscripten-internals"; -import { runtimeHelpers } from "../../imports"; +import { runtimeHelpers } from "../../globals"; import { MonoConfig } from "../../types-api"; const threads: Map = new Map(); diff --git a/src/mono/wasm/runtime/pthreads/shared/emscripten-internals.ts b/src/mono/wasm/runtime/pthreads/shared/emscripten-internals.ts index c0ac8c79c280c0..106d4318d37b24 100644 --- a/src/mono/wasm/runtime/pthreads/shared/emscripten-internals.ts +++ b/src/mono/wasm/runtime/pthreads/shared/emscripten-internals.ts @@ -1,7 +1,7 @@ // 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 "../../imports"; +import { Module } from "../../globals"; import { pthread_ptr } from "./types"; /** @module emscripten-internals accessors to the functions in the emscripten PThreads library, including diff --git a/src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts b/src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts index 77b9c1fc0aeea3..681a64bb21a71f 100644 --- a/src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts +++ b/src/mono/wasm/runtime/pthreads/shared/emscripten-replacements.ts @@ -8,7 +8,7 @@ import { afterThreadInitTLS } from "../worker"; import Internals from "./emscripten-internals"; import { resolve_asset_path } from "../../assets"; import { mono_assert } from "../../types"; -import { runtimeHelpers } from "../../imports"; +import { runtimeHelpers } from "../../globals"; /** @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 diff --git a/src/mono/wasm/runtime/pthreads/shared/index.ts b/src/mono/wasm/runtime/pthreads/shared/index.ts index 1d387bb9cd36c6..e5a8d655f3a639 100644 --- a/src/mono/wasm/runtime/pthreads/shared/index.ts +++ b/src/mono/wasm/runtime/pthreads/shared/index.ts @@ -1,7 +1,7 @@ // 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 "../../imports"; +import { Module } from "../../globals"; import { MonoConfig } from "../../types-api"; import { pthread_ptr } from "./types"; diff --git a/src/mono/wasm/runtime/pthreads/worker/index.ts b/src/mono/wasm/runtime/pthreads/worker/index.ts index 715620521cbcd3..df8dbbb723e680 100644 --- a/src/mono/wasm/runtime/pthreads/worker/index.ts +++ b/src/mono/wasm/runtime/pthreads/worker/index.ts @@ -4,7 +4,7 @@ /// import MonoWasmThreads from "consts:monoWasmThreads"; -import { Module, ENVIRONMENT_IS_PTHREAD, runtimeHelpers, ENVIRONMENT_IS_WEB } from "../../imports"; +import { Module, ENVIRONMENT_IS_PTHREAD, runtimeHelpers, ENVIRONMENT_IS_WEB } from "../../globals"; import { makeChannelCreatedMonoMessage, makePreloadMonoMessage } from "../shared"; import type { pthread_ptr } from "../shared/types"; import { is_nullish, MonoConfigInternal, mono_assert } from "../../types"; diff --git a/src/mono/wasm/runtime/roots.ts b/src/mono/wasm/runtime/roots.ts index 58e9114c3ae042..05b49a0b81df0e 100644 --- a/src/mono/wasm/runtime/roots.ts +++ b/src/mono/wasm/runtime/roots.ts @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. import cwraps from "./cwraps"; -import { Module } from "./imports"; +import { Module } from "./globals"; import { VoidPtr, ManagedPointer, NativePointer } from "./types/emscripten"; import { MonoObjectRef, MonoObjectRefNull, MonoObject, is_nullish, WasmRoot, WasmRootBuffer } from "./types"; import { _zero_region } from "./memory"; diff --git a/src/mono/wasm/runtime/run-outer.ts b/src/mono/wasm/runtime/run-outer.ts index dd2d0e612f6f2a..b28dc694a25e9a 100644 --- a/src/mono/wasm/runtime/run-outer.ts +++ b/src/mono/wasm/runtime/run-outer.ts @@ -4,16 +4,16 @@ // 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-api"; -import type { MonoConfigInternal, RuntimeHelpers, EarlyExports, DotnetModuleInternal, EmscriptenModuleInternal } from "./types"; +import type { MonoConfigInternal, GlobalObjects, EmscriptenModuleInternal } from "./types"; -import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WEB, set_module_and_helpers } from "./imports"; +import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_WEB, setGlobalObjects } from "./globals"; import { mono_exit } from "./run"; import { mono_assert } from "./types"; import { setup_proxy_console } from "./logging"; import { deep_merge_config, deep_merge_module } from "./config"; import { initializeExports } from "./exports"; -export const earlyExports: EarlyExports = { +export const globalObjectsRoot: GlobalObjects = { mono: {}, binding: {}, internal: {}, @@ -21,18 +21,10 @@ export const earlyExports: EarlyExports = { helpers: {}, api: {} } as any; -const module: DotnetModuleInternal = Object.assign(earlyExports.module, { - disableDotnet6Compatibility: true, - config: {} -}); -const monoConfig: MonoConfigInternal = Object.assign(module.config!, {}) as any; -const helpers: RuntimeHelpers = earlyExports.helpers; -const api: RuntimeAPI = Object.assign(earlyExports.api, { Module: module, ...module }); -Object.assign(api, { - INTERNAL: earlyExports.internal, -}); - -set_module_and_helpers(module, helpers, earlyExports.internal); + +setGlobalObjects(globalObjectsRoot); +const module = globalObjectsRoot.module; +const monoConfig = module.config as MonoConfigInternal; export class HostBuilder implements DotnetHostBuilder { private instance?: RuntimeAPI; @@ -315,7 +307,7 @@ export class HostBuilder implements DotnetHostBuilder { mono_assert(module, "Null moduleConfig"); mono_assert(module.config, "Null moduleConfig.config"); await createEmscripten(module); - this.instance = api; + this.instance = globalObjectsRoot.api; } if (this.virtualWorkingDirectory) { const FS = (this.instance!.Module as any).FS; @@ -356,10 +348,10 @@ export class HostBuilder implements DotnetHostBuilder { } export function unifyModuleConfig(originalModule: EmscriptenModuleInternal, moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): DotnetModuleConfig { - initializeExports(earlyExports); + initializeExports(); Object.assign(module, { ready: originalModule.ready }); if (typeof moduleFactory === "function") { - const extension = moduleFactory(api) as any; + const extension = moduleFactory(globalObjectsRoot.api) as any; if (extension.ready) { throw new Error("MONO_WASM: Module.ready couldn't be redefined."); } diff --git a/src/mono/wasm/runtime/run.ts b/src/mono/wasm/runtime/run.ts index e5d1136828a09e..1c1d805e3a7dfa 100644 --- a/src/mono/wasm/runtime/run.ts +++ b/src/mono/wasm/runtime/run.ts @@ -1,7 +1,7 @@ // 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, Module, runtimeHelpers } from "./imports"; +import { ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./globals"; import { mono_wasm_wait_for_debugger } from "./debug"; import { abort_startup, mono_wasm_set_main_args } from "./startup"; import cwraps from "./cwraps"; diff --git a/src/mono/wasm/runtime/snapshot.ts b/src/mono/wasm/runtime/snapshot.ts index e3f2c24997bdc3..cf225916edeeab 100644 --- a/src/mono/wasm/runtime/snapshot.ts +++ b/src/mono/wasm/runtime/snapshot.ts @@ -4,7 +4,7 @@ import ProductVersion from "consts:productVersion"; import GitHash from "consts:gitHash"; import MonoWasmThreads from "consts:monoWasmThreads"; -import { ENVIRONMENT_IS_WEB, runtimeHelpers } from "./imports"; +import { ENVIRONMENT_IS_WEB, runtimeHelpers } from "./globals"; const memoryPrefix = "https://dotnet.generated.invalid/wasm-memory"; diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index eb31d66f7e52d9..8f84d6edba8457 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -8,7 +8,7 @@ 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 "./imports"; +import { disableLegacyJsInterop, ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, exportedRuntimeAPI, INTERNAL, 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"; @@ -34,7 +34,7 @@ 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/imports"; +import { BINDING, MONO } from "./net6-legacy/globals"; import { init_globalization } from "./icu"; let config: MonoConfigInternal = undefined as any; diff --git a/src/mono/wasm/runtime/strings.ts b/src/mono/wasm/runtime/strings.ts index 8eba930124db5c..9ec559ff219997 100644 --- a/src/mono/wasm/runtime/strings.ts +++ b/src/mono/wasm/runtime/strings.ts @@ -3,7 +3,7 @@ import { mono_wasm_new_root_buffer } from "./roots"; import { MonoString, MonoStringNull, is_nullish, WasmRoot, WasmRootBuffer } from "./types"; -import { Module } from "./imports"; +import { Module } from "./globals"; import cwraps from "./cwraps"; import { mono_wasm_new_root } from "./roots"; import { getI32, getU32 } from "./memory"; diff --git a/src/mono/wasm/runtime/types.ts b/src/mono/wasm/runtime/types.ts index f4762513c83cd4..53e493077afd1a 100644 --- a/src/mono/wasm/runtime/types.ts +++ b/src/mono/wasm/runtime/types.ts @@ -231,26 +231,24 @@ export function is_nullish(value: T | null | undefined): value is null | unde return (value === undefined) || (value === null); } -export type EarlyImports = { - isNode: boolean, +export type EmscriptenInternals = { isWorker: boolean, isShell: boolean, - isWeb: boolean, isPThread: boolean, disableLegacyJsInterop: boolean, quit_: Function, ExitStatus: ExitStatusError, requirePromise: Promise }; -export type EarlyExports = { +export type GlobalObjects = { mono: any, binding: any, internal: any, - module: any, - helpers: any, - api: any, + module: DotnetModuleInternal, + helpers: RuntimeHelpers, + api: RuntimeAPI, }; -export type EarlyReplacements = { +export type EmscriptenReplacements = { fetch: any, require: any, requirePromise: Promise, @@ -409,15 +407,5 @@ export declare interface EmscriptenModuleInternal { getWasmTableEntry(index: number): any; removeRunDependency(id: string): void; addRunDependency(id: string): void; - initializeImportsAndExports: (imports: EarlyImports, replacements: EarlyReplacements) => void; onConfigLoaded?: (config: MonoConfig, api: RuntimeAPI) => void | Promise; } - -export declare function initializeImportsAndExports( - imports: EarlyImports, - exports: EarlyExports, -): RuntimeAPI; - -export type RuntimeModuleAPI = { - initializeImportsAndExports: typeof initializeImportsAndExports; -} diff --git a/src/mono/wasm/runtime/web-socket.ts b/src/mono/wasm/runtime/web-socket.ts index ea9dc2a8922879..9b2e1042cb4c00 100644 --- a/src/mono/wasm/runtime/web-socket.ts +++ b/src/mono/wasm/runtime/web-socket.ts @@ -5,7 +5,7 @@ import { prevent_timer_throttling } from "./scheduling"; import { Queue } from "./queue"; import { PromiseController, createPromiseController } from "./promise-controller"; import { mono_assert } from "./types"; -import { Module } from "./imports"; +import { Module } from "./globals"; import { setI32 } from "./memory"; import { VoidPtr } from "./types/emscripten";