Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ private static ResolvedGeneratorAndType Create(TypePositionInfo info, StubCodeCo
(KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Byte], [JSTypeFlags.Number]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Byte]),
(KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.String], [JSTypeFlags.String]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.String]),
(KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Double], [JSTypeFlags.Number]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Double]),
(KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Single], [JSTypeFlags.Number]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Single]),
(KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Int32], [JSTypeFlags.Number]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Int32]),
(KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.JSObject], [JSTypeFlags.Object]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.JSObject]),
(KnownManagedType.Array, JSTypeFlags.Array, [KnownManagedType.Object], [JSTypeFlags.Any]) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Object]),
Expand All @@ -222,6 +223,7 @@ private static ResolvedGeneratorAndType Create(TypePositionInfo info, StubCodeCo
(KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.Byte], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Byte]),
(KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.String], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.String]),
(KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.Double], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Double]),
(KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.Single], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Single]),
(KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.Int32], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.Int32]),
(KnownManagedType.Array, JSTypeFlags.Missing, [KnownManagedType.JSObject], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Array), MarshalerType.Array, [MarshalerType.JSObject]),

Expand All @@ -235,19 +237,22 @@ private static ResolvedGeneratorAndType Create(TypePositionInfo info, StubCodeCo
(KnownManagedType.Span, JSTypeFlags.MemoryView, [KnownManagedType.Byte], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Span), MarshalerType.Span, [MarshalerType.Byte]),
(KnownManagedType.Span, JSTypeFlags.MemoryView, [KnownManagedType.Int32], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Span), MarshalerType.Span, [MarshalerType.Int32]),
(KnownManagedType.Span, JSTypeFlags.MemoryView, [KnownManagedType.Double], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Span), MarshalerType.Span, [MarshalerType.Double]),
(KnownManagedType.Span, JSTypeFlags.MemoryView, [KnownManagedType.Single], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Span), MarshalerType.Span, [MarshalerType.Single]),

(KnownManagedType.Span, JSTypeFlags.MemoryView, _, _) => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),

// span forced
(KnownManagedType.Span, JSTypeFlags.Missing, [KnownManagedType.Byte], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
(KnownManagedType.Span, JSTypeFlags.Missing, [KnownManagedType.Int32], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
(KnownManagedType.Span, JSTypeFlags.Missing, [KnownManagedType.Double], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),
(KnownManagedType.Span, JSTypeFlags.Missing, [KnownManagedType.Single], _) => failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)),

// segment view
(KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, _, [_]) => failWithReason(null!),
(KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, [KnownManagedType.Byte], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.ArraySegment), MarshalerType.ArraySegment, [MarshalerType.Byte]),
(KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, [KnownManagedType.Int32], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.ArraySegment), MarshalerType.ArraySegment, [MarshalerType.Int32]),
(KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, [KnownManagedType.Double], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.ArraySegment), MarshalerType.ArraySegment, [MarshalerType.Double]),
(KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, [KnownManagedType.Single], _) => resolved(new PrimitiveJSGenerator(info, context, MarshalerType.ArraySegment), MarshalerType.ArraySegment, [MarshalerType.Single]),

