[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void CreateCSOwnedObjectRef(in string className, in object[] parms, out int exceptionalResult, out object result);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern void TypedArrayCopyToRef(IntPtr jsHandle, int arrayPtr, int begin, int end, int bytesPerElement, out int exceptionalResult, out object result);
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void TypedArrayFromRef(int arrayPtr, int begin, int end, int bytesPerElement, int type, out int exceptionalResult, out object result);
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern void TypedArrayCopyFromRef(IntPtr jsHandle, int arrayPtr, int begin, int end, int bytesPerElement, out int exceptionalResult, out object result);
#endregion
{
throw new Exception($"At attempt={attempt}, index={index}: {ex.Message}", ex);
}
+ await Task.Yield();
}
}
Assert.Equal(16, HelperMarshal._byteBuffer.Length);
}
-
-
-
[Fact]
public static void MarshalStringToCS()
{
{
HelperMarshal._intValue = 0;
Utils.InvokeJS(@$"
- var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
+ var invoke_int = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
invoke_int (200);
");
{
HelperMarshal._intPtrValue = IntPtr.Zero;
Utils.InvokeJS(@$"
- var invoke_int_ptr = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeIntPtr"");
+ var invoke_int_ptr = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeIntPtr"");
invoke_int_ptr (42);
");
Assert.Equal(42, (int)HelperMarshal._intPtrValue);
{
HelperMarshal._marshaledIntPtrValue = IntPtr.Zero;
Utils.InvokeJS(@$"
- var invokeMarshalIntPtr = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeMarshalIntPtr"");
+ var invokeMarshalIntPtr = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeMarshalIntPtr"");
var r = invokeMarshalIntPtr ();
if (r != 42) throw `Invalid int_ptr value`;
}
[Fact]
- public static void InvokeStaticMethod()
- {
- HelperMarshal._intValue = 0;
- Utils.InvokeJS(@$"
- INTERNAL.call_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"", [ 300 ]);
- ");
-
- Assert.Equal(300, HelperMarshal._intValue);
- }
-
- [Fact]
public static void ResolveMethod()
{
HelperMarshal._intValue = 0;
Assert.Equal(16, HelperMarshal._byteBuffer.Length);
}
+ [Fact]
+ public static void MarshalUri()
+ {
+ HelperMarshal._blobURI = null;
+ Utils.InvokeJS(@"
+ App.call_test_method (""SetBlobAsUri"", [ ""https://dotnet.microsoft.com/en-us/"" ]);
+ ");
+
+ Assert.NotNull(HelperMarshal._blobURI);
+ }
+
private static void RunMarshalTypedArrayJS(string type)
{
Utils.InvokeJS(@"
Assert.Equal("hic sunt dracones", System.Text.Encoding.Default.GetString(HelperMarshal._taByte));
}
-
-
[Fact]
public static void TestFunctionSum()
{
{
HelperMarshal._intValue = 1;
var ex = Assert.Throws<JSException>(() => Utils.InvokeJS(@$"
- var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
+ var invoke_int = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
invoke_int ();
"));
Assert.Contains("Value is not an integer: undefined (undefined)", ex.Message);
{
HelperMarshal._intValue = 0;
Utils.InvokeJS(@$"
- var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
+ var invoke_int = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
invoke_int (200, 400);
");
Assert.Equal(200, HelperMarshal._intValue);
HelperMarshal._intValue = 0;
// no numbers bigger than 32 bits
var ex = Assert.Throws<JSException>(() => Utils.InvokeJS(@$"
- var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
+ var invoke_int = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
invoke_int (Number.MAX_SAFE_INTEGER);
"));
Assert.Contains("Overflow: value 9007199254740991 is out of -2147483648 2147483647 range", ex.Message);
HelperMarshal._intValue = 0;
// no floating point rounding
var ex = Assert.Throws<JSException>(() => Utils.InvokeJS(@$"
- var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
+ var invoke_int = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
invoke_int (3.14);
"));
Assert.Contains("Value is not an integer: 3.14 (number)", ex.Message);
HelperMarshal._intValue = 0;
// no string conversion
var ex = Assert.Throws<JSException>(() => Utils.InvokeJS(@$"
- var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
+ var invoke_int = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"");
invoke_int (""200"");
"));
Assert.Contains("Value is not an integer: 200 (string)", ex.Message);
{
HelperMarshal._uintValue = 0;
Utils.InvokeJS(@$"
- var invoke_uint = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeUInt"");
+ var invoke_uint = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeUInt"");
invoke_uint (0xFFFFFFFE);
");
HelperMarshal._uintValue = 0;
HelperMarshal._enumValue = TestEnum.BigValue;
Utils.InvokeJS(@$"
- var get_value = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}GetEnumValue"");
+ var get_value = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}GetEnumValue"");
var e = get_value ();
- var invoke_uint = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeUInt"");
+ var invoke_uint = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeUInt"");
invoke_uint (e);
");
Assert.Equal((uint)TestEnum.BigValue, HelperMarshal._uintValue);
{
HelperMarshal._enumValue = TestEnum.Zero;
Utils.InvokeJS(@$"
- var set_enum = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""j"");
+ var set_enum = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""j"");
set_enum (0xFFFFFFFE);
");
Assert.Equal(TestEnum.BigValue, HelperMarshal._enumValue);
HelperMarshal._enumValue = TestEnum.Zero;
var exc = Assert.Throws<JSException>(() =>
Utils.InvokeJS(@$"
- var set_enum = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""j"");
+ var set_enum = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""j"");
set_enum (""BigValue"");
")
);
{
var exc = Assert.Throws<JSException>(() =>
Utils.InvokeJS(@$"
- var get_u64 = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}GetUInt64"", """");
+ var get_u64 = BINDING.bind_static_method (""{HelperMarshal.INTEROP_CLASS}GetUInt64"", """");
var u64 = get_u64();
")
);
HelperMarshal._stringResource = HelperMarshal._stringResource2 = null;
var fqn = "[System.Private.Runtime.InteropServices.JavaScript.Tests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:StoreArgumentAndReturnLiteral";
Utils.InvokeJS(
- $"var a = INTERNAL.mono_bind_static_method('{fqn}')('test');\r\n" +
- $"var b = INTERNAL.mono_bind_static_method('{fqn}')(a);\r\n" +
+ $"var a = BINDING.bind_static_method('{fqn}')('test');\r\n" +
+ $"var b = BINDING.bind_static_method('{fqn}')(a);\r\n" +
"App.call_test_method ('InvokeString2', [ b ]);"
);
Assert.Equal("s: 1 length: 1", HelperMarshal._stringResource);
@"globalThis.__test_promise_completed = false; " +
@"globalThis.__test_promise_resolved = false; " +
@"globalThis.__test_promise_failed = false; " +
- $@"var t = App.call_test_method ('{helperMethodName}', [ {helperMethodArgs} ], 'i'); " +
+ $@"var t = App.call_test_method ('{helperMethodName}', [ {helperMethodArgs} ]); " +
"t.then(result => { globalThis.__test_promise_resolved = true; " + resolvedBody + " })" +
" .catch(e => { globalThis.__test_promise_failed = true; })" +
" .finally(result => { globalThis.__test_promise_completed = true; }); " +
<Compile Include="System\Runtime\InteropServices\JavaScript\Interop\JavaScriptImports.Generated.cs" />
<Compile Include="System\Runtime\InteropServices\JavaScript\Interop\JavaScriptExports.cs" />
<Compile Include="System\Runtime\InteropServices\JavaScript\Interop\JavaScriptImports.cs" />
+ <Compile Include="System\Runtime\InteropServices\JavaScript\Interop\LegacyExports.cs" />
<Compile Include="System\Runtime\InteropServices\JavaScript\Legacy\Runtime.cs" />
<Compile Include="System\Runtime\InteropServices\JavaScript\Legacy\Array.cs" />
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Diagnostics;
-using System.Reflection;
using System.Runtime.CompilerServices;
-using System.Threading.Tasks;
namespace System.Runtime.InteropServices.JavaScript
{
- // this maps to src\mono\wasm\runtime\corebindings.c
- // the methods are protected from trimming by DynamicDependency on JSFunctionBinding
+ // this maps to src\mono\wasm\runtime\corebindings.ts
+ // the methods are protected from trimming by DynamicDependency on JSFunctionBinding.BindJSFunction
internal static unsafe partial class JavaScriptExports
{
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void GetCSOwnedObjectByJSHandleRef(IntPtr jsHandle, int shouldAddInflight, out JSObject? result)
- {
- lock (JSHostImplementation.s_csOwnedObjects)
+
+ // The JS layer invokes this method when the JS wrapper for a JS owned object
+ // has been collected by the JS garbage collector
+ [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ // the marshaled signature is:
+ // void ReleaseJSOwnedObjectByGCHandle(GCHandle gcHandle)
+ public static void ReleaseJSOwnedObjectByGCHandle(JSMarshalerArgument* arguments_buffer)
+ {
+ ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame()
+ ref JSMarshalerArgument arg_1 = ref arguments_buffer[2]; // initialized and set by caller
+ try
{
- if (JSHostImplementation.s_csOwnedObjects.TryGetValue((int)jsHandle, out WeakReference<JSObject>? reference))
+ GCHandle handle = (GCHandle)arg_1.slot.GCHandle;
+
+ lock (JSHostImplementation.s_gcHandleFromJSOwnedObject)
{
- reference.TryGetTarget(out JSObject? jsObject);
- if (shouldAddInflight != 0)
- {
- jsObject?.AddInFlight();
- }
- result = jsObject;
- return;
+ JSHostImplementation.s_gcHandleFromJSOwnedObject.Remove(handle.Target!);
+ handle.Free();
}
}
- result = null;
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static IntPtr GetCSOwnedObjectJSHandleRef(in JSObject jsObject, int shouldAddInflight)
- {
- jsObject.AssertNotDisposed();
-
- if (shouldAddInflight != 0)
+ catch (Exception ex)
{
- jsObject.AddInFlight();
+ arg_exc.ToJS(ex);
}
- return jsObject.JSHandle;
}
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static IntPtr TryGetCSOwnedObjectJSHandleRef(in object rawObj, int shouldAddInflight)
+ [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ // the marshaled signature is:
+ // GCHandle CreateTaskCallback()
+ public static void CreateTaskCallback(JSMarshalerArgument* arguments_buffer)
{
- JSObject? jsObject = rawObj as JSObject;
- if (jsObject != null && shouldAddInflight != 0)
+ ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame()
+ ref JSMarshalerArgument arg_return = ref arguments_buffer[1]; // used as return vaule
+ try
{
- jsObject.AddInFlight();
+ JSHostImplementation.TaskCallback holder = new JSHostImplementation.TaskCallback();
+ arg_return.slot.Type = MarshalerType.Object;
+ arg_return.slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(holder);
+ }
+ catch (Exception ex)
+ {
+ arg_exc.ToJS(ex);
}
- return jsObject?.JSHandle ?? IntPtr.Zero;
}
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void CreateCSOwnedProxyRef(IntPtr jsHandle, JSHostImplementation.MappedType mappedType, int shouldAddInflight, out JSObject jsObject)
+ [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ // the marshaled signature is:
+ // TRes? CallDelegate<T1,T2,T3TRes>(GCHandle callback, T1? arg1, T2? arg2, T3? arg3)
+ public static void CallDelegate(JSMarshalerArgument* arguments_buffer)
{
- JSObject? res = null;
-
- lock (JSHostImplementation.s_csOwnedObjects)
+ ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by JS caller in alloc_stack_frame()
+ // arg_res is initialized by JS caller
+ ref JSMarshalerArgument arg_1 = ref arguments_buffer[2];// initialized and set by JS caller
+ // arg_2 set by JS caller when there are arguments
+ // arg_3 set by JS caller when there are arguments
+ // arg_4 set by JS caller when there are arguments
+ try
{
- if (!JSHostImplementation.s_csOwnedObjects.TryGetValue((int)jsHandle, out WeakReference<JSObject>? reference) ||
- !reference.TryGetTarget(out res) ||
- res.IsDisposed)
+ GCHandle callback_gc_handle = (GCHandle)arg_1.slot.GCHandle;
+ if (callback_gc_handle.Target is JSHostImplementation.ToManagedCallback callback)
+ {
+ // arg_2, arg_3, arg_4, arg_res are processed by the callback
+ callback(arguments_buffer);
+ }
+ else
{
-#pragma warning disable CS0612 // Type or member is obsolete
- res = mappedType switch
- {
- JSHostImplementation.MappedType.JSObject => new JSObject(jsHandle),
- JSHostImplementation.MappedType.Array => new Array(jsHandle),
- JSHostImplementation.MappedType.ArrayBuffer => new ArrayBuffer(jsHandle),
- JSHostImplementation.MappedType.DataView => new DataView(jsHandle),
- JSHostImplementation.MappedType.Function => new Function(jsHandle),
- JSHostImplementation.MappedType.Uint8Array => new Uint8Array(jsHandle),
- _ => throw new ArgumentOutOfRangeException(nameof(mappedType))
- };
-#pragma warning restore CS0612 // Type or member is obsolete
- JSHostImplementation.s_csOwnedObjects[(int)jsHandle] = new WeakReference<JSObject>(res, trackResurrection: true);
+ throw new InvalidOperationException("ToManagedCallback is null");
}
}
- if (shouldAddInflight != 0)
+ catch (Exception ex)
{
- res.AddInFlight();
+ arg_exc.ToJS(ex);
}
- jsObject = res;
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void GetJSOwnedObjectByGCHandleRef(int gcHandle, out object result)
- {
- GCHandle h = (GCHandle)(IntPtr)gcHandle;
- result = h.Target!;
}
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static IntPtr GetJSOwnedObjectGCHandleRef(in object obj)
- {
- return JSHostImplementation.GetJSOwnedObjectGCHandleRef(obj, GCHandleType.Normal);
- }
-
- // The JS layer invokes this method when the JS wrapper for a JS owned object
- // has been collected by the JS garbage collector
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void ReleaseJSOwnedObjectByGCHandle(IntPtr gcHandle)
- {
- GCHandle handle = (GCHandle)gcHandle;
- lock (JSHostImplementation.s_gcHandleFromJSOwnedObject)
- {
- JSHostImplementation.s_gcHandleFromJSOwnedObject.Remove(handle.Target!);
- handle.Free();
- }
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static IntPtr CreateTaskSource()
- {
- var tcs = new TaskCompletionSource<object>();
- return GetJSOwnedObjectGCHandleRef(tcs);
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void SetTaskSourceResultRef(int tcsGCHandle, in object result)
- {
- GCHandle handle = (GCHandle)(IntPtr)tcsGCHandle;
- // this is JS owned Normal handle. We always have a Target
- TaskCompletionSource<object> tcs = (TaskCompletionSource<object>)handle.Target!;
- tcs.SetResult(result);
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void SetTaskSourceFailure(int tcsGCHandle, string reason)
- {
- GCHandle handle = (GCHandle)(IntPtr)tcsGCHandle;
- // this is JS owned Normal handle. We always have a Target
- TaskCompletionSource<object> tcs = (TaskCompletionSource<object>)handle.Target!;
- tcs.SetException(new JSException(reason));
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void GetTaskSourceTaskRef(int tcsGCHandle, out object result)
- {
- GCHandle handle = (GCHandle)(IntPtr)tcsGCHandle;
- // this is JS owned Normal handle. We always have a Target
- TaskCompletionSource<object> tcs = (TaskCompletionSource<object>)handle.Target!;
- result = tcs.Task;
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void TaskFromResultRef(in object obj, out object result)
- {
- result = Task.FromResult(obj);
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void SetupJSContinuationRef(in Task _task, JSObject continuationObj)
+ [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ // the marshaled signature is:
+ // void CompleteTask<T>(GCHandle holder, Exception? exceptionResult, T? result)
+ public static void CompleteTask(JSMarshalerArgument* arguments_buffer)
{
- // HACK: Attempting to use the in-param will produce CS1628, so we make a temporary copy
- // on the stack that can be captured by our local functions below
- var task = _task;
-
- if (task.IsCompleted)
- Complete();
- else
- task.GetAwaiter().OnCompleted(Complete);
-
- void Complete()
+ ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame()
+ ref JSMarshalerArgument arg_1 = ref arguments_buffer[2];// initialized and set by caller
+ // arg_2 set by caller when this is SetException call
+ // arg_3 set by caller when this is SetResult call
+ try
{
- try
- {
- if (task.Exception == null)
- {
- object? result;
- Type task_type = task.GetType();
- if (task_type == typeof(Task))
- {
- result = System.Array.Empty<object>();
- }
- else
- {
- result = JSHostImplementation.GetTaskResultMethodInfo(task_type)?.Invoke(task, null);
- }
-
- continuationObj.Invoke("resolve", result);
- }
- else
- {
- continuationObj.Invoke("reject", task.Exception.ToString());
- }
- }
- catch (Exception e)
+ GCHandle callback_gc_handle = (GCHandle)arg_1.slot.GCHandle;
+ if (callback_gc_handle.Target is JSHostImplementation.TaskCallback holder && holder.Callback is not null)
{
- continuationObj.Invoke("reject", e.ToString());
+ // arg_2, arg_3 are processed by the callback
+ holder.Callback(arguments_buffer);
}
- finally
+ else
{
- continuationObj.Dispose();
+ throw new InvalidOperationException("TaskCallback is null");
}
}
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static string ObjectToStringRef(ref object o)
- {
- return o.ToString() ?? string.Empty;
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static double GetDateValueRef(ref object dtv)
- {
- ArgumentNullException.ThrowIfNull(dtv);
-
- if (!(dtv is DateTime dt))
- throw new InvalidCastException(SR.Format(SR.UnableCastObjectToType, dtv.GetType(), typeof(DateTime)));
- if (dt.Kind == DateTimeKind.Local)
- dt = dt.ToUniversalTime();
- else if (dt.Kind == DateTimeKind.Unspecified)
- dt = new DateTime(dt.Ticks, DateTimeKind.Utc);
- return new DateTimeOffset(dt).ToUnixTimeMilliseconds();
- }
-
- // HACK: We need to implicitly box by using an 'object' out-param.
- // Note that the return value would have been boxed on the C#->JS transition anyway.
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void CreateDateTimeRef(double ticks, out object result)
- {
- DateTimeOffset unixTime = DateTimeOffset.FromUnixTimeMilliseconds((long)ticks);
- result = unixTime.DateTime;
- }
-
- // TODO remove this to allow trimming of Uri assembly
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void CreateUriRef(string uri, out Uri result)
- {
- result = new Uri(uri);
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static bool IsSimpleArrayRef(ref object a)
- {
- return a is System.Array arr && arr.Rank == 1 && arr.GetLowerBound(0) == 0;
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static string GetCallSignatureRef(IntPtr _methodHandle, in object objForRuntimeType)
- {
- var methodHandle = JSHostImplementation.GetMethodHandleFromIntPtr(_methodHandle);
-
- MethodBase? mb = objForRuntimeType is null ? MethodBase.GetMethodFromHandle(methodHandle) : MethodBase.GetMethodFromHandle(methodHandle, Type.GetTypeHandle(objForRuntimeType));
- if (mb is null)
- return string.Empty;
-
- ParameterInfo[] parms = mb.GetParameters();
- int parmsLength = parms.Length;
- if (parmsLength == 0)
- return string.Empty;
-
- var result = new char[parmsLength];
- for (int i = 0; i < parmsLength; i++)
+ catch (Exception ex)
{
- Type t = parms[i].ParameterType;
- var mt = JSHostImplementation.GetMarshalTypeFromType(t);
- result[i] = JSHostImplementation.GetCallSignatureCharacterForMarshalType(mt, null);
+ arg_exc.ToJS(ex);
}
-
- return new string(result);
}
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
public static void StopProfile()
{
}
// Called by the AOT profiler to save profile data into INTERNAL.aot_profile_data
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ [MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
public static unsafe void DumpAotProfileData(ref byte buf, int len, string extraArg)
{
if (len == 0)
module.SetProperty("aot_profile_data", span.ToArray());
}
}
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- internal static JSObject CreateCSOwnedProxy(IntPtr jsHandle)
- {
- CreateCSOwnedProxyRef(jsHandle, JSHostImplementation.MappedType.JSObject, 0, out JSObject? res);
- return res;
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static IntPtr CreateTaskCallback()
- {
- JSHostImplementation.TaskCallback holder = new JSHostImplementation.TaskCallback();
- return GetJSOwnedObjectGCHandleRef(holder);
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void CallDelegate(JSMarshalerArgument* arguments_buffer)
- {
- ref JSMarshalerArgument arg_return = ref arguments_buffer[1];
- GCHandle callback_gc_handle = (GCHandle)arg_return.slot.GCHandle;
-
- JSHostImplementation.ToManagedCallback? cb = (JSHostImplementation.ToManagedCallback?)callback_gc_handle.Target;
- if (cb == null)
- throw new InvalidOperationException("ToManagedCallback is null");
-
- cb(arguments_buffer);
- }
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
- public static void CompleteTask(JSMarshalerArgument* arguments_buffer)
- {
- ref JSMarshalerArgument arg_return = ref arguments_buffer[1];
- GCHandle callback_gc_handle = (GCHandle)arg_return.slot.GCHandle;
-
- JSHostImplementation.TaskCallback? holder = (JSHostImplementation.TaskCallback?)callback_gc_handle.Target;
- if (holder == null || holder.Callback == null)
- throw new InvalidOperationException("TaskCallback is null");
-
- holder.Callback(arguments_buffer);
- }
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+namespace System.Runtime.InteropServices.JavaScript
+{
+ // this maps to src\mono\wasm\runtime\legacy\corebindings.ts
+ // the methods are protected from trimming by DynamicDependency on JSFunctionBinding.BindJSFunction
+ internal static unsafe partial class LegacyExports
+ {
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void GetCSOwnedObjectByJSHandleRef(IntPtr jsHandle, int shouldAddInflight, out JSObject? result)
+ {
+ lock (JSHostImplementation.s_csOwnedObjects)
+ {
+ if (JSHostImplementation.s_csOwnedObjects.TryGetValue((int)jsHandle, out WeakReference<JSObject>? reference))
+ {
+ reference.TryGetTarget(out JSObject? jsObject);
+ if (shouldAddInflight != 0)
+ {
+ jsObject?.AddInFlight();
+ }
+ result = jsObject;
+ return;
+ }
+ }
+ result = null;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static IntPtr GetCSOwnedObjectJSHandleRef(in JSObject jsObject, int shouldAddInflight)
+ {
+ jsObject.AssertNotDisposed();
+
+ if (shouldAddInflight != 0)
+ {
+ jsObject.AddInFlight();
+ }
+ return jsObject.JSHandle;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static IntPtr TryGetCSOwnedObjectJSHandleRef(in object rawObj, int shouldAddInflight)
+ {
+ JSObject? jsObject = rawObj as JSObject;
+ if (jsObject != null && shouldAddInflight != 0)
+ {
+ jsObject.AddInFlight();
+ }
+ return jsObject?.JSHandle ?? IntPtr.Zero;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void CreateCSOwnedProxyRef(IntPtr jsHandle, JSHostImplementation.MappedType mappedType, int shouldAddInflight, out JSObject jsObject)
+ {
+ JSObject? res = null;
+
+ lock (JSHostImplementation.s_csOwnedObjects)
+ {
+ if (!JSHostImplementation.s_csOwnedObjects.TryGetValue((int)jsHandle, out WeakReference<JSObject>? reference) ||
+ !reference.TryGetTarget(out res) ||
+ res.IsDisposed)
+ {
+#pragma warning disable CS0612 // Type or member is obsolete
+ res = mappedType switch
+ {
+ JSHostImplementation.MappedType.JSObject => new JSObject(jsHandle),
+ JSHostImplementation.MappedType.Array => new Array(jsHandle),
+ JSHostImplementation.MappedType.ArrayBuffer => new ArrayBuffer(jsHandle),
+ JSHostImplementation.MappedType.DataView => new DataView(jsHandle),
+ JSHostImplementation.MappedType.Function => new Function(jsHandle),
+ JSHostImplementation.MappedType.Uint8Array => new Uint8Array(jsHandle),
+ _ => throw new ArgumentOutOfRangeException(nameof(mappedType))
+ };
+#pragma warning restore CS0612 // Type or member is obsolete
+ JSHostImplementation.s_csOwnedObjects[(int)jsHandle] = new WeakReference<JSObject>(res, trackResurrection: true);
+ }
+ }
+ if (shouldAddInflight != 0)
+ {
+ res.AddInFlight();
+ }
+ jsObject = res;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void GetJSOwnedObjectByGCHandleRef(int gcHandle, out object result)
+ {
+ GCHandle h = (GCHandle)(IntPtr)gcHandle;
+ result = h.Target!;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static IntPtr GetJSOwnedObjectGCHandleRef(in object obj)
+ {
+ return JSHostImplementation.GetJSOwnedObjectGCHandle(obj, GCHandleType.Normal);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static IntPtr CreateTaskSource()
+ {
+ var tcs = new TaskCompletionSource<object>();
+ return GetJSOwnedObjectGCHandleRef(tcs);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void SetTaskSourceResultRef(int tcsGCHandle, in object result)
+ {
+ GCHandle handle = (GCHandle)(IntPtr)tcsGCHandle;
+ // this is JS owned Normal handle. We always have a Target
+ TaskCompletionSource<object> tcs = (TaskCompletionSource<object>)handle.Target!;
+ tcs.SetResult(result);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void SetTaskSourceFailure(int tcsGCHandle, string reason)
+ {
+ GCHandle handle = (GCHandle)(IntPtr)tcsGCHandle;
+ // this is JS owned Normal handle. We always have a Target
+ TaskCompletionSource<object> tcs = (TaskCompletionSource<object>)handle.Target!;
+ tcs.SetException(new JSException(reason));
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void GetTaskSourceTaskRef(int tcsGCHandle, out object result)
+ {
+ GCHandle handle = (GCHandle)(IntPtr)tcsGCHandle;
+ // this is JS owned Normal handle. We always have a Target
+ TaskCompletionSource<object> tcs = (TaskCompletionSource<object>)handle.Target!;
+ result = tcs.Task;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void SetupJSContinuationRef(in Task _task, JSObject continuationObj)
+ {
+ // HACK: Attempting to use the in-param will produce CS1628, so we make a temporary copy
+ // on the stack that can be captured by our local functions below
+ var task = _task;
+
+ if (task.IsCompleted)
+ Complete();
+ else
+ task.GetAwaiter().OnCompleted(Complete);
+
+ void Complete()
+ {
+ try
+ {
+ if (task.Exception == null)
+ {
+ object? result;
+ Type task_type = task.GetType();
+ if (task_type == typeof(Task))
+ {
+ result = System.Array.Empty<object>();
+ }
+ else
+ {
+ result = JSHostImplementation.GetTaskResultMethodInfo(task_type)?.Invoke(task, null);
+ }
+
+ continuationObj.Invoke("resolve", result);
+ }
+ else
+ {
+ continuationObj.Invoke("reject", task.Exception.ToString());
+ }
+ }
+ catch (Exception e)
+ {
+ continuationObj.Invoke("reject", e.ToString());
+ }
+ finally
+ {
+ continuationObj.Dispose();
+ }
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static string ObjectToStringRef(ref object o)
+ {
+ return o.ToString() ?? string.Empty;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static double GetDateValueRef(ref object dtv)
+ {
+ ArgumentNullException.ThrowIfNull(dtv);
+
+ if (!(dtv is DateTime dt))
+ throw new InvalidCastException(SR.Format(SR.UnableCastObjectToType, dtv.GetType(), typeof(DateTime)));
+ if (dt.Kind == DateTimeKind.Local)
+ dt = dt.ToUniversalTime();
+ else if (dt.Kind == DateTimeKind.Unspecified)
+ dt = new DateTime(dt.Ticks, DateTimeKind.Utc);
+ return new DateTimeOffset(dt).ToUnixTimeMilliseconds();
+ }
+
+ // HACK: We need to implicitly box by using an 'object' out-param.
+ // Note that the return value would have been boxed on the C#->JS transition anyway.
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void CreateDateTimeRef(double ticks, out object result)
+ {
+ DateTimeOffset unixTime = DateTimeOffset.FromUnixTimeMilliseconds((long)ticks);
+ result = unixTime.DateTime;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static void CreateUriRef(string uri, out object? result)
+ {
+ // we do this via reflection to allow linker to trim dependency on URI and it's assembly
+ // if the user code has methods with Uri signature, this should work too
+ // System.Private.Uri is large assembly so it's worth trimming
+ var uriType = Type.GetType("System.Uri, System.Private.Uri");
+ if (uriType == null) throw new InvalidProgramException();
+ result = Activator.CreateInstance(uriType, uri);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static bool IsSimpleArrayRef(ref object a)
+ {
+ return a is System.Array arr && arr.Rank == 1 && arr.GetLowerBound(0) == 0;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
+ public static string GetCallSignatureRef(IntPtr _methodHandle, in object objForRuntimeType)
+ {
+ var methodHandle = JSHostImplementation.GetMethodHandleFromIntPtr(_methodHandle);
+
+ MethodBase? mb = objForRuntimeType is null ? MethodBase.GetMethodFromHandle(methodHandle) : MethodBase.GetMethodFromHandle(methodHandle, Type.GetTypeHandle(objForRuntimeType));
+ if (mb is null)
+ return string.Empty;
+
+ ParameterInfo[] parms = mb.GetParameters();
+ int parmsLength = parms.Length;
+ if (parmsLength == 0)
+ return string.Empty;
+
+ var result = new char[parmsLength];
+ for (int i = 0; i < parmsLength; i++)
+ {
+ Type t = parms[i].ParameterType;
+ var mt = JSHostImplementation.GetMarshalTypeFromType(t);
+ result[i] = JSHostImplementation.GetCallSignatureCharacterForMarshalType(mt, null);
+ }
+
+ return new string(result);
+ }
+ }
+}
/// </summary>
// JavaScriptExports need to be protected from trimming because they are used from C/JS code which IL linker can't see
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, "System.Runtime.InteropServices.JavaScript.JavaScriptExports", "System.Runtime.InteropServices.JavaScript")]
+ // TODO make this DynamicDependency conditional
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, "System.Runtime.InteropServices.JavaScript.LegacyExports", "System.Runtime.InteropServices.JavaScript")]
public static JSFunctionBinding BindJSFunction(string functionName, string moduleName, ReadOnlySpan<JSMarshalerType> signatures)
{
if (RuntimeInformation.OSArchitecture != Architecture.Wasm)
if (isException != 0)
throw new JSException((string)exceptionMessage);
- signature.JSFunction = JavaScriptExports.CreateCSOwnedProxy(jsFunctionHandle);
+ signature.JSFunction = JSHostImplementation.CreateCSOwnedProxy(jsFunctionHandle);
return signature;
}
// strong references, allowing the managed object to be collected.
// This ensures that things like delegates and promises will never 'go away' while JS
// is expecting to be able to invoke or await them.
- public static IntPtr GetJSOwnedObjectGCHandleRef(object obj, GCHandleType handleType)
+ public static IntPtr GetJSOwnedObjectGCHandle(object obj, GCHandleType handleType = GCHandleType.Normal)
{
if (obj == null)
return IntPtr.Zero;
return MarshalType.DELEGATE;
else if ((type == typeof(Task)) || typeof(Task).IsAssignableFrom(type))
return MarshalType.TASK;
+ else if (type.FullName == "System.Uri")
+ return MarshalType.URI;
else if (type.IsPointer)
return MarshalType.POINTER;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static void ThrowException(ref JSMarshalerArgument arg)
+ public static void ThrowException(ref JSMarshalerArgument arg)
{
arg.ToManaged(out Exception? ex);
return await wrappedTask.ConfigureAwait(true);
}
- private static async Task<JSObject> CancelationHelper(Task<JSObject> jsTask, CancellationToken cancellationToken)
+ public static async Task<JSObject> CancelationHelper(Task<JSObject> jsTask, CancellationToken cancellationToken)
{
if (jsTask.IsCompletedSuccessfully)
{
}
// res type is first argument
- internal static unsafe JSFunctionBinding GetMethodSignature(ReadOnlySpan<JSMarshalerType> types)
+ public static unsafe JSFunctionBinding GetMethodSignature(ReadOnlySpan<JSMarshalerType> types)
{
int argsCount = types.Length - 1;
int size = JSFunctionBinding.JSBindingHeader.JSMarshalerSignatureHeaderSize + ((argsCount + 2) * sizeof(JSFunctionBinding.JSBindingType));
return signature;
}
+
+ public static JSObject CreateCSOwnedProxy(IntPtr jsHandle)
+ {
+ JSObject? res = null;
+
+ lock (s_csOwnedObjects)
+ {
+ if (!s_csOwnedObjects.TryGetValue((int)jsHandle, out WeakReference<JSObject>? reference) ||
+ !reference.TryGetTarget(out res) ||
+ res.IsDisposed)
+ {
+ res = new JSObject(jsHandle);
+ s_csOwnedObjects[(int)jsHandle] = new WeakReference<JSObject>(res, trackResurrection: true);
+ }
+ }
+ return res;
+ }
}
}
public static class Runtime
{
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, "System.Runtime.InteropServices.JavaScript.JavaScriptExports", "System.Runtime.InteropServices.JavaScript")]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, "System.Runtime.InteropServices.JavaScript.LegacyExports", "System.Runtime.InteropServices.JavaScript")]
public static object GetGlobalObject(string str)
=> JavaScriptImports.GetGlobalObject(str);
return;
}
slot.Type = MarshalerType.ArraySegment;
- slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandleRef(value.Array, GCHandleType.Pinned);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(value.Array, GCHandleType.Pinned);
var refPtr = (IntPtr)Unsafe.AsPointer(ref MemoryMarshal.GetArrayDataReference(value.Array));
slot.IntPtrValue = refPtr + value.Offset;
slot.Length = value.Count;
return;
}
slot.Type = MarshalerType.ArraySegment;
- slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandleRef(value.Array, GCHandleType.Pinned);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(value.Array, GCHandleType.Pinned);
var refPtr = (IntPtr)Unsafe.AsPointer(ref MemoryMarshal.GetArrayDataReference(value.Array));
slot.IntPtrValue = refPtr + (value.Offset * sizeof(double));
slot.Length = value.Count;
if (slot.JSHandle != IntPtr.Zero)
{
// this is JSException round-trip
- jsException = JavaScriptExports.CreateCSOwnedProxy(slot.JSHandle);
+ jsException = JSHostImplementation.CreateCSOwnedProxy(slot.JSHandle);
}
string? message;
{
ToJS(cpy.Message);
slot.Type = MarshalerType.Exception;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cpy);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cpy);
}
}
}
public ActionJS(IntPtr jsHandle)
{
- JSObject = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
}
public void InvokeJS()
public ActionJS(IntPtr jsHandle, ArgumentToJSCallback<T> arg1Marshaler)
{
- JSObject = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
Arg1Marshaler = arg1Marshaler;
}
public ActionJS(IntPtr jsHandle, ArgumentToJSCallback<T1> arg1Marshaler, ArgumentToJSCallback<T2> arg2Marshaler)
{
- JSObject = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
Arg1Marshaler = arg1Marshaler;
Arg2Marshaler = arg2Marshaler;
}
public ActionJS(IntPtr jsHandle, ArgumentToJSCallback<T1> arg1Marshaler, ArgumentToJSCallback<T2> arg2Marshaler, ArgumentToJSCallback<T3> arg3Marshaler)
{
- JSObject = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
Arg1Marshaler = arg1Marshaler;
Arg2Marshaler = arg2Marshaler;
Arg3Marshaler = arg3Marshaler;
public FuncJS(IntPtr jsHandle, ArgumentToManagedCallback<TResult> resMarshaler)
{
- JSObject = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
ResMarshaler = resMarshaler;
}
public FuncJS(IntPtr jsHandle, ArgumentToJSCallback<T> arg1Marshaler, ArgumentToManagedCallback<TResult> resMarshaler)
{
- JSObject = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
Arg1Marshaler = arg1Marshaler;
ResMarshaler = resMarshaler;
}
public FuncJS(IntPtr jsHandle, ArgumentToJSCallback<T1> arg1Marshaler, ArgumentToJSCallback<T2> arg2Marshaler, ArgumentToManagedCallback<TResult> resMarshaler)
{
- JSObject = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
Arg1Marshaler = arg1Marshaler;
Arg2Marshaler = arg2Marshaler;
ResMarshaler = resMarshaler;
public FuncJS(IntPtr jsHandle, ArgumentToJSCallback<T1> arg1Marshaler, ArgumentToJSCallback<T2> arg2Marshaler, ArgumentToJSCallback<T3> arg3Marshaler, ArgumentToManagedCallback<TResult> resMarshaler)
{
- JSObject = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
Arg1Marshaler = arg1Marshaler;
Arg2Marshaler = arg2Marshaler;
Arg3Marshaler = arg3Marshaler;
// TODO: we could try to cache value -> existing GCHandle
JSHostImplementation.ToManagedCallback cb = (JSMarshalerArgument* arguments) =>
{
- ref JSMarshalerArgument exc = ref arguments[0];
- try
- {
- cpy.Invoke();
- }
- catch (Exception ex)
- {
- exc.ToJS(ex);
- }
+ cpy.Invoke();
+ // eventual exception is handled by C# caller
};
slot.Type = MarshalerType.Function;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cb);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cb);
}
/// <summary>
Action<T> cpy = value;
JSHostImplementation.ToManagedCallback cb = (JSMarshalerArgument* arguments) =>
{
- ref JSMarshalerArgument exc = ref arguments[0];
- ref JSMarshalerArgument arg1 = ref arguments[2];
- try
- {
- arg1Marshaler(ref arg1, out T arg1cs);
- cpy.Invoke(arg1cs);
- }
- catch (Exception ex)
- {
- exc.ToJS(ex);
- }
+ ref JSMarshalerArgument arg2 = ref arguments[3]; // set by JS caller
+ arg1Marshaler(ref arg2, out T arg1cs);
+ cpy.Invoke(arg1cs);
+ // eventual exception is handled by C# caller
};
slot.Type = MarshalerType.Action;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cb);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cb);
}
/// <summary>
Action<T1, T2> cpy = value;
JSHostImplementation.ToManagedCallback cb = (JSMarshalerArgument* arguments) =>
{
- ref JSMarshalerArgument exc = ref arguments[0];
- ref JSMarshalerArgument arg1 = ref arguments[2];
- ref JSMarshalerArgument arg2 = ref arguments[3];
- try
- {
- arg1Marshaler(ref arg1, out T1 arg1cs);
- arg2Marshaler(ref arg2, out T2 arg2cs);
- cpy.Invoke(arg1cs, arg2cs);
- }
- catch (Exception ex)
- {
- exc.ToJS(ex);
- }
+ ref JSMarshalerArgument arg2 = ref arguments[3];// set by JS caller
+ ref JSMarshalerArgument arg3 = ref arguments[4];// set by JS caller
+ arg1Marshaler(ref arg2, out T1 arg1cs);
+ arg2Marshaler(ref arg3, out T2 arg2cs);
+ cpy.Invoke(arg1cs, arg2cs);
+ // eventual exception is handled by C# caller
};
slot.Type = MarshalerType.Action;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cb);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cb);
}
/// <summary>
Action<T1, T2, T3> cpy = value;
JSHostImplementation.ToManagedCallback cb = (JSMarshalerArgument* arguments) =>
{
- ref JSMarshalerArgument exc = ref arguments[0];
- ref JSMarshalerArgument arg1 = ref arguments[2];
- ref JSMarshalerArgument arg2 = ref arguments[3];
- ref JSMarshalerArgument arg3 = ref arguments[4];
- try
- {
- arg1Marshaler(ref arg1, out T1 arg1cs);
- arg2Marshaler(ref arg2, out T2 arg2cs);
- arg3Marshaler(ref arg3, out T3 arg3cs);
- cpy.Invoke(arg1cs, arg2cs, arg3cs);
- }
- catch (Exception ex)
- {
- exc.ToJS(ex);
- }
+ ref JSMarshalerArgument arg2 = ref arguments[3];// set by JS caller
+ ref JSMarshalerArgument arg3 = ref arguments[4];// set by JS caller
+ ref JSMarshalerArgument arg4 = ref arguments[5];// set by JS caller
+ arg1Marshaler(ref arg2, out T1 arg1cs);
+ arg2Marshaler(ref arg3, out T2 arg2cs);
+ arg3Marshaler(ref arg4, out T3 arg3cs);
+ cpy.Invoke(arg1cs, arg2cs, arg3cs);
+ // eventual exception is handled by C# caller
};
slot.Type = MarshalerType.Action;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cb);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cb);
}
/// <summary>
Func<TResult> cpy = value;
JSHostImplementation.ToManagedCallback cb = (JSMarshalerArgument* arguments) =>
{
- ref JSMarshalerArgument exc = ref arguments[0];
ref JSMarshalerArgument res = ref arguments[1];
- try
- {
- TResult resCs = cpy.Invoke();
- resMarshaler(ref res, resCs);
- }
- catch (Exception ex)
- {
- exc.ToJS(ex);
- }
+ TResult resCs = cpy.Invoke();
+ resMarshaler(ref res, resCs);
+ // eventual exception is handled by C# caller
};
slot.Type = MarshalerType.Function;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cb);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cb);
}
/// <summary>
Func<T, TResult> cpy = value;
JSHostImplementation.ToManagedCallback cb = (JSMarshalerArgument* arguments) =>
{
- ref JSMarshalerArgument exc = ref arguments[0];
ref JSMarshalerArgument res = ref arguments[1];
- ref JSMarshalerArgument arg1 = ref arguments[2];
- try
- {
- arg1Marshaler(ref arg1, out T arg1cs);
- TResult resCs = cpy.Invoke(arg1cs);
- resMarshaler(ref res, resCs);
- }
- catch (Exception ex)
- {
- exc.ToJS(ex);
- }
+ ref JSMarshalerArgument arg2 = ref arguments[3];// set by JS caller
+ arg1Marshaler(ref arg2, out T arg1cs);
+ TResult resCs = cpy.Invoke(arg1cs);
+ resMarshaler(ref res, resCs);
+ // eventual exception is handled by C# caller
};
slot.Type = MarshalerType.Function;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cb);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cb);
}
/// <summary>
Func<T1, T2, TResult> cpy = value;
JSHostImplementation.ToManagedCallback cb = (JSMarshalerArgument* arguments) =>
{
- ref JSMarshalerArgument exc = ref arguments[0];
ref JSMarshalerArgument res = ref arguments[1];
- ref JSMarshalerArgument arg1 = ref arguments[2];
- ref JSMarshalerArgument arg2 = ref arguments[3];
- try
- {
- arg1Marshaler(ref arg1, out T1 arg1cs);
- arg2Marshaler(ref arg2, out T2 arg2cs);
- TResult resCs = cpy.Invoke(arg1cs, arg2cs);
- resMarshaler(ref res, resCs);
- }
- catch (Exception ex)
- {
- exc.ToJS(ex);
- }
+ ref JSMarshalerArgument arg2 = ref arguments[3];// set by JS caller
+ ref JSMarshalerArgument arg3 = ref arguments[4];// set by JS caller
+ arg1Marshaler(ref arg2, out T1 arg1cs);
+ arg2Marshaler(ref arg3, out T2 arg2cs);
+ TResult resCs = cpy.Invoke(arg1cs, arg2cs);
+ resMarshaler(ref res, resCs);
+ // eventual exception is handled by C# caller
};
-
-
slot.Type = MarshalerType.Function;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cb);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cb);
}
/// <summary>
Func<T1, T2, T3, TResult> cpy = value;
JSHostImplementation.ToManagedCallback cb = (JSMarshalerArgument* arguments) =>
{
- ref JSMarshalerArgument exc = ref arguments[0];
ref JSMarshalerArgument res = ref arguments[1];
- ref JSMarshalerArgument arg1 = ref arguments[2];
- ref JSMarshalerArgument arg2 = ref arguments[3];
- ref JSMarshalerArgument arg3 = ref arguments[4];
- try
- {
- arg1Marshaler(ref arg1, out T1 arg1cs);
- arg2Marshaler(ref arg2, out T2 arg2cs);
- arg3Marshaler(ref arg3, out T3 arg3cs);
- TResult resCs = cpy.Invoke(arg1cs, arg2cs, arg3cs);
- resMarshaler(ref res, resCs);
- }
- catch (Exception ex)
- {
- exc.ToJS(ex);
- }
+ ref JSMarshalerArgument arg2 = ref arguments[3];// set by JS caller
+ ref JSMarshalerArgument arg3 = ref arguments[4];// set by JS caller
+ ref JSMarshalerArgument arg4 = ref arguments[5];// set by JS caller
+ arg1Marshaler(ref arg2, out T1 arg1cs);
+ arg2Marshaler(ref arg3, out T2 arg2cs);
+ arg3Marshaler(ref arg4, out T3 arg3cs);
+ TResult resCs = cpy.Invoke(arg1cs, arg2cs, arg3cs);
+ resMarshaler(ref res, resCs);
+ // eventual exception is handled by C# caller
};
-
-
slot.Type = MarshalerType.Function;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(cb);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(cb);
}
}
}
return;
}
slot.Type = MarshalerType.ArraySegment;
- slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandleRef(value.Array, GCHandleType.Pinned);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(value.Array, GCHandleType.Pinned);
var refPtr = (IntPtr)Unsafe.AsPointer(ref MemoryMarshal.GetArrayDataReference(value.Array));
slot.IntPtrValue = refPtr + (value.Offset * sizeof(int));
slot.Length = value.Count;
value = null;
return;
}
- value = JavaScriptExports.CreateCSOwnedProxy(slot.JSHandle);
+ value = JSHostImplementation.CreateCSOwnedProxy(slot.JSHandle);
}
/// <summary>
else
{
slot.Type = MarshalerType.Object;
- slot.GCHandle = JavaScriptExports.GetJSOwnedObjectGCHandleRef(value);
+ slot.GCHandle = JSHostImplementation.GetJSOwnedObjectGCHandle(value);
}
}
TaskCompletionSource tcs = new TaskCompletionSource(gcHandle);
JSHostImplementation.ToManagedCallback callback = (JSMarshalerArgument* arguments_buffer) =>
{
- ref JSMarshalerArgument arg_exception = ref arguments_buffer[0];
- try
+ ref JSMarshalerArgument arg_2 = ref arguments_buffer[3]; // set by caller when this is SetException call
+ // arg_3 set by caller when this is SetResult call, un-used here
+ if (arg_2.slot.Type != MarshalerType.None)
{
- if (arg_exception.slot.Type != MarshalerType.None)
- {
- arg_exception.ToManaged(out Exception? fail);
- tcs.SetException(fail!);
- }
- else
- {
- tcs.SetResult();
- }
- arg_exception.slot.Type = MarshalerType.None;
+ arg_2.ToManaged(out Exception? fail);
+ tcs.SetException(fail!);
}
- catch (Exception ex)
+ else
{
- arg_exception.ToJS(ex);
+ tcs.SetResult();
}
+ // eventual exception is handled by caller
};
holder.Callback = callback;
value = tcs.Task;
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>(gcHandle);
JSHostImplementation.ToManagedCallback callback = (JSMarshalerArgument* arguments_buffer) =>
{
- ref JSMarshalerArgument arg_exception = ref arguments_buffer[0];
- ref JSMarshalerArgument arg1 = ref arguments_buffer[2];
- try
+ ref JSMarshalerArgument arg_2 = ref arguments_buffer[3]; // set by caller when this is SetException call
+ ref JSMarshalerArgument arg_3 = ref arguments_buffer[4]; // set by caller when this is SetResult call
+ if (arg_2.slot.Type != MarshalerType.None)
{
- if (arg_exception.slot.Type != MarshalerType.None)
- {
- arg_exception.ToManaged(out Exception? fail);
- if (fail == null) throw new NullReferenceException("Exception");
- tcs.SetException(fail);
- }
- else
- {
- marshaler(ref arg1, out T result);
- tcs.SetResult(result);
- }
- arg_exception.slot.Type = MarshalerType.None;
+ arg_2.ToManaged(out Exception? fail);
+ if (fail == null) throw new NullReferenceException("Exception");
+ tcs.SetException(fail);
}
- catch (Exception ex)
+ else
{
- arg_exception.ToJS(ex);
+ marshaler(ref arg_3, out T result);
+ tcs.SetResult(result);
}
+ // eventual exception is handled by caller
};
holder.Callback = callback;
value = tcs.Task;
IntPtr jsHandle = CreatePendingPromise();
slot.JSHandle = jsHandle;
- JSObject promise = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject promise = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
task.GetAwaiter().OnCompleted(Complete);
IntPtr jsHandle = CreatePendingPromise();
slot.JSHandle = jsHandle;
- JSObject promise = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject promise = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
task.GetAwaiter().OnCompleted(Complete);
IntPtr jsHandle = CreatePendingPromise();
slot.JSHandle = jsHandle;
- JSObject promise = JavaScriptExports.CreateCSOwnedProxy(jsHandle);
+ JSObject promise = JSHostImplementation.CreateCSOwnedProxy(jsHandle);
task.GetAwaiter().OnCompleted(Complete);
[Fact]
public unsafe void CreateFunctionInternal()
{
- Func<string> internals = Utils.CreateFunctionString("return INTERNAL.BINDING_ASM");
- Assert.Equal("[System.Runtime.InteropServices.JavaScript]System.Runtime.InteropServices.JavaScript.JavaScriptExports", internals());
+ Func<bool> internals = Utils.CreateFunctionBool("return INTERNAL.mono_wasm_runtime_is_ready");
+ Assert.True(internals());
}
#endregion
{
if (_module == null)
{
- Log("JavaScriptTestHelper.mjs importing");
+ // Log("JavaScriptTestHelper.mjs importing");
_module = await JSHost.ImportAsync("JavaScriptTestHelper", "./JavaScriptTestHelper.mjs");
- Log("JavaScriptTestHelper.mjs imported");
+ // Log("JavaScriptTestHelper.mjs imported");
}
}
}
3. Call the `write_at` method at the end of the app, either in C# or in JS. To call the `write_at` method in JS, make use of bindings:
-`INTERNAL.call_static_method("<[ProjectName] Namespace.Class::StopProfile">, []);`
+`BINDING.bind_static_method("<[ProjectName] Namespace.Class::StopProfile">)();`
When the `write_at` method is called, the `send_to` method `DumpAotProfileData` stores the profile data into `INTERNAL.aot_profile_data`
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-import { JSHandle, MonoArray, MonoObject, MonoObjectRef, is_nullish } from "./types";
-import { Module } from "./imports";
-import { mono_wasm_get_jsobj_from_js_handle } from "./gc-handles";
-import { wrap_error_root } from "./method-calls";
-import { js_to_mono_obj_root } from "./js-to-cs";
-import { Int32Ptr, TypedArray, VoidPtr } from "./types/emscripten";
-import { mono_wasm_new_external_root } from "./roots";
-
-// Creates a new typed array from pinned array address from pinned_array allocated on the heap to the typed array.
-// address of managed pinned array -> copy from heap -> typed array memory
-function typed_array_from(pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number, type: number) {
-
- // typed array
- let newTypedArray: TypedArray | null = null;
-
- switch (type) {
- case 5:
- newTypedArray = new Int8Array(end - begin);
- break;
- case 6:
- newTypedArray = new Uint8Array(end - begin);
- break;
- case 7:
- newTypedArray = new Int16Array(end - begin);
- break;
- case 8:
- newTypedArray = new Uint16Array(end - begin);
- break;
- case 9:
- newTypedArray = new Int32Array(end - begin);
- break;
- case 10:
- newTypedArray = new Uint32Array(end - begin);
- break;
- case 13:
- newTypedArray = new Float32Array(end - begin);
- break;
- case 14:
- newTypedArray = new Float64Array(end - begin);
- break;
- case 15: // This is a special case because the typed array is also byte[]
- newTypedArray = new Uint8ClampedArray(end - begin);
- break;
- default:
- throw new Error("Unknown array type " + type);
- }
-
- typedarray_copy_from(newTypedArray, pinned_array, begin, end, bytes_per_element);
- return newTypedArray;
-}
-
-// Copy the existing typed array to the heap pointed to by the pinned array address
-// typed array memory -> copy to heap -> address of managed pinned array
-function typedarray_copy_to(typed_array: TypedArray, pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number) {
-
- // JavaScript typed arrays are array-like objects and provide a mechanism for accessing
- // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays
- // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
- // is an object representing a chunk of data; it has no format to speak of, and offers no
- // mechanism for accessing its contents. In order to access the memory contained in a buffer,
- // you need to use a view. A view provides a context - that is, a data type, starting offset,
- // and number of elements - that turns the data into an actual typed array.
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
- if (has_backing_array_buffer(typed_array) && typed_array.BYTES_PER_ELEMENT) {
- // Some sanity checks of what is being asked of us
- // lets play it safe and throw an error here instead of assuming to much.
- // Better safe than sorry later
- if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
- throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
-
- // how much space we have to work with
- let num_of_bytes = (end - begin) * bytes_per_element;
- // how much typed buffer space are we talking about
- const view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
- // only use what is needed.
- if (num_of_bytes > view_bytes)
- num_of_bytes = view_bytes;
-
- // offset index into the view
- const offset = begin * bytes_per_element;
-
- // Create a view over the heap pointed to by the pinned array address
- const heapBytes = new Uint8Array(Module.HEAPU8.buffer, <any>pinned_array + offset, num_of_bytes);
- // Copy the bytes of the typed array to the heap.
- heapBytes.set(new Uint8Array(typed_array.buffer, typed_array.byteOffset, num_of_bytes));
-
- return num_of_bytes;
- }
- else {
- throw new Error("Object '" + typed_array + "' is not a typed array");
- }
-
-}
-
-// Copy the pinned array address from pinned_array allocated on the heap to the typed array.
-// address of managed pinned array -> copy from heap -> typed array memory
-function typedarray_copy_from(typed_array: TypedArray, pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number) {
-
- // JavaScript typed arrays are array-like objects and provide a mechanism for accessing
- // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays
- // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
- // is an object representing a chunk of data; it has no format to speak of, and offers no
- // mechanism for accessing its contents. In order to access the memory contained in a buffer,
- // you need to use a view. A view provides a context - that is, a data type, starting offset,
- // and number of elements - that turns the data into an actual typed array.
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
- if (has_backing_array_buffer(typed_array) && typed_array.BYTES_PER_ELEMENT) {
- // Some sanity checks of what is being asked of us
- // lets play it safe and throw an error here instead of assuming to much.
- // Better safe than sorry later
- if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
- throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
-
- // how much space we have to work with
- let num_of_bytes = (end - begin) * bytes_per_element;
- // how much typed buffer space are we talking about
- const view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
- // only use what is needed.
- if (num_of_bytes > view_bytes)
- num_of_bytes = view_bytes;
-
- // Create a new view for mapping
- const typedarrayBytes = new Uint8Array(typed_array.buffer, 0, num_of_bytes);
- // offset index into the view
- const offset = begin * bytes_per_element;
- // Set view bytes to value from HEAPU8
- typedarrayBytes.set(Module.HEAPU8.subarray(<any>pinned_array + offset, <any>pinned_array + offset + num_of_bytes));
- return num_of_bytes;
- }
- else {
- throw new Error("Object '" + typed_array + "' is not a typed array");
- }
-}
-
-export function mono_wasm_typed_array_copy_to_ref(js_handle: JSHandle, pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number, is_exception: Int32Ptr, result_address: MonoObjectRef): void {
- const resultRoot = mono_wasm_new_external_root<MonoObject>(result_address);
- try {
- const js_obj = mono_wasm_get_jsobj_from_js_handle(js_handle);
- if (is_nullish(js_obj)) {
- wrap_error_root(is_exception, "ERR07: Invalid JS object handle '" + js_handle + "'", resultRoot);
- return;
- }
-
- const res = typedarray_copy_to(js_obj, pinned_array, begin, end, bytes_per_element);
- // FIXME: We should just return an int
- // returns num_of_bytes boxed
- js_to_mono_obj_root(res, resultRoot, false);
- } catch (exc) {
- wrap_error_root(is_exception, String(exc), resultRoot);
- } finally {
- resultRoot.release();
- }
-}
-
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-export function mono_wasm_typed_array_from_ref(pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number, type: number, is_exception: Int32Ptr, result_address: MonoObjectRef): void {
- const resultRoot = mono_wasm_new_external_root<MonoObject>(result_address);
- try {
- const res = typed_array_from(pinned_array, begin, end, bytes_per_element, type);
- // returns JS typed array like Int8Array, to be wraped with JSObject proxy
- js_to_mono_obj_root(res, resultRoot, true);
- } catch (exc) {
- wrap_error_root(is_exception, String(exc), resultRoot);
- } finally {
- resultRoot.release();
- }
-}
-
-export function mono_wasm_typed_array_copy_from_ref(js_handle: JSHandle, pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number, is_exception: Int32Ptr, result_address: MonoObjectRef): void {
- const resultRoot = mono_wasm_new_external_root<MonoObject>(result_address);
- try {
- const js_obj = mono_wasm_get_jsobj_from_js_handle(js_handle);
- if (is_nullish(js_obj)) {
- wrap_error_root(is_exception, "ERR08: Invalid JS object handle '" + js_handle + "'", resultRoot);
- return;
- }
-
- const res = typedarray_copy_from(js_obj, pinned_array, begin, end, bytes_per_element);
- // FIXME: We should just return an int
- // returns num_of_bytes boxed
- js_to_mono_obj_root(res, resultRoot, false);
- } catch (exc) {
- wrap_error_root(is_exception, String(exc), resultRoot);
- } finally {
- resultRoot.release();
- }
-}
-
-export function has_backing_array_buffer(js_obj: TypedArray): boolean {
- return typeof SharedArrayBuffer !== "undefined"
- ? js_obj.buffer instanceof ArrayBuffer || js_obj.buffer instanceof SharedArrayBuffer
- : js_obj.buffer instanceof ArrayBuffer;
-}
-
-// @bytes must be a typed array. space is allocated for it in the native heap
-// and it is copied to that location. returns the address of the allocation.
-export function mono_wasm_load_bytes_into_heap(bytes: Uint8Array): VoidPtr {
- const memoryOffset = Module._malloc(bytes.length);
- const heapBytes = new Uint8Array(Module.HEAPU8.buffer, <any>memoryOffset, bytes.length);
- heapBytes.set(bytes);
- return memoryOffset;
-}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+/* eslint-disable no-undef */
+
+"use strict";
+
+#if USE_PTHREADS
+const usePThreads = `true`;
+const isPThread = `ENVIRONMENT_IS_PTHREAD`;
+#else
+const usePThreads = `false`;
+const isPThread = `false`;
+#endif
+
+const DotnetSupportLib = {
+ $DOTNET: {},
+ // these lines will be placed early on emscripten runtime creation, passing import and export objects into __dotnet_runtime IFFE
+ // we replace implementation of fetch
+ // replacement of require is there for consistency with ES6 code
+ $DOTNET__postset: `
+let __dotnet_replacement_PThread = ${usePThreads} ? {} : undefined;
+if (${usePThreads}) {
+ __dotnet_replacement_PThread.loadWasmModuleToWorker = PThread.loadWasmModuleToWorker;
+ __dotnet_replacement_PThread.threadInitTLS = PThread.threadInitTLS;
+}
+let __dotnet_replacements = {scriptUrl: undefined, fetch: globalThis.fetch, require, updateGlobalBufferAndViews, pthreadReplacements: __dotnet_replacement_PThread};
+if (ENVIRONMENT_IS_NODE) {
+ __dotnet_replacements.requirePromise = Promise.resolve(require);
+}
+let __dotnet_exportedAPI = __dotnet_runtime.__initializeImportsAndExports(
+ { isESM:false, isGlobal:ENVIRONMENT_IS_GLOBAL, isNode:ENVIRONMENT_IS_NODE, isWorker:ENVIRONMENT_IS_WORKER, isShell:ENVIRONMENT_IS_SHELL, isWeb:ENVIRONMENT_IS_WEB, isPThread:${isPThread}, quit_, ExitStatus, requirePromise:Promise.resolve(require)},
+ { mono:MONO, binding:BINDING, internal:INTERNAL, module:Module, marshaled_exports: EXPORTS, marshaled_imports: IMPORTS },
+ __dotnet_replacements);
+updateGlobalBufferAndViews = __dotnet_replacements.updateGlobalBufferAndViews;
+var fetch = __dotnet_replacements.fetch;
+_scriptDir = __dirname = scriptDirectory = __dotnet_replacements.scriptDirectory;
+if (ENVIRONMENT_IS_NODE) {
+ __dotnet_replacements.requirePromise.then(someRequire => {
+ require = someRequire;
+ });
+}
+var noExitRuntime = __dotnet_replacements.noExitRuntime;
+if (${usePThreads}) {
+ PThread.loadWasmModuleToWorker = __dotnet_replacements.pthreadReplacements.loadWasmModuleToWorker;
+ PThread.threadInitTLS = __dotnet_replacements.pthreadReplacements.threadInitTS;
+}
+`,
+};
+
+// the methods would be visible to EMCC linker
+// --- keep in sync with exports.ts ---
+const linked_functions = [
+ // mini-wasm.c
+ "mono_set_timeout",
+
+ // mini-wasm-debugger.c
+ "mono_wasm_asm_loaded",
+ "mono_wasm_fire_debugger_agent_message",
+ "mono_wasm_debugger_log",
+ "mono_wasm_add_dbg_command_received",
+
+ // mono-threads-wasm.c
+ "schedule_background_exec",
+
+ // driver.c
+ "mono_wasm_invoke_js_blazor",
+ "mono_wasm_trace_logger",
+ "mono_wasm_set_entrypoint_breakpoint",
+ "mono_wasm_event_pipe_early_startup_callback",
+
+ // 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_release_cs_owned_object",
+ "mono_wasm_typed_array_to_array_ref",
+ "mono_wasm_typed_array_from_ref",
+ "mono_wasm_compile_function_ref",
+ "mono_wasm_bind_js_function",
+ "mono_wasm_invoke_bound_function",
+ "mono_wasm_bind_cs_function",
+ "mono_wasm_marshal_promise",
+
+ // pal_icushim_static.c
+ "mono_wasm_load_icu_data",
+ "mono_wasm_get_icudt_name",
+
+ // pal_crypto_webworker.c
+ "dotnet_browser_can_use_subtle_crypto_impl",
+ "dotnet_browser_simple_digest_hash",
+ "dotnet_browser_sign",
+ "dotnet_browser_encrypt_decrypt",
+ "dotnet_browser_derive_bits",
+
+ #if USE_PTHREADS
+ /// mono-threads-wasm.c
+ "mono_wasm_pthread_on_pthread_attached",
+ /// 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
+];
+
+// -- 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) {
+ const fn_template = `return __dotnet_runtime.__linker_exports.${linked_function}.apply(__dotnet_runtime, arguments)`;
+ DotnetSupportLib[linked_function] = new Function(fn_template);
+}
+
+autoAddDeps(DotnetSupportLib, "$DOTNET");
+mergeInto(LibraryManager.library, DotnetSupportLib);
extern void mono_wasm_release_cs_owned_object (int js_handle);
extern void mono_wasm_create_cs_owned_object_ref (MonoString **core_name, MonoArray **args, int *is_exception, MonoObject** result);
extern void mono_wasm_typed_array_to_array_ref (int js_handle, int *is_exception, MonoObject **result);
-extern void mono_wasm_typed_array_copy_to_ref (int js_handle, int ptr, int begin, int end, int bytes_per_element, int *is_exception, MonoObject** result);
extern void mono_wasm_typed_array_from_ref (int ptr, int begin, int end, int bytes_per_element, int type, int *is_exception, MonoObject** result);
-extern void mono_wasm_typed_array_copy_from_ref (int js_handle, int ptr, int begin, int end, int bytes_per_element, int *is_exception, MonoObject** result);
extern void mono_wasm_bind_js_function(MonoString **function_name, MonoString **module_name, void *signature, int* function_js_handle, int *is_exception, MonoObject **result);
extern void mono_wasm_invoke_bound_function(int function_js_handle, void *data);
mono_add_internal_call ("Interop/Runtime::CreateCSOwnedObjectRef", mono_wasm_create_cs_owned_object_ref);
mono_add_internal_call ("Interop/Runtime::ReleaseCSOwnedObject", mono_wasm_release_cs_owned_object);
mono_add_internal_call ("Interop/Runtime::TypedArrayToArrayRef", mono_wasm_typed_array_to_array_ref);
- mono_add_internal_call ("Interop/Runtime::TypedArrayCopyToRef", mono_wasm_typed_array_copy_to_ref);
mono_add_internal_call ("Interop/Runtime::TypedArrayFromRef", mono_wasm_typed_array_from_ref);
- mono_add_internal_call ("Interop/Runtime::TypedArrayCopyFromRef", mono_wasm_typed_array_copy_from_ref);
mono_add_internal_call ("Interop/Runtime::BindJSFunction", mono_wasm_bind_js_function);
mono_add_internal_call ("Interop/Runtime::InvokeJSFunction", mono_wasm_invoke_bound_function);
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-import { JSHandle, GCHandle, MonoObjectRef } from "./types";
-import { PromiseController } from "./promise-controller";
-import { runtimeHelpers } from "./imports";
-
-// TODO replace all of this with [JSExport]
-const fn_signatures: [jsname: string, csname: string, signature: string/*ArgsMarshalString*/][] = [
- ["_get_cs_owned_object_by_js_handle_ref", "GetCSOwnedObjectByJSHandleRef", "iim"],
- ["_get_cs_owned_object_js_handle_ref", "GetCSOwnedObjectJSHandleRef", "mi"],
- ["_try_get_cs_owned_object_js_handle_ref", "TryGetCSOwnedObjectJSHandleRef", "mi"],
- ["_create_cs_owned_proxy_ref", "CreateCSOwnedProxyRef", "iiim"],
-
- ["_get_js_owned_object_by_gc_handle_ref", "GetJSOwnedObjectByGCHandleRef", "im"],
- ["_get_js_owned_object_gc_handle_ref", "GetJSOwnedObjectGCHandleRef", "m"],
- ["_release_js_owned_object_by_gc_handle", "ReleaseJSOwnedObjectByGCHandle", "i"],
-
- ["_create_tcs", "CreateTaskSource", ""],
- ["_create_task_callback", "CreateTaskCallback", ""],
- ["_set_tcs_result_ref", "SetTaskSourceResultRef", "iR"],
- ["_set_tcs_failure", "SetTaskSourceFailure", "is"],
- ["_get_tcs_task_ref", "GetTaskSourceTaskRef", "im"],
- ["_task_from_result_ref", "TaskFromResultRef", "Rm"],
- ["_setup_js_cont_ref", "SetupJSContinuationRef", "mo"],
-
- ["_object_to_string_ref", "ObjectToStringRef", "m"],
- ["_get_date_value_ref", "GetDateValueRef", "m"],
- ["_create_date_time_ref", "CreateDateTimeRef", "dm"],
- ["_create_uri_ref", "CreateUriRef", "sm"],
- ["_is_simple_array_ref", "IsSimpleArrayRef", "m"],
-];
-
-export interface t_CSwraps {
- // BINDING
- _get_cs_owned_object_by_js_handle_ref(jsHandle: JSHandle, shouldAddInflight: 0 | 1, result: MonoObjectRef): void;
- _get_cs_owned_object_js_handle_ref(obj: MonoObjectRef, shouldAddInflight: 0 | 1): JSHandle;
- _try_get_cs_owned_object_js_handle_ref(obj: MonoObjectRef, shouldAddInflight: 0 | 1): JSHandle;
- _create_cs_owned_proxy_ref(jsHandle: JSHandle, mappedType: number, shouldAddInflight: 0 | 1, result: MonoObjectRef): void;
-
- _get_js_owned_object_by_gc_handle_ref(gcHandle: GCHandle, result: MonoObjectRef): void;
- _get_js_owned_object_gc_handle_ref(obj: MonoObjectRef): GCHandle
- _release_js_owned_object_by_gc_handle(gcHandle: GCHandle): void;
-
- _create_tcs(): GCHandle;
- _set_tcs_result_ref(gcHandle: GCHandle, result: any): void
- _set_tcs_failure(gcHandle: GCHandle, result: string): void
- _get_tcs_task_ref(gcHandle: GCHandle, result: MonoObjectRef): void;
- _task_from_result_ref(value: any, result: MonoObjectRef): void;
- _setup_js_cont_ref(task: MonoObjectRef, continuation: PromiseController): void;
-
- _object_to_string_ref(obj: MonoObjectRef): string;
- _get_date_value_ref(obj: MonoObjectRef): number;
- _create_date_time_ref(ticks: number, result: MonoObjectRef): void;
- _create_uri_ref(uri: string, result: MonoObjectRef): void;
- _is_simple_array_ref(obj: MonoObjectRef): boolean;
-
- _create_task_callback(): GCHandle;
-}
-
-const wrapped_cs_functions: t_CSwraps = <any>{};
-for (const sig of fn_signatures) {
- const wf: any = wrapped_cs_functions;
- // lazy init on first run
- wf[sig[0]] = function (...args: any[]) {
- const fce = runtimeHelpers.bind_runtime_method(sig[1], sig[2]);
- wf[sig[0]] = fce;
- return fce(...args);
- };
-}
-
-export default wrapped_cs_functions;
// The .NET Foundation licenses this file to you under the MIT license.
import {
- mono_assert,
MonoArray, MonoAssembly, MonoClass,
MonoMethod, MonoObject, MonoString,
MonoType, MonoObjectRef, MonoStringRef
import { JSMarshalerArguments } from "./marshal";
import { VoidPtr, CharPtrPtr, Int32Ptr, CharPtr, ManagedPointer } from "./types/emscripten";
-const fn_signatures: [ident: string, returnType: string | null, argTypes?: string[], opts?: any][] = [
+type SigLine = [lazy: boolean, name: string, returnType: string | null, argTypes?: string[], opts?: any];
+
+// when the method is assigned/cached at usage, instead of being invoked directly from cwraps, it can't be marked lazy, because it would be re-bound on each call
+const fn_signatures: SigLine[] = [
// MONO
- ["mono_wasm_register_root", "number", ["number", "number", "string"]],
- ["mono_wasm_deregister_root", null, ["number"]],
- ["mono_wasm_string_get_data", null, ["number", "number", "number", "number"]],
- ["mono_wasm_string_get_data_ref", null, ["number", "number", "number", "number"]],
- ["mono_wasm_set_is_debugger_attached", "void", ["bool"]],
- ["mono_wasm_send_dbg_command", "bool", ["number", "number", "number", "number", "number"]],
- ["mono_wasm_send_dbg_command_with_parms", "bool", ["number", "number", "number", "number", "number", "number", "string"]],
- ["mono_wasm_setenv", null, ["string", "string"]],
- ["mono_wasm_parse_runtime_options", null, ["number", "number"]],
- ["mono_wasm_strdup", "number", ["string"]],
- ["mono_background_exec", null, []],
- ["mono_set_timeout_exec", null, []],
- ["mono_wasm_load_icu_data", "number", ["number"]],
- ["mono_wasm_get_icudt_name", "string", ["string"]],
- ["mono_wasm_add_assembly", "number", ["string", "number", "number"]],
- ["mono_wasm_add_satellite_assembly", "void", ["string", "string", "number", "number"]],
- ["mono_wasm_load_runtime", null, ["string", "number"]],
- ["mono_wasm_exit", null, ["number"]],
- ["mono_wasm_change_debugger_log_level", "void", ["number"]],
+ [true, "mono_wasm_register_root", "number", ["number", "number", "string"]],
+ [true, "mono_wasm_deregister_root", null, ["number"]],
+ [true, "mono_wasm_string_get_data", null, ["number", "number", "number", "number"]],
+ [true, "mono_wasm_string_get_data_ref", null, ["number", "number", "number", "number"]],
+ [true, "mono_wasm_set_is_debugger_attached", "void", ["bool"]],
+ [true, "mono_wasm_send_dbg_command", "bool", ["number", "number", "number", "number", "number"]],
+ [true, "mono_wasm_send_dbg_command_with_parms", "bool", ["number", "number", "number", "number", "number", "number", "string"]],
+ [true, "mono_wasm_setenv", null, ["string", "string"]],
+ [true, "mono_wasm_parse_runtime_options", null, ["number", "number"]],
+ [true, "mono_wasm_strdup", "number", ["string"]],
+ [true, "mono_background_exec", null, []],
+ [true, "mono_set_timeout_exec", null, []],
+ [true, "mono_wasm_load_icu_data", "number", ["number"]],
+ [true, "mono_wasm_get_icudt_name", "string", ["string"]],
+ [false, "mono_wasm_add_assembly", "number", ["string", "number", "number"]],
+ [true, "mono_wasm_add_satellite_assembly", "void", ["string", "string", "number", "number"]],
+ [false, "mono_wasm_load_runtime", null, ["string", "number"]],
+ [true, "mono_wasm_change_debugger_log_level", "void", ["number"]],
// BINDING
- ["mono_wasm_get_corlib", "number", []],
- ["mono_wasm_assembly_load", "number", ["string"]],
- ["mono_wasm_find_corlib_class", "number", ["string", "string"]],
- ["mono_wasm_assembly_find_class", "number", ["number", "string", "string"]],
- ["mono_wasm_runtime_run_module_cctor", "void", ["number"]],
- ["mono_wasm_find_corlib_type", "number", ["string", "string"]],
- ["mono_wasm_assembly_find_type", "number", ["number", "string", "string"]],
- ["mono_wasm_assembly_find_method", "number", ["number", "string", "number"]],
- ["mono_wasm_invoke_method", "number", ["number", "number", "number", "number"]],
- ["mono_wasm_invoke_method_ref", "void", ["number", "number", "number", "number", "number"]],
- ["mono_wasm_string_get_utf8", "number", ["number"]],
- ["mono_wasm_string_from_utf16_ref", "void", ["number", "number", "number"]],
- ["mono_wasm_get_obj_type", "number", ["number"]],
- ["mono_wasm_array_length", "number", ["number"]],
- ["mono_wasm_array_get", "number", ["number", "number"]],
- ["mono_wasm_array_get_ref", "void", ["number", "number", "number"]],
- ["mono_wasm_obj_array_new", "number", ["number"]],
- ["mono_wasm_obj_array_new_ref", "void", ["number", "number"]],
- ["mono_wasm_obj_array_set", "void", ["number", "number", "number"]],
- ["mono_wasm_obj_array_set_ref", "void", ["number", "number", "number"]],
- ["mono_wasm_register_bundled_satellite_assemblies", "void", []],
- ["mono_wasm_try_unbox_primitive_and_get_type_ref", "number", ["number", "number", "number"]],
- ["mono_wasm_box_primitive_ref", "void", ["number", "number", "number", "number"]],
- ["mono_wasm_intern_string_ref", "void", ["number"]],
- ["mono_wasm_assembly_get_entry_point", "number", ["number"]],
- ["mono_wasm_get_delegate_invoke_ref", "number", ["number"]],
- ["mono_wasm_string_array_new_ref", "void", ["number", "number"]],
- ["mono_wasm_typed_array_new_ref", "void", ["number", "number", "number", "number", "number"]],
- ["mono_wasm_class_get_type", "number", ["number"]],
- ["mono_wasm_type_get_class", "number", ["number"]],
- ["mono_wasm_get_type_name", "string", ["number"]],
- ["mono_wasm_get_type_aqn", "string", ["number"]],
+ [true, "mono_wasm_get_corlib", "number", []],
+ [true, "mono_wasm_assembly_load", "number", ["string"]],
+ [true, "mono_wasm_find_corlib_class", "number", ["string", "string"]],
+ [true, "mono_wasm_assembly_find_class", "number", ["number", "string", "string"]],
+ [true, "mono_wasm_runtime_run_module_cctor", "void", ["number"]],
+ [true, "mono_wasm_find_corlib_type", "number", ["string", "string"]],
+ [true, "mono_wasm_assembly_find_type", "number", ["number", "string", "string"]],
+ [true, "mono_wasm_assembly_find_method", "number", ["number", "string", "number"]],
+ [true, "mono_wasm_invoke_method", "number", ["number", "number", "number", "number"]],
+ [false, "mono_wasm_invoke_method_ref", "void", ["number", "number", "number", "number", "number"]],
+ [true, "mono_wasm_string_get_utf8", "number", ["number"]],
+ [true, "mono_wasm_string_from_utf16_ref", "void", ["number", "number", "number"]],
+ [true, "mono_wasm_get_obj_type", "number", ["number"]],
+ [true, "mono_wasm_array_length", "number", ["number"]],
+ [true, "mono_wasm_array_get", "number", ["number", "number"]],
+ [true, "mono_wasm_array_get_ref", "void", ["number", "number", "number"]],
+ [false, "mono_wasm_obj_array_new", "number", ["number"]],
+ [false, "mono_wasm_obj_array_new_ref", "void", ["number", "number"]],
+ [false, "mono_wasm_obj_array_set", "void", ["number", "number", "number"]],
+ [false, "mono_wasm_obj_array_set_ref", "void", ["number", "number", "number"]],
+ [true, "mono_wasm_register_bundled_satellite_assemblies", "void", []],
+ [false, "mono_wasm_try_unbox_primitive_and_get_type_ref", "number", ["number", "number", "number"]],
+ [true, "mono_wasm_box_primitive_ref", "void", ["number", "number", "number", "number"]],
+ [true, "mono_wasm_intern_string_ref", "void", ["number"]],
+ [true, "mono_wasm_assembly_get_entry_point", "number", ["number"]],
+ [true, "mono_wasm_get_delegate_invoke_ref", "number", ["number"]],
+ [true, "mono_wasm_string_array_new_ref", "void", ["number", "number"]],
+ [true, "mono_wasm_typed_array_new_ref", "void", ["number", "number", "number", "number", "number"]],
+ [true, "mono_wasm_class_get_type", "number", ["number"]],
+ [true, "mono_wasm_type_get_class", "number", ["number"]],
+ [true, "mono_wasm_get_type_name", "string", ["number"]],
+ [true, "mono_wasm_get_type_aqn", "string", ["number"]],
// MONO.diagnostics
- ["mono_wasm_event_pipe_enable", "bool", ["string", "number", "number", "string", "bool", "number"]],
- ["mono_wasm_event_pipe_session_start_streaming", "bool", ["number"]],
- ["mono_wasm_event_pipe_session_disable", "bool", ["number"]],
- ["mono_wasm_diagnostic_server_create_thread", "bool", ["string", "number"]],
- ["mono_wasm_diagnostic_server_thread_attach_to_runtime", "void", []],
- ["mono_wasm_diagnostic_server_post_resume_runtime", "void", []],
- ["mono_wasm_diagnostic_server_create_stream", "number", []],
+ [true, "mono_wasm_event_pipe_enable", "bool", ["string", "number", "string", "bool", "number"]],
+ [true, "mono_wasm_event_pipe_session_start_streaming", "bool", ["number"]],
+ [true, "mono_wasm_event_pipe_session_disable", "bool", ["number"]],
//DOTNET
- ["mono_wasm_string_from_js", "number", ["string"]],
+ [true, "mono_wasm_string_from_js", "number", ["string"]],
//INTERNAL
- ["mono_wasm_exit", "void", ["number"]],
- ["mono_wasm_set_main_args", "void", ["number", "number"]],
- ["mono_wasm_enable_on_demand_gc", "void", ["number"]],
- ["mono_profiler_init_aot", "void", ["number"]],
- ["mono_wasm_exec_regression", "number", ["number", "string"]],
- ["mono_wasm_invoke_method_bound", "number", ["number", "number"]],
- ["mono_wasm_write_managed_pointer_unsafe", "void", ["number", "number"]],
- ["mono_wasm_copy_managed_pointer", "void", ["number", "number"]],
- ["mono_wasm_i52_to_f64", "number", ["number", "number"]],
- ["mono_wasm_u52_to_f64", "number", ["number", "number"]],
- ["mono_wasm_f64_to_i52", "number", ["number", "number"]],
- ["mono_wasm_f64_to_u52", "number", ["number", "number"]],
+ [false, "mono_wasm_exit", "void", ["number"]],
+ [true, "mono_wasm_set_main_args", "void", ["number", "number"]],
+ [false, "mono_wasm_enable_on_demand_gc", "void", ["number"]],
+ [false, "mono_profiler_init_aot", "void", ["number"]],
+ [false, "mono_wasm_exec_regression", "number", ["number", "string"]],
+ [false, "mono_wasm_invoke_method_bound", "number", ["number", "number"]],
+ [true, "mono_wasm_write_managed_pointer_unsafe", "void", ["number", "number"]],
+ [true, "mono_wasm_copy_managed_pointer", "void", ["number", "number"]],
+ [true, "mono_wasm_i52_to_f64", "number", ["number", "number"]],
+ [true, "mono_wasm_u52_to_f64", "number", ["number", "number"]],
+ [true, "mono_wasm_f64_to_i52", "number", ["number", "number"]],
+ [true, "mono_wasm_f64_to_u52", "number", ["number", "number"]],
];
export interface t_Cwraps {
}
const wrapped_c_functions: t_Cwraps = <any>{};
-for (const sig of fn_signatures) {
- const wf: any = wrapped_c_functions;
- // lazy init on first run
- wf[sig[0]] = function (...args: any[]) {
- const fce = Module.cwrap(sig[0], sig[1], sig[2], sig[3]);
- wf[sig[0]] = fce;
- return fce(...args);
- };
-}
export default wrapped_c_functions;
-export function wrap_c_function(name: string): Function {
- const wf: any = wrapped_c_functions;
- const sig = fn_signatures.find(s => s[0] === name);
- mono_assert(sig, () => `Function ${name} not found`);
- const fce = Module.cwrap(sig[0], sig[1], sig[2], sig[3]);
- wf[sig[0]] = fce;
- return fce;
-}
// see src/mono/wasm/driver.c I52_ERROR_xxx
export const enum I52Error {
NON_INTEGRAL = 1,
OUT_OF_RANGE = 2,
}
+
+export function init_c_exports(): void {
+ for (const sig of fn_signatures) {
+ const wf: any = wrapped_c_functions;
+ const [lazy, name, returnType, argTypes, opts] = sig;
+ if (lazy) {
+ // lazy init on first run
+ wf[name] = function (...args: any[]) {
+ const fce = Module.cwrap(name, returnType, argTypes, opts);
+ wf[name] = fce;
+ return fce(...args);
+ };
+ } else {
+ const fce = Module.cwrap(name, returnType, argTypes, opts);
+ wf[name] = fce;
+ }
+ }
+}
\ No newline at end of file
}
declare type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;
+declare function mono_wasm_runtime_ready(): void;
+
/**
* Allocates a block of memory that can safely contain pointers into the managed heap.
* The result object has get(index) and set(index, value) methods that can be used to retrieve and store managed pointers.
toString(): string;
}
+interface IDisposable {
+ dispose(): void;
+ get isDisposed(): boolean;
+}
+declare class ManagedObject implements IDisposable {
+ dispose(): void;
+ get isDisposed(): boolean;
+ toString(): string;
+}
+declare class ManagedError extends Error implements IDisposable {
+ constructor(message: string);
+ get stack(): string | undefined;
+ dispose(): void;
+ get isDisposed(): boolean;
+ toString(): string;
+}
+declare const enum MemoryViewType {
+ Byte = 0,
+ Int32 = 1,
+ Double = 2
+}
+interface IMemoryView {
+ /**
+ * copies elements from provided source to the wasm memory.
+ * target has to have the elements of the same type as the underlying C# array.
+ * same as TypedArray.set()
+ */
+ set(source: TypedArray, targetOffset?: number): void;
+ /**
+ * copies elements from wasm memory to provided target.
+ * target has to have the elements of the same type as the underlying C# array.
+ */
+ copyTo(target: TypedArray, sourceOffset?: number): void;
+ /**
+ * same as TypedArray.slice()
+ */
+ slice(start?: number, end?: number): TypedArray;
+ get length(): number;
+ get byteLength(): number;
+}
+
interface MonoObject extends ManagedPointer {
__brandMonoObject: "MonoObject";
}
response: Promise<Response>;
}
declare type EventPipeSessionID = bigint;
+interface DotnetPublicAPI {
+ MONO: MONOType;
+ BINDING: BINDINGType;
+ INTERNAL: any;
+ EXPORTS: any;
+ IMPORTS: any;
+ Module: EmscriptenModule;
+ RuntimeId: number;
+ RuntimeBuildInfo: {
+ ProductVersion: string;
+ Configuration: string;
+ };
+}
declare const eventLevel: {
readonly LogAlways: 0;
getStartupSessions(): (EventPipeSession | null)[];
}
-declare function mono_wasm_runtime_ready(): void;
-
-declare function mono_wasm_setenv(name: string, value: string): void;
-declare function mono_wasm_load_runtime(unused?: string, debug_level?: number): void;
-declare function mono_wasm_load_data_archive(data: Uint8Array, prefix: string): boolean;
-/**
- * Loads the mono config file (typically called mono-config.json) asynchroniously
- * Note: the run dependencies are so emsdk actually awaits it in order.
- *
- * @param {string} configFilePath - relative path to the config file
- * @throws Will throw an error if the config file loading fails
- */
-declare function mono_wasm_load_config(configFilePath: string): Promise<void>;
-/**
-* @deprecated
-*/
-declare function mono_load_runtime_and_bcl_args(cfg?: MonoConfig | MonoConfigError | undefined): Promise<void>;
-
declare function mono_wasm_load_icu_data(offset: VoidPtr): boolean;
-/**
- * @deprecated Not GC or thread safe
- */
-declare function conv_string(mono_obj: MonoString): string | null;
-declare function conv_string_root(root: WasmRoot<MonoString>): string | null;
-declare function js_string_to_mono_string_root(string: string, result: WasmRoot<MonoString>): void;
-/**
- * @deprecated Not GC or thread safe
- */
-declare function js_string_to_mono_string(string: string): MonoString;
-
-/**
- * @deprecated Not GC or thread safe. For blazor use only
- */
-declare function js_to_mono_obj(js_obj: any): MonoObject;
-declare function js_to_mono_obj_root(js_obj: any, result: WasmRoot<MonoObject>, should_add_in_flight: boolean): void;
-declare function js_typed_array_to_array_root(js_obj: any, result: WasmRoot<MonoArray>): void;
-/**
- * @deprecated Not GC or thread safe
- */
-declare function js_typed_array_to_array(js_obj: any): MonoArray;
-
-declare function unbox_mono_obj(mono_obj: MonoObject): any;
-declare function unbox_mono_obj_root(root: WasmRoot<any>): any;
-declare function mono_array_to_js_array(mono_array: MonoArray): any[] | null;
-declare function mono_array_root_to_js_array(arrayRoot: WasmRoot<MonoArray>): any[] | null;
-
-declare function mono_bind_static_method(fqn: string, signature?: string): Function;
-declare function mono_call_assembly_entry_point(assembly: string, args?: any[], signature?: string): number;
-
-declare function mono_wasm_load_bytes_into_heap(bytes: Uint8Array): VoidPtr;
+declare function mono_wasm_get_assembly_exports(assembly: string): Promise<any>;
declare type _MemOffset = number | VoidPtr | NativePointer | ManagedPointer;
declare type _NumberOrPointer = number | VoidPtr | NativePointer | ManagedPointer;
declare function getI64Big(offset: _MemOffset): bigint;
declare function getF32(offset: _MemOffset): number;
declare function getF64(offset: _MemOffset): number;
+declare function mono_wasm_load_bytes_into_heap(bytes: Uint8Array): VoidPtr;
declare function mono_run_main_and_exit(main_assembly_name: string, args: string[]): Promise<void>;
declare function mono_run_main(main_assembly_name: string, args: string[]): Promise<number>;
-interface IDisposable {
- dispose(): void;
- get isDisposed(): boolean;
-}
-declare class ManagedObject implements IDisposable {
- dispose(): void;
- get isDisposed(): boolean;
- toString(): string;
-}
-declare class ManagedError extends Error implements IDisposable {
- constructor(message: string);
- get stack(): string | undefined;
- dispose(): void;
- get isDisposed(): boolean;
- toString(): string;
-}
-declare const enum MemoryViewType {
- Byte = 0,
- Int32 = 1,
- Double = 2
-}
-interface IMemoryView {
+declare function mono_wasm_setenv(name: string, value: string): void;
+declare function mono_wasm_load_data_archive(data: Uint8Array, prefix: string): boolean;
+/**
+ * Loads the mono config file (typically called mono-config.json) asynchroniously
+ * Note: the run dependencies are so emsdk actually awaits it in order.
+ *
+ * @param {string} configFilePath - relative path to the config file
+ * @throws Will throw an error if the config file loading fails
+ */
+declare function mono_wasm_load_config(configFilePath: string): Promise<void>;
+/**
+* @deprecated
+*/
+declare function mono_load_runtime_and_bcl_args(cfg?: MonoConfig | MonoConfigError | undefined): Promise<void>;
+
+/**
+ * @deprecated Not GC or thread safe
+ */
+declare function conv_string(mono_obj: MonoString): string | null;
+declare function conv_string_root(root: WasmRoot<MonoString>): string | null;
+declare function js_string_to_mono_string_root(string: string, result: WasmRoot<MonoString>): void;
+/**
+ * @deprecated Not GC or thread safe
+ */
+declare function js_string_to_mono_string(string: string): MonoString;
+
+declare function unbox_mono_obj(mono_obj: MonoObject): any;
+declare function unbox_mono_obj_root(root: WasmRoot<any>): any;
+declare function mono_array_to_js_array(mono_array: MonoArray): any[] | null;
+declare function mono_array_root_to_js_array(arrayRoot: WasmRoot<MonoArray>): any[] | null;
+
+/**
+ * @deprecated Not GC or thread safe. For blazor use only
+ */
+declare function js_to_mono_obj(js_obj: any): MonoObject;
+declare function js_to_mono_obj_root(js_obj: any, result: WasmRoot<MonoObject>, should_add_in_flight: boolean): void;
+declare function js_typed_array_to_array_root(js_obj: any, result: WasmRoot<MonoArray>): void;
+/**
+ * @deprecated Not GC or thread safe
+ */
+declare function js_typed_array_to_array(js_obj: any): MonoArray;
+
+declare function mono_bind_static_method(fqn: string, signature?: string): Function;
+declare function mono_call_assembly_entry_point(assembly: string, args?: any[], signature?: string): number;
+
+declare type BINDINGType = {
+ bind_static_method: typeof mono_bind_static_method;
+ call_assembly_entry_point: typeof mono_call_assembly_entry_point;
/**
- * copies elements from provided source to the wasm memory.
- * target has to have the elements of the same type as the underlying C# array.
- * same as TypedArray.set()
+ * @deprecated Not GC or thread safe
*/
- set(source: TypedArray, targetOffset?: number): void;
+ mono_obj_array_new: (size: number) => MonoArray;
/**
- * copies elements from wasm memory to provided target.
- * target has to have the elements of the same type as the underlying C# array.
+ * @deprecated Not GC or thread safe
*/
- copyTo(target: TypedArray, sourceOffset?: number): void;
+ mono_obj_array_set: (array: MonoArray, idx: number, obj: MonoObject) => void;
/**
- * same as TypedArray.slice()
+ * @deprecated Not GC or thread safe
*/
- slice(start?: number, end?: number): TypedArray;
- get length(): number;
- get byteLength(): number;
-}
-
-declare function mono_wasm_get_assembly_exports(assembly: string): Promise<any>;
-
-declare const MONO: {
+ js_string_to_mono_string: typeof js_string_to_mono_string;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ js_typed_array_to_array: typeof js_typed_array_to_array;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ mono_array_to_js_array: typeof mono_array_to_js_array;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ js_to_mono_obj: typeof js_to_mono_obj;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ conv_string: typeof conv_string;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ unbox_mono_obj: typeof unbox_mono_obj;
+ mono_obj_array_new_ref: (size: number, result: MonoObjectRef) => void;
+ mono_obj_array_set_ref: (array: MonoObjectRef, idx: number, obj: MonoObjectRef) => void;
+ js_string_to_mono_string_root: typeof js_string_to_mono_string_root;
+ js_typed_array_to_array_root: typeof js_typed_array_to_array_root;
+ js_to_mono_obj_root: typeof js_to_mono_obj_root;
+ conv_string_root: typeof conv_string_root;
+ unbox_mono_obj_root: typeof unbox_mono_obj_root;
+ mono_array_root_to_js_array: typeof mono_array_root_to_js_array;
+};
+declare type MONOType = {
mono_wasm_setenv: typeof mono_wasm_setenv;
mono_wasm_load_bytes_into_heap: typeof mono_wasm_load_bytes_into_heap;
mono_wasm_load_icu_data: typeof mono_wasm_load_icu_data;
mono_run_main_and_exit: typeof mono_run_main_and_exit;
mono_wasm_get_assembly_exports: typeof mono_wasm_get_assembly_exports;
mono_wasm_add_assembly: (name: string, data: VoidPtr, size: number) => number;
- mono_wasm_load_runtime: typeof mono_wasm_load_runtime;
+ mono_wasm_load_runtime: (unused: string, debug_level: number) => void;
config: MonoConfig | MonoConfigError;
loaded_files: string[];
setB32: typeof setB32;
getF64: typeof getF64;
diagnostics: Diagnostics;
};
-declare type MONOType = typeof MONO;
-declare const BINDING: {
- /**
- * @deprecated Not GC or thread safe
- */
- mono_obj_array_new: (size: number) => MonoArray;
- /**
- * @deprecated Not GC or thread safe
- */
- mono_obj_array_set: (array: MonoArray, idx: number, obj: MonoObject) => void;
- /**
- * @deprecated Not GC or thread safe
- */
- js_string_to_mono_string: typeof js_string_to_mono_string;
- /**
- * @deprecated Not GC or thread safe
- */
- js_typed_array_to_array: typeof js_typed_array_to_array;
- /**
- * @deprecated Not GC or thread safe
- */
- mono_array_to_js_array: typeof mono_array_to_js_array;
- /**
- * @deprecated Not GC or thread safe
- */
- js_to_mono_obj: typeof js_to_mono_obj;
- /**
- * @deprecated Not GC or thread safe
- */
- conv_string: typeof conv_string;
- /**
- * @deprecated Not GC or thread safe
- */
- unbox_mono_obj: typeof unbox_mono_obj;
- /**
- * @deprecated Renamed to conv_string_root
- */
- conv_string_rooted: typeof conv_string_root;
- mono_obj_array_new_ref: (size: number, result: MonoObjectRef) => void;
- mono_obj_array_set_ref: (array: MonoObjectRef, idx: number, obj: MonoObjectRef) => void;
- js_string_to_mono_string_root: typeof js_string_to_mono_string_root;
- js_typed_array_to_array_root: typeof js_typed_array_to_array_root;
- js_to_mono_obj_root: typeof js_to_mono_obj_root;
- conv_string_root: typeof conv_string_root;
- unbox_mono_obj_root: typeof unbox_mono_obj_root;
- mono_array_root_to_js_array: typeof mono_array_root_to_js_array;
- bind_static_method: typeof mono_bind_static_method;
- call_assembly_entry_point: typeof mono_call_assembly_entry_point;
-};
-declare type BINDINGType = typeof BINDING;
-interface DotnetPublicAPI {
- MONO: typeof MONO;
- BINDING: typeof BINDING;
- INTERNAL: any;
- EXPORTS: any;
- IMPORTS: any;
- Module: EmscriptenModule;
- RuntimeId: number;
- RuntimeBuildInfo: {
- ProductVersion: string;
- Configuration: string;
- };
-}
declare function createDotnetRuntime(moduleFactory: DotnetModuleConfig | ((api: DotnetPublicAPI) => DotnetModuleConfig)): Promise<DotnetPublicAPI>;
declare type CreateDotnetRuntimeType = typeof createDotnetRuntime;
"mono_wasm_create_cs_owned_object_ref",
"mono_wasm_release_cs_owned_object",
"mono_wasm_typed_array_to_array_ref",
- "mono_wasm_typed_array_copy_to_ref",
"mono_wasm_typed_array_from_ref",
- "mono_wasm_typed_array_copy_from_ref",
"mono_wasm_compile_function_ref",
"mono_wasm_bind_js_function",
"mono_wasm_invoke_bound_function",
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { BINDINGType, DotnetPublicAPI, MONOType } from "./exports";
+import { BINDINGType, MONOType } from "./net6-legacy/exports-legacy";
import { IDisposable, IMemoryView, ManagedError, ManagedObject, MemoryViewType } from "./marshal";
-import { AssetBehaviours, AssetEntry, DotnetModuleConfig, LoadingResource, MonoArray, MonoConfig, MonoObject, MonoString, ResourceRequest } from "./types";
+import { AssetBehaviours, AssetEntry, DotnetModuleConfig, DotnetPublicAPI, LoadingResource, MonoArray, MonoConfig, MonoObject, MonoString, ResourceRequest } from "./types";
import { EmscriptenModule, TypedArray, VoidPtr } from "./types/emscripten";
// -----------------------------------------------------------
--- /dev/null
+import { mono_wasm_cancel_promise } from "./cancelable-promise";
+import cwraps from "./cwraps";
+import { mono_wasm_symbolicate_string, mono_wasm_stringify_as_error_with_stack, mono_wasm_get_loaded_files, 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 { get_dotnet_instance } from "./exports";
+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 { Module, runtimeHelpers } from "./imports";
+import { get_property, set_property, has_property, get_typeof_property, get_global_this, dynamic_import } from "./invoke-js";
+import { mono_method_resolve } from "./net6-legacy/method-binding";
+import { mono_wasm_set_runtime_options } from "./startup";
+import { mono_intern_string } from "./strings";
+import { ws_wasm_create, ws_wasm_open, ws_wasm_send, ws_wasm_receive, ws_wasm_close, ws_wasm_abort } from "./web-socket";
+
+export function export_internal(): any {
+ return {
+ // tests
+ mono_wasm_exit: (exit_code: number) => { Module.printErr("MONO_WASM: early exit " + exit_code); },
+ mono_wasm_enable_on_demand_gc: cwraps.mono_wasm_enable_on_demand_gc,
+ mono_profiler_init_aot: cwraps.mono_profiler_init_aot,
+ mono_wasm_set_runtime_options,
+ mono_wasm_exec_regression: cwraps.mono_wasm_exec_regression,
+ mono_method_resolve,//MarshalTests.cs
+ mono_intern_string,// MarshalTests.cs
+
+ // with mono_wasm_debugger_log and mono_wasm_trace_logger
+ logging: undefined,
+
+ //
+ mono_wasm_symbolicate_string,
+ mono_wasm_stringify_as_error_with_stack,
+
+ // used in debugger DevToolsHelper.cs
+ mono_wasm_get_loaded_files,
+ 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,
+ mono_wasm_runtime_is_ready: runtimeHelpers.mono_wasm_runtime_is_ready,
+
+ // interop
+ get_property,
+ set_property,
+ has_property,
+ get_typeof_property,
+ get_global_this,
+ get_dotnet_instance,
+ dynamic_import,
+
+ // BrowserWebSocket
+ mono_wasm_cancel_promise,
+ ws_wasm_create,
+ ws_wasm_open,
+ ws_wasm_send,
+ ws_wasm_receive,
+ ws_wasm_close,
+ ws_wasm_abort,
+
+ // BrowserHttpHandler
+ 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,
+ };
+}
+
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+export function cwraps_internal(internal: any): void {
+ Object.assign(internal, {
+ mono_wasm_exit: cwraps.mono_wasm_exit,
+ mono_wasm_enable_on_demand_gc: cwraps.mono_wasm_enable_on_demand_gc,
+ mono_profiler_init_aot: cwraps.mono_profiler_init_aot,
+ mono_wasm_exec_regression: cwraps.mono_wasm_exec_regression,
+ });
+}
--- /dev/null
+import MonoWasmThreads from "consts:monoWasmThreads";
+import { dotnet_browser_can_use_subtle_crypto_impl, dotnet_browser_simple_digest_hash, dotnet_browser_sign, dotnet_browser_encrypt_decrypt, dotnet_browser_derive_bits } from "./crypto-worker";
+import { mono_wasm_fire_debugger_agent_message, mono_wasm_debugger_log, mono_wasm_add_dbg_command_received, mono_wasm_trace_logger, mono_wasm_set_entrypoint_breakpoint } from "./debug";
+import { mono_wasm_release_cs_owned_object } from "./gc-handles";
+import { mono_wasm_load_icu_data, mono_wasm_get_icudt_name } from "./icu";
+import { mono_wasm_bind_cs_function } from "./invoke-cs";
+import { mono_wasm_bind_js_function, mono_wasm_invoke_bound_function } from "./invoke-js";
+import { mono_wasm_typed_array_from_ref } from "./net6-legacy/buffers";
+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_marshal_promise } from "./marshal-to-js";
+import { mono_wasm_pthread_on_pthread_attached } from "./pthreads/worker";
+import { mono_set_timeout, 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_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";
+
+// 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,
+ // 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,
+};
+
+// 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_set_timeout,
+
+ // mini-wasm-debugger.c
+ mono_wasm_asm_loaded,
+ mono_wasm_fire_debugger_agent_message,
+ mono_wasm_debugger_log,
+ mono_wasm_add_dbg_command_received,
+
+ // mono-threads-wasm.c
+ schedule_background_exec,
+
+ // also keep in sync with driver.c
+ mono_wasm_invoke_js_blazor,
+ mono_wasm_trace_logger,
+ mono_wasm_set_entrypoint_breakpoint,
+ mono_wasm_event_pipe_early_startup_callback,
+
+ // also keep in sync with 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_release_cs_owned_object,
+ mono_wasm_typed_array_to_array_ref,
+ mono_wasm_typed_array_from_ref,
+ mono_wasm_bind_js_function,
+ mono_wasm_invoke_bound_function,
+ mono_wasm_bind_cs_function,
+ mono_wasm_marshal_promise,
+
+ // also keep in sync with pal_icushim_static.c
+ mono_wasm_load_icu_data,
+ mono_wasm_get_icudt_name,
+
+ // pal_crypto_webworker.c
+ dotnet_browser_can_use_subtle_crypto_impl,
+ dotnet_browser_simple_digest_hash,
+ dotnet_browser_sign,
+ dotnet_browser_encrypt_decrypt,
+ dotnet_browser_derive_bits,
+
+ // threading exports, if threading is enabled
+ ...mono_wasm_threads_exports,
+ };
+}
\ No newline at end of file
import ProductVersion from "consts:productVersion";
import Configuration from "consts:configuration";
-import MonoWasmThreads from "consts:monoWasmThreads";
-import {
- mono_wasm_new_root, mono_wasm_release_roots, mono_wasm_new_external_root,
- mono_wasm_new_root_buffer
-} from "./roots";
-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_runtime_ready,
- mono_wasm_get_loaded_files,
- mono_wasm_raise_debug_event,
- mono_wasm_fire_debugger_agent_message,
- mono_wasm_debugger_log,
- mono_wasm_trace_logger,
- mono_wasm_add_dbg_command_received,
- mono_wasm_change_debugger_log_level,
- mono_wasm_symbolicate_string,
- mono_wasm_stringify_as_error_with_stack,
- mono_wasm_debugger_attached,
- mono_wasm_set_entrypoint_breakpoint,
-} from "./debug";
-import { ENVIRONMENT_IS_WORKER, runtimeHelpers, set_imports_exports } from "./imports";
-import { DotnetModule, is_nullish, MonoConfig, MonoConfigError, EarlyImports, EarlyExports, EarlyReplacements } from "./types";
-import {
- mono_load_runtime_and_bcl_args, mono_wasm_load_config,
- mono_wasm_setenv, mono_wasm_set_runtime_options,
- mono_wasm_load_data_archive, mono_wasm_asm_loaded,
- configure_emscripten_startup,
- mono_wasm_load_runtime,
-} from "./startup";
-import { mono_set_timeout, schedule_background_exec } from "./scheduling";
-import { mono_wasm_load_icu_data, mono_wasm_get_icudt_name } from "./icu";
-import { conv_string, conv_string_root, js_string_to_mono_string, js_string_to_mono_string_root, mono_intern_string } from "./strings";
-import { js_to_mono_obj, js_typed_array_to_array, mono_wasm_typed_array_to_array_ref, js_to_mono_obj_root, js_typed_array_to_array_root } from "./js-to-cs";
-import {
- mono_array_to_js_array, mono_wasm_create_cs_owned_object_ref, unbox_mono_obj, unbox_mono_obj_root, mono_array_root_to_js_array
-} from "./cs-to-js";
-import {
- call_static_method, mono_bind_static_method, mono_call_assembly_entry_point,
- mono_method_resolve,
- mono_wasm_get_by_index_ref, mono_wasm_get_global_object_ref, mono_wasm_get_object_property_ref,
- mono_wasm_invoke_js_blazor,
- mono_wasm_invoke_js_with_args_ref, mono_wasm_set_by_index_ref, mono_wasm_set_object_property_ref
-} from "./method-calls";
-import {
- mono_wasm_event_pipe_early_startup_callback,
- mono_wasm_diagnostic_server_on_runtime_server_init
-} from "./diagnostics";
-import {
- mono_wasm_diagnostic_server_on_server_thread_created,
-} from "./diagnostics/server_pthread";
-import {
- mono_wasm_diagnostic_server_stream_signal_work_available
-} from "./diagnostics/server_pthread/stream-queue";
-import { mono_wasm_typed_array_copy_to_ref, mono_wasm_typed_array_from_ref, mono_wasm_typed_array_copy_from_ref, mono_wasm_load_bytes_into_heap } from "./buffers";
-import { mono_wasm_release_cs_owned_object } from "./gc-handles";
-import cwraps from "./cwraps";
-import {
- setI8, setI16, setI32, setI52,
- setU8, setU16, setU32, setF32, setF64,
- getI8, getI16, getI32, getI52,
- getU8, getU16, getU32, getF32, getF64, getI64Big, setI64Big, getU52, setU52, setB32, getB32,
-} from "./memory";
+import { ENVIRONMENT_IS_WORKER, set_imports_exports } from "./imports";
+import { DotnetModule, is_nullish, DotnetPublicAPI, EarlyImports, EarlyExports, EarlyReplacements } from "./types";
+import { configure_emscripten_startup } from "./startup";
+import { mono_bind_static_method } from "./net6-legacy/method-calls";
+
import { create_weak_ref } from "./weak-ref";
-import { EmscriptenModule } from "./types/emscripten";
-import { mono_run_main, mono_run_main_and_exit } from "./run";
-import { dynamic_import, get_global_this, get_property, get_typeof_property, has_property, mono_wasm_bind_js_function, mono_wasm_invoke_bound_function, set_property } from "./invoke-js";
-import { mono_wasm_bind_cs_function, mono_wasm_get_assembly_exports } from "./invoke-cs";
-import { mono_wasm_marshal_promise } from "./marshal-to-js";
-import { ws_wasm_abort, ws_wasm_close, ws_wasm_create, ws_wasm_open, ws_wasm_receive, ws_wasm_send } from "./web-socket";
-import { http_wasm_abort_request, http_wasm_abort_response, http_wasm_create_abort_controler, http_wasm_fetch, http_wasm_fetch_bytes, http_wasm_get_response_bytes, http_wasm_get_response_header_names, http_wasm_get_response_header_values, http_wasm_get_response_length, http_wasm_get_streamed_response_bytes, http_wasm_supports_streaming_response } from "./http";
-import { diagnostics } from "./diagnostics";
-import { mono_wasm_cancel_promise } from "./cancelable-promise";
-import {
- dotnet_browser_can_use_subtle_crypto_impl,
- dotnet_browser_simple_digest_hash,
- dotnet_browser_sign,
- dotnet_browser_encrypt_decrypt,
- dotnet_browser_derive_bits,
-} from "./crypto-worker";
-import { mono_wasm_pthread_on_pthread_attached } from "./pthreads/worker";
+import { export_binding_api, export_mono_api } from "./net6-legacy/exports-legacy";
+import { export_internal } from "./exports-internal";
+import { export_linker } from "./exports-linker";
import { init_polyfills } from "./polyfills";
-const MONO = {
- // current "public" MONO API
- mono_wasm_setenv,
- mono_wasm_load_bytes_into_heap,
- mono_wasm_load_icu_data,
- mono_wasm_runtime_ready,
- mono_wasm_load_data_archive,
- mono_wasm_load_config,
- mono_load_runtime_and_bcl_args,
- mono_wasm_new_root_buffer,
- mono_wasm_new_root,
- mono_wasm_new_external_root,
- mono_wasm_release_roots,
- mono_run_main,
- mono_run_main_and_exit,
- mono_wasm_get_assembly_exports,
-
- mono_wasm_add_assembly: cwraps.mono_wasm_add_assembly,
- mono_wasm_load_runtime,
-
- config: <MonoConfig | MonoConfigError>runtimeHelpers.config,
- loaded_files: <string[]>[],
-
- // memory accessors
- setB32,
- setI8,
- setI16,
- setI32,
- setI52,
- setU52,
- setI64Big,
- setU8,
- setU16,
- setU32,
- setF32,
- setF64,
- getB32,
- getI8,
- getI16,
- getI32,
- getI52,
- getU52,
- getI64Big,
- getU8,
- getU16,
- getU32,
- getF32,
- getF64,
-
- // Diagnostics
- diagnostics
-};
-export type MONOType = typeof MONO;
-
-const BINDING = {
- //current "public" BINDING API
- /**
- * @deprecated Not GC or thread safe
- */
- mono_obj_array_new: cwraps.mono_wasm_obj_array_new,
- /**
- * @deprecated Not GC or thread safe
- */
- mono_obj_array_set: cwraps.mono_wasm_obj_array_set,
- /**
- * @deprecated Not GC or thread safe
- */
- js_string_to_mono_string,
- /**
- * @deprecated Not GC or thread safe
- */
- js_typed_array_to_array,
- /**
- * @deprecated Not GC or thread safe
- */
- mono_array_to_js_array,
- /**
- * @deprecated Not GC or thread safe
- */
- js_to_mono_obj,
- /**
- * @deprecated Not GC or thread safe
- */
- conv_string,
- /**
- * @deprecated Not GC or thread safe
- */
- unbox_mono_obj,
- /**
- * @deprecated Renamed to conv_string_root
- */
- conv_string_rooted: conv_string_root,
-
- mono_obj_array_new_ref: cwraps.mono_wasm_obj_array_new_ref,
- mono_obj_array_set_ref: cwraps.mono_wasm_obj_array_set_ref,
- js_string_to_mono_string_root,
- js_typed_array_to_array_root,
- js_to_mono_obj_root,
- conv_string_root,
- unbox_mono_obj_root,
- mono_array_root_to_js_array,
-
- bind_static_method: mono_bind_static_method,
- call_assembly_entry_point: mono_call_assembly_entry_point,
-};
-export type BINDINGType = typeof BINDING;
-
+export const __initializeImportsAndExports: any = initializeImportsAndExports; // don't want to export the type
+export let __linker_exports: any = null;
let exportedAPI: DotnetPublicAPI;
+
// 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'
init_polyfills(replacements);
// here we merge methods from the local objects into exported objects
- Object.assign(exports.mono, MONO);
- Object.assign(exports.binding, BINDING);
- Object.assign(exports.internal, INTERNAL);
+ Object.assign(exports.mono, export_mono_api());
+ Object.assign(exports.binding, export_binding_api());
+ Object.assign(exports.internal, export_internal());
+ __linker_exports = export_linker();
exportedAPI = <any>{
MONO: exports.mono,
return exportedAPI;
}
-export const __initializeImportsAndExports: any = initializeImportsAndExports; // don't want to export the type
-
-// the methods would be visible to EMCC linker
-// --- keep in sync with dotnet.es6.lib.js ---
-const mono_wasm_threads_exports = !MonoWasmThreads ? undefined : {
- // mono-threads-wasm.c
- mono_wasm_pthread_on_pthread_attached,
- // 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,
-};
-
-// the methods would be visible to EMCC linker
-// --- keep in sync with dotnet.es6.lib.js ---
-export const __linker_exports: any = {
- // mini-wasm.c
- mono_set_timeout,
-
- // mini-wasm-debugger.c
- mono_wasm_asm_loaded,
- mono_wasm_fire_debugger_agent_message,
- mono_wasm_debugger_log,
- mono_wasm_add_dbg_command_received,
-
- // mono-threads-wasm.c
- schedule_background_exec,
-
- // also keep in sync with driver.c
- mono_wasm_invoke_js_blazor,
- mono_wasm_trace_logger,
- mono_wasm_set_entrypoint_breakpoint,
- mono_wasm_event_pipe_early_startup_callback,
-
- // also keep in sync with 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_release_cs_owned_object,
- mono_wasm_typed_array_to_array_ref,
- mono_wasm_typed_array_copy_to_ref,
- mono_wasm_typed_array_from_ref,
- mono_wasm_typed_array_copy_from_ref,
- mono_wasm_bind_js_function,
- mono_wasm_invoke_bound_function,
- mono_wasm_bind_cs_function,
- mono_wasm_marshal_promise,
-
- // also keep in sync with pal_icushim_static.c
- mono_wasm_load_icu_data,
- mono_wasm_get_icudt_name,
-
- // pal_crypto_webworker.c
- dotnet_browser_can_use_subtle_crypto_impl,
- dotnet_browser_simple_digest_hash,
- dotnet_browser_sign,
- dotnet_browser_encrypt_decrypt,
- dotnet_browser_derive_bits,
-
- // threading exports, if threading is enabled
- ...mono_wasm_threads_exports,
-};
-
-const INTERNAL: any = {
- // startup
- BINDING_ASM: "[System.Runtime.InteropServices.JavaScript]System.Runtime.InteropServices.JavaScript.JavaScriptExports",
-
- // tests
- call_static_method,
- mono_wasm_exit: cwraps.mono_wasm_exit,
- mono_wasm_enable_on_demand_gc: cwraps.mono_wasm_enable_on_demand_gc,
- mono_profiler_init_aot: cwraps.mono_profiler_init_aot,
- mono_wasm_set_runtime_options,
- mono_wasm_exec_regression: cwraps.mono_wasm_exec_regression,
- mono_method_resolve,//MarshalTests.cs
- mono_bind_static_method,// MarshalTests.cs
- mono_intern_string,// MarshalTests.cs
-
- // with mono_wasm_debugger_log and mono_wasm_trace_logger
- logging: undefined,
-
- //
- mono_wasm_symbolicate_string,
- mono_wasm_stringify_as_error_with_stack,
-
- // used in debugger DevToolsHelper.cs
- mono_wasm_get_loaded_files,
- 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,
- mono_wasm_runtime_is_ready: <boolean>runtimeHelpers.mono_wasm_runtime_is_ready,
-
- // interop
- get_property,
- set_property,
- has_property,
- get_typeof_property,
- get_global_this,
- get_dotnet_instance,
- dynamic_import,
-
- // BrowserWebSocket
- mono_wasm_cancel_promise,
- ws_wasm_create,
- ws_wasm_open,
- ws_wasm_send,
- ws_wasm_receive,
- ws_wasm_close,
- ws_wasm_abort,
-
- // BrowserHttpHandler
- 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,
-};
-
-// this represents visibility in the javascript
-// like https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web.JS/src/Platform/Mono/MonoTypes.ts
-export interface DotnetPublicAPI {
- MONO: typeof MONO,
- BINDING: typeof BINDING,
- INTERNAL: any,
- EXPORTS: any,
- IMPORTS: any,
- Module: EmscriptenModule,
- RuntimeId: number,
- RuntimeBuildInfo: {
- ProductVersion: string,
- Configuration: string,
- }
-}
class RuntimeList {
private list: { [runtimeId: number]: WeakRef<DotnetPublicAPI> } = {};
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import corebindings from "./corebindings";
-import { GCHandle, GCHandleNull, JSHandle, JSHandleDisposed, JSHandleNull, MonoObjectRef, mono_assert } from "./types";
-import { setI32_unchecked } from "./memory";
+import { runtimeHelpers } from "./imports";
+import { GCHandle, GCHandleNull, JSHandle, JSHandleDisposed, JSHandleNull, mono_assert } from "./types";
import { create_weak_ref } from "./weak-ref";
const _use_finalization_registry = typeof globalThis.FinalizationRegistry === "function";
return null;
}
-// when should_add_in_flight === true, the JSObject would be temporarily hold by Normal gc_handle, so that it would not get collected during transition to the managed stack.
-// its InFlight gc_handle would be freed when the instance arrives to managed side via Interop.Runtime.ReleaseInFlight
-export function get_cs_owned_object_by_js_handle_ref(js_handle: JSHandle, should_add_in_flight: boolean, result: MonoObjectRef): void {
- if (js_handle === JSHandleNull || js_handle === JSHandleDisposed) {
- setI32_unchecked(result, 0);
- return;
- }
- corebindings._get_cs_owned_object_by_js_handle_ref(js_handle, should_add_in_flight ? 1 : 0, result);
-}
-
export function get_js_obj(js_handle: JSHandle): any {
if (js_handle !== JSHandleNull && js_handle !== JSHandleDisposed)
return mono_wasm_get_jsobj_from_js_handle(js_handle);
}
}
if (gc_handle !== GCHandleNull && _js_owned_object_table.delete(gc_handle)) {
- corebindings._release_js_owned_object_by_gc_handle(gc_handle);
+ runtimeHelpers.javaScriptExports._release_js_owned_object_by_gc_handle(gc_handle);
}
}
}
return null;
}
-
-export function get_js_owned_object_by_gc_handle_ref(gc_handle: GCHandle, result: MonoObjectRef): void {
- if (!gc_handle) {
- setI32_unchecked(result, 0);
- return;
- }
- // this is always strong gc_handle
- corebindings._get_js_owned_object_by_gc_handle_ref(gc_handle, result);
-}
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="./types/v8.d.ts" />
+import { BINDINGType, MONOType } from "./net6-legacy/exports-legacy";
import { DotnetModule, EarlyExports, EarlyImports, MonoConfig, RuntimeHelpers } from "./types";
import { EmscriptenModule } from "./types/emscripten";
// these are our public API (except internal)
export let Module: EmscriptenModule & DotnetModule;
-export let MONO: any;
-export let BINDING: any;
+export let MONO: MONOType;
+export let BINDING: BINDINGType;
export let INTERNAL: any;
export let EXPORTS: any;
export let IMPORTS: any;
let runtime_is_ready = false;
export const runtimeHelpers: RuntimeHelpers = <any>{
- namespace: "System.Runtime.InteropServices.JavaScript",
- classname: "Runtime",
+ javaScriptExports: {},
mono_wasm_load_runtime_done: false,
mono_wasm_bindings_is_ready: false,
get mono_wasm_runtime_is_ready() {
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { MonoObject, MonoString } from "./export-types";
import { EXPORTS, Module, runtimeHelpers } from "./imports";
import { generate_arg_marshal_to_cs } from "./marshal-to-cs";
import { marshal_exception_to_js, generate_arg_marshal_to_js } from "./marshal-to-js";
import {
JSMarshalerArguments, JavaScriptMarshalerArgSize, JSFunctionSignature,
JSMarshalerTypeSize, JSMarshalerSignatureHeaderSize,
- get_arg, get_sig, set_arg_type,
- get_signature_argument_count, is_args_exception, bound_cs_function_symbol, get_signature_version, MarshalerType,
+ get_arg, get_sig,
+ get_signature_argument_count, is_args_exception, bound_cs_function_symbol, get_signature_version, MarshalerType, alloc_stack_frame,
} from "./marshal";
-import { parseFQN, wrap_error_root } from "./method-calls";
-import { mono_wasm_new_external_root, mono_wasm_new_root } from "./roots";
+import { mono_wasm_new_external_root } from "./roots";
import { conv_string, conv_string_root } from "./strings";
-import { mono_assert, MonoObjectRef, MonoStringRef } from "./types";
+import { mono_assert, MonoObjectRef, MonoStringRef, MonoString, MonoObject, MonoMethod } from "./types";
import { Int32Ptr } from "./types/emscripten";
-import cwraps, { wrap_c_function } from "./cwraps";
-import { find_method } from "./method-binding";
+import cwraps from "./cwraps";
import { assembly_load } from "./class-loader";
+import { wrap_error_root } from "./invoke-js";
const exportedMethods = new Map<string, Function>();
throw new Error("Could not find class: " + namespace + ":" + classname + " in assembly " + assembly);
const wrapper_name = `__Wrapper_${methodname}_${signature_hash}`;
- const method = find_method(klass, wrapper_name, -1);
+ const method = cwraps.mono_wasm_assembly_find_method(klass, wrapper_name, -1);
if (!method)
throw new Error(`Could not find method: ${wrapper_name} in ${klass} [${assembly}]`);
const closure: any = {
- method, get_arg, signature,
- stackSave: anyModule.stackSave, stackAlloc: anyModule.stackAlloc, stackRestore: anyModule.stackRestore,
- conv_string,
- mono_wasm_new_root, init_void, init_result, /*init_argument,*/ marshal_exception_to_js, is_args_exception,
- mono_wasm_invoke_method_bound: wrap_c_function("mono_wasm_invoke_method_bound"),
+ method, signature,
+ stackSave: anyModule.stackSave, stackRestore: anyModule.stackRestore,
+ alloc_stack_frame,
+ invoke_method_and_handle_exception
};
const bound_js_function_name = "_bound_cs_" + `${namespace}_${classname}_${methodname}`.replace(/\./g, "_").replace(/\//g, "_");
let body = `//# sourceURL=https://mono-wasm.invalid/${bound_js_function_name} \n`;
const { converters: res_converters, call_body: res_call_body, marshaler_type: res_marshaler_type } = generate_arg_marshal_to_js(get_sig(signature, 1), 1, JavaScriptMarshalerArgSize, JSMarshalerTypeSize + JSMarshalerSignatureHeaderSize, "js_result", closure);
converter_names += res_converters;
- body += `const { method, get_arg, signature, stackSave, stackAlloc, stackRestore, mono_wasm_new_root, conv_string, init_void, init_result, init_argument, marshal_exception_to_js, is_args_exception, mono_wasm_invoke_method_bound ${converter_names} } = closure;\n`;
+ body += `const { method, signature, stackSave, stackRestore, alloc_stack_frame, invoke_method_and_handle_exception ${converter_names} } = closure;\n`;
// TODO named arguments instead of arguments keyword
body += `return function ${bound_js_function_name} () {\n`;
- if (res_marshaler_type === MarshalerType.String) {
- body += "let root = null;\n";
- }
body += "const sp = stackSave();\n";
body += "try {\n";
- body += ` const args = stackAlloc(${(args_count + 2) * JavaScriptMarshalerArgSize});\n`;
- if (res_marshaler_type !== MarshalerType.Void && res_marshaler_type !== MarshalerType.Discard) {
- if (res_marshaler_type === MarshalerType.String) {
- body += " root = mono_wasm_new_root(0);\n";
- body += " init_result(args);\n";
- }
- else {
- body += " init_result(args);\n";
- }
- } else {
- body += " init_void(args);\n";
- }
+ body += ` const args = alloc_stack_frame(${(args_count + 2)});\n`;
body += bodyToCs;
- body += " const fail = mono_wasm_invoke_method_bound(method, args);\n";
- body += " if (fail) throw new Error(\"ERR22: Unexpected error: \" + conv_string(fail));\n";
- body += " if (is_args_exception(args)) throw marshal_exception_to_js(get_arg(args, 0));\n";
+ body += " invoke_method_and_handle_exception(method, args);\n";
if (res_marshaler_type !== MarshalerType.Void && res_marshaler_type !== MarshalerType.Discard) {
body += res_call_body;
}
if (res_marshaler_type !== MarshalerType.Void && res_marshaler_type !== MarshalerType.Discard) {
- body += "return js_result;\n";
+ body += " return js_result;\n";
}
body += "} finally {\n";
body += " stackRestore(sp);\n";
- if (res_marshaler_type === MarshalerType.String) {
- body += " if(root) root.release()\n";
- }
body += "}}";
const factory = new Function("closure", body);
const bound_fn = factory(closure);
}
}
-function init_void(args: JSMarshalerArguments) {
- mono_assert(args && (<any>args) % 8 == 0, "Arg alignment");
- const exc = get_arg(args, 0);
- set_arg_type(exc, MarshalerType.None);
-
- const res = get_arg(args, 1);
- set_arg_type(res, MarshalerType.None);
-}
-
-function init_result(args: JSMarshalerArguments) {
- mono_assert(args && (<any>args) % 8 == 0, "Arg alignment");
- const exc = get_arg(args, 0);
- set_arg_type(exc, MarshalerType.None);
-
- const res = get_arg(args, 1);
- set_arg_type(res, MarshalerType.None);
+export function invoke_method_and_handle_exception(method: MonoMethod, args: JSMarshalerArguments): void {
+ const fail = cwraps.mono_wasm_invoke_method_bound(method, args);
+ if (fail) throw new Error("ERR24: Unexpected error: " + conv_string(fail));
+ if (is_args_exception(args)) {
+ const exc = get_arg(args, 0);
+ throw marshal_exception_to_js(exc);
+ }
}
export const exportsByAssembly: Map<string, any> = new Map();
export async function mono_wasm_get_assembly_exports(assembly: string): Promise<any> {
mono_assert(runtimeHelpers.mono_wasm_bindings_is_ready, "Expected binding to be initialized later during startup sequence.");
- const asm = assembly_load(assembly);
- if (!asm)
- throw new Error("Could not find assembly: " + assembly);
- cwraps.mono_wasm_runtime_run_module_cctor(asm);
+ const result = exportsByAssembly.get(assembly);
+ if (!result) {
+ const asm = assembly_load(assembly);
+ if (!asm)
+ throw new Error("Could not find assembly: " + assembly);
+ cwraps.mono_wasm_runtime_run_module_cctor(asm);
+ }
return exportsByAssembly.get(assembly) || {};
+}
+
+export function parseFQN(fqn: string)
+ : { assembly: string, namespace: string, classname: string, methodname: string } {
+ const assembly = fqn.substring(fqn.indexOf("[") + 1, fqn.indexOf("]")).trim();
+ fqn = fqn.substring(fqn.indexOf("]") + 1).trim();
+
+ const methodname = fqn.substring(fqn.indexOf(":") + 1);
+ fqn = fqn.substring(0, fqn.indexOf(":")).trim();
+
+ let namespace = "";
+ let classname = fqn;
+ if (fqn.indexOf(".") != -1) {
+ const idx = fqn.lastIndexOf(".");
+ namespace = fqn.substring(0, idx);
+ classname = fqn.substring(idx + 1);
+ }
+
+ if (!assembly.trim())
+ throw new Error("No assembly name specified " + fqn);
+ if (!classname.trim())
+ throw new Error("No class name specified " + fqn);
+ if (!methodname.trim())
+ throw new Error("No method name specified " + fqn);
+ return { assembly, namespace, classname, methodname };
}
\ No newline at end of file
import { marshal_exception_to_cs, generate_arg_marshal_to_cs } from "./marshal-to-cs";
import { get_signature_argument_count, JSMarshalerArguments as JSMarshalerArguments, JavaScriptMarshalerArgSize, JSFunctionSignature as JSFunctionSignature, bound_js_function_symbol, JSMarshalerTypeSize, get_sig, JSMarshalerSignatureHeaderSize, get_signature_version, MarshalerType, get_signature_type } from "./marshal";
import { setI32 } from "./memory";
-import { wrap_error_root } from "./method-calls";
-import { conv_string_root } from "./strings";
+import { conv_string_root, js_string_to_mono_string_root } from "./strings";
import { mono_assert, JSHandle, MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "./types";
import { Int32Ptr } from "./types/emscripten";
-import { IMPORTS, INTERNAL, runtimeHelpers } from "./imports";
+import { IMPORTS, INTERNAL, Module, runtimeHelpers } from "./imports";
import { generate_arg_marshal_to_js } from "./marshal-to-js";
-import { mono_wasm_new_external_root } from "./roots";
+import { mono_wasm_new_external_root, WasmRoot } from "./roots";
+import { mono_wasm_symbolicate_string } from "./debug";
export function mono_wasm_bind_js_function(function_name: MonoStringRef, module_name: MonoStringRef, signature: JSFunctionSignature, function_js_handle: Int32Ptr, is_exception: Int32Ptr, result_address: MonoObjectRef): void {
const function_name_root = mono_wasm_new_external_root<MonoString>(function_name),
}
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+function _wrap_error_flag(is_exception: Int32Ptr | null, ex: any): string {
+ let res = "unknown exception";
+ if (ex) {
+ res = ex.toString();
+ const stack = ex.stack;
+ if (stack) {
+ // Some JS runtimes insert the error message at the top of the stack, some don't,
+ // so normalize it by using the stack as the result if it already contains the error
+ if (stack.startsWith(res))
+ res = stack;
+ else
+ res += "\n" + stack;
+ }
+
+ res = mono_wasm_symbolicate_string(res);
+ }
+ if (is_exception) {
+ Module.setValue(is_exception, 1, "i32");
+ }
+ return res;
+}
+
+// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+export function wrap_error_root(is_exception: Int32Ptr | null, ex: any, result: WasmRoot<MonoObject>): void {
+ const res = _wrap_error_flag(is_exception, ex);
+ js_string_to_mono_string_root(res, <any>result);
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import { GCHandle, MonoMethod, mono_assert } from "./types";
+import cwraps from "./cwraps";
+import { Module, runtimeHelpers } from "./imports";
+import { alloc_stack_frame, get_arg, get_arg_gc_handle, MarshalerToCs, MarshalerToJs, MarshalerType, set_arg_type, set_gc_handle } from "./marshal";
+import { invoke_method_and_handle_exception } from "./invoke-cs";
+import { marshal_exception_to_cs } from "./marshal-to-cs";
+
+// in all the exported internals methods, we use the same data structures for stack frame as normal full blow interop
+// see src\libraries\System.Runtime.InteropServices.JavaScript\src\System\Runtime\InteropServices\JavaScript\Interop\JavaScriptExports.cs
+export interface JavaScriptExports {
+ // the marshaled signature is: void ReleaseJSOwnedObjectByGCHandle(GCHandle gcHandle)
+ _release_js_owned_object_by_gc_handle(gc_handle: GCHandle): void;
+ // the marshaled signature is: GCHandle CreateTaskCallback()
+ _create_task_callback(): GCHandle;
+ // the marshaled signature is: void CompleteTask<T>(GCHandle holder, Exception? exceptionResult, T? result)
+ _complete_task(holder_gc_handle: GCHandle, error?: any, data?: any, res_converter?: MarshalerToCs): void;
+ // the marshaled signature is: TRes? CallDelegate<T1,T2,T3TRes>(GCHandle callback, T1? arg1, T2? arg2, T3? arg3)
+ _call_delegate(callback_gc_handle: GCHandle, arg1_js: any, arg2_js: any, arg3_js: any,
+ res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs, arg3_converter?: MarshalerToCs): any;
+}
+
+export function init_managed_exports(): void {
+ const anyModule = Module as any;
+ const exports_fqn_asm = "System.Runtime.InteropServices.JavaScript";
+ runtimeHelpers.runtime_interop_module = cwraps.mono_wasm_assembly_load(exports_fqn_asm);
+ if (!runtimeHelpers.runtime_interop_module)
+ throw "Can't find bindings module assembly: " + exports_fqn_asm;
+
+ runtimeHelpers.runtime_interop_namespace = "System.Runtime.InteropServices.JavaScript";
+ runtimeHelpers.runtime_interop_exports_classname = "JavaScriptExports";
+ runtimeHelpers.runtime_interop_exports_class = cwraps.mono_wasm_assembly_find_class(runtimeHelpers.runtime_interop_module, runtimeHelpers.runtime_interop_namespace, runtimeHelpers.runtime_interop_exports_classname);
+ if (!runtimeHelpers.runtime_interop_exports_class)
+ throw "Can't find " + runtimeHelpers.runtime_interop_namespace + "." + runtimeHelpers.runtime_interop_exports_classname + " class";
+
+
+ const release_js_owned_object_by_gc_handle_method = get_method("ReleaseJSOwnedObjectByGCHandle");
+ mono_assert(release_js_owned_object_by_gc_handle_method, "Can't find ReleaseJSOwnedObjectByGCHandle method");
+ const create_task_callback_method = get_method("CreateTaskCallback");
+ mono_assert(create_task_callback_method, "Can't find CreateTaskCallback method");
+ const complete_task_method = get_method("CompleteTask");
+ mono_assert(complete_task_method, "Can't find CompleteTask method");
+ const call_delegate_method = get_method("CallDelegate");
+ mono_assert(call_delegate_method, "Can't find CallDelegate method");
+
+ runtimeHelpers.javaScriptExports._release_js_owned_object_by_gc_handle = (gc_handle: GCHandle) => {
+ if (!gc_handle) {
+ Module.printErr("Must be valid gc_handle");
+ }
+ mono_assert(gc_handle, "Must be valid gc_handle");
+ const sp = anyModule.stackSave();
+ try {
+ const args = alloc_stack_frame(3);
+ const arg1 = get_arg(args, 2);
+ set_gc_handle(arg1, gc_handle);
+ invoke_method_and_handle_exception(release_js_owned_object_by_gc_handle_method, args);
+ } finally {
+ anyModule.stackRestore(sp);
+ }
+ };
+ runtimeHelpers.javaScriptExports._create_task_callback = () => {
+ const sp = anyModule.stackSave();
+ try {
+ const args = alloc_stack_frame(2);
+ invoke_method_and_handle_exception(create_task_callback_method, args);
+ const res = get_arg(args, 1);
+ return get_arg_gc_handle(res);
+ } finally {
+ anyModule.stackRestore(sp);
+ }
+ };
+ runtimeHelpers.javaScriptExports._complete_task = (holder_gc_handle: GCHandle, error?: any, data?: any, res_converter?: MarshalerToCs) => {
+ const sp = anyModule.stackSave();
+ try {
+ const args = alloc_stack_frame(5);
+ const arg1 = get_arg(args, 2);
+ set_gc_handle(arg1, holder_gc_handle);
+ const arg2 = get_arg(args, 3);
+ if (error) {
+ marshal_exception_to_cs(arg2, error);
+ } else {
+ set_arg_type(arg2, MarshalerType.None);
+ const arg3 = get_arg(args, 4);
+ mono_assert(res_converter, "res_converter missing");
+ res_converter(arg3, data);
+ }
+ invoke_method_and_handle_exception(complete_task_method, args);
+ } finally {
+ anyModule.stackRestore(sp);
+ }
+ };
+ runtimeHelpers.javaScriptExports._call_delegate = (callback_gc_handle: GCHandle, arg1_js: any, arg2_js: any, arg3_js: any, res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs, arg3_converter?: MarshalerToCs) => {
+ const sp = anyModule.stackSave();
+ try {
+ const args = alloc_stack_frame(6);
+
+ const arg1 = get_arg(args, 2);
+ set_gc_handle(arg1, callback_gc_handle);
+ // payload arg numbers are shifted by one, the real first is a gc handle of the callback
+
+ if (arg1_converter) {
+ const arg2 = get_arg(args, 3);
+ arg1_converter(arg2, arg1_js);
+ }
+ if (arg2_converter) {
+ const arg3 = get_arg(args, 4);
+ arg2_converter(arg3, arg2_js);
+ }
+ if (arg3_converter) {
+ const arg4 = get_arg(args, 5);
+ arg3_converter(arg4, arg3_js);
+ }
+
+ invoke_method_and_handle_exception(call_delegate_method, args);
+
+ if (res_converter) {
+ const res = get_arg(args, 1);
+ return res_converter(res);
+ }
+ } finally {
+ anyModule.stackRestore(sp);
+ }
+ };
+}
+
+export function get_method(method_name: string): MonoMethod {
+ const res = cwraps.mono_wasm_assembly_find_method(runtimeHelpers.runtime_interop_exports_class, method_name, -1);
+ if (!res)
+ throw "Can't find method " + runtimeHelpers.runtime_interop_namespace + "." + runtimeHelpers.runtime_interop_exports_classname + "." + method_name;
+ return res;
+}
\ No newline at end of file
// The .NET Foundation licenses this file to you under the MIT license.
import { isThenable } from "./cancelable-promise";
-import wrapped_cs_functions from "./corebindings";
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 {
JSMarshalerArgument, 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,
- set_arg_length, get_arg, is_args_exception, JavaScriptMarshalerArgSize, get_signature_type, get_signature_arg1_type, get_signature_arg2_type, cs_to_js_marshalers, js_to_cs_marshalers,
- MarshalerToCs, MarshalerToJs, get_signature_res_type, JSMarshalerArguments, bound_js_function_symbol, set_arg_u16, JSMarshalerType, array_element_size, get_string_root, Span, ArraySegment, MemoryViewType, get_signature_arg3_type, MarshalerType, set_arg_i64_big, set_arg_intptr, IDisposable, set_arg_element_type, ManagedObject
+ set_arg_length, get_arg, get_signature_type, get_signature_arg1_type, get_signature_arg2_type, cs_to_js_marshalers, js_to_cs_marshalers,
+ MarshalerToCs, MarshalerToJs, get_signature_res_type, JSMarshalerArguments, bound_js_function_symbol, set_arg_u16, JSMarshalerType, array_element_size,
+ get_string_root, Span, ArraySegment, MemoryViewType, get_signature_arg3_type, MarshalerType, set_arg_i64_big, set_arg_intptr, IDisposable,
+ set_arg_element_type, ManagedObject
} from "./marshal";
-import { marshal_exception_to_js } from "./marshal-to-js";
import { _zero_region } from "./memory";
-import { conv_string, js_string_to_mono_string_root } from "./strings";
+import { js_string_to_mono_string_root } from "./strings";
import { mono_assert, GCHandle, GCHandleNull } from "./types";
import { TypedArray } from "./types/emscripten";
}
mono_assert(isThenable(value), "Value is not a Promise");
- const anyModule = Module as any;
- const gc_handle: GCHandle = wrapped_cs_functions._create_task_callback();
+ const gc_handle: GCHandle = runtimeHelpers.javaScriptExports._create_task_callback();
set_gc_handle(arg, gc_handle);
set_arg_type(arg, MarshalerType.Task);
const holder = new TaskCallbackHolder(value);
setup_managed_proxy(holder, gc_handle);
value.then(data => {
- const sp = anyModule.stackSave();
- try {
- const args = anyModule.stackAlloc(JavaScriptMarshalerArgSize * 3);
- const exc = get_arg(args, 0);
- set_arg_type(exc, MarshalerType.None);
- const res = get_arg(args, 1);
- set_arg_type(res, MarshalerType.None);
- set_gc_handle(res, <any>gc_handle);
- const arg1 = get_arg(args, 2);
- if (!res_converter) {
- _marshal_cs_object_to_cs(arg1, data);
- } else {
- res_converter(arg1, data);
- }
- const fail = cwraps.mono_wasm_invoke_method_bound(runtimeHelpers.complete_task_method, args);
- if (fail) throw new Error("ERR22: Unexpected error: " + conv_string(fail));
- if (is_args_exception(args)) throw marshal_exception_to_js(exc);
- } finally {
- anyModule.stackRestore(sp);
- }
+ runtimeHelpers.javaScriptExports._complete_task(gc_handle, null, data, res_converter || _marshal_cs_object_to_cs);
teardown_managed_proxy(holder, gc_handle); // this holds holder alive for finalizer, until the promise is freed, (holding promise instead would not work)
}).catch(reason => {
- const sp = anyModule.stackSave();
- try {
- const args = anyModule.stackAlloc(JavaScriptMarshalerArgSize * 3);
- const res = get_arg(args, 1);
- set_arg_type(res, MarshalerType.None);
- set_gc_handle(res, gc_handle);
- const exc = get_arg(args, 0);
- if (typeof reason === "string" || reason === null || reason === undefined) {
- reason = new Error(reason || "");
- }
- marshal_exception_to_cs(exc, reason);
- const fail = cwraps.mono_wasm_invoke_method_bound(runtimeHelpers.complete_task_method, args);
- if (fail) throw new Error("ERR24: Unexpected error: " + conv_string(fail));
- if (is_args_exception(args)) throw marshal_exception_to_js(exc);
- } finally {
- anyModule.stackRestore(sp);
- }
+ runtimeHelpers.javaScriptExports._complete_task(gc_handle, reason, null, undefined);
teardown_managed_proxy(holder, gc_handle); // this holds holder alive for finalizer, until the promise is freed
});
}
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,
get_arg_b8, get_arg_date, get_arg_length, set_js_handle, get_arg, set_arg_type,
get_signature_arg2_type, get_signature_arg1_type, get_signature_type, cs_to_js_marshalers, js_to_cs_marshalers,
- get_signature_res_type, JavaScriptMarshalerArgSize, set_gc_handle, is_args_exception, get_arg_u16, array_element_size, get_string_root, ArraySegment, Span, MemoryViewType, get_signature_arg3_type, MarshalerType, get_arg_i64_big, get_arg_intptr, get_arg_element_type
+ get_signature_res_type, get_arg_u16, array_element_size, get_string_root,
+ ArraySegment, Span, MemoryViewType, get_signature_arg3_type, MarshalerType, get_arg_i64_big, get_arg_intptr, get_arg_element_type
} from "./marshal";
-import { conv_string, conv_string_root } from "./strings";
+import { conv_string_root } from "./strings";
import { mono_assert, JSHandleNull, GCHandleNull } from "./types";
import { TypedArray } from "./types/emscripten";
return null;
}
- const anyModule = Module as any;
const gc_handle = get_arg_gc_handle(arg);
let result = _lookup_js_owned_object(gc_handle);
if (result === null || result === undefined) {
// this will create new Function for the C# delegate
- result = (arg1_js: any, arg2_js: any, arg3_js: any) => {
-
- const sp = anyModule.stackSave();
- try {
- const args = anyModule.stackAlloc(JavaScriptMarshalerArgSize * 5);
- const exc = get_arg(args, 0);
- set_arg_type(exc, MarshalerType.None);
- const res = get_arg(args, 1);
- set_arg_type(res, MarshalerType.None);
- set_gc_handle(res, <any>gc_handle);
- const arg1 = get_arg(args, 2);
- const arg2 = get_arg(args, 3);
- const arg3 = get_arg(args, 4);
-
- if (arg1_converter) {
- arg1_converter(arg1, arg1_js);
- }
- if (arg2_converter) {
- arg2_converter(arg2, arg2_js);
- }
- if (arg3_converter) {
- arg3_converter(arg3, arg3_js);
- }
-
- const fail = cwraps.mono_wasm_invoke_method_bound(runtimeHelpers.call_delegate, args);
- if (fail) throw new Error("ERR23: Unexpected error: " + conv_string(fail));
- if (is_args_exception(args)) throw marshal_exception_to_js(exc);
-
- if (res_converter) {
- return res_converter(res);
- }
-
- } finally {
- anyModule.stackRestore(sp);
- }
+ result = (arg1_js: any, arg2_js: any, arg3_js: any): any => {
+ // arg numbers are shifted by one, the real first is a gc handle of the callback
+ return runtimeHelpers.javaScriptExports._call_delegate(gc_handle, arg1_js, arg2_js, arg3_js, res_converter, arg1_converter, arg2_converter, arg3_converter);
};
-
setup_managed_proxy(result, gc_handle);
}
__brand: "JSMarshalerArgument"
}
+export function alloc_stack_frame(size: number): JSMarshalerArguments {
+ const anyModule = Module as any;
+ const args = anyModule.stackAlloc(JavaScriptMarshalerArgSize * size);
+ mono_assert(args && (<any>args) % 8 == 0, "Arg alignment");
+ const exc = get_arg(args, 0);
+ set_arg_type(exc, MarshalerType.None);
+ const res = get_arg(args, 1);
+ set_arg_type(res, MarshalerType.None);
+ return args;
+}
+
export function get_arg(args: JSMarshalerArguments, index: number): JSMarshalerArgument {
mono_assert(args, "Null args");
return <any>args + (index * JavaScriptMarshalerArgSize);
}
}
+// @bytes must be a typed array. space is allocated for it in the native heap
+// and it is copied to that location. returns the address of the allocation.
+export function mono_wasm_load_bytes_into_heap(bytes: Uint8Array): VoidPtr {
+ const memoryOffset = Module._malloc(bytes.length);
+ const heapBytes = new Uint8Array(Module.HEAPU8.buffer, <any>memoryOffset, bytes.length);
+ heapBytes.set(bytes);
+ return memoryOffset;
+}
+
const BuiltinAtomics = globalThis.Atomics;
export const Atomics = monoWasmThreads ? {
} : {
storeI32: setI32,
notifyI32: () => { /*empty*/ }
-};
+};
\ No newline at end of file
--- /dev/null
+import { Module } from "../imports";
+import { wrap_error_root } from "../invoke-js";
+import { mono_wasm_new_external_root } from "../roots";
+import { MonoArray, MonoObjectRef, MonoObject } from "../types";
+import { Int32Ptr, TypedArray } from "../types/emscripten";
+import { js_to_mono_obj_root } from "./js-to-cs";
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export function mono_wasm_typed_array_from_ref(pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number, type: number, is_exception: Int32Ptr, result_address: MonoObjectRef): void {
+ const resultRoot = mono_wasm_new_external_root<MonoObject>(result_address);
+ try {
+ const res = typed_array_from(pinned_array, begin, end, bytes_per_element, type);
+ // returns JS typed array like Int8Array, to be wraped with JSObject proxy
+ js_to_mono_obj_root(res, resultRoot, true);
+ } catch (exc) {
+ wrap_error_root(is_exception, String(exc), resultRoot);
+ } finally {
+ resultRoot.release();
+ }
+}
+
+// Creates a new typed array from pinned array address from pinned_array allocated on the heap to the typed array.
+// address of managed pinned array -> copy from heap -> typed array memory
+function typed_array_from(pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number, type: number) {
+
+ // typed array
+ let newTypedArray: TypedArray | null = null;
+
+ switch (type) {
+ case 5:
+ newTypedArray = new Int8Array(end - begin);
+ break;
+ case 6:
+ newTypedArray = new Uint8Array(end - begin);
+ break;
+ case 7:
+ newTypedArray = new Int16Array(end - begin);
+ break;
+ case 8:
+ newTypedArray = new Uint16Array(end - begin);
+ break;
+ case 9:
+ newTypedArray = new Int32Array(end - begin);
+ break;
+ case 10:
+ newTypedArray = new Uint32Array(end - begin);
+ break;
+ case 13:
+ newTypedArray = new Float32Array(end - begin);
+ break;
+ case 14:
+ newTypedArray = new Float64Array(end - begin);
+ break;
+ case 15: // This is a special case because the typed array is also byte[]
+ newTypedArray = new Uint8ClampedArray(end - begin);
+ break;
+ default:
+ throw new Error("Unknown array type " + type);
+ }
+
+ typedarray_copy_from(newTypedArray, pinned_array, begin, end, bytes_per_element);
+ return newTypedArray;
+}
+
+// Copy the pinned array address from pinned_array allocated on the heap to the typed array.
+// address of managed pinned array -> copy from heap -> typed array memory
+function typedarray_copy_from(typed_array: TypedArray, pinned_array: MonoArray, begin: number, end: number, bytes_per_element: number) {
+
+ // JavaScript typed arrays are array-like objects and provide a mechanism for accessing
+ // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays
+ // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
+ // is an object representing a chunk of data; it has no format to speak of, and offers no
+ // mechanism for accessing its contents. In order to access the memory contained in a buffer,
+ // you need to use a view. A view provides a context - that is, a data type, starting offset,
+ // and number of elements - that turns the data into an actual typed array.
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
+ if (has_backing_array_buffer(typed_array) && typed_array.BYTES_PER_ELEMENT) {
+ // Some sanity checks of what is being asked of us
+ // lets play it safe and throw an error here instead of assuming to much.
+ // Better safe than sorry later
+ if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
+ throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
+
+ // how much space we have to work with
+ let num_of_bytes = (end - begin) * bytes_per_element;
+ // how much typed buffer space are we talking about
+ const view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
+ // only use what is needed.
+ if (num_of_bytes > view_bytes)
+ num_of_bytes = view_bytes;
+
+ // Create a new view for mapping
+ const typedarrayBytes = new Uint8Array(typed_array.buffer, 0, num_of_bytes);
+ // offset index into the view
+ const offset = begin * bytes_per_element;
+ // Set view bytes to value from HEAPU8
+ typedarrayBytes.set(Module.HEAPU8.subarray(<any>pinned_array + offset, <any>pinned_array + offset + num_of_bytes));
+ return num_of_bytes;
+ }
+ else {
+ throw new Error("Object '" + typed_array + "' is not a typed array");
+ }
+}
+
+
+export function has_backing_array_buffer(js_obj: TypedArray): boolean {
+ return typeof SharedArrayBuffer !== "undefined"
+ ? js_obj.buffer instanceof ArrayBuffer || js_obj.buffer instanceof SharedArrayBuffer
+ : js_obj.buffer instanceof ArrayBuffer;
+}
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import { JSHandle, GCHandle, MonoObjectRef, MonoMethod, MonoObject } from "../types";
+import { mono_bind_method, _create_primitive_converters } from "./method-binding";
+import { WasmRoot } from "../roots";
+import { runtimeHelpers } from "../imports";
+import cwraps from "../cwraps";
+import { PromiseController } from "../promise-controller";
+type SigLine = [lazy: boolean, jsname: string, csname: string, signature: string/*ArgsMarshalString*/];
+const fn_signatures: SigLine[] = [
+ [true, "_get_cs_owned_object_by_js_handle_ref", "GetCSOwnedObjectByJSHandleRef", "iim"],
+ [true, "_get_cs_owned_object_js_handle_ref", "GetCSOwnedObjectJSHandleRef", "mi"],
+ [true, "_try_get_cs_owned_object_js_handle_ref", "TryGetCSOwnedObjectJSHandleRef", "mi"],
+ [false, "_create_cs_owned_proxy_ref", "CreateCSOwnedProxyRef", "iiim"],
+
+ [false, "_get_js_owned_object_by_gc_handle_ref", "GetJSOwnedObjectByGCHandleRef", "im"],
+ [true, "_get_js_owned_object_gc_handle_ref", "GetJSOwnedObjectGCHandleRef", "m"],
+
+ [true, "_create_tcs", "CreateTaskSource", ""],
+ [true, "_set_tcs_result_ref", "SetTaskSourceResultRef", "iR"],
+ [true, "_set_tcs_failure", "SetTaskSourceFailure", "is"],
+ [true, "_get_tcs_task_ref", "GetTaskSourceTaskRef", "im"],
+ [true, "_setup_js_cont_ref", "SetupJSContinuationRef", "mo"],
+
+ [true, "_object_to_string_ref", "ObjectToStringRef", "m"],
+ [true, "_get_date_value_ref", "GetDateValueRef", "m"],
+ [true, "_create_date_time_ref", "CreateDateTimeRef", "dm"],
+ [true, "_create_uri_ref", "CreateUriRef", "sm"],
+ [true, "_is_simple_array_ref", "IsSimpleArrayRef", "m"],
+ [false, "_get_call_sig_ref", "GetCallSignatureRef", "im"],
+];
+
+export interface LegacyExports {
+ // see src\libraries\System.Runtime.InteropServices.JavaScript\src\System\Runtime\InteropServices\JavaScript\Interop\LegacyExports.cs
+ _get_cs_owned_object_by_js_handle_ref(jsHandle: JSHandle, shouldAddInflight: 0 | 1, result: MonoObjectRef): void;
+ _get_cs_owned_object_js_handle_ref(obj: MonoObjectRef, shouldAddInflight: 0 | 1): JSHandle;
+ _try_get_cs_owned_object_js_handle_ref(obj: MonoObjectRef, shouldAddInflight: 0 | 1): JSHandle;
+ _create_cs_owned_proxy_ref(jsHandle: JSHandle, mappedType: number, shouldAddInflight: 0 | 1, result: MonoObjectRef): void;
+
+ _get_js_owned_object_by_gc_handle_ref(gcHandle: GCHandle, result: MonoObjectRef): void;
+ _get_js_owned_object_gc_handle_ref(obj: MonoObjectRef): GCHandle
+
+ _create_tcs(): GCHandle;
+ _set_tcs_result_ref(gcHandle: GCHandle, result: any): void
+ _set_tcs_failure(gcHandle: GCHandle, result: string): void
+ _get_tcs_task_ref(gcHandle: GCHandle, result: MonoObjectRef): void;
+ _setup_js_cont_ref(task: MonoObjectRef, continuation: PromiseController): void;
+
+ _object_to_string_ref(obj: MonoObjectRef): string;
+ _get_date_value_ref(obj: MonoObjectRef): number;
+ _create_date_time_ref(ticks: number, result: MonoObjectRef): void;
+ _create_uri_ref(uri: string, result: MonoObjectRef): void;
+ _is_simple_array_ref(obj: MonoObjectRef): boolean;
+ _get_call_sig_ref(method: MonoMethod, obj: WasmRoot<MonoObject>): string;
+}
+
+export const legacyManagedExports: LegacyExports = <any>{};
+
+
+export function bind_runtime_method(method_name: string, signature: string): Function {
+ const method = get_method(method_name);
+ return mono_bind_method(method, signature, false, "BINDINGS_" + method_name);
+}
+
+export function init_legacy_exports(): void {
+ _create_primitive_converters();
+
+ runtimeHelpers.runtime_legacy_exports_classname = "LegacyExports";
+ runtimeHelpers.runtime_legacy_exports_class = cwraps.mono_wasm_assembly_find_class(runtimeHelpers.runtime_interop_module, runtimeHelpers.runtime_interop_namespace, runtimeHelpers.runtime_legacy_exports_classname);
+ if (!runtimeHelpers.runtime_legacy_exports_class)
+ throw "Can't find " + runtimeHelpers.runtime_interop_namespace + "." + runtimeHelpers.runtime_interop_exports_classname + " class";
+
+ for (const sig of fn_signatures) {
+ const wf: any = legacyManagedExports;
+ const [lazy, jsname, csname, signature] = sig;
+ if (lazy) {
+ // lazy init on first run
+ wf[jsname] = function (...args: any[]) {
+ const fce = bind_runtime_method(csname, signature);
+ wf[jsname] = fce;
+ return fce(...args);
+ };
+ }
+ else {
+ const fce = bind_runtime_method(csname, signature);
+ wf[jsname] = fce;
+ }
+ }
+}
+
+export function get_method(method_name: string): MonoMethod {
+ const res = cwraps.mono_wasm_assembly_find_method(runtimeHelpers.runtime_legacy_exports_class, method_name, -1);
+ if (!res)
+ throw "Can't find method " + runtimeHelpers.runtime_interop_namespace + "." + runtimeHelpers.runtime_legacy_exports_classname + "." + method_name;
+ return res;
+}
\ 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 { mono_wasm_new_root, WasmRoot, mono_wasm_new_external_root } from "./roots";
-import {
- GCHandle, JSHandleDisposed, MarshalError, MarshalType, MonoArray,
- MonoArrayNull, MonoObject, MonoObjectNull, MonoString,
- MonoType, MonoTypeNull, MonoObjectRef, MonoStringRef, is_nullish
-} from "./types";
-import { runtimeHelpers } from "./imports";
-import { conv_string_root } from "./strings";
-import corebindings from "./corebindings";
-import cwraps from "./cwraps";
-import { get_js_owned_object_by_gc_handle_ref, js_owned_gc_handle_symbol, mono_wasm_get_jsobj_from_js_handle, mono_wasm_get_js_handle, setup_managed_proxy, teardown_managed_proxy, _lookup_js_owned_object } from "./gc-handles";
-import { mono_method_get_call_signature_ref, call_method_ref, wrap_error_root } from "./method-calls";
+import { _are_promises_supported } from "../cancelable-promise";
+import cwraps from "../cwraps";
+import { mono_wasm_get_jsobj_from_js_handle, _lookup_js_owned_object, setup_managed_proxy, mono_wasm_get_js_handle, teardown_managed_proxy, assert_not_disposed } from "../gc-handles";
+import { runtimeHelpers } from "../imports";
+import { wrap_error_root } from "../invoke-js";
+import { ManagedObject } from "../marshal";
+import { getU32, getI32, getF32, getF64, setI32_unchecked } from "../memory";
+import { createPromiseController } from "../promise-controller";
+import { WasmRoot, mono_wasm_new_root, mono_wasm_new_external_root } from "../roots";
+import { conv_string_root } from "../strings";
+import { MarshalType, MonoType, MarshalError, MonoTypeNull, MonoArray, MonoArrayNull, MonoObject, MonoObjectNull, GCHandle, MonoStringRef, MonoObjectRef, MonoString, JSHandleDisposed, is_nullish } from "../types";
+import { Int32Ptr, VoidPtr } from "../types/emscripten";
+import { legacyManagedExports } from "./corebindings";
import { js_to_mono_obj_root } from "./js-to-cs";
-import { _are_promises_supported } from "./cancelable-promise";
-import { getU32, getI32, getF32, getF64 } from "./memory";
-import { Int32Ptr, VoidPtr } from "./types/emscripten";
-import { ManagedObject } from "./marshal";
-import { createPromiseController } from "./promise-controller";
+import { mono_bind_method, mono_method_get_call_signature_ref } from "./method-binding";
const delegate_invoke_symbol = Symbol.for("wasm delegate_invoke");
-const delegate_invoke_signature_symbol = Symbol.for("wasm delegate_invoke_signature");
// this is only used from Blazor
export function unbox_mono_obj(mono_obj: MonoObject): any {
function _unbox_cs_owned_root_as_js_object(root: WasmRoot<any>) {
// we don't need in-flight reference as we already have it rooted here
- const js_handle = corebindings._get_cs_owned_object_js_handle_ref(root.address, 0);
+ const js_handle = legacyManagedExports._get_cs_owned_object_js_handle_ref(root.address, 0);
const js_obj = mono_wasm_get_jsobj_from_js_handle(js_handle);
return js_obj;
}
case MarshalType.ARRAY_DOUBLE:
throw new Error("Marshaling of primitive arrays are not supported.");
case <MarshalType>20: // clr .NET DateTime
- return new Date(corebindings._get_date_value_ref(root.address));
+ return new Date(legacyManagedExports._get_date_value_ref(root.address));
case <MarshalType>21: // clr .NET DateTimeOffset
- return corebindings._object_to_string_ref(root.address);
+ return legacyManagedExports._object_to_string_ref(root.address);
case MarshalType.URI:
- return corebindings._object_to_string_ref(root.address);
+ return legacyManagedExports._object_to_string_ref(root.address);
case MarshalType.SAFEHANDLE:
return _unbox_cs_owned_root_as_js_object(root);
case MarshalType.VOID:
}
function is_nested_array_ref(ele: WasmRoot<MonoObject>) {
- return corebindings._is_simple_array_ref(ele.address);
+ return legacyManagedExports._is_simple_array_ref(ele.address);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
return null;
// get strong reference to the Delegate
- const gc_handle = corebindings._get_js_owned_object_gc_handle_ref(root.address);
+ const gc_handle = legacyManagedExports._get_js_owned_object_gc_handle_ref(root.address);
return _wrap_delegate_gc_handle_as_function(gc_handle);
}
-export function _wrap_delegate_gc_handle_as_function(gc_handle: GCHandle, after_listener_callback?: () => void): Function {
+export function _wrap_delegate_gc_handle_as_function(gc_handle: GCHandle): Function {
// see if we have js owned instance for this gc_handle already
let result = _lookup_js_owned_object(gc_handle);
+
// If the function for this gc_handle was already collected (or was never created)
if (!result) {
+
// note that we do not implement function/delegate roundtrip
result = function (...args: any[]) {
- const delegateRoot = mono_wasm_new_root<MonoObject>();
- get_js_owned_object_by_gc_handle_ref(gc_handle, delegateRoot.address);
- try {
- // FIXME: Pass delegateRoot by-ref
- const res = call_method_ref(result[delegate_invoke_symbol], delegateRoot, result[delegate_invoke_signature_symbol], args);
- if (after_listener_callback) {
- after_listener_callback();
- }
- return res;
- } finally {
- delegateRoot.release();
- }
+ assert_not_disposed(result);
+ const boundMethod = result[delegate_invoke_symbol];
+ return boundMethod(...args);
};
// bind the method
get_js_owned_object_by_gc_handle_ref(gc_handle, delegateRoot.address);
try {
if (typeof result[delegate_invoke_symbol] === "undefined") {
- result[delegate_invoke_symbol] = cwraps.mono_wasm_get_delegate_invoke_ref(delegateRoot.address);
+ const method = cwraps.mono_wasm_get_delegate_invoke_ref(delegateRoot.address);
+ const signature = mono_method_get_call_signature_ref(method, delegateRoot);
+ const js_method = mono_bind_method(method, signature, true);
+ result[delegate_invoke_symbol] = js_method.bind({ this_arg_gc_handle: gc_handle });
if (!result[delegate_invoke_symbol]) {
throw new Error("System.Delegate Invoke method can not be resolved.");
}
}
-
- if (typeof result[delegate_invoke_signature_symbol] === "undefined") {
- result[delegate_invoke_signature_symbol] = mono_method_get_call_signature_ref(result[delegate_invoke_symbol], delegateRoot);
- }
} finally {
delegateRoot.release();
}
setup_managed_proxy(result, gc_handle);
+ } else {
+ assert_not_disposed(result);
}
return result;
throw new Error("Promises are not supported thus 'System.Threading.Tasks.Task' can not work in this context.");
// get strong reference to Task
- const gc_handle = corebindings._get_js_owned_object_gc_handle_ref(root.address);
+ const gc_handle = legacyManagedExports._get_js_owned_object_gc_handle_ref(root.address);
// see if we have js owned instance for this gc_handle already
let result = _lookup_js_owned_object(gc_handle);
result = promise;
// register C# side of the continuation
- corebindings._setup_js_cont_ref(root.address, promise_control);
+ legacyManagedExports._setup_js_cont_ref(root.address, promise_control);
setup_managed_proxy(result, gc_handle);
}
// this could be JSObject proxy of a js native object
// we don't need in-flight reference as we already have it rooted here
- const js_handle = corebindings._try_get_cs_owned_object_js_handle_ref(root.address, 0);
+ const js_handle = legacyManagedExports._try_get_cs_owned_object_js_handle_ref(root.address, 0);
if (js_handle) {
if (js_handle === JSHandleDisposed) {
throw new Error("Cannot access a disposed JSObject at " + root.value);
// otherwise this is C# only object
// get strong reference to Object
- const gc_handle = corebindings._get_js_owned_object_gc_handle_ref(root.address);
+ const gc_handle = legacyManagedExports._get_js_owned_object_gc_handle_ref(root.address);
// see if we have js owned instance for this gc_handle already
let result = _lookup_js_owned_object(gc_handle);
if (is_nullish(result)) {
result = new ManagedObject();
- // keep the gc_handle so that we could easily convert it back to original C# object for roundtrip
- result[js_owned_gc_handle_symbol] = gc_handle;
-
setup_managed_proxy(result, gc_handle);
}
return result;
}
+
+export function get_js_owned_object_by_gc_handle_ref(gc_handle: GCHandle, result: MonoObjectRef): void {
+ if (!gc_handle) {
+ setI32_unchecked(result, 0);
+ return;
+ }
+ // this is always strong gc_handle
+ legacyManagedExports._get_js_owned_object_by_gc_handle_ref(gc_handle, result);
+}
\ No newline at end of file
--- /dev/null
+import cwraps from "../cwraps";
+import { mono_wasm_runtime_ready } from "../debug";
+import diagnostics, { Diagnostics } from "../diagnostics";
+import { mono_wasm_load_icu_data } from "../icu";
+import { runtimeHelpers } from "../imports";
+import { mono_wasm_get_assembly_exports } from "../invoke-cs";
+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";
+import { mono_wasm_setenv, mono_wasm_load_data_archive, mono_wasm_load_config, mono_load_runtime_and_bcl_args } from "../startup";
+import { js_string_to_mono_string, conv_string, js_string_to_mono_string_root, conv_string_root } from "../strings";
+import { MonoArray, MonoConfig, MonoConfigError, MonoObject, MonoObjectRef } from "../types";
+import { VoidPtr } from "../types/emscripten";
+import { mono_array_to_js_array, unbox_mono_obj, unbox_mono_obj_root, mono_array_root_to_js_array } from "./cs-to-js";
+import { js_typed_array_to_array, js_to_mono_obj, js_typed_array_to_array_root, js_to_mono_obj_root } from "./js-to-cs";
+import { mono_bind_static_method, mono_call_assembly_entry_point } from "./method-calls";
+import { mono_wasm_load_runtime } from "../startup";
+
+export function export_mono_api(): MONOType {
+ return {
+ // current "public" MONO API
+ mono_wasm_setenv,
+ mono_wasm_load_bytes_into_heap,
+ mono_wasm_load_icu_data,
+ mono_wasm_runtime_ready,
+ mono_wasm_load_data_archive,
+ mono_wasm_load_config,
+ mono_load_runtime_and_bcl_args,
+ mono_wasm_new_root_buffer,
+ mono_wasm_new_root,
+ mono_wasm_new_external_root,
+ mono_wasm_release_roots,
+ mono_run_main,
+ mono_run_main_and_exit,
+ mono_wasm_get_assembly_exports,
+
+ // for Blazor's future!
+ mono_wasm_add_assembly: <any>null,
+ mono_wasm_load_runtime,
+
+ config: <MonoConfig | MonoConfigError>runtimeHelpers.config,
+ loaded_files: <string[]>[],
+
+ // memory accessors
+ setB32,
+ setI8,
+ setI16,
+ setI32,
+ setI52,
+ setU52,
+ setI64Big,
+ setU8,
+ setU16,
+ setU32,
+ setF32,
+ setF64,
+ getB32,
+ getI8,
+ getI16,
+ getI32,
+ getI52,
+ getU52,
+ getI64Big,
+ getU8,
+ getU16,
+ getU32,
+ getF32,
+ getF64,
+
+ // Diagnostics
+ diagnostics
+ };
+}
+
+export function cwraps_mono_api(mono: MONOType): void {
+ Object.assign(mono, {
+ mono_wasm_add_assembly: cwraps.mono_wasm_add_assembly,
+ });
+}
+
+export function export_binding_api(): BINDINGType {
+ return {
+ //current "public" BINDING API
+ bind_static_method: mono_bind_static_method,
+ call_assembly_entry_point: mono_call_assembly_entry_point,
+ mono_obj_array_new: <any>null,
+ mono_obj_array_set: <any>null,
+ js_string_to_mono_string,
+ js_typed_array_to_array,
+ mono_array_to_js_array,
+ js_to_mono_obj,
+ conv_string,
+ unbox_mono_obj,
+
+ mono_obj_array_new_ref: <any>null,
+ mono_obj_array_set_ref: <any>null,
+ js_string_to_mono_string_root,
+ js_typed_array_to_array_root,
+ js_to_mono_obj_root,
+ conv_string_root,
+ unbox_mono_obj_root,
+ mono_array_root_to_js_array,
+ };
+}
+
+export function cwraps_binding_api(binding: BINDINGType): void {
+ Object.assign(binding, {
+ mono_obj_array_new: cwraps.mono_wasm_obj_array_new,
+ mono_obj_array_set: cwraps.mono_wasm_obj_array_set,
+ mono_obj_array_new_ref: cwraps.mono_wasm_obj_array_new_ref,
+ mono_obj_array_set_ref: cwraps.mono_wasm_obj_array_set_ref,
+ });
+}
+
+export type BINDINGType = {
+ bind_static_method: typeof mono_bind_static_method;
+ call_assembly_entry_point: typeof mono_call_assembly_entry_point;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ mono_obj_array_new: (size: number) => MonoArray;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ mono_obj_array_set: (array: MonoArray, idx: number, obj: MonoObject) => void;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ js_string_to_mono_string: typeof js_string_to_mono_string;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ js_typed_array_to_array: typeof js_typed_array_to_array;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ mono_array_to_js_array: typeof mono_array_to_js_array;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ js_to_mono_obj: typeof js_to_mono_obj;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ conv_string: typeof conv_string;
+ /**
+ * @deprecated Not GC or thread safe
+ */
+ unbox_mono_obj: typeof unbox_mono_obj;
+
+ // do we really want to advertize add these below ?
+ mono_obj_array_new_ref: (size: number, result: MonoObjectRef) => void;
+ mono_obj_array_set_ref: (array: MonoObjectRef, idx: number, obj: MonoObjectRef) => void;
+ js_string_to_mono_string_root: typeof js_string_to_mono_string_root;
+ js_typed_array_to_array_root: typeof js_typed_array_to_array_root;
+ js_to_mono_obj_root: typeof js_to_mono_obj_root;
+ conv_string_root: typeof conv_string_root;
+ unbox_mono_obj_root: typeof unbox_mono_obj_root;
+ mono_array_root_to_js_array: typeof mono_array_root_to_js_array;
+}
+
+export type MONOType = {
+ mono_wasm_setenv: typeof mono_wasm_setenv;
+ mono_wasm_load_bytes_into_heap: typeof mono_wasm_load_bytes_into_heap;
+ mono_wasm_load_icu_data: typeof mono_wasm_load_icu_data;
+ mono_wasm_runtime_ready: typeof mono_wasm_runtime_ready;
+ mono_wasm_load_data_archive: typeof mono_wasm_load_data_archive;
+ mono_wasm_load_config: typeof mono_wasm_load_config;
+ mono_load_runtime_and_bcl_args: typeof mono_load_runtime_and_bcl_args;
+ mono_wasm_new_root_buffer: typeof mono_wasm_new_root_buffer;
+ mono_wasm_new_root: typeof mono_wasm_new_root;
+ mono_wasm_new_external_root: typeof mono_wasm_new_external_root;
+ mono_wasm_release_roots: typeof mono_wasm_release_roots;
+ mono_run_main: typeof mono_run_main;
+ mono_run_main_and_exit: typeof mono_run_main_and_exit;
+ mono_wasm_get_assembly_exports: typeof mono_wasm_get_assembly_exports;
+ mono_wasm_add_assembly: (name: string, data: VoidPtr, size: number) => number;
+ mono_wasm_load_runtime: (unused: string, debug_level: number) => void;
+ config: MonoConfig | MonoConfigError;
+ loaded_files: string[];
+ setB32: typeof setB32;
+ setI8: typeof setI8;
+ setI16: typeof setI16;
+ setI32: typeof setI32;
+ setI52: typeof setI52;
+ setU52: typeof setU52;
+ setI64Big: typeof setI64Big;
+ setU8: typeof setU8;
+ setU16: typeof setU16;
+ setU32: typeof setU32;
+ setF32: typeof setF32;
+ setF64: typeof setF64;
+ getB32: typeof getB32;
+ getI8: typeof getI8;
+ getI16: typeof getI16;
+ getI32: typeof getI32;
+ getI52: typeof getI52;
+ getU52: typeof getU52;
+ getI64Big: typeof getI64Big;
+ getU8: typeof getU8;
+ getU16: typeof getU16;
+ getU32: typeof getU32;
+ getF32: typeof getF32;
+ getF64: typeof getF64;
+ diagnostics: Diagnostics;
+
+}
\ 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 { Module, runtimeHelpers } from "./imports";
-import {
- assert_not_disposed,
- cs_owned_js_handle_symbol, get_cs_owned_object_by_js_handle_ref,
- get_js_owned_object_by_gc_handle_ref, js_owned_gc_handle_symbol,
- mono_wasm_get_jsobj_from_js_handle, mono_wasm_get_js_handle,
- mono_wasm_release_cs_owned_object, setup_managed_proxy, teardown_managed_proxy
-} from "./gc-handles";
-import corebindings from "./corebindings";
-import cwraps from "./cwraps";
-import { mono_wasm_new_root, mono_wasm_release_roots, WasmRoot, mono_wasm_new_external_root } from "./roots";
-import { wrap_error_root } from "./method-calls";
-import { js_string_to_mono_string_root, js_string_to_mono_string_interned_root } from "./strings";
-import { isThenable } from "./cancelable-promise";
+import { isThenable } from "../cancelable-promise";
+import 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 { runtimeHelpers, Module } from "../imports";
+import { wrap_error_root } from "../invoke-js";
+import { setI32_unchecked, setU32_unchecked, setF64, setB32 } from "../memory";
+import { WasmRoot, mono_wasm_new_root, mono_wasm_release_roots, mono_wasm_new_external_root } from "../roots";
+import { js_string_to_mono_string_root, js_string_to_mono_string_interned_root } from "../strings";
+import { MonoObject, is_nullish, MonoClass, wasm_type_symbol, MonoArray, MonoMethod, MonoObjectNull, JSHandle, MonoObjectRef, JSHandleNull, JSHandleDisposed } from "../types";
+import { TypedArray, Int32Ptr } from "../types/emscripten";
import { has_backing_array_buffer } from "./buffers";
-import { JSHandle, MonoArray, MonoMethod, MonoObject, MonoObjectNull, wasm_type_symbol, MonoClass, MonoObjectRef, is_nullish } from "./types";
-import { setF64, setI32_unchecked, setU32_unchecked, setB32 } from "./memory";
-import { Int32Ptr, TypedArray } from "./types/emscripten";
+import { legacyManagedExports } from "./corebindings";
+import { get_js_owned_object_by_gc_handle_ref } from "./cs-to-js";
// 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<MonoObject>): void {
return;
case typeof js_obj === "symbol":
case typeof js_obj === "string":
- corebindings._create_uri_ref(js_obj, result.address);
+ legacyManagedExports._create_uri_ref(js_obj, result.address);
return;
default:
_extract_mono_obj_root(should_add_in_flight, js_obj, result);
}
case js_obj.constructor.name === "Date":
// getTime() is always UTC
- corebindings._create_date_time_ref(js_obj.getTime(), result.address);
+ legacyManagedExports._create_date_time_ref(js_obj.getTime(), result.address);
return;
default:
_extract_mono_obj_root(should_add_in_flight, js_obj, result);
if (js_obj[js_owned_gc_handle_symbol] !== undefined) {
// for js_owned_gc_handle we don't want to create new proxy
// since this is strong gc_handle we don't need to in-flight reference
- assert_not_disposed(js_obj);
- get_js_owned_object_by_gc_handle_ref(js_obj[js_owned_gc_handle_symbol], result.address);
+ const gc_handle = assert_not_disposed(js_obj);
+ get_js_owned_object_by_gc_handle_ref(gc_handle, result.address);
return;
}
if (js_obj[cs_owned_js_handle_symbol]) {
const js_handle = mono_wasm_get_js_handle(js_obj);
- corebindings._create_cs_owned_proxy_ref(js_handle, wasm_type_id, should_add_in_flight ? 1 : 0, result.address);
+ legacyManagedExports._create_cs_owned_proxy_ref(js_handle, wasm_type_id, should_add_in_flight ? 1 : 0, result.address);
}
}
// Note that we do not implement promise/task roundtrip.
// With more complexity we could recover original instance when this Task is marshaled back to JS.
// TODO optimization: return the tcs.Task on this same call instead of _get_tcs_task
- const tcs_gc_handle = corebindings._create_tcs();
+ const tcs_gc_handle = legacyManagedExports._create_tcs();
const holder: any = { tcs_gc_handle };
setup_managed_proxy(holder, tcs_gc_handle);
thenable.then((result) => {
- corebindings._set_tcs_result_ref(tcs_gc_handle, result);
+ legacyManagedExports._set_tcs_result_ref(tcs_gc_handle, result);
}, (reason) => {
- corebindings._set_tcs_failure(tcs_gc_handle, reason ? reason.toString() : "");
+ legacyManagedExports._set_tcs_failure(tcs_gc_handle, reason ? reason.toString() : "");
}).finally(() => {
// let go of the thenable reference
mono_wasm_release_cs_owned_object(thenable_js_handle);
});
- corebindings._get_tcs_task_ref(tcs_gc_handle, resultRoot.address);
+ legacyManagedExports._get_tcs_task_ref(tcs_gc_handle, resultRoot.address);
// returns raw pointer to tcs.Task
return {
resultRoot.release();
}
}
+
+// when should_add_in_flight === true, the JSObject would be temporarily hold by Normal gc_handle, so that it would not get collected during transition to the managed stack.
+// its InFlight gc_handle would be freed when the instance arrives to managed side via Interop.Runtime.ReleaseInFlight
+export function get_cs_owned_object_by_js_handle_ref(js_handle: JSHandle, should_add_in_flight: boolean, result: MonoObjectRef): void {
+ if (js_handle === JSHandleNull || js_handle === JSHandleDisposed) {
+ setI32_unchecked(result, 0);
+ return;
+ }
+ legacyManagedExports._get_cs_owned_object_by_js_handle_ref(js_handle, should_add_in_flight ? 1 : 0, result);
+}
+
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { WasmRoot, WasmRootBuffer, mono_wasm_new_root, mono_wasm_new_external_root } from "./roots";
-import { MonoClass, MonoMethod, MonoObject, VoidPtrNull, MonoType, MarshalType, mono_assert } from "./types";
-import { BINDING, Module, runtimeHelpers } from "./imports";
-import { js_to_mono_enum, js_to_mono_obj_root, _js_to_mono_uri_root } from "./js-to-cs";
-import { js_string_to_mono_string_root, js_string_to_mono_string_interned_root } from "./strings";
-import { _unbox_mono_obj_root_with_known_nonprimitive_type } from "./cs-to-js";
-import {
- _create_temp_frame, _zero_region,
- getI32, getU32, getF32, getF64,
- setI32, setU32, setF32, setF64, setI52, setU52,
- setB32, getB32, setI32_unchecked, setU32_unchecked
-} from "./memory";
-import {
- _handle_exception_for_call, _teardown_after_call
-} from "./method-calls";
-import cwraps, { wrap_c_function } from "./cwraps";
-import { VoidPtr } from "./types/emscripten";
-
+import cwraps from "../cwraps";
+import { runtimeHelpers, BINDING, Module } from "../imports";
+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 { WasmRoot, mono_wasm_new_external_root, mono_wasm_new_root, WasmRootBuffer } from "../roots";
+import { js_string_to_mono_string_root, js_string_to_mono_string_interned_root, conv_string_root } from "../strings";
+import { MonoMethod, MonoObject, MonoType, MonoClass, mono_assert, VoidPtrNull, MarshalType, MonoString, MonoObjectNull } from "../types";
+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 { 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";
+
+
+const escapeRE = /[^A-Za-z0-9_$]/g;
const primitiveConverters = new Map<string, Converter>();
const _signature_converters = new Map<string, Converter>();
-
+const boundMethodsByMethod: Map<string, Function> = new Map();
export function _get_type_name(typePtr: MonoType): string {
if (!typePtr)
return cwraps.mono_wasm_get_type_name(cwraps.mono_wasm_class_get_type(classPtr));
}
-export function find_method(klass: MonoClass, name: string, n: number): MonoMethod {
- return cwraps.mono_wasm_assembly_find_method(klass, name, n);
-}
-
-export function get_method(method_name: string): MonoMethod {
- const res = find_method(runtimeHelpers.runtime_interop_exports_class, method_name, -1);
- if (!res)
- throw "Can't find method " + runtimeHelpers.runtime_interop_namespace + "." + runtimeHelpers.runtime_interop_exports_classname + ":" + method_name;
- return res;
-}
-
-export function bind_runtime_method(method_name: string, signature: string): Function {
- const method = get_method(method_name);
- return mono_bind_method(method, null, signature, "BINDINGS_" + method_name);
-}
-
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function _create_named_function(name: string, argumentNames: string[], body: string, closure: any): Function {
let result = null;
}
}
-export function mono_bind_method(method: MonoMethod, this_arg: null, args_marshal: string/*ArgsMarshalString*/, friendly_name: string): Function {
+
+export function mono_bind_method(method: MonoMethod, args_marshal: string/*ArgsMarshalString*/, has_this_arg: boolean, friendly_name?: string): Function {
if (typeof (args_marshal) !== "string")
throw new Error("args_marshal argument invalid, expected string");
+ const key = `managed_${method}_${args_marshal}`;
+ let result = boundMethodsByMethod.get(key);
+ if (result) {
+ return result;
+ }
+ if (!friendly_name) {
+ friendly_name = key;
+ }
+
let converter: Converter | null = null;
if (typeof (args_marshal) === "string") {
converter = _compile_converter_for_marshal_string(args_marshal);
const unbox_buffer = Module._malloc(unbox_buffer_size);
const token: BoundMethodToken = {
- friendlyName: friendly_name,
method,
converter,
scratchRootBuffer: null,
scratchBuffer: VoidPtrNull,
scratchResultRoot: mono_wasm_new_root(),
- scratchExceptionRoot: mono_wasm_new_root()
+ scratchExceptionRoot: mono_wasm_new_root(),
+ scratchThisArgRoot: mono_wasm_new_root()
};
const closure: any = {
Module,
mono_wasm_new_root,
+ get_js_owned_object_by_gc_handle_ref,
_create_temp_frame,
_handle_exception_for_call,
_teardown_after_call,
- mono_wasm_try_unbox_primitive_and_get_type_ref: wrap_c_function("mono_wasm_try_unbox_primitive_and_get_type_ref"),
+ mono_wasm_try_unbox_primitive_and_get_type_ref: cwraps.mono_wasm_try_unbox_primitive_and_get_type_ref,
_unbox_mono_obj_root_with_known_nonprimitive_type,
- invoke_method_ref: wrap_c_function("mono_wasm_invoke_method_ref"),
+ invoke_method_ref: cwraps.mono_wasm_invoke_method_ref,
method,
token,
unbox_buffer,
const argumentNames = [];
const body = [
"_create_temp_frame();",
- "let resultRoot = token.scratchResultRoot, exceptionRoot = token.scratchExceptionRoot, sp = stackSave();",
+ "let resultRoot = token.scratchResultRoot, exceptionRoot = token.scratchExceptionRoot, thisArgRoot = token.scratchThisArgRoot , sp = stackSave();",
"token.scratchResultRoot = null;",
"token.scratchExceptionRoot = null;",
+ "token.scratchThisArgRoot = null;",
"if (resultRoot === null)",
" resultRoot = mono_wasm_new_root ();",
"if (exceptionRoot === null)",
" exceptionRoot = mono_wasm_new_root ();",
+ "if (thisArgRoot === null)",
+ " thisArgRoot = mono_wasm_new_root ();",
""
];
// The end result is that bound method invocations don't always allocate, so no more nursery GCs. Yay! -kg
body.push(
"",
- "invoke_method_ref (method, 0, buffer, exceptionRoot.address, resultRoot.address);",
- `_handle_exception_for_call (${converterKey}, token, buffer, resultRoot, exceptionRoot, sp);`,
+ "",
+ "",
+ );
+ if (has_this_arg) {
+ body.push("get_js_owned_object_by_gc_handle_ref(this.this_arg_gc_handle, thisArgRoot.address);");
+ body.push("invoke_method_ref (method, thisArgRoot.address, buffer, exceptionRoot.address, resultRoot.address);");
+ } else {
+ body.push("invoke_method_ref (method, 0, buffer, exceptionRoot.address, resultRoot.address);");
+ }
+
+ body.push(
+ `_handle_exception_for_call (${converterKey}, token, buffer, resultRoot, exceptionRoot, thisArgRoot, sp);`,
"",
"let resultPtr = resultRoot.value, result = undefined;"
);
throw new Error("No converter");
}
- if (friendly_name) {
- const escapeRE = /[^A-Za-z0-9_$]/g;
- friendly_name = friendly_name.replace(escapeRE, "_");
- }
-
- let displayName = friendly_name || ("clr_" + method);
+ let displayName = friendly_name.replace(escapeRE, "_");
- if (this_arg)
- displayName += "_this" + this_arg;
+ if (has_this_arg)
+ displayName += "_this";
body.push(
- `_teardown_after_call (${converterKey}, token, buffer, resultRoot, exceptionRoot, sp);`,
+ `_teardown_after_call (${converterKey}, token, buffer, resultRoot, exceptionRoot, thisArgRoot, sp);`,
"return result;"
);
const bodyJs = body.join("\r\n");
- const result = _create_named_function(displayName, argumentNames, bodyJs, closure);
+ result = _create_named_function(displayName, argumentNames, bodyJs, closure);
+ boundMethodsByMethod.set(key, result);
return result;
}
}
export type BoundMethodToken = {
- friendlyName: string;
method: MonoMethod;
converter: Converter | null;
scratchRootBuffer: WasmRootBuffer | null;
scratchBuffer: VoidPtr;
scratchResultRoot: WasmRoot<MonoObject>;
scratchExceptionRoot: WasmRoot<MonoObject>;
-}
\ No newline at end of file
+ scratchThisArgRoot: WasmRoot<MonoObject>;
+}
+
+function _handle_exception_for_call(
+ converter: Converter | undefined, token: BoundMethodToken | null,
+ buffer: VoidPtr, resultRoot: WasmRoot<MonoString>,
+ exceptionRoot: WasmRoot<MonoObject>,
+ thisArgRoot: WasmRoot<MonoObject>,
+ sp: VoidPtr
+): void {
+ const exc = _convert_exception_for_method_call(resultRoot, exceptionRoot);
+ if (!exc)
+ return;
+
+ _teardown_after_call(converter, token, buffer, resultRoot, exceptionRoot, thisArgRoot, sp);
+ throw exc;
+}
+
+function _convert_exception_for_method_call(result: WasmRoot<MonoString>, exception: WasmRoot<MonoObject>) {
+ if (exception.value === MonoObjectNull)
+ return null;
+
+ const msg = conv_string_root(result);
+ const err = new Error(msg!); //the convention is that invoke_method ToString () any outgoing exception
+ // console.warn (`error ${msg} at location ${err.stack});
+ return err;
+}
+
+export function mono_method_resolve(fqn: string): MonoMethod {
+ const { assembly, namespace, classname, methodname } = parseFQN(fqn);
+
+ const asm = cwraps.mono_wasm_assembly_load(assembly);
+ if (!asm)
+ throw new Error("Could not find assembly: " + assembly);
+
+ const klass = cwraps.mono_wasm_assembly_find_class(asm, namespace, classname);
+ if (!klass)
+ throw new Error("Could not find class: " + namespace + ":" + classname + " in assembly " + assembly);
+
+ const method = cwraps.mono_wasm_assembly_find_method(klass, methodname, -1);
+ if (!method)
+ throw new Error("Could not find method: " + methodname);
+ return method;
+}
+
+export function mono_method_get_call_signature_ref(method: MonoMethod, mono_obj?: WasmRoot<MonoObject>): string/*ArgsMarshalString*/ {
+ return legacyManagedExports._get_call_sig_ref(method, mono_obj ? mono_obj.address : runtimeHelpers._null_root.address);
+}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-import { mono_wasm_new_root, WasmRoot, mono_wasm_new_external_root } from "./roots";
-import {
- JSHandle, MonoArray, MonoMethod, MonoObject,
- MonoObjectNull, MonoString, coerceNull as coerceNull,
- VoidPtrNull, MonoObjectRef,
- MonoStringRef, is_nullish, mono_assert
-} from "./types";
-import { INTERNAL, Module, runtimeHelpers } from "./imports";
+import { assembly_load } from "../class-loader";
+import cwraps from "../cwraps";
+import { get_js_obj, mono_wasm_get_jsobj_from_js_handle } from "../gc-handles";
+import { Module, runtimeHelpers, INTERNAL } from "../imports";
+import { wrap_error_root } from "../invoke-js";
+import { _release_temp_frame } from "../memory";
+import { WasmRoot, mono_wasm_new_external_root, mono_wasm_new_root } from "../roots";
+import { conv_string_root, js_string_to_mono_string_root } from "../strings";
+import { JSHandle, MonoStringRef, MonoObjectRef, MonoArray, MonoString, MonoObject, is_nullish, mono_assert } from "../types";
+import { Int32Ptr, VoidPtr } from "../types/emscripten";
import { mono_array_root_to_js_array, unbox_mono_obj_root } from "./cs-to-js";
-import { get_js_obj, mono_wasm_get_jsobj_from_js_handle } from "./gc-handles";
-// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-// @ts-ignore used by unsafe export
import { js_array_to_mono_array, js_to_mono_obj_root } from "./js-to-cs";
-import {
- mono_bind_method,
- Converter, _compile_converter_for_marshal_string,
- _decide_if_result_is_marshaled, find_method,
- BoundMethodToken
-} from "./method-binding";
-import { conv_string_root, js_string_to_mono_string, js_string_to_mono_string_root } from "./strings";
-import cwraps from "./cwraps";
-import { _create_temp_frame, _release_temp_frame } from "./memory";
-import { VoidPtr, Int32Ptr } from "./types/emscripten";
-import { assembly_load } from "./class-loader";
-
-function _verify_args_for_method_call(args_marshal: string/*ArgsMarshalString*/, args: any) {
- const has_args = args && (typeof args === "object") && args.length > 0;
- const has_args_marshal = typeof args_marshal === "string";
-
- if (has_args) {
- if (!has_args_marshal)
- throw new Error("No signature provided for method call.");
- else if (args.length > args_marshal.length)
- throw new Error("Too many parameter values. Expected at most " + args_marshal.length + " value(s) for signature " + args_marshal);
- }
-
- return has_args_marshal && has_args;
-}
-
-function _convert_exception_for_method_call(result: WasmRoot<MonoString>, exception: WasmRoot<MonoObject>) {
- if (exception.value === MonoObjectNull)
- return null;
-
- const msg = conv_string_root(result);
- const err = new Error(msg!); //the convention is that invoke_method ToString () any outgoing exception
- // console.warn (`error ${msg} at location ${err.stack});
- return err;
-}
-
-/*
-args_marshal is a string with one character per parameter that tells how to marshal it, here are the valid values:
-
-i: int32
-j: int32 - Enum with underlying type of int32
-l: int64
-k: int64 - Enum with underlying type of int64
-f: float
-d: double
-s: string
-S: interned string
-o: js object will be converted to a C# object (this will box numbers/bool/promises)
-m: raw mono object. Don't use it unless you know what you're doing
-
-to suppress marshaling of the return value, place '!' at the end of args_marshal, i.e. 'ii!' instead of 'ii'
-*/
-export function call_method_ref(method: MonoMethod, this_arg: WasmRoot<MonoObject> | MonoObjectRef | undefined, args_marshal: string/*ArgsMarshalString*/, args: ArrayLike<any>): any {
- // HACK: Sometimes callers pass null or undefined, coerce it to 0 since that's what wasm expects
- let this_arg_ref: MonoObjectRef | undefined = undefined;
- if (typeof (this_arg) === "number")
- this_arg_ref = this_arg;
- else if (typeof (this_arg) === "object")
- this_arg_ref = (<any>this_arg).address;
- else
- this_arg_ref = <any>coerceNull(this_arg);
-
- // Detect someone accidentally passing the wrong type of value to method
- if (typeof method !== "number")
- throw new Error(`method must be an address in the native heap, but was '${method}'`);
- if (!method)
- throw new Error("no method specified");
- if (typeof (this_arg_ref) !== "number")
- throw new Error(`this_arg must be a root instance, the address of a root, or undefined, but was ${this_arg}`);
-
- const needs_converter = _verify_args_for_method_call(args_marshal, args);
-
- let buffer = VoidPtrNull, converter = undefined;
- const sp = Module.stackSave();
- let is_result_marshaled = true;
-
- // TODO: Only do this if the signature needs marshaling
- _create_temp_frame();
-
- // check if the method signature needs argument mashalling
- if (needs_converter) {
- converter = _compile_converter_for_marshal_string(args_marshal);
-
- is_result_marshaled = _decide_if_result_is_marshaled(converter, args.length);
-
- buffer = converter.compiled_variadic_function!(method, args);
- }
-
- return _call_method_with_converted_args(method, <any>this_arg_ref, converter, null, buffer, is_result_marshaled, sp);
-}
-
+import { Converter, BoundMethodToken, mono_method_resolve, mono_method_get_call_signature_ref, mono_bind_method } from "./method-binding";
-export function _handle_exception_for_call(
- converter: Converter | undefined, token: BoundMethodToken | null,
- buffer: VoidPtr, resultRoot: WasmRoot<MonoString>,
- exceptionRoot: WasmRoot<MonoObject>, sp: VoidPtr
-): void {
- const exc = _convert_exception_for_method_call(resultRoot, exceptionRoot);
- if (!exc)
- return;
-
- _teardown_after_call(converter, token, buffer, resultRoot, exceptionRoot, sp);
- throw exc;
-}
-
-function _handle_exception_and_produce_result_for_call(
- converter: Converter | undefined, token: BoundMethodToken | null,
- buffer: VoidPtr, resultRoot: WasmRoot<MonoString>,
- exceptionRoot: WasmRoot<MonoObject>, sp: VoidPtr,
- is_result_marshaled: boolean
-): any {
- _handle_exception_for_call(converter, token, buffer, resultRoot, exceptionRoot, sp);
-
- let result: any;
-
- if (is_result_marshaled)
- result = unbox_mono_obj_root(resultRoot);
- else
- result = resultRoot.value;
-
- _teardown_after_call(converter, token, buffer, resultRoot, exceptionRoot, sp);
- return result;
-}
+const boundMethodsByFqn: Map<string, Function> = new Map();
export function _teardown_after_call(
converter: Converter | undefined, token: BoundMethodToken | null,
- buffer: VoidPtr, resultRoot: WasmRoot<any>,
- exceptionRoot: WasmRoot<any>, sp: VoidPtr
+ buffer: VoidPtr,
+ resultRoot: WasmRoot<any>,
+ exceptionRoot: WasmRoot<any>,
+ thisArgRoot: WasmRoot<MonoObject>,
+ sp: VoidPtr
): void {
_release_temp_frame();
Module.stackRestore(sp);
else
exceptionRoot.release();
}
-}
-
-function _call_method_with_converted_args(
- method: MonoMethod, this_arg_ref: MonoObjectRef, converter: Converter | undefined,
- token: BoundMethodToken | null, buffer: VoidPtr,
- is_result_marshaled: boolean, sp: VoidPtr
-): any {
- const resultRoot = mono_wasm_new_root<MonoString>(), exceptionRoot = mono_wasm_new_root<MonoObject>();
- cwraps.mono_wasm_invoke_method_ref(method, this_arg_ref, buffer, exceptionRoot.address, resultRoot.address);
- return _handle_exception_and_produce_result_for_call(converter, token, buffer, resultRoot, exceptionRoot, sp, is_result_marshaled);
-}
-
-export function call_static_method(fqn: string, args: any[], signature: string/*ArgsMarshalString*/): any {
- mono_assert(runtimeHelpers.mono_wasm_bindings_is_ready, "Expected binding to be initialized later during startup sequence.");
- const method = mono_method_resolve(fqn);
-
- if (typeof signature === "undefined")
- signature = mono_method_get_call_signature_ref(method, undefined);
-
- return call_method_ref(method, undefined, signature, args);
+ if (typeof (thisArgRoot) === "object") {
+ thisArgRoot.clear();
+ if ((token !== null) && (token.scratchThisArgRoot === null))
+ token.scratchThisArgRoot = thisArgRoot;
+ else
+ thisArgRoot.release();
+ }
}
export function mono_bind_static_method(fqn: string, signature?: string/*ArgsMarshalString*/): Function {
mono_assert(runtimeHelpers.mono_wasm_bindings_is_ready, "Expected binding to be initialized later during startup sequence.");
- const method = mono_method_resolve(fqn);
- if (typeof signature === "undefined")
- signature = mono_method_get_call_signature_ref(method, undefined);
+ const key = `${fqn}-${signature}`;
+ let js_method = boundMethodsByFqn.get(key);
+ if (js_method === undefined) {
+ const method = mono_method_resolve(fqn);
- return mono_bind_method(method, null, signature!, fqn);
+ if (typeof signature === "undefined")
+ signature = mono_method_get_call_signature_ref(method, undefined);
+
+ js_method = mono_bind_method(method, signature!, false, fqn);
+ boundMethodsByFqn.set(key, js_method);
+ }
+ return js_method;
}
export function mono_bind_assembly_entry_point(assembly: string, signature?: string/*ArgsMarshalString*/): Function {
if (typeof (signature) !== "string")
signature = mono_method_get_call_signature_ref(method, undefined);
+ const js_method = mono_bind_method(method, signature!, false, "_" + assembly + "__entrypoint");
+
return async function (...args: any[]) {
if (args.length > 0 && Array.isArray(args[0]))
args[0] = js_array_to_mono_array(args[0], true, false);
- return call_method_ref(method, undefined, signature!, args);
+ return js_method(...args);
};
}
}
}
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-function _wrap_error_flag(is_exception: Int32Ptr | null, ex: any): string {
- let res = "unknown exception";
- if (ex) {
- res = ex.toString();
- const stack = ex.stack;
- if (stack) {
- // Some JS runtimes insert the error message at the top of the stack, some don't,
- // so normalize it by using the stack as the result if it already contains the error
- if (stack.startsWith(res))
- res = stack;
- else
- res += "\n" + stack;
- }
-
- res = INTERNAL.mono_wasm_symbolicate_string(res);
- }
- if (is_exception) {
- Module.setValue(is_exception, 1, "i32");
- }
- return res;
-}
-
-/**
- * @deprecated Not GC or thread safe
- */
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-export function wrap_error(is_exception: Int32Ptr | null, ex: any): MonoString {
- const res = _wrap_error_flag(is_exception, ex);
- return js_string_to_mono_string(res)!;
-}
-
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-export function wrap_error_root(is_exception: Int32Ptr | null, ex: any, result: WasmRoot<MonoObject>): void {
- const res = _wrap_error_flag(is_exception, ex);
- js_string_to_mono_string_root(res, <any>result);
-}
-
-export function mono_method_get_call_signature_ref(method: MonoMethod, mono_obj?: WasmRoot<MonoObject>): string/*ArgsMarshalString*/ {
- return call_method_ref(
- runtimeHelpers.get_call_sig_ref, undefined, "im",
- [method, mono_obj ? mono_obj.address : runtimeHelpers._null_root.address]
- );
-}
-
-export function parseFQN(fqn: string)
- : { assembly: string, namespace: string, classname: string, methodname: string } {
- const assembly = fqn.substring(fqn.indexOf("[") + 1, fqn.indexOf("]")).trim();
- fqn = fqn.substring(fqn.indexOf("]") + 1).trim();
-
- const methodname = fqn.substring(fqn.indexOf(":") + 1);
- fqn = fqn.substring(0, fqn.indexOf(":")).trim();
-
- let namespace = "";
- let classname = fqn;
- if (fqn.indexOf(".") != -1) {
- const idx = fqn.lastIndexOf(".");
- namespace = fqn.substring(0, idx);
- classname = fqn.substring(idx + 1);
- }
-
- if (!assembly.trim())
- throw new Error("No assembly name specified " + fqn);
- if (!classname.trim())
- throw new Error("No class name specified " + fqn);
- if (!methodname.trim())
- throw new Error("No method name specified " + fqn);
- return { assembly, namespace, classname, methodname };
-}
-
-export function mono_method_resolve(fqn: string): MonoMethod {
- const { assembly, namespace, classname, methodname } = parseFQN(fqn);
-
- const asm = cwraps.mono_wasm_assembly_load(assembly);
- if (!asm)
- throw new Error("Could not find assembly: " + assembly);
-
- const klass = cwraps.mono_wasm_assembly_find_class(asm, namespace, classname);
- if (!klass)
- throw new Error("Could not find class: " + namespace + ":" + classname + " in assembly " + assembly);
-
- const method = find_method(klass, methodname, -1);
- if (!method)
- throw new Error("Could not find method: " + methodname);
- return method;
-}
-
// Blazor specific custom routine
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function mono_wasm_invoke_js_blazor(exceptionMessage: Int32Ptr, callInfo: any, arg0: any, arg1: any, arg2: any): void | number {
import { INTERNAL, Module, runtimeHelpers } from "./imports";
-import { mono_call_assembly_entry_point } from "./method-calls";
+import { mono_call_assembly_entry_point } from "./net6-legacy/method-calls";
import { mono_wasm_wait_for_debugger } from "./debug";
import { abort_startup, mono_wasm_set_main_args } from "./startup";
// The .NET Foundation licenses this file to you under the MIT license.
import MonoWasmThreads from "consts:monoWasmThreads";
-import { mono_assert, CharPtrNull, DotnetModule, MonoConfig, wasm_type_symbol, MonoObject, MonoConfigError, LoadingResource, AssetEntry, ResourceRequest } from "./types";
-import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_PTHREAD, ENVIRONMENT_IS_SHELL, INTERNAL, Module, MONO, runtimeHelpers } from "./imports";
-import cwraps from "./cwraps";
+import { mono_assert, CharPtrNull, DotnetModule, MonoConfig, wasm_type_symbol, MonoObject, MonoConfigError, LoadingResource, AssetEntry, ResourceRequest, DotnetPublicAPI } from "./types";
+import { BINDING, ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_PTHREAD, ENVIRONMENT_IS_SHELL, INTERNAL, Module, MONO, runtimeHelpers } from "./imports";
+import cwraps, { init_c_exports } from "./cwraps";
import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug";
import { mono_wasm_globalization_init, mono_wasm_load_icu_data } from "./icu";
import { toBase64StringImpl } from "./base64";
import { mono_wasm_init_aot_profiler, mono_wasm_init_coverage_profiler } from "./profiler";
-import { mono_wasm_load_bytes_into_heap } from "./buffers";
-import { bind_runtime_method, get_method, _create_primitive_converters } from "./method-binding";
import { find_corlib_class } from "./class-loader";
import { VoidPtr, CharPtr } from "./types/emscripten";
-import { DotnetPublicAPI } from "./exports";
import { mono_on_abort, set_exit_code } from "./run";
import { initialize_marshalers_to_cs } from "./marshal-to-cs";
import { initialize_marshalers_to_js } from "./marshal-to-js";
import { createPromiseController } from "./promise-controller";
import { string_decoder } from "./strings";
import { mono_wasm_init_diagnostics } from "./diagnostics/index";
+import { init_managed_exports } from "./managed-exports";
+import { init_legacy_exports } from "./net6-legacy/corebindings";
+import { mono_wasm_load_bytes_into_heap } from "./memory";
+import { cwraps_internal } from "./exports-internal";
+import { cwraps_binding_api, cwraps_mono_api } from "./net6-legacy/exports-legacy";
let all_assets_loaded_in_memory: Promise<void> | null = null;
-const loaded_files: { url?: string, file: string }[] = [];
+const loaded_files: { url: string, file: string }[] = [];
const loaded_assets: { [id: string]: [VoidPtr, number] } = Object.create(null);
let instantiated_assets_count = 0;
let downloded_assets_count = 0;
// init_polyfills() is already called from export.ts
init_crypto();
+ init_c_exports();
+ cwraps_internal(INTERNAL);
+ cwraps_mono_api(MONO);
+ cwraps_binding_api(BINDING);
Module.removeRunDependency("mono_wasm_pre_init_essential");
}
runtimeHelpers._class_uint32 = find_corlib_class("System", "UInt32");
runtimeHelpers._class_double = find_corlib_class("System", "Double");
runtimeHelpers._class_boolean = find_corlib_class("System", "Boolean");
- runtimeHelpers.bind_runtime_method = bind_runtime_method;
-
- const bindingAssembly = INTERNAL.BINDING_ASM;
- const binding_fqn_asm = bindingAssembly.substring(bindingAssembly.indexOf("[") + 1, bindingAssembly.indexOf("]")).trim();
- const binding_fqn_class = bindingAssembly.substring(bindingAssembly.indexOf("]") + 1).trim();
-
- const binding_module = cwraps.mono_wasm_assembly_load(binding_fqn_asm);
- if (!binding_module)
- throw "Can't find bindings module assembly: " + binding_fqn_asm;
-
- if (binding_fqn_class && binding_fqn_class.length) {
- runtimeHelpers.runtime_interop_exports_classname = binding_fqn_class;
- if (binding_fqn_class.indexOf(".") != -1) {
- const idx = binding_fqn_class.lastIndexOf(".");
- runtimeHelpers.runtime_interop_namespace = binding_fqn_class.substring(0, idx);
- runtimeHelpers.runtime_interop_exports_classname = binding_fqn_class.substring(idx + 1);
- }
- }
-
- runtimeHelpers.runtime_interop_exports_class = cwraps.mono_wasm_assembly_find_class(binding_module, runtimeHelpers.runtime_interop_namespace, runtimeHelpers.runtime_interop_exports_classname);
- if (!runtimeHelpers.runtime_interop_exports_class)
- throw "Can't find " + binding_fqn_class + " class";
-
- runtimeHelpers.get_call_sig_ref = get_method("GetCallSignatureRef");
- if (!runtimeHelpers.get_call_sig_ref)
- throw "Can't find GetCallSignatureRef method";
-
- runtimeHelpers.complete_task_method = get_method("CompleteTask");
- if (!runtimeHelpers.complete_task_method)
- throw "Can't find CompleteTask method";
-
- runtimeHelpers.create_task_method = get_method("CreateTaskCallback");
- if (!runtimeHelpers.create_task_method)
- throw "Can't find CreateTaskCallback method";
-
- runtimeHelpers.call_delegate = get_method("CallDelegate");
- if (!runtimeHelpers.call_delegate)
- throw "Can't find CallDelegate method";
+ init_managed_exports();
+ init_legacy_exports();
initialize_marshalers_to_js();
initialize_marshalers_to_cs();
- _create_primitive_converters();
-
runtimeHelpers._box_root = mono_wasm_new_root<MonoObject>();
runtimeHelpers._null_root = mono_wasm_new_root<MonoObject>();
} catch (err) {
// The .NET Foundation licenses this file to you under the MIT license.
import "node/buffer"; // we use the Buffer type to type some of Emscripten's APIs
-import { bind_runtime_method } from "./method-binding";
+import { JavaScriptExports } from "./managed-exports";
+import { BINDINGType, MONOType } from "./net6-legacy/exports-legacy";
import { CharPtr, EmscriptenModule, ManagedPointer, NativePointer, VoidPtr, Int32Ptr } from "./types/emscripten";
export type GCHandle = {
complete_task_method: MonoMethod;
create_task_method: MonoMethod;
call_delegate: MonoMethod;
+ runtime_interop_module: MonoAssembly;
runtime_interop_namespace: string;
runtime_interop_exports_classname: string;
runtime_interop_exports_class: MonoClass;
- bind_runtime_method: typeof bind_runtime_method;
+ runtime_legacy_exports_classname: string;
+ runtime_legacy_exports_class: MonoClass;
_box_buffer_size: number;
_unbox_buffer_size: number;
ExitStatus: ExitStatusError;
quit: Function,
locateFile: (path: string, prefix?: string) => string,
+ javaScriptExports: JavaScriptExports,
}
export const wasm_type_symbol = Symbol.for("wasm type");
/// An identifier for an EventPipe session. The id is unique during the lifetime of the runtime.
/// Primarily intended for debugging purposes.
export type EventPipeSessionID = bigint;
+
+// this represents visibility in the javascript
+// like https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web.JS/src/Platform/Mono/MonoTypes.ts
+export interface DotnetPublicAPI {
+ MONO: MONOType,
+ BINDING: BINDINGType,
+ INTERNAL: any,
+ EXPORTS: any,
+ IMPORTS: any,
+ Module: EmscriptenModule,
+ RuntimeId: number,
+ RuntimeBuildInfo: {
+ ProductVersion: string,
+ Configuration: string,
+ }
+}
\ No newline at end of file
const fqn = "[System.Private.Runtime.InteropServices.JavaScript.Tests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:" + method_name;
try {
- return App.INTERNAL.call_static_method(fqn, args || [], signature);
+ const method = App.BINDING.bind_static_method(fqn, signature);
+ return method.apply(null, args || []);
} catch (exc) {
console.error("exception thrown in", fqn);
throw exc;