Переглянути джерело

Add typed array helpers for IsArray and AsArray (#971)

* Add typed array helpers for IsArray and AsArray
* add IsCallable and AsCallable
* add JsValue Call(this ICallable value, params JsValue[] arguments)
Marko Lahma 3 роки тому
батько
коміт
21d1dc1d61

+ 15 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -2686,5 +2686,20 @@ namespace Jint.Tests.Runtime
             result = engine.Evaluate(script).ToString();
             Assert.Equal("0,1,2", result);
         }
+
+        [Fact]
+        public void CanCheckIfCallable()
+        {
+            var engine = new Engine();
+            engine.Evaluate("var f = () => true;");
+
+            var result = engine.GetValue("f");
+            Assert.True(result.IsCallable());
+
+            var callable = result.AsCallable();
+            Assert.True(callable.Call(JsValue.Undefined, Array.Empty<JsValue>()).AsBoolean());
+
+            Assert.True(callable.Call().AsBoolean());
+        }
     }
 }

+ 57 - 10
Jint.Tests/Runtime/TypedArrayInteropTests.cs

@@ -8,79 +8,126 @@ namespace Jint.Tests.Runtime
         public void CanInteropWithInt8()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int8Array.Construct(new sbyte[] { 42 }));
+            var source = new sbyte[] { 42, 12 };
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int8Array.Construct(source));
             ValidateCreatedTypeArray(engine, "Int8Array");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsInt8Array());
+            Assert.Equal(source, fromEngine.AsInt8Array());
         }
 
         [Fact]
         public void CanInteropWithUint8()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint8Array.Construct(new byte[] { 42 }));
+            var source = new byte[] { 42, 12 };
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint8Array.Construct(source));
             ValidateCreatedTypeArray(engine, "Uint8Array");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsUint8Array());
+            Assert.Equal(source, fromEngine.AsUint8Array());
         }
 
         [Fact]
         public void CanInteropWithUint8Clamped()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint8ClampedArray.Construct(new byte[] { 42 }));
+            var source = new byte[] { 42, 12 };
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint8ClampedArray.Construct(source));
             ValidateCreatedTypeArray(engine, "Uint8ClampedArray");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsUint8ClampedArray());
+            Assert.Equal(source, fromEngine.AsUint8ClampedArray());
         }
 
         [Fact]
         public void CanInteropWithInt16()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int16Array.Construct(new short[] { 42 }));
+            var source = new short[] { 42, 12 };
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int16Array.Construct(source));
             ValidateCreatedTypeArray(engine, "Int16Array");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsInt16Array());
+            Assert.Equal(source, fromEngine.AsInt16Array());
         }
 
         [Fact]
         public void CanInteropWithUint16()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint16Array.Construct(new ushort[] { 42 }));
+            var source = new ushort[] { 42, 12 };
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint16Array.Construct(source));
             ValidateCreatedTypeArray(engine, "Uint16Array");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsUint16Array());
+            Assert.Equal(source, fromEngine.AsUint16Array());
         }
 
         [Fact]
         public void CanInteropWithInt32()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int32Array.Construct(new int[] { 42 }));
+            var source = new int[] { 42, 12 };
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.Int32Array.Construct(source));
             ValidateCreatedTypeArray(engine, "Int32Array");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsInt32Array());
+            Assert.Equal(source, fromEngine.AsInt32Array());
         }
 
         [Fact]
         public void CanInteropWithUint32()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint32Array.Construct(new uint[] { 42 }));
+            var source = new uint[] { 42, 12 };
+
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.Uint32Array.Construct(source));
             ValidateCreatedTypeArray(engine, "Uint32Array");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsUint32Array());
+            Assert.Equal(source, fromEngine.AsUint32Array());
         }
 
         [Fact(Skip = "BigInt not implemented")]
         public void CanInteropWithBigInt64()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.BigInt64Array.Construct(new long[] { 42 }));
+            var source = new long[] { 42, 12 };
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.BigInt64Array.Construct(source));
             ValidateCreatedTypeArray(engine, "BigInt64Array");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsBigInt64Array());