(KnownManagedType.ArraySegment, JSTypeFlags.MemoryView, _, _) => failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ public struct JSMarshalerArgument
public void ToJS(float value) { throw null; }
public void ToManaged(out float? value) { throw null; }
public void ToJS(float? value) { throw null; }
public void ToManaged(out float[]? value) { throw null; }
public void ToJS(float[]? value) { throw null; }
public void ToManaged(out double value) { throw null; }
public void ToJS(double value) { throw null; }
public void ToManaged(out double? value) { throw null; }
Expand Down Expand Up @@ -309,4 +311,8 @@ public struct JSMarshalerArgument
public void ToJS(ArraySegment<int> value) { throw null; }
public void ToManaged(out ArraySegment<double> value) { throw null; }
public void ToJS(ArraySegment<double> value) { throw null; }
public void ToManaged(out Span<float> value) { throw null; }
public void ToJS(Span<float> value) { throw null; }
public void ToManaged(out ArraySegment<float> value) { throw null; }
public void ToJS(ArraySegment<float> value) { throw null; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ internal static void CheckArray(JSMarshalerType underlyingType)
if (underlying == MarshalerType.Byte
|| underlying == MarshalerType.Int32
|| underlying == MarshalerType.Double
|| underlying == MarshalerType.Single
|| underlying == MarshalerType.String
|| underlying == MarshalerType.Object
|| underlying == MarshalerType.JSObject
Expand All @@ -475,6 +476,7 @@ internal static void CheckArraySegment(JSMarshalerType underlyingType)
if (underlying == MarshalerType.Byte
|| underlying == MarshalerType.Int32
|| underlying == MarshalerType.Double
|| underlying == MarshalerType.Single
) return;
throw new ArgumentException(SR.Format(SR.UnsupportedElementType, underlying), nameof(underlyingType));
}
Expand All @@ -486,7 +488,6 @@ internal static void CheckTask(JSMarshalerType underlyingType)
if (underlying == MarshalerType.Array
|| underlying == MarshalerType.ArraySegment
|| underlying == MarshalerType.Span

|| underlying == MarshalerType.Task
|| underlying == MarshalerType.Action
|| underlying == MarshalerType.Function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public void ToManaged(out object? value)
ToManaged(out double v);
value = v;
}
else if (slot.Type == MarshalerType.Single)
{
ToManaged(out float v);
value = v;
}
else if (slot.Type == MarshalerType.JSObject)
{
ToManaged(out JSObject? val);
Expand Down Expand Up @@ -78,6 +83,11 @@ public void ToManaged(out object? value)
ToManaged(out double[]? val);
value = val;
}
else if (slot.ElementType == MarshalerType.Single)
{
ToManaged(out float[]? val);
value = val;
}
else if (slot.ElementType == MarshalerType.Int32)
{
ToManaged(out int[]? val);
Expand Down Expand Up @@ -287,6 +297,11 @@ public void ToJS(object? value)
int[] val = (int[])value;
ToJS(val);
}
else if (typeof(float[]) == type)
{
float[] val = (float[])value;
ToJS(val);
}
else if (typeof(double[]) == type)
{
double[] val = (double[])value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,104 @@ public void ToJS(float? value)
slot.Type = MarshalerType.None;
}
}

/// <summary>
/// Implementation of the argument marshaling.
/// It's used by JSImport code generator and should not be used by developers in source code.
/// </summary>
/// <param name="value">The value to be marshaled.</param>
#if !DEBUG
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public unsafe void ToManaged(out float[]? value)
{
if (slot.Type == MarshalerType.None)
{
value = null;
return;
}
value = new float[slot.Length];
Marshal.Copy(slot.IntPtrValue, value, 0, slot.Length);
NativeMemory.Free((void*)slot.IntPtrValue);
}

/// <summary>
/// Implementation of the argument marshaling.
/// It's used by JSImport code generator and should not be used by developers in source code.
/// </summary>
/// <param name="value">The value to be marshaled.</param>
#if !DEBUG
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public unsafe void ToJS(float[] value)
{
if (value == null)
{
slot.Type = MarshalerType.None;
return;
}
slot.Type = MarshalerType.Array;
slot.IntPtrValue = (IntPtr)NativeMemory.Alloc((nuint)(value.Length * sizeof(float)));
slot.Length = value.Length;
slot.ElementType = MarshalerType.Single;
Marshal.Copy(value, 0, slot.IntPtrValue, slot.Length);
}

/// <summary>
/// Implementation of the argument marshaling.
/// It's used by JSImport code generator and should not be used by developers in source code.
/// </summary>
/// <param name="value">The value to be marshaled.</param>
// this only supports array round-trip
public unsafe void ToManaged(out ArraySegment<float> value)
{
var array = (float[])((GCHandle)slot.GCHandle).Target!;
var refPtr = (IntPtr)Unsafe.AsPointer(ref MemoryMarshal.GetArrayDataReference(array));
int byteOffset = (int)(slot.IntPtrValue - (nint)refPtr);
value = new ArraySegment<float>(array, byteOffset / sizeof(float), slot.Length);
}

