未验证 提交 df26db30 编写于 作者: P Pavel Savara 提交者: GitHub

[browser] bind JS methods to minified WASM imports (#90145)

上级 26c7d40e
......@@ -35,7 +35,7 @@ type SyncSendClose = () => void;
const STREAM_CLOSE_SENTINEL = -1;
export class StreamQueue {
readonly workAvailable: EventTarget = new EventTarget();
readonly workAvailable: EventTarget = new globalThis.EventTarget();
readonly signalWorkAvailable = this.signalWorkAvailableImpl.bind(this);
constructor(readonly queue_addr: VoidPtr, readonly syncSendBuffer: SyncSendBuffer, readonly syncSendClose: SyncSendClose) {
......
......@@ -4,6 +4,7 @@
"use strict";
// -- this javascript file is evaluated by emcc during compilation! --
// 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";
......@@ -11,6 +12,8 @@ const WASM_ENABLE_SIMD = process.env.WASM_ENABLE_SIMD === "1";
const WASM_ENABLE_EH = process.env.WASM_ENABLE_EH === "1";
const ENABLE_BROWSER_PROFILER = process.env.ENABLE_BROWSER_PROFILER === "1";
const ENABLE_AOT_PROFILER = process.env.ENABLE_AOT_PROFILER === "1";
var methodIndexByName = undefined;
var gitHash = undefined;
function setup(linkerSetup) {
const pthreadReplacements = {};
......@@ -61,127 +64,46 @@ function setup(linkerSetup) {
#endif
}
const postset = `
DOTNET.setup({ `+
`linkerDisableLegacyJsInterop: ${DISABLE_LEGACY_JS_INTEROP ? "true" : "false"},` +
`linkerWasmEnableSIMD: ${WASM_ENABLE_SIMD ? "true" : "false"},` +
`linkerWasmEnableEH: ${WASM_ENABLE_EH ? "true" : "false"},` +
`linkerEnableAotProfiler: ${ENABLE_AOT_PROFILER ? "true" : "false"}, ` +
`linkerEnableBrowserProfiler: ${ENABLE_BROWSER_PROFILER ? "true" : "false"}` +
`});
`;
const DotnetSupportLib = {
$DOTNET: { setup },
$DOTNET__postset: postset
icudt68_dat: function () { throw new Error('dummy link symbol') },
};
// the methods would be visible to EMCC linker
// --- keep in sync with exports.ts ---
let linked_functions = [
// mini-wasm.c
"mono_wasm_schedule_timer",
// mini-wasm-debugger.c
"mono_wasm_asm_loaded",
"mono_wasm_fire_debugger_agent_message_with_data",
"mono_wasm_debugger_log",
"mono_wasm_add_dbg_command_received",
"mono_wasm_set_entrypoint_breakpoint",
// mono-threads-wasm.c
"schedule_background_exec",
// interp.c
"mono_wasm_profiler_enter",
"mono_wasm_profiler_leave",
// driver.c
"mono_wasm_trace_logger",
"mono_wasm_event_pipe_early_startup_callback",
// jiterpreter.c / interp.c / transform.c
"mono_interp_tier_prepare_jiterpreter",
"mono_interp_record_interp_entry",
"mono_interp_jit_wasm_entry_trampoline",
"mono_interp_jit_wasm_jit_call_trampoline",
"mono_interp_invoke_wasm_jit_call_trampoline",
"mono_interp_flush_jitcall_queue",
"mono_jiterp_do_jit_call_indirect",
// corebindings.c
"mono_wasm_release_cs_owned_object",
"mono_wasm_bind_js_function",
"mono_wasm_invoke_bound_function",
"mono_wasm_invoke_import",
"mono_wasm_bind_cs_function",
"mono_wasm_marshal_promise",
"mono_wasm_change_case_invariant",
"mono_wasm_change_case",
"mono_wasm_compare_string",
"mono_wasm_starts_with",
"mono_wasm_ends_with",
"mono_wasm_index_of",
"mono_wasm_get_calendar_info",
"mono_wasm_get_culture_info",
"mono_wasm_get_first_day_of_week",
"mono_wasm_get_first_week_of_year",
"icudt68_dat",
];
#if USE_PTHREADS
linked_functions = [...linked_functions,
// mono-threads-wasm.c
"mono_wasm_pthread_on_pthread_attached",
"mono_wasm_pthread_on_pthread_detached",
// 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",
// corebindings.c
"mono_wasm_install_js_worker_interop",
"mono_wasm_uninstall_js_worker_interop",
]
#endif
if (ENABLE_AOT_PROFILER) {
linked_functions = [...linked_functions,
"mono_wasm_invoke_js_with_args_ref",
"mono_wasm_get_object_property_ref",
"mono_wasm_set_object_property_ref",
"mono_wasm_get_by_index_ref",
"mono_wasm_set_by_index_ref",
"mono_wasm_get_global_object_ref",
"mono_wasm_create_cs_owned_object_ref",
"mono_wasm_typed_array_to_array_ref",
"mono_wasm_typed_array_from_ref",
"mono_wasm_invoke_js_blazor",
]
function createWasmImportStubsFrom(collection) {
for (let functionName in collection) {
if (functionName in DotnetSupportLib) throw new Error(`Function ${functionName} is already defined`);
const runtime_idx = collection[functionName]
const stub_fn = new Function(`return {runtime_idx:${runtime_idx}};//${functionName}`);
DotnetSupportLib[functionName] = stub_fn;
}
}
if (!DISABLE_LEGACY_JS_INTEROP) {
linked_functions = [...linked_functions,
"mono_wasm_invoke_js_with_args_ref",
"mono_wasm_get_object_property_ref",
"mono_wasm_set_object_property_ref",
"mono_wasm_get_by_index_ref",
"mono_wasm_set_by_index_ref",
"mono_wasm_get_global_object_ref",
"mono_wasm_create_cs_owned_object_ref",
"mono_wasm_typed_array_to_array_ref",
"mono_wasm_typed_array_from_ref",
"mono_wasm_invoke_js_blazor",
]
}
// the JS methods would be visible to EMCC linker and become imports of the WASM module
// we generate simple stub for each exported function so that emcc will include them in the final output
// we will replace them with the real implementation in replace_linker_placeholders
function injectDependencies() {
createWasmImportStubsFrom(methodIndexByName.mono_wasm_imports);
// -- this javascript file is evaluated by emcc during compilation! --
// we generate simple proxy for each exported function so that emcc will include them in the final output
for (let linked_function of linked_functions) {
DotnetSupportLib[linked_function] = new Function('throw new Error("unreachable");');
#if USE_PTHREADS
createWasmImportStubsFrom(methodIndexByName.mono_wasm_threads_imports);
#endif
if (!DISABLE_LEGACY_JS_INTEROP) {
createWasmImportStubsFrom(methodIndexByName.mono_wasm_legacy_interop_imports);
}
DotnetSupportLib["$DOTNET__postset"] = `DOTNET.setup({ ` +
`linkerDisableLegacyJsInterop: ${DISABLE_LEGACY_JS_INTEROP ? "true" : "false"},` +
`linkerWasmEnableSIMD: ${WASM_ENABLE_SIMD ? "true" : "false"},` +
`linkerWasmEnableEH: ${WASM_ENABLE_EH ? "true" : "false"},` +
`linkerEnableAotProfiler: ${ENABLE_AOT_PROFILER ? "true" : "false"}, ` +
`linkerEnableBrowserProfiler: ${ENABLE_BROWSER_PROFILER ? "true" : "false"}, ` +
`gitHash: "${gitHash}", ` +
`});`;
autoAddDeps(DotnetSupportLib, "$DOTNET");
mergeInto(LibraryManager.library, DotnetSupportLib);
}
autoAddDeps(DotnetSupportLib, "$DOTNET");
mergeInto(LibraryManager.library, DotnetSupportLib);
\ No newline at end of file
// var methodIndexByName wil be appended below by the MSBuild in wasm.proj
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import MonoWasmThreads from "consts:monoWasmThreads";
import WasmEnableLegacyJsInterop from "consts:wasmEnableLegacyJsInterop";
import { mono_wasm_debugger_log, mono_wasm_add_dbg_command_received, mono_wasm_set_entrypoint_breakpoint, mono_wasm_fire_debugger_agent_message_with_data, mono_wasm_fire_debugger_agent_message_with_data_to_pause } from "./debug";
import { mono_wasm_release_cs_owned_object } from "./gc-handles";
import { mono_wasm_bind_cs_function } from "./invoke-cs";
import { mono_wasm_bind_js_function, mono_wasm_invoke_bound_function, mono_wasm_invoke_import } from "./invoke-js";
import { mono_interp_tier_prepare_jiterpreter } from "./jiterpreter";
import { mono_interp_jit_wasm_entry_trampoline, mono_interp_record_interp_entry } from "./jiterpreter-interp-entry";
import { mono_interp_jit_wasm_jit_call_trampoline, mono_interp_invoke_wasm_jit_call_trampoline, mono_interp_flush_jitcall_queue, mono_jiterp_do_jit_call_indirect } from "./jiterpreter-jit-call";
import { mono_wasm_marshal_promise } from "./marshal-to-js";
import { mono_wasm_eventloop_has_unsettled_interop_promises } from "./pthreads/shared/eventloop";
import { mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_detached } from "./pthreads/worker";
import { mono_wasm_schedule_timer, schedule_background_exec } from "./scheduling";
import { mono_wasm_asm_loaded } from "./startup";
import { mono_wasm_diagnostic_server_on_server_thread_created } from "./diagnostics/server_pthread";
import { mono_wasm_diagnostic_server_on_runtime_server_init, mono_wasm_event_pipe_early_startup_callback } from "./diagnostics";
import { mono_wasm_diagnostic_server_stream_signal_work_available } from "./diagnostics/server_pthread/stream-queue";
import { mono_log_debug, mono_log_warn, mono_wasm_trace_logger } from "./logging";
import { mono_wasm_profiler_leave, mono_wasm_profiler_enter } from "./profiler";
import { mono_wasm_change_case, mono_wasm_change_case_invariant } from "./hybrid-globalization/change-case";
import { mono_wasm_compare_string, mono_wasm_ends_with, mono_wasm_starts_with, mono_wasm_index_of } from "./hybrid-globalization/collations";
import { mono_wasm_get_calendar_info } from "./hybrid-globalization/calendar";
import { mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop } from "./pthreads/shared";
import {
mono_wasm_invoke_js_blazor, mono_wasm_invoke_js_with_args_ref, mono_wasm_get_object_property_ref, mono_wasm_set_object_property_ref,
mono_wasm_get_by_index_ref, mono_wasm_set_by_index_ref, mono_wasm_get_global_object_ref
} from "./net6-legacy/method-calls";
import { mono_wasm_create_cs_owned_object_ref } from "./net6-legacy/cs-to-js";
import { mono_wasm_typed_array_to_array_ref } from "./net6-legacy/js-to-cs";
import { mono_wasm_typed_array_from_ref } from "./net6-legacy/buffers";
import { mono_wasm_get_culture_info } from "./hybrid-globalization/culture-info";
import { mono_wasm_get_first_day_of_week, mono_wasm_get_first_week_of_year } from "./hybrid-globalization/locales";
// the JS methods would be visible to EMCC linker and become imports of the WASM module
export const mono_wasm_threads_imports = !MonoWasmThreads ? [] : [
// mono-threads-wasm.c
mono_wasm_pthread_on_pthread_attached,
mono_wasm_pthread_on_pthread_detached,
// 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,
// corebindings.c
mono_wasm_install_js_worker_interop,
mono_wasm_uninstall_js_worker_interop,
];
export const mono_wasm_legacy_interop_imports = !WasmEnableLegacyJsInterop ? [] : [
// corebindings.c
mono_wasm_invoke_js_with_args_ref,
mono_wasm_get_object_property_ref,
mono_wasm_set_object_property_ref,
mono_wasm_get_by_index_ref,
mono_wasm_set_by_index_ref,
mono_wasm_get_global_object_ref,
mono_wasm_create_cs_owned_object_ref,
mono_wasm_typed_array_to_array_ref,
mono_wasm_typed_array_from_ref,
mono_wasm_invoke_js_blazor,
];
export const mono_wasm_imports = [
// mini-wasm.c
mono_wasm_schedule_timer,
// mini-wasm-debugger.c
mono_wasm_asm_loaded,
mono_wasm_debugger_log,
mono_wasm_add_dbg_command_received,
mono_wasm_fire_debugger_agent_message_with_data,
mono_wasm_fire_debugger_agent_message_with_data_to_pause,
// mono-threads-wasm.c
schedule_background_exec,
// interp.c and jiterpreter.c
mono_interp_tier_prepare_jiterpreter,
mono_interp_record_interp_entry,
mono_interp_jit_wasm_entry_trampoline,
mono_interp_jit_wasm_jit_call_trampoline,
mono_interp_invoke_wasm_jit_call_trampoline,
mono_interp_flush_jitcall_queue,
mono_jiterp_do_jit_call_indirect,
mono_wasm_profiler_enter,
mono_wasm_profiler_leave,
// driver.c
mono_wasm_trace_logger,
mono_wasm_set_entrypoint_breakpoint,
mono_wasm_event_pipe_early_startup_callback,
// corebindings.c
mono_wasm_release_cs_owned_object,
mono_wasm_bind_js_function,
mono_wasm_invoke_bound_function,
mono_wasm_invoke_import,
mono_wasm_bind_cs_function,
mono_wasm_marshal_promise,
mono_wasm_change_case_invariant,
mono_wasm_change_case,
mono_wasm_compare_string,
mono_wasm_starts_with,
mono_wasm_ends_with,
mono_wasm_index_of,
mono_wasm_get_calendar_info,
mono_wasm_get_culture_info,
mono_wasm_get_first_day_of_week,
mono_wasm_get_first_week_of_year,
];
const wasmImports: Function[] = [
...mono_wasm_imports,
// threading exports, if threading is enabled
...mono_wasm_threads_imports,
// legacy interop exports, if enabled
...mono_wasm_legacy_interop_imports
];
export function replace_linker_placeholders(imports: WebAssembly.Imports) {
// the output from emcc contains wrappers for these linker imports which add overhead,
// but now we have what we need to replace them with the actual functions
// By default the imports all live inside of 'env', but emscripten minification could rename it to 'a'.
// See https://github.com/emscripten-core/emscripten/blob/c5d1a856592b788619be11bbdc1dd119dec4e24c/src/preamble.js#L933-L936
const env = imports.env || imports.a;
if (!env) {
mono_log_warn("WARNING: Neither imports.env or imports.a were present when instantiating the wasm module. This likely indicates an emscripten configuration issue.");
return;
}
// the import names could be minified by applyImportAndExportNameChanges in emcc
// we call each stub function to get the runtime_idx, which is the index into the wasmImports array
const indexToNameMap: string[] = new Array(wasmImports.length);
for (const shortName in env) {
const stub_fn = env[shortName] as Function;
if (typeof stub_fn === "function" && stub_fn.toString().indexOf("runtime_idx") !== -1) {
try {
const { runtime_idx } = stub_fn();
if (indexToNameMap[runtime_idx] !== undefined) throw new Error(`Duplicate runtime_idx ${runtime_idx}`);
indexToNameMap[runtime_idx] = shortName;
} catch {
// no-action
}
}
}
for (const [idx, realFn] of wasmImports.entries()) {
const shortName = indexToNameMap[idx];
// if it's not found it means the emcc linker didn't include it, which is fine
if (shortName !== undefined) {
const stubFn = env[shortName];
if (typeof stubFn !== "function") throw new Error(`Expected ${shortName} to be a function`);
env[shortName] = realFn;
mono_log_debug(`Replaced WASM import ${shortName} stub ${stubFn.name} with ${realFn.name || "minified implementation"}`);
}
}
}
\ No newline at end of file
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import MonoWasmThreads from "consts:monoWasmThreads";
import WasmEnableLegacyJsInterop from "consts:wasmEnableLegacyJsInterop";
import { mono_wasm_debugger_log, mono_wasm_add_dbg_command_received, mono_wasm_set_entrypoint_breakpoint, mono_wasm_fire_debugger_agent_message_with_data, mono_wasm_fire_debugger_agent_message_with_data_to_pause } from "./debug";
import { mono_wasm_release_cs_owned_object } from "./gc-handles";
import { mono_wasm_bind_cs_function } from "./invoke-cs";
import { mono_wasm_bind_js_function, mono_wasm_invoke_bound_function, mono_wasm_invoke_import } from "./invoke-js";
import { mono_interp_tier_prepare_jiterpreter } from "./jiterpreter";
import { mono_interp_jit_wasm_entry_trampoline, mono_interp_record_interp_entry } from "./jiterpreter-interp-entry";
import { mono_interp_jit_wasm_jit_call_trampoline, mono_interp_invoke_wasm_jit_call_trampoline, mono_interp_flush_jitcall_queue, mono_jiterp_do_jit_call_indirect } from "./jiterpreter-jit-call";
import { mono_wasm_marshal_promise } from "./marshal-to-js";
import { mono_wasm_eventloop_has_unsettled_interop_promises } from "./pthreads/shared/eventloop";
import { mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_detached } from "./pthreads/worker";
import { mono_wasm_schedule_timer, schedule_background_exec } from "./scheduling";
import { mono_wasm_asm_loaded } from "./startup";
import { mono_wasm_diagnostic_server_on_server_thread_created } from "./diagnostics/server_pthread";
import { mono_wasm_diagnostic_server_on_runtime_server_init, mono_wasm_event_pipe_early_startup_callback } from "./diagnostics";
import { mono_wasm_diagnostic_server_stream_signal_work_available } from "./diagnostics/server_pthread/stream-queue";
import { mono_wasm_trace_logger } from "./logging";
import { mono_wasm_profiler_leave, mono_wasm_profiler_enter } from "./profiler";
import { mono_wasm_change_case, mono_wasm_change_case_invariant } from "./hybrid-globalization/change-case";
import { mono_wasm_compare_string, mono_wasm_ends_with, mono_wasm_starts_with, mono_wasm_index_of } from "./hybrid-globalization/collations";
import { mono_wasm_get_calendar_info } from "./hybrid-globalization/calendar";
import { mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop } from "./pthreads/shared";
import {
mono_wasm_invoke_js_blazor, mono_wasm_invoke_js_with_args_ref, mono_wasm_get_object_property_ref, mono_wasm_set_object_property_ref,
mono_wasm_get_by_index_ref, mono_wasm_set_by_index_ref, mono_wasm_get_global_object_ref
} from "./net6-legacy/method-calls";
import { mono_wasm_create_cs_owned_object_ref } from "./net6-legacy/cs-to-js";
import { mono_wasm_typed_array_to_array_ref } from "./net6-legacy/js-to-cs";
import { mono_wasm_typed_array_from_ref } from "./net6-legacy/buffers";
import { mono_wasm_get_culture_info } from "./hybrid-globalization/culture-info";
import { mono_wasm_get_first_day_of_week, mono_wasm_get_first_week_of_year } from "./hybrid-globalization/locales";
// the methods would be visible to EMCC linker
// --- keep in sync with dotnet.cjs.lib.js ---
const mono_wasm_threads_exports = !MonoWasmThreads ? undefined : {
// mono-threads-wasm.c
mono_wasm_pthread_on_pthread_attached,
mono_wasm_pthread_on_pthread_detached,
// 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,
// corebindings.c
mono_wasm_install_js_worker_interop,
mono_wasm_uninstall_js_worker_interop,
};
const mono_wasm_legacy_interop_exports = !WasmEnableLegacyJsInterop ? undefined : {
// corebindings.c
mono_wasm_invoke_js_with_args_ref,
mono_wasm_get_object_property_ref,
mono_wasm_set_object_property_ref,
mono_wasm_get_by_index_ref,
mono_wasm_set_by_index_ref,
mono_wasm_get_global_object_ref,
mono_wasm_create_cs_owned_object_ref,
mono_wasm_typed_array_to_array_ref,
mono_wasm_typed_array_from_ref,
mono_wasm_invoke_js_blazor,
};
// the methods would be visible to EMCC linker
// --- keep in sync with dotnet.cjs.lib.js ---
// --- keep in sync with dotnet.es6.lib.js ---
export function export_linker(): any {
return {
// mini-wasm.c
mono_wasm_schedule_timer,
// mini-wasm-debugger.c
mono_wasm_asm_loaded,
mono_wasm_debugger_log,
mono_wasm_add_dbg_command_received,
mono_wasm_fire_debugger_agent_message_with_data,
mono_wasm_fire_debugger_agent_message_with_data_to_pause,
// mono-threads-wasm.c
schedule_background_exec,
// interp.c and jiterpreter.c
mono_interp_tier_prepare_jiterpreter,
mono_interp_record_interp_entry,
mono_interp_jit_wasm_entry_trampoline,
mono_interp_jit_wasm_jit_call_trampoline,
mono_interp_invoke_wasm_jit_call_trampoline,
mono_interp_flush_jitcall_queue,
mono_jiterp_do_jit_call_indirect,
mono_wasm_profiler_enter,
mono_wasm_profiler_leave,
// driver.c
mono_wasm_trace_logger,
mono_wasm_set_entrypoint_breakpoint,
mono_wasm_event_pipe_early_startup_callback,
// corebindings.c
mono_wasm_release_cs_owned_object,
mono_wasm_bind_js_function,
mono_wasm_invoke_bound_function,
mono_wasm_invoke_import,
mono_wasm_bind_cs_function,
mono_wasm_marshal_promise,
mono_wasm_change_case_invariant,
mono_wasm_change_case,
mono_wasm_compare_string,
mono_wasm_starts_with,
mono_wasm_ends_with,
mono_wasm_index_of,
mono_wasm_get_calendar_info,
mono_wasm_get_culture_info,
mono_wasm_get_first_day_of_week,
mono_wasm_get_first_week_of_year,
// threading exports, if threading is enabled
...mono_wasm_threads_exports,
// legacy interop exports, if enabled
...mono_wasm_legacy_interop_exports
import { mono_wasm_imports, mono_wasm_legacy_interop_imports, mono_wasm_threads_imports } from "./exports-binding";
import gitHash from "consts:gitHash";
export function export_linker_indexes_as_code(): string {
const indexByName: any = {
mono_wasm_imports: {},
mono_wasm_threads_imports: {},
mono_wasm_legacy_interop_imports: {},
};
}
\ No newline at end of file
let idx = 0;
for (const wi of mono_wasm_imports) {
indexByName.mono_wasm_imports[wi.name] = idx;
idx++;
}
for (const wi of mono_wasm_threads_imports) {
indexByName.mono_wasm_threads_imports[wi.name] = idx;
idx++;
}
for (const wi of mono_wasm_legacy_interop_imports) {
indexByName.mono_wasm_legacy_interop_imports[wi.name] = idx;
idx++;
}
return `
var gitHash = "${gitHash}";
var methodIndexByName = ${JSON.stringify(indexByName, null, 2)};
injectDependencies();
`;
}
// this is running during runtime compile time inside rollup process.
(globalThis as any).export_linker_indexes_as_code = export_linker_indexes_as_code;
\ No newline at end of file
......@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
import ProductVersion from "consts:productVersion";
import GitHash from "consts:gitHash";
import BuildConfiguration from "consts:configuration";
import WasmEnableLegacyJsInterop from "consts:wasmEnableLegacyJsInterop";
import type { RuntimeAPI } from "./types";
......@@ -55,7 +54,7 @@ function initializeExports(globalObjects: GlobalObjects): RuntimeAPI {
Module: module,
runtimeBuildInfo: {
productVersion: ProductVersion,
gitHash: GitHash,
gitHash: runtimeHelpers.gitHash,
buildConfiguration: BuildConfiguration
},
...API,
......
......@@ -5,6 +5,8 @@
/// <reference path="./types/v8.d.ts" />
/// <reference path="./types/node.d.ts" />
import gitHash from "consts:gitHash";
import { RuntimeAPI } from "./types/index";
import type { GlobalObjects, EmscriptenInternals, RuntimeHelpers, LoaderHelpers, DotnetModuleInternal, PromiseAndController } from "./types/internal";
......@@ -38,6 +40,7 @@ export function passEmscriptenInternals(internals: EmscriptenInternals): void {
linkerEnableBrowserProfiler = internals.linkerEnableBrowserProfiler;
runtimeHelpers.quit = internals.quit_;
runtimeHelpers.ExitStatus = internals.ExitStatus;
runtimeHelpers.moduleGitHash = internals.gitHash;
}
// NOTE: this is called AFTER the config is loaded
......@@ -53,6 +56,7 @@ export function setRuntimeGlobals(globalObjects: GlobalObjects) {
exportedRuntimeAPI = globalObjects.api;
Object.assign(runtimeHelpers, {
gitHash,
allAssetsInMemory: createPromiseController<void>(),
dotnetReady: createPromiseController<any>(),
memorySnapshotSkippedOrDone: createPromiseController<void>(),
......
......@@ -3,6 +3,8 @@
import { exceptions, simd } from "wasm-feature-detect";
import gitHash from "consts:gitHash";
import type { AssetEntryInternal, GlobalObjects, LoaderHelpers, RuntimeHelpers } from "../types/internal";
import type { MonoConfig, RuntimeAPI } from "../types";
import { assert_runtime_running, is_exited, is_runtime_running, mono_exit } from "./exit";
......@@ -64,6 +66,7 @@ export function setLoaderGlobals(
abort: (reason: any) => { throw reason; },
});
Object.assign(loaderHelpers, {
gitHash,
config: globalObjects.module.config,
diagnosticTracing: false,
......
......@@ -55,9 +55,12 @@ export let pthread_self: PThreadSelf = null as any as PThreadSelf;
/// currentWorkerThreadEvents.addEventListener(dotnetPthreadCreated, (ev: WorkerThreadEvent) => {
/// mono_trace("thread created on worker with id", ev.pthread_ptr);
/// });
export const currentWorkerThreadEvents: WorkerThreadEventTarget =
MonoWasmThreads ? new EventTarget() : null as any as WorkerThreadEventTarget; // treeshake if threads are disabled
export let currentWorkerThreadEvents: WorkerThreadEventTarget = undefined as any;
export function initWorkerThreadEvents() {
// treeshake if threads are disabled
currentWorkerThreadEvents = MonoWasmThreads ? new globalThis.EventTarget() : null as any as WorkerThreadEventTarget;
}
// this is the message handler for the worker that receives messages from the main thread
// extend this with new cases as needed
......
......@@ -18,23 +18,28 @@ const isDebug = configuration !== "Release";
const isContinuousIntegrationBuild = process.env.ContinuousIntegrationBuild === "true" ? true : false;
const productVersion = process.env.ProductVersion || "8.0.0-dev";
const nativeBinDir = process.env.NativeBinDir ? process.env.NativeBinDir.replace(/"/g, "") : "bin";
const wasmObjDir = process.env.WasmObjDir ? process.env.WasmObjDir.replace(/"/g, "") : "obj";
const monoWasmThreads = process.env.MonoWasmThreads === "true" ? true : false;
const wasmEnableSIMD = process.env.WASM_ENABLE_SIMD === "1" ? true : false;
const wasmEnableExceptionHandling = process.env.WASM_ENABLE_EH === "1" ? true : false;
const wasmEnableLegacyJsInterop = process.env.DISABLE_LEGACY_JS_INTEROP !== "1" ? true : false;
const monoDiagnosticsMock = process.env.MonoDiagnosticsMock === "true" ? true : false;
// because of stack walk at src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
// and unit test at src\libraries\System.Runtime.InteropServices.JavaScript\tests\System.Runtime.InteropServices.JavaScript.Legacy.UnitTests\timers.mjs
const keep_fnames = /(mono_wasm_runtime_ready|mono_wasm_fire_debugger_agent_message_with_data|mono_wasm_fire_debugger_agent_message_with_data_to_pause|mono_wasm_schedule_timer_tick)/;
const keep_classnames = /(ManagedObject|ManagedError|Span|ArraySegment|WasmRootBuffer|SessionOptionsBuilder)/;
const terserConfig = {
compress: {
defaults: true,
passes: 2,
drop_debugger: false, // we invoke debugger
drop_console: false, // we log to console
keep_fnames,
keep_classnames,
},
mangle: {
// because of stack walk at src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
// and unit test at src\libraries\System.Runtime.InteropServices.JavaScript\tests\System.Runtime.InteropServices.JavaScript.Legacy.UnitTests\timers.mjs
keep_fnames: /(mono_wasm_runtime_ready|mono_wasm_fire_debugger_agent_message_with_data|mono_wasm_fire_debugger_agent_message_with_data_to_pause|mono_wasm_schedule_timer_tick)/,
keep_classnames: /(ManagedObject|ManagedError|Span|ArraySegment|WasmRootBuffer|SessionOptionsBuilder)/,
keep_fnames,
keep_classnames,
},
};
const plugins = isDebug ? [writeOnChangePlugin()] : [terser(terserConfig), writeOnChangePlugin()];
......@@ -179,6 +184,22 @@ const runtimeConfig = {
plugins: [regexReplace(inlineAssert), regexCheck([checkAssert, checkNoLoader]), ...outputCodePlugins],
onwarn: onwarn
};
const wasmImportsConfig = {
treeshake: true,
input: "exports-linker.ts",
output: [
{
format: "iife",
name: "exportsLinker",
file: wasmObjDir + "/exports-linker.js",
plugins: [evalCodePlugin()],
sourcemap: false
}
],
external: externalDependencies,
plugins: [...outputCodePlugins],
onwarn: onwarn
};
const typesConfig = {
input: "./types/export-types.ts",
output: [
......@@ -264,12 +285,35 @@ const workerConfigs = findWebWorkerInputs("./workers").map((workerInput) => make
const allConfigs = [
loaderConfig,
runtimeConfig,
wasmImportsConfig,
typesConfig,
legacyTypesConfig,
].concat(workerConfigs)
.concat(diagnosticMockTypesConfig ? [diagnosticMockTypesConfig] : []);
export default defineConfig(allConfigs);
function evalCodePlugin() {
return {
name: "evalCode",
generateBundle: evalCode
};
}
async function evalCode(options, bundle) {
try {
const name = Object.keys(bundle)[0];
const asset = bundle[name];
const code = asset.code;
eval(code);
const extractedCode = globalThis.export_linker_indexes_as_code();
asset.code = extractedCode;
} catch (ex) {
this.warn(ex.toString());
throw ex;
}
}
// this would create .sha256 file next to the output file, so that we do not touch datetime of the file if it's same -> faster incremental build.
function writeOnChangePlugin() {
return {
......@@ -442,6 +486,10 @@ function onwarn(warning) {
return;
}
if (warning.code === "PLUGIN_WARNING" && warning.message.indexOf("sourcemap") !== -1) {
return;
}
// eslint-disable-next-line no-console
console.warn(`(!) ${warning.toString()}`);
console.warn(`(!) ${warning.toString()} ${warning.code}`);
}
......@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
import ProductVersion from "consts:productVersion";
import GitHash from "consts:gitHash";
import MonoWasmThreads from "consts:monoWasmThreads";
import { ENVIRONMENT_IS_WEB, loaderHelpers, runtimeHelpers } from "./globals";
import { mono_log_warn } from "./logging";
......@@ -167,7 +166,7 @@ async function getCacheKey(): Promise<string | null> {
delete inputs.exitAfterSnapshot;
delete inputs.extensions;
inputs.GitHash = GitHash;
inputs.GitHash = loaderHelpers.gitHash;
inputs.ProductVersion = ProductVersion;
const inputsJson = JSON.stringify(inputs);
......
......@@ -13,18 +13,20 @@ import { mono_wasm_init_aot_profiler, mono_wasm_init_browser_profiler } from "./
import { initialize_marshalers_to_cs } from "./marshal-to-cs";
import { initialize_marshalers_to_js } from "./marshal-to-js";
import { init_polyfills_async } from "./polyfills";
import * as pthreads_worker from "./pthreads/worker";
import { strings_init, utf8ToString } from "./strings";
import { init_managed_exports } from "./managed-exports";
import { cwraps_internal } from "./exports-internal";
import { CharPtr, InstantiateWasmCallBack, InstantiateWasmSuccessCallback } from "./types/emscripten";
import { instantiate_wasm_asset, wait_for_all_assets } from "./assets";
import { mono_wasm_init_diagnostics } from "./diagnostics";
import { preAllocatePThreadWorkerPool, instantiateWasmPThreadWorkerPool } from "./pthreads/browser";
import { export_linker } from "./exports-linker";
import { replace_linker_placeholders } from "./exports-binding";
import { endMeasure, MeasuredBlock, startMeasure } from "./profiler";
import { getMemorySnapshot, storeMemorySnapshot, getMemorySnapshotSize } from "./snapshot";
import { mono_log_debug, mono_log_error, mono_log_warn, mono_set_thread_id } from "./logging";
// threads
import { preAllocatePThreadWorkerPool, instantiateWasmPThreadWorkerPool } from "./pthreads/browser";
import { currentWorkerThreadEvents, dotnetPthreadCreated, initWorkerThreadEvents } from "./pthreads/worker";
import { getBrowserThreadID } from "./pthreads/shared";
// legacy
......@@ -136,7 +138,7 @@ async function instantiateWasmWorker(
// wait for the config to arrive by message from the main thread
await loaderHelpers.afterConfigLoaded.promise;
replace_linker_placeholders(imports, export_linker());
replace_linker_placeholders(imports);
// Instantiate from the module posted from the main thread.
// We can just use sync instantiation in the worker.
......@@ -340,6 +342,13 @@ function mono_wasm_pre_init_essential(isWorker: boolean): void {
mono_log_debug("mono_wasm_pre_init_essential");
if (loaderHelpers.gitHash !== runtimeHelpers.gitHash) {
mono_log_warn("The version of dotnet.runtime.js is different from the version of dotnet.js!");
}
if (loaderHelpers.gitHash !== runtimeHelpers.moduleGitHash) {
mono_log_warn("The version of dotnet.native.js is different from the version of dotnet.js!");
}
init_c_exports();
runtimeHelpers.mono_wasm_exit = cwraps.mono_wasm_exit;
runtimeHelpers.abort = (reason: any) => {
......@@ -442,28 +451,6 @@ export function mono_wasm_set_runtime_options(options: string[]): void {
cwraps.mono_wasm_parse_runtime_options(options.length, argv);
}
function replace_linker_placeholders(
imports: WebAssembly.Imports,
realFunctions: any
) {
// the output from emcc contains wrappers for these linker imports which add overhead,
// but now we have what we need to replace them with the actual functions
// By default the imports all live inside of 'env', but emscripten minification could rename it to 'a'.
// See https://github.com/emscripten-core/emscripten/blob/c5d1a856592b788619be11bbdc1dd119dec4e24c/src/preamble.js#L933-L936
const env = imports.env || imports.a;
if (!env) {
mono_log_warn("WARNING: Neither imports.env or imports.a were present when instantiating the wasm module. This likely indicates an emscripten configuration issue.");
return;
}
for (const k in realFunctions) {
const v = realFunctions[k];
if (typeof (v) !== "function")
continue;
if (k in env)
env[k] = v;
}
}
async function instantiate_wasm_module(
imports: WebAssembly.Imports,
successCallback: InstantiateWasmSuccessCallback,
......@@ -487,7 +474,7 @@ async function instantiate_wasm_module(
await runtimeHelpers.beforePreInit.promise;
Module.addRunDependency("instantiate_wasm_module");
replace_linker_placeholders(imports, export_linker());
replace_linker_placeholders(imports);
const assetToLoad = await loaderHelpers.wasmDownloadPromise.promise;
await instantiate_wasm_asset(assetToLoad, imports, successCallback);
assetToLoad.pendingDownloadInternal = null as any; // GC
......@@ -654,8 +641,8 @@ export function mono_wasm_set_main_args(name: string, allRuntimeArguments: strin
/// 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 configureWorkerStartup(module: DotnetModuleInternal): Promise<void> {
// This is a good place for subsystems to attach listeners for pthreads_worker.currentWorkerThreadEvents
pthreads_worker.currentWorkerThreadEvents.addEventListener(pthreads_worker.dotnetPthreadCreated, (ev) => {
initWorkerThreadEvents();
currentWorkerThreadEvents.addEventListener(dotnetPthreadCreated, (ev) => {
mono_log_debug("pthread created 0x" + ev.pthread_self.pthreadId.toString(16));
});
......
......@@ -100,6 +100,7 @@ export interface AssetEntryInternal extends AssetEntry {
}
export type LoaderHelpers = {
gitHash: string,
config: MonoConfigInternal;
diagnosticTracing: boolean;
......@@ -161,6 +162,8 @@ export type LoaderHelpers = {
simd: () => Promise<boolean>,
}
export type RuntimeHelpers = {
gitHash: string,
moduleGitHash: string,
config: MonoConfigInternal;
diagnosticTracing: boolean;
......@@ -279,6 +282,7 @@ export type EmscriptenInternals = {
linkerEnableBrowserProfiler: boolean,
quit_: Function,
ExitStatus: ExitStatusError,
gitHash: string,
};
export type GlobalObjects = {
mono: any,
......
......@@ -431,6 +431,14 @@
DestinationFolder="$(NativeBinDir)src/es6"
SkipUnchangedFiles="true" />
<ReadLinesFromFile File="$(WasmObjDir)/exports-linker.js">
<Output TaskParameter="Lines" ItemName="_WasmImportedMethodNames" />
</ReadLinesFromFile>
<!-- append at the end of dotnet.es6.lib.js -->
<WriteLinesToFile File="$(NativeBinDir)src/es6/dotnet.es6.lib.js"
Lines="@(_WasmImportedMethodNames)"
Overwrite="false" />
<Copy SourceFiles="runtime\pinvoke.h;runtime\gc-common.h"
DestinationFolder="$(NativeBinDir)include\wasm"
SkipUnchangedFiles="true" />
......@@ -526,6 +534,7 @@
<ItemGroup>
<_MonoRollupEnvironmentVariable Include="Configuration:$(Configuration)" />
<_MonoRollupEnvironmentVariable Include="NativeBinDir:$(NativeBinDir)" />
<_MonoRollupEnvironmentVariable Include="WasmObjDir:$(WasmObjDir)" />
<_MonoRollupEnvironmentVariable Include="ProductVersion:$(ProductVersion)" />
<_MonoRollupEnvironmentVariable Include="MonoWasmThreads:$(MonoWasmThreads)" />
<_MonoRollupEnvironmentVariable Include="WASM_ENABLE_SIMD:1" Condition="'$(WasmEnableSIMD)' != 'false'" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册