+            Assert.Equal(source, fromEngine.AsBigInt64Array());
         }
 
         [Fact(Skip = "BigInt not implemented")]
         public void CanInteropWithBigUint64()
         {
             var engine = new Engine();
-            engine.SetValue("testSubject", engine.Realm.Intrinsics.BigUint64Array.Construct(new ulong[] { 42 }));
+            var source = new ulong[] { 42, 12 };
+            engine.SetValue("testSubject", engine.Realm.Intrinsics.BigUint64Array.Construct(source));
             ValidateCreatedTypeArray(engine, "BigUint64Array");
+
+            var fromEngine = engine.GetValue("testSubject");
+            Assert.True(fromEngine.IsBigUint64Array());
+            Assert.Equal(source, fromEngine.AsBigUint64Array());
         }
 
         private static void ValidateCreatedTypeArray(Engine engine, string arrayName)
         {
             Assert.Equal(arrayName, engine.Evaluate("testSubject.constructor.name").AsString());
-            Assert.Equal(1, engine.Evaluate("testSubject.length").AsNumber());
+            Assert.Equal(2, engine.Evaluate("testSubject.length").AsNumber());
             Assert.Equal(42, engine.Evaluate("testSubject[0]").AsNumber());
+            Assert.Equal(12, engine.Evaluate("testSubject[1]").AsNumber());
         }
     }
 }

+ 384 - 1
Jint/JsValueExtensions.cs

@@ -1,12 +1,181 @@
-using System.Runtime.CompilerServices;
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
 using Jint.Native;
+using Jint.Native.Array;
+using Jint.Native.Date;
+using Jint.Native.Object;
 using Jint.Native.Promise;
