diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs
index 9d0577cb7d541..16f2dda426a1c 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs
@@ -42,8 +42,8 @@ ResolvedGenerator fail(string failReason)
return ResolvedGenerator.NotSupported(new(info, context));
// void
- case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.OneWay }:
- return ResolvedGenerator.Resolved(new VoidGenerator(MarshalerType.OneWay));
+ case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.DiscardNoWait }:
+ return ResolvedGenerator.Resolved(new VoidGenerator(MarshalerType.DiscardNoWait));
case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.Discard }:
case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.Void }:
case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.None }:
@@ -55,8 +55,8 @@ ResolvedGenerator fail(string failReason)
return fail(SR.DiscardOnlyVoid);
// oneway no void
- case { JSType: JSTypeFlags.OneWay }:
- return fail(SR.OneWayOnlyVoid);
+ case { JSType: JSTypeFlags.DiscardNoWait }:
+ return fail(SR.DiscardNoWaitOnlyVoid);
// primitive
case { TypeInfo: JSSimpleTypeInfo simple }:
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSTypeFlags.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSTypeFlags.cs
index e39fbe19425ba..5b34284f2225b 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSTypeFlags.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSTypeFlags.cs
@@ -22,7 +22,7 @@ internal enum JSTypeFlags : int
MemoryView = 0x800,
Any = 0x1000,
Discard = 0x2000,
- OneWay = 0x4000,
+ DiscardNoWait = 0x4000,
Missing = 0x4000_0000,
}
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Resources/Strings.resx
index 1e27fdcd8bb96..6aa6b8b9bb337 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Resources/Strings.resx
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Resources/Strings.resx
@@ -184,8 +184,8 @@
'JSType.Discard' could be only used with void return argument.
-
- 'JSType.OneWay' could be only used with void returning method.
+
+ 'JSType.DiscardNoWait' could be only used with void returning method.
Type {0} is not supported as argument of marshaled function.
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/CompatibilitySuppressions.xml b/src/libraries/System.Runtime.InteropServices.JavaScript/src/CompatibilitySuppressions.xml
index b5cc7926a5169..07a5ec1d2531e 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/CompatibilitySuppressions.xml
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/CompatibilitySuppressions.xml
@@ -14,13 +14,13 @@
CP0001
- T:System.Runtime.InteropServices.JavaScript.JSType.OneWay
+ T:System.Runtime.InteropServices.JavaScript.JSType.DiscardNoWait
ref/net9.0/System.Runtime.InteropServices.JavaScript.dll
runtimes/browser/lib/net9.0/System.Runtime.InteropServices.JavaScript.dll
CP0002
- M:System.Runtime.InteropServices.JavaScript.JSMarshalerType.get_OneWay
+ M:System.Runtime.InteropServices.JavaScript.JSMarshalerType.get_DiscardNoWait
ref/net9.0/System.Runtime.InteropServices.JavaScript.dll
runtimes/browser/lib/net9.0/System.Runtime.InteropServices.JavaScript.dll
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptImports.Generated.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptImports.Generated.cs
index db356f8afe4c2..7d734d8babe78 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptImports.Generated.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptImports.Generated.cs
@@ -57,7 +57,7 @@ internal static unsafe partial class JavaScriptImports
#if DEBUG
[JSImport("globalThis.console.log")]
- [return: JSMarshalAs]
+ [return: JSMarshalAs] // this means that the message will arrive out of order, especially across threads.
public static partial void Log([JSMarshalAs] string message);
#endif
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs
index 43afa95f76b1d..666f2caeb5a4a 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs
@@ -30,54 +30,51 @@ internal JSFunctionBinding() { }
internal static volatile uint nextImportHandle = 1;
internal int ImportHandle;
internal bool IsAsync;
- internal bool IsOneWay;
+ internal bool IsDiscardNoWait;
#if DEBUG
internal string? FunctionName;
#endif
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ // keep in sync with JSBindingHeaderOffsets in marshal.ts
+ [StructLayout(LayoutKind.Explicit, Pack = 4)]
internal struct JSBindingHeader
{
internal const int JSMarshalerSignatureHeaderSize = 4 * 8; // without Exception and Result
+ [FieldOffset(0)]
public int Version;
+ [FieldOffset(4)]
public int ArgumentCount;
+ [FieldOffset(8)]
public int ImportHandle;
- public int _Reserved;
+ [FieldOffset(16)]
public int FunctionNameOffset;
+ [FieldOffset(20)]
public int FunctionNameLength;
+ [FieldOffset(24)]
public int ModuleNameOffset;
+ [FieldOffset(28)]
public int ModuleNameLength;
+ [FieldOffset(32)]
public JSBindingType Exception;
+ [FieldOffset(64)]
public JSBindingType Result;
}
- [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 32)]
+ // keep in sync with JSBindingTypeOffsets in marshal.ts
+ [StructLayout(LayoutKind.Explicit, Pack = 4, Size = 32)]
internal struct JSBindingType
{
+ [FieldOffset(0)]
internal MarshalerType Type;
- internal MarshalerType __ReservedB1;
- internal MarshalerType __ReservedB2;
- internal MarshalerType __ReservedB3;
- internal IntPtr __Reserved;
- internal IntPtr JSCustomMarshallerCode;
- internal int JSCustomMarshallerCodeLength;
+ [FieldOffset(16)]
internal MarshalerType ResultMarshalerType;
- internal MarshalerType __ReservedB4;
- internal MarshalerType __ReservedB5;
- internal MarshalerType __ReservedB6;
+ [FieldOffset(20)]
internal MarshalerType Arg1MarshalerType;
- internal MarshalerType __ReservedB7;
- internal MarshalerType __ReservedB8;
- internal MarshalerType __ReservedB9;
+ [FieldOffset(24)]
internal MarshalerType Arg2MarshalerType;
- internal MarshalerType __ReservedB10;
- internal MarshalerType __ReservedB11;
- internal MarshalerType __ReservedB12;
+ [FieldOffset(28)]
internal MarshalerType Arg3MarshalerType;
- internal MarshalerType __ReservedB13;
- internal MarshalerType __ReservedB14;
- internal MarshalerType __ReservedB15;
}
internal unsafe int ArgumentCount
@@ -286,9 +283,9 @@ internal static unsafe void InvokeJSImportImpl(JSFunctionBinding signature, Span
arguments[1].slot.GCHandle = holder.GCHandle;
}
- if (signature.IsOneWay)
+ if (signature.IsDiscardNoWait)
{
- arguments[1].slot.Type = MarshalerType.OneWay;
+ arguments[1].slot.Type = MarshalerType.DiscardNoWait;
}
#if FEATURE_WASM_MANAGED_THREADS
@@ -305,7 +302,7 @@ internal static unsafe void InvokeJSImportImpl(JSFunctionBinding signature, Span
#endif
}
- else if (signature.IsAsync || signature.IsOneWay)
+ else if (signature.IsAsync || signature.IsDiscardNoWait)
{
//async
DispatchJSImportAsyncPost(signature, targetContext, arguments);
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs
index 335aa72371eee..736f2de5a134d 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs
@@ -153,7 +153,7 @@ public static unsafe JSFunctionBinding GetMethodSignature(ReadOnlySpan
/// The marshaler metadata.
- public static JSMarshalerType OneWay { get; } = new JSMarshalerType(new JSFunctionBinding.JSBindingType
+ public static JSMarshalerType DiscardNoWait { get; } = new JSMarshalerType(new JSFunctionBinding.JSBindingType
{
- Type = MarshalerType.OneWay
+ Type = MarshalerType.DiscardNoWait
});
///
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSType.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSType.cs
index 8f9a5ef68f156..7d86122eae7f5 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSType.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSType.cs
@@ -32,9 +32,9 @@ internal Discard() { }
/// Could return immediately without waiting for the execution to finish, when dispatching the call to another thread.
/// Suppresses marshaling of the JavaScript function's return value.
///
- public sealed class OneWay : JSType
+ public sealed class DiscardNoWait : JSType
{
- internal OneWay() { }
+ internal DiscardNoWait() { }
}
///
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/MarshalerType.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/MarshalerType.cs
index d9f11387dedaa..ee9e4e247b25e 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/MarshalerType.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/MarshalerType.cs
@@ -34,7 +34,7 @@ internal enum MarshalerType : byte
Span,
Action,
Function,
- OneWay,
+ DiscardNoWait,
#if !JSIMPORTGENERATOR
// only on runtime
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Marshaling/JSMarshalerArgument.Func.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Marshaling/JSMarshalerArgument.Func.cs
index 271acab66bae0..d53c92400755c 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Marshaling/JSMarshalerArgument.Func.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Marshaling/JSMarshalerArgument.Func.cs
@@ -20,7 +20,7 @@ public void InvokeJS()
// and would also allow the JS function to be collected
- Span arguments = stackalloc JSMarshalerArgument[4];
+ Span arguments = stackalloc JSMarshalerArgument[2];
ref JSMarshalerArgument args_exception = ref arguments[0];
ref JSMarshalerArgument args_return = ref arguments[1];
#if FEATURE_WASM_MANAGED_THREADS
@@ -51,7 +51,7 @@ public ActionJS(JSObject holder, ArgumentToJSCallback arg1Marshaler)
public void InvokeJS(T arg1)
{
- Span arguments = stackalloc JSMarshalerArgument[4];
+ Span arguments = stackalloc JSMarshalerArgument[3];
ref JSMarshalerArgument args_exception = ref arguments[0];
ref JSMarshalerArgument args_return = ref arguments[1];
ref JSMarshalerArgument args_arg1 = ref arguments[2];
@@ -258,7 +258,7 @@ public TResult InvokeJS()
// JSObject (held by this lambda) would be collected by GC after the lambda is collected
// and would also allow the JS function to be collected
- Span arguments = stackalloc JSMarshalerArgument[4];
+ Span arguments = stackalloc JSMarshalerArgument[2];
ref JSMarshalerArgument args_exception = ref arguments[0];
ref JSMarshalerArgument args_return = ref arguments[1];
#if FEATURE_WASM_MANAGED_THREADS
@@ -295,7 +295,7 @@ public FuncJS(JSObject holder, ArgumentToJSCallback arg1Marshaler, ArgumentTo
public TResult InvokeJS(T arg1)
{
- Span arguments = stackalloc JSMarshalerArgument[4];
+ Span arguments = stackalloc JSMarshalerArgument[3];
ref JSMarshalerArgument args_exception = ref arguments[0];
ref JSMarshalerArgument args_return = ref arguments[1];
ref JSMarshalerArgument args_arg1 = ref arguments[2];
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSExportTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSExportTest.cs
index 30eadd7a7f2c7..bcc2c85e9e785 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSExportTest.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSExportTest.cs
@@ -26,12 +26,11 @@ await JsExportTestAsync(value,
[Theory]
[MemberData(nameof(MarshalInt32Cases))]
- public async Task JsExportInt32OneWay(int value)
+ public async Task JsExportInt32DiscardNoWait(int value)
{
JavaScriptTestHelper.optimizedReached=0;
-
JavaScriptTestHelper.invoke1O(value);
- await Task.Yield();
+ await JavaScriptTestHelper.Delay(0);
Assert.Equal(value, JavaScriptTestHelper.optimizedReached);
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportTest.cs
index 68598527681bd..96b89ffa9e4f4 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportTest.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportTest.cs
@@ -529,10 +529,10 @@ public void JsImportInt16(short value)
#region Int32
[Theory]
[MemberData(nameof(MarshalInt32Cases))]
- public async Task JsImportInt32OneWay(int value)
+ public async Task JsImportInt32DiscardNoWait(int value)
{
- JavaScriptTestHelper.store1OneWay_Int32(value);
- await Task.Yield();
+ JavaScriptTestHelper.store1DiscardNoWait_Int32(value);
+ await JavaScriptTestHelper.Delay(0);
Assert.Equal(value, JavaScriptTestHelper.retrieve1_Int32());
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs
index 6d6a484890782..e5ea3a887e24b 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JavaScriptTestHelper.cs
@@ -15,7 +15,7 @@ namespace System.Runtime.InteropServices.JavaScript.Tests
public partial class JavaScriptTestHelper
{
[JSImport("globalThis.console.log")]
- [return: JSMarshalAs]
+ [return: JSMarshalAs]
public static partial void Log([JSMarshalAs] string message);
[JSImport("globalThis.window.location.toString")]
@@ -28,12 +28,15 @@ public partial class JavaScriptTestHelper
public static partial string ReboundMemberEcho(string message);
[JSExport]
- [return: JSMarshalAs]
+ [return: JSMarshalAs] // this means that the message will arrive out of order, especially across threads.
public static void ConsoleWriteLine([JSMarshalAs] string message)
{
Console.WriteLine(message);
}
+ [JSImport("delay", "JavaScriptTestHelper")]
+ public static partial Task Delay(int ms);
+
[JSImport("catch1toString", "JavaScriptTestHelper")]
public static partial string catch1toString(string message, string functionName);
@@ -76,7 +79,7 @@ public static void Optimized1V(int a1)
public static partial void invoke1V(int a1);
[JSExport]
- [return: JSMarshalAs]
+ [return: JSMarshalAs] // this means that the message will arrive out of order, especially across threads.
public static void Optimized1O(int a1)
{
optimizedReached += a1;
@@ -274,8 +277,8 @@ internal static partial void Relaxed(string a1, Exception ex,
internal static partial void store1_Int32([JSMarshalAs] int value);
[JSImport("store1", "JavaScriptTestHelper")]
- [return: JSMarshalAs]
- internal static partial void store1OneWay_Int32([JSMarshalAs] int value);
+ [return: JSMarshalAs] // this means that the message will arrive out of order, especially across threads.
+ internal static partial void store1DiscardNoWait_Int32([JSMarshalAs] int value);
[JSImport("retrieve1", "JavaScriptTestHelper")]
[return: JSMarshalAs]
diff --git a/src/mono/browser/runtime/driver.c b/src/mono/browser/runtime/driver.c
index 1d0133a57e6e8..d76a8bacd9282 100644
--- a/src/mono/browser/runtime/driver.c
+++ b/src/mono/browser/runtime/driver.c
@@ -263,7 +263,8 @@ mono_wasm_invoke_jsexport_async_post_cb (MonoMethod *method, void* args)
{
mono_wasm_invoke_jsexport (method, args);
// TODO assert receiver_should_free ?
- free (args);
+ if (args)
+ free (args);
}
// async
diff --git a/src/mono/browser/runtime/invoke-cs.ts b/src/mono/browser/runtime/invoke-cs.ts
index 2978e7ea8afce..287ee5ca6f681 100644
--- a/src/mono/browser/runtime/invoke-cs.ts
+++ b/src/mono/browser/runtime/invoke-cs.ts
@@ -39,15 +39,15 @@ export function mono_wasm_bind_cs_function(method: MonoMethod, assemblyName: str
const res_sig = get_sig(signature, 1);
let res_marshaler_type = get_signature_type(res_sig);
- // hack until we have public API for JSType.OneWay
+ // hack until we have public API for JSType.DiscardNoWait
if (WasmEnableThreads && shortClassName === "DefaultWebAssemblyJSRuntime"
&& namespaceName === "Microsoft.AspNetCore.Components.WebAssembly.Services"
&& (methodName === "BeginInvokeDotNet" || methodName === "EndInvokeJS")) {
- res_marshaler_type = MarshalerType.OneWay;
+ res_marshaler_type = MarshalerType.DiscardNoWait;
}
const is_async = res_marshaler_type == MarshalerType.Task;
- const is_oneway = res_marshaler_type == MarshalerType.OneWay;
+ const is_discard_no_wait = res_marshaler_type == MarshalerType.DiscardNoWait;
if (is_async) {
res_marshaler_type = MarshalerType.TaskPreCreated;
}
@@ -60,7 +60,7 @@ export function mono_wasm_bind_cs_function(method: MonoMethod, assemblyName: str
arg_marshalers,
res_converter,
is_async,
- is_oneway,
+ is_discard_no_wait,
isDisposed: false,
};
let bound_fn: Function;
@@ -75,7 +75,7 @@ export function mono_wasm_bind_cs_function(method: MonoMethod, assemblyName: str
else {
bound_fn = bind_fn(closure);
}
- } else if (is_oneway) {
+ } else if (is_discard_no_wait) {
bound_fn = bind_fn(closure);
} else {
if (args_count == 0 && !res_converter) {
@@ -285,7 +285,7 @@ function bind_fn(closure: BindingClosure) {
const method = closure.method;
const fqn = closure.fullyQualifiedName;
const is_async = closure.is_async;
- const is_oneway = closure.is_oneway;
+ const is_discard_no_wait = closure.is_discard_no_wait;
if (!WasmEnableThreads) (closure) = null;
return function bound_fn(...js_args: any[]) {
const mark = startMeasure();
@@ -313,7 +313,7 @@ function bind_fn(closure: BindingClosure) {
// in case the C# side returned synchronously
js_result = end_marshal_task_to_js(args, undefined, js_result);
}
- else if (is_oneway) {
+ else if (is_discard_no_wait) {
// call C# side, fire and forget
invoke_async_jsexport(method, args, 2 + args_count);
}
@@ -338,7 +338,7 @@ type BindingClosure = {
arg_marshalers: (BoundMarshalerToCs)[],
res_converter: BoundMarshalerToJs | undefined,
is_async: boolean,
- is_oneway: boolean,
+ is_discard_no_wait: boolean,
isDisposed: boolean,
}
diff --git a/src/mono/browser/runtime/invoke-js.ts b/src/mono/browser/runtime/invoke-js.ts
index f429bf3e98b9f..75d7c96b9c737 100644
--- a/src/mono/browser/runtime/invoke-js.ts
+++ b/src/mono/browser/runtime/invoke-js.ts
@@ -96,7 +96,7 @@ function bind_js_import(signature: JSFunctionSignature): Function {
const res_marshaler_type = get_signature_type(res_sig);
const res_converter = bind_arg_marshal_to_cs(res_sig, res_marshaler_type, 1);
- const is_oneway = res_marshaler_type == MarshalerType.OneWay;
+ const is_discard_no_wait = res_marshaler_type == MarshalerType.DiscardNoWait;
const is_async = res_marshaler_type == MarshalerType.Task || res_marshaler_type == MarshalerType.TaskPreCreated;
const closure: BindingClosure = {
@@ -107,12 +107,12 @@ function bind_js_import(signature: JSFunctionSignature): Function {
res_converter,
has_cleanup,
arg_cleanup,
- is_oneway,
+ is_discard_no_wait,
is_async,
isDisposed: false,
};
let bound_fn: WrappedJSFunction;
- if (is_async || is_oneway || has_cleanup) {
+ if (is_async || is_discard_no_wait || has_cleanup) {
bound_fn = bind_fn(closure);
}
else {
@@ -165,7 +165,7 @@ function bind_js_import(signature: JSFunctionSignature): Function {
}
let wrapped_fn: WrappedJSFunction;
- if (is_async || is_oneway) {
+ if (is_async || is_discard_no_wait) {
wrapped_fn = async_bound_fn;
}
else {
@@ -279,7 +279,7 @@ function bind_fn(closure: BindingClosure) {
const fqn = closure.fqn;
if (!WasmEnableThreads) (closure) = null;
return function bound_fn(args: JSMarshalerArguments) {
- const is_async = WasmEnableThreads && is_receiver_should_free(args);
+ const receiver_should_free = WasmEnableThreads && is_receiver_should_free(args);
const mark = startMeasure();
try {
mono_assert(!WasmEnableThreads || !closure.isDisposed, "The function was already disposed");
@@ -309,7 +309,7 @@ function bind_fn(closure: BindingClosure) {
marshal_exception_to_cs(args, ex);
}
finally {
- if (is_async) {
+ if (receiver_should_free) {
Module._free(args as any);
}
endMeasure(mark, MeasuredBlock.callCsFunction, fqn);
@@ -327,7 +327,7 @@ type BindingClosure = {
arg_marshalers: (BoundMarshalerToJs)[],
res_converter: BoundMarshalerToCs | undefined,
has_cleanup: boolean,
- is_oneway: boolean,
+ is_discard_no_wait: boolean,
is_async: boolean,
arg_cleanup: (Function | undefined)[]
}
diff --git a/src/mono/browser/runtime/marshal-to-cs.ts b/src/mono/browser/runtime/marshal-to-cs.ts
index 132de0f75dcd4..fa0f299a5f2b8 100644
--- a/src/mono/browser/runtime/marshal-to-cs.ts
+++ b/src/mono/browser/runtime/marshal-to-cs.ts
@@ -59,12 +59,12 @@ export function initialize_marshalers_to_cs(): void {
js_to_cs_marshalers.set(MarshalerType.None, _marshal_null_to_cs);// also void
js_to_cs_marshalers.set(MarshalerType.Discard, _marshal_null_to_cs);// also void
js_to_cs_marshalers.set(MarshalerType.Void, _marshal_null_to_cs);// also void
- js_to_cs_marshalers.set(MarshalerType.OneWay, _marshal_null_to_cs);// also void
+ js_to_cs_marshalers.set(MarshalerType.DiscardNoWait, _marshal_null_to_cs);// also void
}
}
export function bind_arg_marshal_to_cs(sig: JSMarshalerType, marshaler_type: MarshalerType, index: number): BoundMarshalerToCs | undefined {
- if (marshaler_type === MarshalerType.None || marshaler_type === MarshalerType.Void || marshaler_type === MarshalerType.Discard || marshaler_type === MarshalerType.OneWay) {
+ if (marshaler_type === MarshalerType.None || marshaler_type === MarshalerType.Void || marshaler_type === MarshalerType.Discard || marshaler_type === MarshalerType.DiscardNoWait) {
return undefined;
}
let res_marshaler: MarshalerToCs | undefined = undefined;
diff --git a/src/mono/browser/runtime/marshal-to-js.ts b/src/mono/browser/runtime/marshal-to-js.ts
index 29f6bcdb54c45..f02c81765e6a4 100644
--- a/src/mono/browser/runtime/marshal-to-js.ts
+++ b/src/mono/browser/runtime/marshal-to-js.ts
@@ -55,12 +55,12 @@ export function initialize_marshalers_to_js(): void {
cs_to_js_marshalers.set(MarshalerType.None, _marshal_null_to_js);
cs_to_js_marshalers.set(MarshalerType.Void, _marshal_null_to_js);
cs_to_js_marshalers.set(MarshalerType.Discard, _marshal_null_to_js);
- cs_to_js_marshalers.set(MarshalerType.OneWay, _marshal_null_to_js);
+ cs_to_js_marshalers.set(MarshalerType.DiscardNoWait, _marshal_null_to_js);
}
}
export function bind_arg_marshal_to_js(sig: JSMarshalerType, marshaler_type: MarshalerType, index: number): BoundMarshalerToJs | undefined {
- if (marshaler_type === MarshalerType.None || marshaler_type === MarshalerType.Void || marshaler_type === MarshalerType.Discard || marshaler_type === MarshalerType.OneWay) {
+ if (marshaler_type === MarshalerType.None || marshaler_type === MarshalerType.Void || marshaler_type === MarshalerType.Discard || marshaler_type === MarshalerType.DiscardNoWait) {
return undefined;
}
@@ -338,7 +338,7 @@ function create_task_holder(res_converter?: MarshalerToJs) {
export function mono_wasm_resolve_or_reject_promise(args: JSMarshalerArguments): void {
const exc = get_arg(args, 0);
- const is_async = WasmEnableThreads && is_receiver_should_free(args);
+ const receiver_should_free = WasmEnableThreads && is_receiver_should_free(args);
try {
loaderHelpers.assert_runtime_running();
@@ -353,7 +353,7 @@ export function mono_wasm_resolve_or_reject_promise(args: JSMarshalerArguments):
mono_assert(holder, () => `Cannot find Promise for JSHandle ${js_handle}`);
holder.resolve_or_reject(type, js_handle, arg_value);
- if (is_async) {
+ if (receiver_should_free) {
// this works together with AllocHGlobal in JSFunctionBinding.ResolveOrRejectPromise
Module._free(args as any);
}
@@ -363,7 +363,7 @@ export function mono_wasm_resolve_or_reject_promise(args: JSMarshalerArguments):
}
} catch (ex: any) {
- if (is_async) {
+ if (receiver_should_free) {
mono_assert(false, () => `Failed to resolve or reject promise ${ex}`);
}
marshal_exception_to_cs(exc, ex);
diff --git a/src/mono/browser/runtime/marshal.ts b/src/mono/browser/runtime/marshal.ts
index 6d0f6ec0308fa..c3c07d1c18895 100644
--- a/src/mono/browser/runtime/marshal.ts
+++ b/src/mono/browser/runtime/marshal.ts
@@ -20,8 +20,47 @@ export const imported_js_function_symbol = Symbol.for("wasm imported_js_function
export const proxy_debug_symbol = Symbol.for("wasm proxy_debug");
export const JavaScriptMarshalerArgSize = 32;
+// keep in sync with JSMarshalerArgumentImpl offsets
+const enum JSMarshalerArgumentOffsets {
+ BooleanValue = 0,
+ ByteValue = 0,
+ CharValue = 0,
+ Int16Value = 0,
+ Int32Value = 0,
+ Int64Value = 0,
+ SingleValue = 0,
+ DoubleValue = 0,
+ IntPtrValue = 0,
+ JSHandle = 4,
+ GCHandle = 4,
+ Length = 8,
+ Type = 12,
+ ElementType = 13,
+ ContextHandle = 16,
+ ReceiverShouldFree = 20,
+}
export const JSMarshalerTypeSize = 32;
+// keep in sync with JSFunctionBinding.JSBindingType
+const enum JSBindingTypeOffsets {
+ Type = 0,
+ ResultMarshalerType = 16,
+ Arg1MarshalerType = 20,
+ Arg2MarshalerType = 24,
+ Arg3MarshalerType = 28,
+}
export const JSMarshalerSignatureHeaderSize = 4 * 8; // without Exception and Result
+// keep in sync with JSFunctionBinding.JSBindingHeader
+const enum JSBindingHeaderOffsets {
+ Version = 0,
+ ArgumentCount = 4,
+ ImportHandle = 8,
+ FunctionNameOffset = 16,
+ FunctionNameLength = 20,
+ ModuleNameOffset = 24,
+ ModuleNameLength = 28,
+ Exception = 32,
+ Result = 64,
+}
export function alloc_stack_frame(size: number): JSMarshalerArguments {
if (WasmEnableThreads) {
@@ -48,12 +87,12 @@ 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 + 20);
+ return getB32(args + JSMarshalerArgumentOffsets.ReceiverShouldFree);
}
export function set_receiver_should_free(args: JSMarshalerArguments): void {
mono_assert(args, "Null args");
- setB32(args + 20, true);
+ setB32(args + JSMarshalerArgumentOffsets.ReceiverShouldFree, true);
}
export function set_args_context(args: JSMarshalerArguments): void {
@@ -72,58 +111,58 @@ export function get_sig(signature: JSFunctionSignature, index: number): JSMarsha
export function get_signature_type(sig: JSMarshalerType): MarshalerType {
mono_assert(sig, "Null sig");
- return getU8(sig);
+ return getU8(sig + JSBindingTypeOffsets.Type);
}
export function get_signature_res_type(sig: JSMarshalerType): MarshalerType {
mono_assert(sig, "Null sig");
- return getU8(sig + 16);
+ return getU8(sig + JSBindingTypeOffsets.ResultMarshalerType);
}
export function get_signature_arg1_type(sig: JSMarshalerType): MarshalerType {
mono_assert(sig, "Null sig");
- return getU8(sig + 20);
+ return getU8(sig + JSBindingTypeOffsets.Arg1MarshalerType);
}
export function get_signature_arg2_type(sig: JSMarshalerType): MarshalerType {
mono_assert(sig, "Null sig");
- return getU8(sig + 24);
+ return getU8(sig + JSBindingTypeOffsets.Arg2MarshalerType);
}
export function get_signature_arg3_type(sig: JSMarshalerType): MarshalerType {
mono_assert(sig, "Null sig");
- return getU8(sig + 28);
+ return getU8(sig + JSBindingTypeOffsets.Arg2MarshalerType);
}
export function get_signature_argument_count(signature: JSFunctionSignature): number {
mono_assert(signature, "Null signatures");
- return getI32(signature + 4);
+ return getI32(signature + JSBindingHeaderOffsets.ArgumentCount);
}
export function get_signature_version(signature: JSFunctionSignature): number {
mono_assert(signature, "Null signatures");
- return getI32(signature);
+ return getI32(signature + JSBindingHeaderOffsets.Version);
}
export function get_signature_handle(signature: JSFunctionSignature): number {
mono_assert(signature, "Null signatures");
- return getI32(signature + 8);
+ return getI32(signature + JSBindingHeaderOffsets.ImportHandle);
}
export function get_signature_function_name(signature: JSFunctionSignature): string | null {
mono_assert(signature, "Null signatures");
- const functionNameOffset = getI32(signature + 16);
+ const functionNameOffset = getI32(signature + JSBindingHeaderOffsets.FunctionNameOffset);
if (functionNameOffset === 0) return null;
- const functionNameLength = getI32(signature + 20);
+ const functionNameLength = getI32(signature + JSBindingHeaderOffsets.FunctionNameLength);
mono_assert(functionNameOffset, "Null name");
return utf16ToString(signature + functionNameOffset, signature + functionNameOffset + functionNameLength);
}
export function get_signature_module_name(signature: JSFunctionSignature): string | null {
mono_assert(signature, "Null signatures");
- const moduleNameOffset = getI32(signature + 24);
+ const moduleNameOffset = getI32(signature + JSBindingHeaderOffsets.ModuleNameOffset);
if (moduleNameOffset === 0) return null;
- const moduleNameLength = getI32(signature + 28);
+ const moduleNameLength = getI32(signature + JSBindingHeaderOffsets.ModuleNameLength);
return utf16ToString(signature + moduleNameOffset, signature + moduleNameOffset + moduleNameLength);
}
@@ -134,24 +173,24 @@ export function get_sig_type(sig: JSMarshalerType): MarshalerType {
export function get_arg_type(arg: JSMarshalerArgument): MarshalerType {
mono_assert(arg, "Null arg");
- const type = getU8(arg + 12);
+ const type = getU8(arg + JSMarshalerArgumentOffsets.Type);
return type;
}
export function get_arg_element_type(arg: JSMarshalerArgument): MarshalerType {
mono_assert(arg, "Null arg");
- const type = getU8(arg + 13);
+ const type = getU8(arg + JSMarshalerArgumentOffsets.ElementType);
return type;
}
export function set_arg_type(arg: JSMarshalerArgument, type: MarshalerType): void {
mono_assert(arg, "Null arg");
- setU8(arg + 12, type);
+ setU8(arg + JSMarshalerArgumentOffsets.Type, type);
}
export function set_arg_element_type(arg: JSMarshalerArgument, type: MarshalerType): void {
mono_assert(arg, "Null arg");
- setU8(arg + 13, type);
+ setU8(arg + JSMarshalerArgumentOffsets.ElementType, type);
}
export function get_arg_b8(arg: JSMarshalerArgument): boolean {
@@ -274,29 +313,29 @@ export function set_arg_f32(arg: JSMarshalerArgument, value: number): void {
export function get_arg_js_handle(arg: JSMarshalerArgument): JSHandle {
mono_assert(arg, "Null arg");
- return getI32(arg + 4);
+ return getI32(arg + JSMarshalerArgumentOffsets.JSHandle);
}
export function set_arg_proxy_context(arg: JSMarshalerArgument): void {
if (!WasmEnableThreads) return;
mono_assert(arg, "Null arg");
- setI32(arg + 16, runtimeHelpers.proxyGCHandle);
+ setI32(arg + JSMarshalerArgumentOffsets.ContextHandle, runtimeHelpers.proxyGCHandle);
}
export function set_js_handle(arg: JSMarshalerArgument, jsHandle: JSHandle): void {
mono_assert(arg, "Null arg");
- setI32(arg + 4, jsHandle);
+ setI32(arg + JSMarshalerArgumentOffsets.JSHandle, jsHandle);
set_arg_proxy_context(arg);
}
export function get_arg_gc_handle(arg: JSMarshalerArgument): GCHandle {
mono_assert(arg, "Null arg");
- return getI32(arg + 4);
+ return getI32(arg + JSMarshalerArgumentOffsets.GCHandle);
}
export function set_gc_handle(arg: JSMarshalerArgument, gcHandle: GCHandle): void {
mono_assert(arg, "Null arg");
- setI32(arg + 4, gcHandle);
+ setI32(arg + JSMarshalerArgumentOffsets.GCHandle, gcHandle);
set_arg_proxy_context(arg);
}
@@ -307,12 +346,12 @@ export function get_string_root(arg: JSMarshalerArgument): WasmRoot
export function get_arg_length(arg: JSMarshalerArgument): number {
mono_assert(arg, "Null arg");
- return getI32(arg + 8);
+ return getI32(arg + JSMarshalerArgumentOffsets.Length);
}
export function set_arg_length(arg: JSMarshalerArgument, size: number): void {
mono_assert(arg, "Null arg");
- setI32(arg + 8, size);
+ setI32(arg + JSMarshalerArgumentOffsets.Length, size);
}
export function set_root(arg: JSMarshalerArgument, root: WasmRoot): void {
@@ -393,7 +432,7 @@ export class ManagedError extends Error implements IDisposable {
export function get_signature_marshaler(signature: JSFunctionSignature, index: number): JSHandle {
mono_assert(signature, "Null signatures");
const sig = get_sig(signature, index);
- return getU32(sig + 8);
+ return getU32(sig + JSBindingHeaderOffsets.ImportHandle);
}
diff --git a/src/mono/browser/runtime/memory.ts b/src/mono/browser/runtime/memory.ts
index cef0f641e50bf..ab4beebf1285a 100644
--- a/src/mono/browser/runtime/memory.ts
+++ b/src/mono/browser/runtime/memory.ts
@@ -392,9 +392,7 @@ export function localHeapViewF64(): Float64Array {
export function copyBytes(srcPtr: VoidPtr, dstPtr: VoidPtr, bytes: number): void {
const heap = localHeapViewU8();
- const src = heap.subarray(srcPtr as any, srcPtr as any + bytes);
- const dst = heap.subarray(dstPtr as any, dstPtr as any + bytes);
- dst.set(src);
+ heap.copyWithin(dstPtr as any, srcPtr as any, srcPtr as any + bytes);
}
// when we run with multithreading enabled, we need to make sure that the memory views are updated on each worker
diff --git a/src/mono/browser/runtime/strings.ts b/src/mono/browser/runtime/strings.ts
index aae59c50b69a9..d0d798c161b28 100644
--- a/src/mono/browser/runtime/strings.ts
+++ b/src/mono/browser/runtime/strings.ts
@@ -244,7 +244,9 @@ function storeStringInInternTable(string: string, root: WasmRoot, in
function stringToMonoStringNewRoot(string: string, result: WasmRoot): void {
const bufferLen = (string.length + 1) * 2;
- // TODO this could be stack allocated
+ // TODO this could be stack allocated for small strings
+ // or temp_malloc/alloca for large strings
+ // or skip the scratch buffer entirely, and make a new MonoString of size string.length, pin it, and then call stringToUTF16 to write directly into the MonoString's chars
const buffer = Module._malloc(bufferLen);
stringToUTF16(buffer as any, buffer as any + bufferLen, string);
cwraps.mono_wasm_string_from_utf16_ref(buffer, string.length, result.address);
diff --git a/src/mono/browser/runtime/types/internal.ts b/src/mono/browser/runtime/types/internal.ts
index a2eb9b623f90c..3f021a50a01ce 100644
--- a/src/mono/browser/runtime/types/internal.ts
+++ b/src/mono/browser/runtime/types/internal.ts
@@ -337,7 +337,7 @@ export enum MarshalerType {
Span,
Action,
Function,
- OneWay,
+ DiscardNoWait,
// only on runtime
JSException,