Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[browser][MT] deputy thread #98118

Merged
merged 9 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eng/testing/tests.browser.targets
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@
<_AppArgs Condition="'$(IsFunctionalTest)' != 'true' and '$(WasmMainAssemblyFileName)' != ''">--run $(WasmMainAssemblyFileName)</_AppArgs>
<_AppArgs Condition="'$(IsFunctionalTest)' == 'true'">--run $(AssemblyName).dll</_AppArgs>

<_XUnitBackgroundExec Condition="'$(_XUnitBackgroundExec)' == '' and '$(WasmEnableThreads)' == 'true'">true</_XUnitBackgroundExec>
<WasmTestAppArgs Condition="'$(_XUnitBackgroundExec)' == 'true'">$(WasmTestAppArgs) -backgroundExec</WasmTestAppArgs>
<WasmXHarnessMonoArgs Condition="'$(_XUnitBackgroundExec)' == 'true'">$(WasmXHarnessMonoArgs) --setenv=IsWasmBackgroundExec=true</WasmXHarnessMonoArgs>
<_AppArgs Condition="'$(WasmTestAppArgs)' != ''">$(_AppArgs) $(WasmTestAppArgs)</_AppArgs>

<WasmXHarnessMonoArgs Condition="'$(XunitShowProgress)' == 'true'">$(WasmXHarnessMonoArgs) --setenv=XHARNESS_LOG_TEST_START=true</WasmXHarnessMonoArgs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ internal static unsafe partial class Runtime

#if FEATURE_WASM_MANAGED_THREADS
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern void InstallWebWorkerInterop(nint proxyContextGCHandle);
public static extern void InstallWebWorkerInterop(nint proxyContextGCHandle, void* beforeSyncJSImport, void* afterSyncJSImport);
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern void UninstallWebWorkerInterop();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ public static int SlowRuntimeTimeoutModifier
public static bool IsThreadingSupported => (!IsWasi && !IsBrowser) || IsWasmThreadingSupported;
public static bool IsWasmThreadingSupported => IsBrowser && IsEnvironmentVariableTrue("IsBrowserThreadingSupported");
public static bool IsNotWasmThreadingSupported => !IsWasmThreadingSupported;
public static bool IsWasmBackgroundExec => IsBrowser && IsEnvironmentVariableTrue("IsWasmBackgroundExec");
public static bool IsWasmBackgroundExecOrSingleThread => IsWasmBackgroundExec || IsNotWasmThreadingSupported;
public static bool IsBinaryFormatterSupported => IsNotMobile && !IsNativeAot;