/// <summary>
/// Implementation of the argument marshaling.
/// It's used by JSImport code generator and should not be used by developers in source code.
/// </summary>
/// <param name="value">The value to be marshaled.</param>
public unsafe void ToJS(ArraySegment<float> value)
{
if (value.Array == null)
{
slot.Type = MarshalerType.None;
return;
}
slot.Type = MarshalerType.ArraySegment;
var ctx = ToJSContext;
slot.GCHandle = ctx.GetJSOwnedObjectGCHandle(value.Array, GCHandleType.Pinned);
var refPtr = (IntPtr)Unsafe.AsPointer(ref MemoryMarshal.GetArrayDataReference(value.Array));
slot.IntPtrValue = refPtr + (value.Offset * sizeof(float));
slot.Length = value.Count;
}

/// <summary>
/// Implementation of the argument marshaling.
/// It's used by JSImport code generator and should not be used by developers in source code.
/// </summary>
/// <param name="value">The value to be marshaled.</param>
public unsafe void ToManaged(out Span<float> value)
{
value = new Span<float>((void*)slot.IntPtrValue, slot.Length);
}

/// <summary>
/// Implementation of the argument marshaling.
/// It's used by JSImport code generator and should not be used by developers in source code.
/// </summary>
/// <remarks>caller is responsible for pinning.</remarks>
/// <param name="value">The value to be marshaled.</param>
public unsafe void ToJS(Span<float> value)
{
slot.Length = value.Length;
slot.IntPtrValue = (IntPtr)Unsafe.AsPointer(ref value.GetPinnableReference());
slot.Type = MarshalerType.Span;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,42 @@ public void JsExportString(string value)
"string");
}

[Fact]
public void JsExportArraySegmentOfDouble()
{
ArraySegment<double> segment = new ArraySegment<double>([1, 2, 3, double.MaxValue, double.MinValue, double.Pi, double.NegativeInfinity, double.PositiveInfinity, double.NaN]);
ArraySegment<double> res = JavaScriptTestHelper.invoke1_ArraySegmentOfDouble(segment, nameof(JavaScriptTestHelper.EchoArraySegmentOfDouble));
Assert.Equal(segment.Count, res.Count);
Assert.Equal(segment.Array, res.Array);
}

[Fact]
public void JsExportArraySegmentOfSingle()
{
ArraySegment<float> segment = new ArraySegment<float>([1, 2, 3, float.MaxValue, float.MinValue, float.Pi, float.NegativeInfinity, float.PositiveInfinity, float.NaN]);
ArraySegment<float> res = JavaScriptTestHelper.invoke1_ArraySegmentOfSingle(segment, nameof(JavaScriptTestHelper.EchoArraySegmentOfSingle));
Assert.Equal(segment.Count, res.Count);
Assert.Equal(segment.Array, res.Array);
}

[Theory]
[MemberData(nameof(MarshalDoubleArrayCases))]
public void JsExportSpanOfDouble(double[] value)
{
Span<double> span = new Span<double>(value);
Span<double> res = JavaScriptTestHelper.invoke1_SpanDouble(span, nameof(JavaScriptTestHelper.EchoSpanDouble));
Assert.Equal(value, res);
}

[Theory]
[MemberData(nameof(MarshalSingleArrayCases))]
public void JsExportSpanOfSingle(float[] value)
{
Span<float> span = new Span<float>(value);
Span<float> res = JavaScriptTestHelper.invoke1_SpanSingle(span, nameof(JavaScriptTestHelper.EchoSpanSingle));
Assert.Equal(value, res);
}

[Fact]
public void JsExportStringNoNs()
{
Expand Down
Loading
Loading