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

Added support to convert JsTypedArray when converting objects. #1646

Merged
merged 1 commit into from
Oct 13, 2023
Merged
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
15 changes: 15 additions & 0 deletions Jint.Tests/Runtime/EngineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3037,6 +3037,21 @@ public void ImportModuleShouldTriggerBeforeEvaluateEvents()
Assert.Equal(2, beforeEvaluateTriggeredCount);
}

[Fact]
public void ShouldConvertJsTypedArraysCorrectly()
{
var engine = new Engine();

var float32 = new float [] { 42f, 23 };

engine.SetValue("float32", float32);
engine.SetValue("testFloat32Array", new Action<float[]>(v => Assert.Equal(v, float32)));

engine.Evaluate(@"
testFloat32Array(new Float32Array(float32));
");
}

private static void TestBeforeEvaluateEvent(Action<Engine, string> call, string expectedSource)
{
var engine = new Engine();
Expand Down
28 changes: 28 additions & 0 deletions Jint.Tests/Runtime/TypedArrayInteropTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,34 @@ public void CanInteropWithBigUint64()
Assert.Equal(source, fromEngine.AsBigUint64Array());
}

[Fact]
public void CanInteropWithFloat32()
{
var engine = new Engine();
var source = new float[] { 42f, 12f };

engine.SetValue("testSubject", engine.Realm.Intrinsics.Float32Array.Construct(source));
ValidateCreatedTypeArray(engine, "Float32Array");

var fromEngine = engine.GetValue("testSubject");
Assert.True(fromEngine.IsFloat32Array());
Assert.Equal(source, fromEngine.AsFloat32Array());
}

[Fact]
public void CanInteropWithFloat64()
{
var engine = new Engine();
var source = new double[] { 42f, 12f };

engine.SetValue("testSubject", engine.Realm.Intrinsics.Float64Array.Construct(source));
ValidateCreatedTypeArray(engine, "Float64Array");

var fromEngine = engine.GetValue("testSubject");
Assert.True(fromEngine.IsFloat64Array());
Assert.Equal(source, fromEngine.AsFloat64Array());
}

private static void ValidateCreatedTypeArray(Engine engine, string arrayName)
{
Assert.Equal(arrayName, engine.Evaluate("testSubject.constructor.name").AsString());
Expand Down
34 changes: 34 additions & 0 deletions Jint/JsValueExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,40 @@ public static ulong[] AsBigUint64Array(this JsValue value)

return ((JsTypedArray) value).ToNativeArray<ulong>();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsFloat32Array(this JsValue value)
{
return value is JsTypedArray { _arrayElementType: TypedArrayElementType.Float32 };
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float[] AsFloat32Array(this JsValue value)
{
if (!value.IsFloat32Array())
{
ThrowWrongTypeException(value, "Float32Array");
}

return ((JsTypedArray) value).ToNativeArray<float>();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsFloat64Array(this JsValue value)
{
return value is JsTypedArray { _arrayElementType: TypedArrayElementType.Float64 };
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double[] AsFloat64Array(this JsValue value)
{
if (!value.IsFloat64Array())
{
ThrowWrongTypeException(value, "Float64Array");
}

return ((JsTypedArray) value).ToNativeArray<double>();
}

[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
22 changes: 22 additions & 0 deletions Jint/Native/Object/ObjectInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Jint.Native.RegExp;
using Jint.Native.String;
using Jint.Native.Symbol;
using Jint.Native.TypedArray;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
using Jint.Runtime.Interop;
Expand Down Expand Up @@ -1054,6 +1055,27 @@ private object ToObject(ObjectTraverseStack stack)
converted = result;
break;
}

if (this is JsTypedArray typedArrayInstance)
{
converted = typedArrayInstance._arrayElementType switch
{
TypedArrayElementType.Int8 => typedArrayInstance.ToNativeArray<sbyte>(),
TypedArrayElementType.Int16 => typedArrayInstance.ToNativeArray<short>(),
TypedArrayElementType.Int32 => typedArrayInstance.ToNativeArray<int>(),
TypedArrayElementType.BigInt64 => typedArrayInstance.ToNativeArray<long>(),
TypedArrayElementType.Float32 => typedArrayInstance.ToNativeArray<float>(),
TypedArrayElementType.Float64 => typedArrayInstance.ToNativeArray<double>(),
TypedArrayElementType.Uint8 => typedArrayInstance.ToNativeArray<byte>(),
TypedArrayElementType.Uint8C => typedArrayInstance.ToNativeArray<byte>(),
TypedArrayElementType.Uint16 => typedArrayInstance.ToNativeArray<ushort>(),
TypedArrayElementType.Uint32 => typedArrayInstance.ToNativeArray<uint>(),
TypedArrayElementType.BigUint64 => typedArrayInstance.ToNativeArray<ulong>(),
_ => throw new ArgumentOutOfRangeException()
};

break;
}

if (this is BigIntInstance bigIntInstance)
{
Expand Down