public static bool IsStartingProcessesSupported => !IsiOS && !IstvOS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace System.Runtime.InteropServices.JavaScript
{
// this maps to src\mono\browser\runtime\managed-exports.ts
// the public methods are protected from trimming by DynamicDependency on JSFunctionBinding.BindJSFunction
// TODO: all the calls here should be running on deputy or TP in MT, not in UI thread
// TODO: change all of these to [UnmanagedCallersOnly] and drop the reflection in mono_wasm_invoke_jsexport
internal static unsafe partial class JavaScriptExports
{
// the marshaled signature is: Task<int>? CallEntrypoint(char* assemblyNamePtr, string[] args)
Expand Down Expand Up @@ -240,15 +240,21 @@ public static void GetManagedStackTrace(JSMarshalerArgument* arguments_buffer)

// this is here temporarily, until JSWebWorker becomes public API
[DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicMethods, "System.Runtime.InteropServices.JavaScript.JSWebWorker", "System.Runtime.InteropServices.JavaScript")]
// the marshaled signature is: GCHandle InstallMainSynchronizationContext(nint jsNativeTID)
// the marshaled signature is: GCHandle InstallMainSynchronizationContext(nint jsNativeTID, JSThreadBlockingMode jsThreadBlockingMode, JSThreadInteropMode jsThreadInteropMode, MainThreadingMode mainThreadingMode)
public static void InstallMainSynchronizationContext(JSMarshalerArgument* arguments_buffer)
{
ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame()
ref JSMarshalerArgument arg_res = ref arguments_buffer[1];// initialized and set by caller
ref JSMarshalerArgument arg_1 = ref arguments_buffer[2];// initialized and set by caller
ref JSMarshalerArgument arg_2 = ref arguments_buffer[3];// initialized and set by caller
ref JSMarshalerArgument arg_3 = ref arguments_buffer[4];// initialized and set by caller
ref JSMarshalerArgument arg_4 = ref arguments_buffer[5];// initialized and set by caller

try
{
JSProxyContext.ThreadBlockingMode = (JSHostImplementation.JSThreadBlockingMode)arg_2.slot.Int32Value;
JSProxyContext.ThreadInteropMode = (JSHostImplementation.JSThreadInteropMode)arg_3.slot.Int32Value;
JSProxyContext.MainThreadingMode = (JSHostImplementation.MainThreadingMode)arg_4.slot.Int32Value;
var jsSynchronizationContext = JSSynchronizationContext.InstallWebWorkerInterop(true, CancellationToken.None);
jsSynchronizationContext.ProxyContext.JSNativeTID = arg_1.slot.IntPtrValue;
arg_res.slot.GCHandle = jsSynchronizationContext.ProxyContext.ContextHandle;
Expand All @@ -259,6 +265,42 @@ public static void InstallMainSynchronizationContext(JSMarshalerArgument* argume
}
}

#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
#pragma warning restore CS3016
// TODO ideally this would be public API callable from generated C# code for JSExport
public static void BeforeSyncJSExport(JSMarshalerArgument* arguments_buffer)
{
ref JSMarshalerArgument arg_exc = ref arguments_buffer[0];
try
{
var ctx = arg_exc.AssertCurrentThreadContext();
ctx.IsPendingSynchronousCall = true;
}
catch (Exception ex)
{
Environment.FailFast($"BeforeSyncJSExport: Unexpected synchronous failure (ManagedThreadId {Environment.CurrentManagedThreadId}): " + ex);
}
}

#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
#pragma warning restore CS3016
// TODO ideally this would be public API callable from generated C# code for JSExport
public static void AfterSyncJSExport(JSMarshalerArgument* arguments_buffer)
{
ref JSMarshalerArgument arg_exc = ref arguments_buffer[0];
try
{
var ctx = arg_exc.AssertCurrentThreadContext();
ctx.IsPendingSynchronousCall = false;
}
catch (Exception ex)
{
Environment.FailFast($"AfterSyncJSExport: Unexpected synchronous failure (ManagedThreadId {Environment.CurrentManagedThreadId}): " + ex);
}
}

#endif

// the marshaled signature is: Task BindAssemblyExports(string assemblyName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@
jsFunction.AssertNotDisposed();

#if FEATURE_WASM_MANAGED_THREADS
ref JSMarshalerArgument exc = ref arguments[0];
exc.slot.CallerNativeTID = jsFunction.ProxyContext.NativeTID;

// if we are on correct thread already, just call it
if (jsFunction.ProxyContext.IsCurrentThread())
{
Expand All @@ -226,6 +229,17 @@
#endif
internal static unsafe void InvokeJSFunctionCurrent(JSObject jsFunction, Span<JSMarshalerArgument> arguments)
{
#if FEATURE_WASM_MANAGED_THREADS
if (JSProxyContext.ThreadInteropMode == JSHostImplementation.JSThreadInteropMode.NoSyncJSInterop)
{
throw new PlatformNotSupportedException("Cannot call synchronous JS functions.");
}
else if (jsFunction.ProxyContext.IsPendingSynchronousCall)
{
throw new PlatformNotSupportedException("Cannot call synchronous JS function from inside a synchronous call to a C# method.");
}
#endif

var functionHandle = (int)jsFunction.JSHandle;
fixed (JSMarshalerArgument* ptr = arguments)
{
Expand All @@ -245,6 +259,16 @@
#endif
internal static unsafe void DispatchJSFunctionSync(JSObject jsFunction, Span<JSMarshalerArgument> arguments)
{
#if FEATURE_WASM_MANAGED_THREADS
if (JSProxyContext.ThreadInteropMode == JSHostImplementation.JSThreadInteropMode.NoSyncJSInterop)
{
throw new PlatformNotSupportedException("Cannot call synchronous JS functions.");
}
else if (jsFunction.ProxyContext.IsPendingSynchronousCall)
{
throw new PlatformNotSupportedException("Cannot call synchronous JS function from inside a synchronous call to a C# method.");
}
#endif
var args = (nint)Unsafe.AsPointer(ref arguments[0]);
var functionHandle = jsFunction.JSHandle;

Expand All @@ -269,10 +293,13 @@
#endif
internal static unsafe void InvokeJSImportImpl(JSFunctionBinding signature, Span<JSMarshalerArgument> arguments)
{
ref JSMarshalerArgument exc = ref arguments[0];
ref JSMarshalerArgument res = ref arguments[1];
#if FEATURE_WASM_MANAGED_THREADS
var targetContext = JSProxyContext.SealJSImportCapturing();
arguments[0].slot.ContextHandle = targetContext.ContextHandle;
arguments[1].slot.ContextHandle = targetContext.ContextHandle;
exc.slot.CallerNativeTID = targetContext.NativeTID;
exc.slot.ContextHandle = targetContext.ContextHandle;
res.slot.ContextHandle = targetContext.ContextHandle;
#else
var targetContext = JSProxyContext.MainThreadContext;
#endif
Expand All @@ -281,9 +308,22 @@
{
// pre-allocate the result handle and Task
var holder = targetContext.CreatePromiseHolder();
arguments[1].slot.Type = MarshalerType.TaskPreCreated;
arguments[1].slot.GCHandle = holder.GCHandle;
res.slot.Type = MarshalerType.TaskPreCreated;
res.slot.GCHandle = holder.GCHandle;
}
#if FEATURE_WASM_MANAGED_THREADS
else
{
if (JSProxyContext.ThreadInteropMode == JSHostImplementation.JSThreadInteropMode.NoSyncJSInterop)
{
throw new PlatformNotSupportedException("Cannot call synchronous JS functions.");
}
else if (targetContext.IsPendingSynchronousCall)
{
throw new PlatformNotSupportedException("Cannot call synchronous JS function from inside a synchronous call to a C# method.");
}
}
#endif

if (signature.IsDiscardNoWait)
{
Expand Down Expand Up @@ -360,6 +400,8 @@
var args = (nint)Unsafe.AsPointer(ref arguments[0]);
var sig = (nint)signature.Header;

ref JSMarshalerArgument exc = ref arguments[0];

// we already know that we are not on the right thread
// this will be blocking until resolved by that thread
// we don't have to disable ThrowOnBlockingWaitOnJSInteropThread, because this is lock in native code
Expand All @@ -368,10 +410,9 @@
// see also https://github.com/dotnet/runtime/issues/76958#issuecomment-1921418290
Interop.Runtime.InvokeJSImportSyncSend(targetContext.JSNativeTID, sig, args);

ref JSMarshalerArgument exceptionArg = ref arguments[0];
if (exceptionArg.slot.Type != MarshalerType.None)
if (exc.slot.Type != MarshalerType.None)
{
JSHostImplementation.ThrowException(ref exceptionArg);
JSHostImplementation.ThrowException(ref exc);
}
}

Expand Down Expand Up @@ -427,11 +468,12 @@
{
fixed (JSMarshalerArgument* ptr = arguments)
{
ref JSMarshalerArgument exc = ref arguments[0];
exc.slot.CallerNativeTID = targetContext.NativeTID;

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_HighResource_AOT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_HighResource_AOT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_NodeJs)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_NodeJs)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release Mono_DebuggerTests_firefox)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release Mono_DebuggerTests_firefox)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_HybridGlobalization_AOT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_HybridGlobalization_AOT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_AOT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_AOT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_HybridGlobalization)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime-wasm (Build browser-wasm linux Release LibraryTests_HybridGlobalization)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release AllSubsets_Mono_RuntimeTests monointerpreter)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release AllSubsets_Mono_RuntimeTests monointerpreter)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / dotnet-linker-tests (Build browser-wasm linux release Runtime_Release)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / dotnet-linker-tests (Build browser-wasm linux release Runtime_Release)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release SingleThreaded_BuildOnly)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release SingleThreaded_BuildOnly)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTests)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTests)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTests_Smoke_AOT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTests_Smoke_AOT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTests_EAT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release LibraryTests_EAT)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release Mono_DebuggerTests_chrome)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,30): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSMarshalerArgument.JSMarshalerArgumentImpl' does not contain a definition for 'CallerNativeTID' and no accessible extension method 'CallerNativeTID' accepting a first argument of type 'JSMarshalerArgument.JSMarshalerArgumentImpl' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 472 in src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs

View check run for this annotation

Azure Pipelines / runtime (Build browser-wasm linux Release Mono_DebuggerTests_chrome)

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs#L472

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs(472,62): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'JSProxyContext' does not contain a definition for 'NativeTID' and no accessible extension method 'NativeTID' accepting a first argument of type 'JSProxyContext' could be found (are you missing a using directive or an assembly reference?)
Interop.Runtime.ResolveOrRejectPromise((nint)ptr);
ref JSMarshalerArgument exceptionArg = ref arguments[0];
if (exceptionArg.slot.Type != MarshalerType.None)
if (exc.slot.Type != MarshalerType.None)
{
JSHostImplementation.ThrowException(ref exceptionArg);
JSHostImplementation.ThrowException(ref exc);
}
}
}
Expand All @@ -441,6 +483,7 @@
// meaning JS side needs to dispose it
ref JSMarshalerArgument exc = ref arguments[0];
exc.slot.ReceiverShouldFree = true;
exc.slot.CallerNativeTID = targetContext.NativeTID;

// this copy is freed in mono_wasm_resolve_or_reject_promise
var bytes = sizeof(JSMarshalerArgument) * arguments.Length;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,38 @@ public struct IntPtrAndHandle
[FieldOffset(0)]
internal RuntimeTypeHandle typeHandle;
}