+using Jint.Native.RegExp;
+using Jint.Native.Symbol;
+using Jint.Native.TypedArray;
 using Jint.Runtime;
 
 namespace Jint
 {
     public static class JsValueExtensions
     {
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsPrimitive(this JsValue value)
+        {
+            return (value._type & (InternalTypes.Primitive | InternalTypes.Undefined | InternalTypes.Null)) != 0;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsUndefined(this JsValue value)
+        {
+            return value._type == InternalTypes.Undefined;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static bool IsNullOrUndefined(this JsValue value)
+        {
+            return value._type < InternalTypes.Boolean;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsDate(this JsValue value)
+        {
+            return value is DateInstance;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsPromise(this JsValue value)
+        {
+            return value is PromiseInstance;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsRegExp(this JsValue value)
+        {
+            if (!(value is ObjectInstance oi))
+            {
+                return false;
+            }
+
+            var matcher = oi.Get(GlobalSymbolRegistry.Match);
+            if (!matcher.IsUndefined())
+            {
+                return TypeConverter.ToBoolean(matcher);
+            }
+
+            return value is RegExpInstance;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsObject(this JsValue value)
+        {
+            return (value._type & InternalTypes.Object) != 0;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsString(this JsValue value)
+        {
+            return (value._type & InternalTypes.String) != 0;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsNumber(this JsValue value)
+        {
+            return (value._type & (InternalTypes.Number | InternalTypes.Integer)) != 0;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static bool IsInteger(this JsValue value)
+        {
+            return value._type == InternalTypes.Integer;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsBoolean(this JsValue value)
+        {
+            return value._type == InternalTypes.Boolean;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsNull(this JsValue value)
+        {
+            return value._type == InternalTypes.Null;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsSymbol(this JsValue value)
+        {
+            return value._type == InternalTypes.Symbol;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static DateInstance AsDate(this JsValue value)
+        {
+            if (!value.IsDate())
+            {
+                ExceptionHelper.ThrowArgumentException("The value is not a date");
+            }
+
+            return value as DateInstance;
+        }
+
+        [Pure]
+        public static RegExpInstance AsRegExp(this JsValue value)
+        {
+            if (!value.IsRegExp())
+            {
+                ExceptionHelper.ThrowArgumentException("The value is not a regex");
+            }
+
+            return value as RegExpInstance;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static ObjectInstance AsObject(this JsValue value)
+        {
+            if (!value.IsObject())
+            {
+                ExceptionHelper.ThrowArgumentException("The value is not an object");
+            }
+
+            return value as ObjectInstance;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static TInstance AsInstance<TInstance>(this JsValue value) where TInstance : class
+        {
+            if (!value.IsObject())
+            {
+                ExceptionHelper.ThrowArgumentException("The value is not an object");
+            }
+
+            return value as TInstance;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static ArrayInstance AsArray(this JsValue value)
+        {
+            if (!value.IsArray())
+            {
+                ExceptionHelper.ThrowArgumentException("The value is not an array");
+            }
+
+            return value as ArrayInstance;
+        }
+
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool AsBoolean(this JsValue value)
         {
@@ -46,6 +215,220 @@ namespace Jint
             return value.ToString();
         }
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsUint8Array(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.Uint8 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static byte[] AsUint8Array(this JsValue value)
+        {
+            if (!value.IsUint8Array())
+            {
+                ThrowWrongTypeException(value, "Uint8Array");
+            }
+
+            return ((TypedArrayInstance) value).ToNativeArray<byte>();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsUint8ClampedArray(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.Uint8C };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static byte[] AsUint8ClampedArray(this JsValue value)
+        {
+            if (!value.IsUint8ClampedArray())
+            {
+                ThrowWrongTypeException(value, "Uint8ClampedArray");
+            }
+
+            return ((TypedArrayInstance) value).ToNativeArray<byte>();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsInt8Array(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.Int8 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static sbyte[] AsInt8Array(this JsValue value)
+        {
+            if (!value.IsInt8Array())
+            {
+                ThrowWrongTypeException(value, "Int8Array");
+            }
+
+            return ((TypedArrayInstance) value).ToNativeArray<sbyte>();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsInt16Array(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.Int16 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static short[] AsInt16Array(this JsValue value)
+        {
+            if (!value.IsInt16Array())
+            {
+                ThrowWrongTypeException(value, "Int16Array");
+            }
+
+            return ((TypedArrayInstance) value).ToNativeArray<short>();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsUint16Array(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.Uint16 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static ushort[] AsUint16Array(this JsValue value)
+        {
+            if (!value.IsUint16Array())
+            {
+                ThrowWrongTypeException(value, "Uint16Array");
+            }
+
+            return ((TypedArrayInstance) value).ToNativeArray<ushort>();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsInt32Array(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.Int32 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static int[] AsInt32Array(this JsValue value)
+        {
+            if (!value.IsInt32Array())
+            {
+                ThrowWrongTypeException(value, "Int32Array");
+            }
+
+            return ((TypedArrayInstance) value).ToNativeArray<int>();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsUint32Array(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.Uint32 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static uint[] AsUint32Array(this JsValue value)
+        {
+            if (!value.IsUint32Array())
+            {
+                ThrowWrongTypeException(value, "Uint32Array");
+            }
+
+            return ((TypedArrayInstance) value).ToNativeArray<uint>();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsBigInt64Array(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.BigInt64 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static long[] AsBigInt64Array(this JsValue value)
+        {
+            if (!value.IsUint32Array())
+            {
+                ThrowWrongTypeException(value, "BigInt64Array");
+            }
+
+            ExceptionHelper.ThrowNotImplementedException();
+            return null;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsBigUint64Array(this JsValue value)
+        {
+            return value is TypedArrayInstance { _arrayElementType: TypedArrayElementType.BigUint64 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static ulong[] AsBigUint64Array(this JsValue value)
+        {
+            if (!value.IsBigUint64Array())
+            {
+                ThrowWrongTypeException(value, "BigUint64Array");
+            }
+
+            ExceptionHelper.ThrowNotImplementedException();
+            return null;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static T TryCast<T>(this JsValue value) where T : class
+        {
+            return value as T;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static T TryCast<T>(this JsValue value, Action<JsValue> fail) where T : class
+        {
+            if (value is T o)
+            {
+                return o;
+            }
+
+            fail.Invoke(value);
+
+            return null;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static T As<T>(this JsValue value) where T : ObjectInstance
+        {
+            if (value.IsObject())
+            {
+                return value as T;
+            }
+
+            return null;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsCallable(this JsValue value)
+        {
+            return value.IsCallable;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static ICallable AsCallable(this JsValue value)
+        {
+            if (!value.IsCallable())
+            {
+                ThrowWrongTypeException(value, "Callable");
+            }
+
+            return value as ICallable;
+        }
+
+        [Pure]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static JsValue Call(this ICallable value, params JsValue[] arguments)
+        {
+            return value.Call(JsValue.Undefined, arguments);
+        }
+
         /// <summary>
         /// If the value is a Promise
         ///     1. If "Fulfilled" returns the value it was fulfilled with

+ 1 - 1
Jint/Native/ArrayBuffer/ArrayBufferInstance.cs

@@ -110,7 +110,7 @@ namespace Jint.Native.ArrayBuffer
         /// <summary>
         /// https://tc39.es/ecma262/#sec-rawbytestonumeric
         /// </summary>
-        private double RawBytesToNumeric(TypedArrayElementType type, int byteIndex, bool isLittleEndian)
+        internal double RawBytesToNumeric(TypedArrayElementType type, int byteIndex, bool isLittleEndian)
         {
             var elementSize = type.GetElementSize();
             var rawBytes = _arrayBufferData;

+ 1 - 195
Jint/Native/JsValue.cs

@@ -31,148 +31,12 @@ namespace Jint.Native
             _type = type;
         }
 
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsPrimitive()
-        {
-            return (_type & (InternalTypes.Primitive | InternalTypes.Undefined | InternalTypes.Null)) != 0;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsUndefined()
-        {
-            return _type == InternalTypes.Undefined;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal bool IsNullOrUndefined()
-        {
-            return _type < InternalTypes.Boolean;
-        }
-
         [Pure]
         public virtual bool IsArray() => false;
 
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsDate()
-        {
-            return this is DateInstance;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsPromise()
-        {
-            return this is PromiseInstance;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsRegExp()
-        {
-            if (!(this is ObjectInstance oi))
-            {
-                return false;
-            }
-
-            var matcher = oi.Get(GlobalSymbolRegistry.Match);
-            if (!matcher.IsUndefined())
-            {
-                return TypeConverter.ToBoolean(matcher);
-            }
-
-            return this is RegExpInstance;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsObject()
-        {
-            return (_type & InternalTypes.Object) != 0;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsString()
-        {
-            return (_type & InternalTypes.String) != 0;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsNumber()
-        {
-            return (_type & (InternalTypes.Number | InternalTypes.Integer)) != 0;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal bool IsInteger()
-        {
-            return _type == InternalTypes.Integer;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsBoolean()
-        {
-            return _type == InternalTypes.Boolean;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsNull()
-        {
-            return _type == InternalTypes.Null;
-        }
-
         internal virtual bool IsIntegerIndexedArray => false;
 
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsSymbol()
-        {
-            return _type == InternalTypes.Symbol;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public ObjectInstance AsObject()
-        {
-            if (!IsObject())
-            {
-                ExceptionHelper.ThrowArgumentException("The value is not an object");
-            }
-
-            return this as ObjectInstance;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public TInstance AsInstance<TInstance>() where TInstance : class
-        {
-            if (!IsObject())
-            {
-                ExceptionHelper.ThrowArgumentException("The value is not an object");
-            }
-
-            return this as TInstance;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public ArrayInstance AsArray()
-        {
-            if (!IsArray())
-            {
-                ExceptionHelper.ThrowArgumentException("The value is not an array");
-            }
-
-            return this as ArrayInstance;
-        }
+        internal virtual bool IsConstructor => false;
 
         [Pure]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -217,62 +81,6 @@ namespace Jint.Native
             return true;
         }
 
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public DateInstance AsDate()
-        {
-            if (!IsDate())
-            {
-                ExceptionHelper.ThrowArgumentException("The value is not a date");
-            }
-
-            return this as DateInstance;
-        }
-
-        [Pure]
-        public RegExpInstance AsRegExp()
-        {
-            if (!IsRegExp())
-            {
-                ExceptionHelper.ThrowArgumentException("The value is not a regex");
-            }
-
-            return this as RegExpInstance;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public T TryCast<T>() where T : class
-        {
-            return this as T;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public T TryCast<T>(Action<JsValue> fail) where T : class
-        {
-            if (this is T o)
-            {
-                return o;
-            }
-
-            fail.Invoke(this);
-
-            return null;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public T As<T>() where T : ObjectInstance
-        {
-            if (IsObject())
-            {
-                return this as T;
-            }
-
-            return null;
-        }
-
         public Types Type
         {
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -281,8 +89,6 @@ namespace Jint.Native
                 : (Types) (_type & ~InternalTypes.InternalFlags);
         }
 
-        internal virtual bool IsConstructor => false;
-
         /// <summary>
         /// Creates a valid <see cref="JsValue"/> instance from any <see cref="Object"/> instance
         /// </summary>

+ 19 - 0
Jint/Native/TypedArray/TypedArrayInstance.cs

@@ -1,3 +1,4 @@
+using System;
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
 using Jint.Native.ArrayBuffer;
@@ -330,5 +331,23 @@ namespace Jint.Native.TypedArray
                    && !double.IsInfinity(value)
                    && System.Math.Floor(System.Math.Abs(value)) == System.Math.Abs(value);
         }
+
+        internal T[] ToNativeArray<T>()
+        {
+            var conversionType = typeof(T);
+            var elementSize = _arrayElementType.GetElementSize();
+            var byteOffset = _byteOffset;
+            var buffer = _viewedArrayBuffer;
+
+            var array = new T[Length];
+            for (var i = 0; i < array.Length; ++i)
+            {
+                var indexedPosition = i * elementSize + byteOffset;
+                var value = buffer.RawBytesToNumeric(_arrayElementType, indexedPosition, BitConverter.IsLittleEndian);
+                array[i] = (T) Convert.ChangeType(value, conversionType);
+            }
+
+            return array;
+        }
     }
 }