Skip to content

Commit fd383b6

Browse files
committed
wip
1 parent 90d0d5c commit fd383b6

File tree

16 files changed

+128
-3
lines changed

16 files changed

+128
-3
lines changed

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/CancelablePromise.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ public static void CancelPromise(Task promise)
2121
GCHandle? promiseGCHandle = promise.AsyncState as GCHandle?;
2222
if (promiseGCHandle == null) throw new InvalidOperationException("Expected Task converted from JS Promise");
2323

24+
#if FEATURE_WASM_THREADS
25+
// TODO JSObject.AssertThreadAffinity(promise);
26+
// in order to remember the thread ID of the promise, we would have to allocate holder object for any Task,
27+
// which would hold thread ID and the GCHandle
28+
// that would be pretty expensive, so we don't do it for now
29+
// the consequences are that calling CancelPromise on wrong thread would do nothing
30+
// because there would not be any object on JS registered under the same GCHandle
31+
// perhaps that's the point when we could throw an exception on JS side.
32+
#endif
2433
_CancelPromise((IntPtr)promiseGCHandle.Value);
2534
}
2635
}

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/LegacyExports.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ public static IntPtr TryGetCSOwnedObjectJSHandleRef(in object rawObj, int should
5353

5454
public static void CreateCSOwnedProxyRef(nint jsHandle, LegacyHostImplementation.MappedType mappedType, int shouldAddInflight, out JSObject jsObject)
5555
{
56+
#if FEATURE_WASM_THREADS
57+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
58+
#endif
59+
5660
JSObject? res = null;
5761

5862
lock (JSHostImplementation.s_csOwnedObjects)
@@ -126,6 +130,9 @@ public static void GetTaskSourceTaskRef(int tcsGCHandle, out object result)
126130

127131
public static void SetupJSContinuationRef(in Task _task, JSObject continuationObj)
128132
{
133+
#if FEATURE_WASM_THREADS
134+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
135+
#endif
129136
// HACK: Attempting to use the in-param will produce CS1628, so we make a temporary copy
130137
// on the stack that can be captured by our local functions below
131138
var task = _task;
@@ -207,6 +214,9 @@ public static void CreateDateTimeRef(double ticks, out object result)
207214
[Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("Trimming", "IL2057", Justification = "Done on purpose, see comment above.")]
208215
public static void CreateUriRef(string uri, out object? result)
209216
{
217+
#if FEATURE_WASM_THREADS
218+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
219+
#endif
210220
if (uriType == null)
211221
{
212222
// StringBuilder to confuse ILLink, which is too smart otherwise

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ public static JSFunctionBinding BindManagedFunction(string fullyQualifiedName, i
172172
[MethodImpl(MethodImplOptions.AggressiveInlining)]
173173
internal static unsafe void InvokeJSImpl(JSObject jsFunction, Span<JSMarshalerArgument> arguments)
174174
{
175+
#if FEATURE_WASM_THREADS
176+
JSObject.AssertThreadAffinity(jsFunction);
177+
#endif
178+
175179
IntPtr functionJSHandle = jsFunction.JSHandle;
176180
fixed (JSMarshalerArgument* ptr = arguments)
177181
{

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSObject.References.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33

44
using System.Diagnostics;
55
using System.Diagnostics.CodeAnalysis;
6+
using System.Threading;
67

78
namespace System.Runtime.InteropServices.JavaScript
89
{
910
public partial class JSObject
1011
{
1112
internal nint JSHandle;
1213

14+
#if FEATURE_WASM_THREADS
15+
// the JavaScript object could only exist on the single web worker and can't migrate to other workers
16+
internal int OwnerThreadId;
17+
#endif
1318
#if ENABLE_LEGACY_JS_INTEROP
1419
internal GCHandle? InFlight;
1520
internal int InFlightCounter;
@@ -19,6 +24,9 @@ public partial class JSObject
1924
internal JSObject(IntPtr jsHandle)
2025
{
2126
JSHandle = jsHandle;
27+
#if FEATURE_WASM_THREADS
28+
OwnerThreadId = Thread.CurrentThread.ManagedThreadId;
29+
#endif
2230
}
2331

2432
#if ENABLE_LEGACY_JS_INTEROP
@@ -56,6 +64,30 @@ internal void ReleaseInFlight()
5664
}
5765
#endif
5866

67+
#if FEATURE_WASM_THREADS
68+
internal static void AssertThreadAffinity(object value)
69+
{
70+
if (value == null)
71+
{
72+
return;
73+
}
74+
if (value is JSObject jsObject)
75+
{
76+
if (jsObject.OwnerThreadId != Thread.CurrentThread.ManagedThreadId)
77+
{
78+
throw new InvalidOperationException("The JavaScript object can be used only on the thread where it was created.");
79+
}
80+
}
81+
if (value is JSException jsException)
82+
{
83+
if(jsException.jsException!=null && jsException.jsException.OwnerThreadId != Thread.CurrentThread.ManagedThreadId)
84+
{
85+
throw new InvalidOperationException("The JavaScript object can be used only on the thread where it was created.");
86+
}
87+
}
88+
}
89+
#endif
90+
5991
/// <inheritdoc />
6092
public override bool Equals([NotNullWhen(true)] object? obj) => obj is JSObject other && JSHandle == other.JSHandle;
6193

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Legacy/Array.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ public class Array : JSObject
1818
public Array(params object[] _params)
1919
: base(JavaScriptImports.CreateCSOwnedObject(nameof(Array), _params))
2020
{
21+
#if FEATURE_WASM_THREADS
22+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
23+
#endif
2124
LegacyHostImplementation.RegisterCSOwnedObject(this);
2225
}
2326

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Legacy/ArrayBuffer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public class ArrayBuffer : JSObject
1313
public ArrayBuffer(int length)
1414
: base(JavaScriptImports.CreateCSOwnedObject(nameof(ArrayBuffer), new object[] { length }))
1515
{
16+
#if FEATURE_WASM_THREADS
17+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
18+
#endif
1619
LegacyHostImplementation.RegisterCSOwnedObject(this);
1720
}
1821

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Legacy/DataView.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ public class DataView : JSObject
1717
public DataView(ArrayBuffer buffer)
1818
: base(JavaScriptImports.CreateCSOwnedObject(nameof(DataView), new object[] { buffer }))
1919
{
20+
#if FEATURE_WASM_THREADS
21+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
22+
#endif
2023
LegacyHostImplementation.RegisterCSOwnedObject(this);
2124
}
2225

@@ -28,6 +31,9 @@ public DataView(ArrayBuffer buffer)
2831
public DataView(ArrayBuffer buffer, int byteOffset)
2932
: base(JavaScriptImports.CreateCSOwnedObject(nameof(DataView), new object[] { buffer, byteOffset }))
3033
{
34+
#if FEATURE_WASM_THREADS
35+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
36+
#endif
3137
LegacyHostImplementation.RegisterCSOwnedObject(this);
3238
}
3339

@@ -40,6 +46,9 @@ public DataView(ArrayBuffer buffer, int byteOffset)
4046
public DataView(ArrayBuffer buffer, int byteOffset, int byteLength)
4147
: base(JavaScriptImports.CreateCSOwnedObject(nameof(DataView), new object[] { buffer, byteOffset, byteLength }))
4248
{
49+
#if FEATURE_WASM_THREADS
50+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
51+
#endif
4352
LegacyHostImplementation.RegisterCSOwnedObject(this);
4453
}
4554

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Legacy/Function.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ public class Function : JSObject
1818
public Function(params object[] args)
1919
: base(JavaScriptImports.CreateCSOwnedObject(nameof(Function), args))
2020
{
21+
#if FEATURE_WASM_THREADS
22+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
23+
#endif
2124
LegacyHostImplementation.RegisterCSOwnedObject(this);
2225
}
2326

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Legacy/LegacyHostImplementation.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Runtime.CompilerServices;
55
using System.Runtime.Versioning;
66
using System.Threading.Tasks;
7+
using System.Threading;
78

89
namespace System.Runtime.InteropServices.JavaScript
910
{
@@ -220,5 +221,15 @@ public enum MappedType
220221
Function = 4,
221222
Uint8Array = 11,
222223
}
224+
225+
#if FEATURE_WASM_THREADS
226+
public static void ThrowIfLegacyWorkerThread()
227+
{
228+
if (Thread.CurrentThread.ManagedThreadId != 1)
229+
{
230+
throw new PlatformNotSupportedException("Legacy interop in not supported with WebAssembly threads."+Thread.CurrentThread.ManagedThreadId);
231+
}
232+
}
233+
#endif
223234
}
224235
}

src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Legacy/Runtime.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ public static object GetGlobalObject(string str)
3434
/// </returns>
3535
public static object Invoke(this JSObject self, string method, params object?[] args)
3636
{
37+
#if FEATURE_WASM_THREADS
38+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
39+
#endif
3740
ArgumentNullException.ThrowIfNull(self);
3841
ObjectDisposedException.ThrowIf(self.IsDisposed, self);
3942
Interop.Runtime.InvokeJSWithArgsRef(self.JSHandle, method, args, out int exception, out object res);
@@ -68,6 +71,9 @@ public static object Invoke(this JSObject self, string method, params object?[]
6871
/// </returns>
6972
public static object GetObjectProperty(this JSObject self, string name)
7073
{
74+
#if FEATURE_WASM_THREADS
75+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
76+
#endif
7177
ArgumentNullException.ThrowIfNull(self);
7278
ObjectDisposedException.ThrowIf(self.IsDisposed, self);
7379

@@ -92,6 +98,9 @@ public static object GetObjectProperty(this JSObject self, string name)
9298
/// <param name="hasOwnProperty"></param>
9399
public static void SetObjectProperty(this JSObject self, string name, object? value, bool createIfNotExists = true, bool hasOwnProperty = false)
94100
{
101+
#if FEATURE_WASM_THREADS
102+
LegacyHostImplementation.ThrowIfLegacyWorkerThread();
103+
#endif
95104
ArgumentNullException.ThrowIfNull(self);
96105
ObjectDisposedException.ThrowIf(self.IsDisposed, self);
97106

0 commit comments

Comments
 (0)