// keep in sync with types\internal.ts
public enum MainThreadingMode : int
{
// Running the managed main thread on UI thread.
// Managed GC and similar scenarios could be blocking the UI.
// Easy to deadlock. Not recommended for production.
UIThread = 0,
// Running the managed main thread on dedicated WebWorker. Marshaling all JavaScript calls to and from the main thread.
DeputyThread = 1,
}

// keep in sync with types\internal.ts
public enum JSThreadBlockingMode : int
{
// throw PlatformNotSupportedException if blocking .Wait is called on threads with JS interop, like JSWebWorker and Main thread.
// Avoids deadlocks (typically with pending JS promises on the same thread) by throwing exceptions.
NoBlockingWait = 0,
// allow .Wait on all threads.
// Could cause deadlocks with blocking .Wait on a pending JS Task/Promise on the same thread or similar Task/Promise chain.
AllowBlockingWait = 100,
}

// keep in sync with types\internal.ts
public enum JSThreadInteropMode : int
{
// throw PlatformNotSupportedException if synchronous JSImport/JSExport is called on threads with JS interop, like JSWebWorker and Main thread.
// calling synchronous JSImport on thread pool or new threads is allowed.
NoSyncJSInterop = 0,
// allow non-re-entrant synchronous blocking calls to and from JS on JSWebWorker on threads with JS interop, like JSWebWorker and Main thread.
// calling synchronous JSImport on thread pool or new threads is allowed.
SimpleSynchronousJSInterop = 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should come with a better name (before api review?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lewing also didn't like it. Please come up with suggestions.

Copy link
Member

@maraf maraf Feb 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm voting for longer and more descriptive name, "simple" has too much meanings

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • SingleSynchronousCallChainJSInterop
  • SingleSynchronousCallJSInterop

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SingleSynchronousCallJSInterop is not bad, I like it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW: those would not be visible on C# API, just JS config

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ internal struct JSMarshalerArgumentImpl

[FieldOffset(20)]
internal bool ReceiverShouldFree;

[FieldOffset(24)]
internal IntPtr CallerNativeTID;
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,17 @@ private JSProxyContext()
public bool IsMainThread;
public JSSynchronizationContext SynchronizationContext;

public static MainThreadingMode MainThreadingMode = MainThreadingMode.DeputyThread;
public static JSThreadBlockingMode ThreadBlockingMode = JSThreadBlockingMode.NoBlockingWait;
public static JSThreadInteropMode ThreadInteropMode = JSThreadInteropMode.SimpleSynchronousJSInterop;
public bool IsPendingSynchronousCall;

#if !DEBUG
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public bool IsCurrentThread()
{
return ManagedTID == Environment.CurrentManagedThreadId;
return ManagedTID == Environment.CurrentManagedThreadId && (!IsMainThread || MainThreadingMode == MainThreadingMode.UIThread);
}

[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "thread_id")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,16 @@ public WorkItem(SendOrPostCallback callback, object? data, ManualResetEventSlim?
}

// this need to be called from JSWebWorker or UI thread
public static JSSynchronizationContext InstallWebWorkerInterop(bool isMainThread, CancellationToken cancellationToken)
public static unsafe JSSynchronizationContext InstallWebWorkerInterop(bool isMainThread, CancellationToken cancellationToken)
{
var ctx = new JSSynchronizationContext(isMainThread, cancellationToken);
ctx.previousSynchronizationContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(ctx);

// FIXME: make this configurable
// we could have 3 different modes of this
// 1) throwing on UI + JSWebWorker
// 2) throwing only on UI - small risk, more convenient.
// 3) not throwing at all - quite risky
// deadlock scenarios are:
// - .Wait for more than 5000ms and deadlock the GC suspend
// - .Wait on the Task from HTTP client, on the same thread as the HTTP client needs to resolve the Task/Promise. This could be also be a chain of promises.
// - try to create new pthread when UI thread is blocked and we run out of posix/emscripten pool of loaded workers.
// Things which lead to it are
// - Task.Wait, Signal.Wait etc
// - Monitor.Enter etc, if the lock is held by another thread for long time
// - synchronous [JSExport] into managed code, which would block
// - synchronous [JSImport] to another thread, which would block
// see also https://github.com/dotnet/runtime/issues/76958#issuecomment-1921418290
Thread.ThrowOnBlockingWaitOnJSInteropThread = true;
if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.NoBlockingWait)
{
Thread.ThrowOnBlockingWaitOnJSInteropThread = true;
}

var proxyContext = ctx.ProxyContext;
JSProxyContext.CurrentThreadContext = proxyContext;
Expand All @@ -77,7 +65,9 @@ public static JSSynchronizationContext InstallWebWorkerInterop(bool isMainThread

ctx.AwaitNewData();

Interop.Runtime.InstallWebWorkerInterop(proxyContext.ContextHandle);
Interop.Runtime.InstallWebWorkerInterop(proxyContext.ContextHandle,
(delegate* unmanaged[Cdecl]<JSMarshalerArgument*, void>)&JavaScriptExports.BeforeSyncJSExport,
(delegate* unmanaged[Cdecl]<JSMarshalerArgument*, void>)&JavaScriptExports.AfterSyncJSExport);

return ctx;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project>
<PropertyGroup>
<_XUnitBackgroundExec Condition="'$(_XUnitBackgroundExec)' == ''">true</_XUnitBackgroundExec>
<AssemblyName>System.Runtime.InteropServices.JavaScript.Tests</AssemblyName>
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>
<Import Project="$(MSBuildThisFileDirectory)..\System.Runtime.InteropServices.JavaScript.Tests.csproj" />
</Project>
Loading
Loading