diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSMarshalerArgument.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSMarshalerArgument.cs index 160cf190e3c12..4312973a388aa 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSMarshalerArgument.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSMarshalerArgument.cs @@ -25,7 +25,7 @@ public partial struct JSMarshalerArgument internal struct JSMarshalerArgumentImpl { [FieldOffset(0)] - internal bool BooleanValue; + internal bool BooleanValue; // note this is 1 byte [FieldOffset(0)] internal byte ByteValue; [FieldOffset(0)] @@ -64,7 +64,7 @@ internal struct JSMarshalerArgumentImpl internal IntPtr ContextHandle; [FieldOffset(20)] - internal bool ReceiverShouldFree; + internal bool ReceiverShouldFree; // note this is 1 byte [FieldOffset(24)] internal IntPtr CallerNativeTID; diff --git a/src/mono/browser/runtime/dotnet.d.ts b/src/mono/browser/runtime/dotnet.d.ts index 2fdf8e16d09f3..e0d644558b46b 100644 --- a/src/mono/browser/runtime/dotnet.d.ts +++ b/src/mono/browser/runtime/dotnet.d.ts @@ -483,6 +483,10 @@ type APIType = { * Writes to the WASM linear memory */ setHeapB32: (offset: NativePointer, value: number | boolean) => void; + /** + * Writes to the WASM linear memory + */ + setHeapB8: (offset: NativePointer, value: number | boolean) => void; /** * Writes to the WASM linear memory */ @@ -531,6 +535,10 @@ type APIType = { * Reads from the WASM linear memory */ getHeapB32: (offset: NativePointer) => boolean; + /** + * Reads from the WASM linear memory + */ + getHeapB8: (offset: NativePointer) => boolean; /** * Reads from the WASM linear memory */ diff --git a/src/mono/browser/runtime/export-api.ts b/src/mono/browser/runtime/export-api.ts index 623c4222218f0..95b9f965a693a 100644 --- a/src/mono/browser/runtime/export-api.ts +++ b/src/mono/browser/runtime/export-api.ts @@ -5,7 +5,7 @@ import type { MonoConfig, APIType } from "./types"; 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, localHeapViewF32, localHeapViewF64, localHeapViewI16, localHeapViewI32, localHeapViewI64Big, localHeapViewI8, localHeapViewU16, localHeapViewU32, localHeapViewU8, setB32, setF32, setF64, setI16, setI32, setI52, setI64Big, setI8, setU16, setU32, setU52, setU8 } from "./memory"; +import { getB32, getB8, getF32, getF64, getI16, getI32, getI52, getI64Big, getI8, getU16, getU32, getU52, getU8, localHeapViewF32, localHeapViewF64, localHeapViewI16, localHeapViewI32, localHeapViewI64Big, localHeapViewI8, localHeapViewU16, localHeapViewU32, localHeapViewU8, setB32, setB8, setF32, setF64, setI16, setI32, setI52, setI64Big, setI8, setU16, setU32, setU52, setU8 } from "./memory"; import { mono_run_main, mono_run_main_and_exit } from "./run"; import { mono_wasm_setenv } from "./startup"; import { loaderHelpers, runtimeHelpers } from "./globals"; @@ -23,6 +23,7 @@ export function export_api(): any { }, invokeLibraryInitializers: loaderHelpers.invokeLibraryInitializers, setHeapB32: setB32, + setHeapB8: setB8, setHeapU8: setU8, setHeapU16: setU16, setHeapU32: setU32, @@ -35,6 +36,7 @@ export function export_api(): any { setHeapF32: setF32, setHeapF64: setF64, getHeapB32: getB32, + getHeapB8: getB8, getHeapU8: getU8, getHeapU16: getU16, getHeapU32: getU32, diff --git a/src/mono/browser/runtime/marshal.ts b/src/mono/browser/runtime/marshal.ts index c2afc7ae6a57c..10896eba1389e 100644 --- a/src/mono/browser/runtime/marshal.ts +++ b/src/mono/browser/runtime/marshal.ts @@ -5,7 +5,7 @@ import WasmEnableThreads from "consts:wasmEnableThreads"; import { js_owned_gc_handle_symbol, teardown_managed_proxy } from "./gc-handles"; import { Module, loaderHelpers, mono_assert, runtimeHelpers } from "./globals"; -import { getF32, getF64, getI16, getI32, getI64Big, getU16, getU32, getU8, setF32, setF64, setI16, setI32, setI64Big, setU16, setU32, setU8, localHeapViewF64, localHeapViewI32, localHeapViewU8, _zero_region, getB32, setB32, forceThreadMemoryViewRefresh } from "./memory"; +import { getF32, getF64, getI16, getI32, getI64Big, getU16, getU32, getU8, setF32, setF64, setI16, setI32, setI64Big, setU16, setU32, setU8, localHeapViewF64, localHeapViewI32, localHeapViewU8, _zero_region, forceThreadMemoryViewRefresh, setB8, getB8 } from "./memory"; import { mono_wasm_new_external_root } from "./roots"; import { GCHandle, JSHandle, MonoObject, MonoString, GCHandleNull, JSMarshalerArguments, JSFunctionSignature, JSMarshalerType, JSMarshalerArgument, MarshalerToJs, MarshalerToCs, WasmRoot, MarshalerType, PThreadPtr, PThreadPtrNull, VoidPtrNull } from "./types/internal"; import { TypedArray, VoidPtr } from "./types/emscripten"; @@ -89,7 +89,7 @@ export function is_args_exception(args: JSMarshalerArguments): boolean { export function is_receiver_should_free(args: JSMarshalerArguments): boolean { if (!WasmEnableThreads) return false; mono_assert(args, "Null args"); - return getB32(args + JSMarshalerArgumentOffsets.ReceiverShouldFree); + return getB8(args + JSMarshalerArgumentOffsets.ReceiverShouldFree); } export function get_sync_done_semaphore_ptr(args: JSMarshalerArguments): VoidPtr { @@ -106,7 +106,7 @@ export function get_caller_native_tid(args: JSMarshalerArguments): PThreadPtr { export function set_receiver_should_free(args: JSMarshalerArguments): void { mono_assert(args, "Null args"); - setB32(args + JSMarshalerArgumentOffsets.ReceiverShouldFree, true); + setB8(args + JSMarshalerArgumentOffsets.ReceiverShouldFree, true); } export function set_args_context(args: JSMarshalerArguments): void { @@ -209,7 +209,7 @@ export function set_arg_element_type(arg: JSMarshalerArgument, type: MarshalerTy export function get_arg_bool(arg: JSMarshalerArgument): boolean { mono_assert(arg, "Null arg"); - return !!getU8(arg); + return getB8(arg); } export function get_arg_u8(arg: JSMarshalerArgument): number { @@ -268,7 +268,7 @@ export function get_arg_f64(arg: JSMarshalerArgument): number { export function set_arg_bool(arg: JSMarshalerArgument, value: boolean): void { mono_assert(arg, "Null arg"); mono_check(typeof value === "boolean", () => `Value is not a Boolean: ${value} (${typeof (value)})`); - setB32(arg, value ? 1 : 0); + setB8(arg, value); } export function set_arg_u8(arg: JSMarshalerArgument, value: number): void { diff --git a/src/mono/browser/runtime/memory.ts b/src/mono/browser/runtime/memory.ts index 585c6e377a1c1..3152afe7eea8f 100644 --- a/src/mono/browser/runtime/memory.ts +++ b/src/mono/browser/runtime/memory.ts @@ -8,6 +8,7 @@ import { VoidPtr, CharPtr } from "./types/emscripten"; import cwraps, { I52Error } from "./cwraps"; import { Module, mono_assert, runtimeHelpers } from "./globals"; import { utf8ToString } from "./strings"; +import { mono_log_warn } from "./logging"; const alloca_stack: Array = []; const alloca_buffer_size = 32 * 1024; @@ -58,6 +59,7 @@ export function _zero_region(byteOffset: VoidPtr, sizeBytes: number): void { localHeapViewU8().fill(0, byteOffset, byteOffset + sizeBytes); } +/** note: MonoBoolean is 8 bits not 32 bits when inside a structure or array */ export function setB32(offset: MemOffset, value: number | boolean): void { receiveWorkerHeapViews(); const boolValue = !!value; @@ -66,6 +68,14 @@ export function setB32(offset: MemOffset, value: number | boolean): void { Module.HEAP32[offset >>> 2] = boolValue ? 1 : 0; } +export function setB8(offset: MemOffset, value: number | boolean): void { + const boolValue = !!value; + if (typeof (value) === "number") + assert_int_in_range(value, 0, 1); + receiveWorkerHeapViews(); + Module.HEAPU8[offset] = boolValue ? 1 : 0; +} + export function setU8(offset: MemOffset, value: number): void { assert_int_in_range(value, 0, 0xFF); receiveWorkerHeapViews(); @@ -177,10 +187,22 @@ export function setF64(offset: MemOffset, value: number): void { Module.HEAPF64[offset >>> 3] = value; } +let warnDirtyBool = true; +/** note: MonoBoolean is 8 bits not 32 bits when inside a structure or array */ export function getB32(offset: MemOffset): boolean { receiveWorkerHeapViews(); - return !!(Module.HEAP32[offset >>> 2]); + const value = (Module.HEAPU32[offset >>> 2]); + if (value > 1 && warnDirtyBool) { + warnDirtyBool = false; + mono_log_warn(`getB32: value at ${offset} is not a boolean, but a number: ${value}`); + } + return !!value; +} + +export function getB8(offset: MemOffset): boolean { + receiveWorkerHeapViews(); + return !!(Module.HEAPU8[offset]); } export function getU8(offset: MemOffset): number { diff --git a/src/mono/browser/runtime/types/index.ts b/src/mono/browser/runtime/types/index.ts index c5754f6c89e8f..73b9f9a2dee63 100644 --- a/src/mono/browser/runtime/types/index.ts +++ b/src/mono/browser/runtime/types/index.ts @@ -452,6 +452,10 @@ export type APIType = { * Writes to the WASM linear memory */ setHeapB32: (offset: NativePointer, value: number | boolean) => void; + /** + * Writes to the WASM linear memory + */ + setHeapB8: (offset: NativePointer, value: number | boolean) => void; /** * Writes to the WASM linear memory */ @@ -500,6 +504,10 @@ export type APIType = { * Reads from the WASM linear memory */ getHeapB32: (offset: NativePointer) => boolean; + /** + * Reads from the WASM linear memory + */ + getHeapB8: (offset: NativePointer) => boolean; /** * Reads from the WASM linear memory */