コード例 #1
0
 private TypedArrayInfo(TypedArrayKind kind, WellKnownObject defaultConstructor, WellKnownObject proto, int elementSize, string typeName)
 {
     this.ArrayKind          = kind;
     this.DefaultConstructor = defaultConstructor;
     this.DefaultPrototype   = proto;
     this.ElementSize        = elementSize;
     this.TypedArrayName     = typeName;
 }
コード例 #2
0
 public TypedArray(TypedArrayKind kind)
     : base(TypedArrayInfo.GetDefaultPrototype(kind))
 {
     this.ArrayKind   = kind;
     this.ElementSize = TypedArrayInfo.GetElementSize(kind);
 }
コード例 #3
0
 public static int GetElementSize(TypedArrayKind kind)
 {
     return(info[(int)kind].ElementSize);
 }
コード例 #4
0
 public static string GetTypedArrayName(TypedArrayKind kind)
 {
     return(info[(int)kind].TypedArrayName);
 }
コード例 #5
0
 public static WellKnownObject GetDefaultPrototype(TypedArrayKind kind)
 {
     return(info[(int)kind].DefaultPrototype);
 }
コード例 #6
0
 public static WellKnownObject GetDefaultConstructor(TypedArrayKind kind)
 {
     return(info[(int)kind].DefaultConstructor);
 }
コード例 #7
0
        public static EcmaValue ConstructTypedArray(TypedArrayKind kind, EcmaValue thisValue, EcmaValue[] args)
        {
            TypedArray array = thisValue.GetUnderlyingObject <TypedArray>();

            if (args.Length == 0)
            {
                array.Init(0);
                return(thisValue);
            }
            if (args[0].Type != EcmaValueType.Object)
            {
                array.Init(args[0].ToIndex());
                return(thisValue);
            }
            RuntimeObject obj             = args[0].ToObject();
            long          bytesPerElement = array.ElementSize;

            if (obj is TypedArray srcArray)
            {
                Guard.BufferNotDetached(srcArray);
                RuntimeObject bufferConstructor;
                if (srcArray.Buffer.IsShared)
                {
                    bufferConstructor = srcArray.Realm.GetRuntimeObject(WellKnownObject.ArrayBuffer);
                }
                else
                {
                    bufferConstructor = RuntimeObject.GetSpeciesConstructor(srcArray.Buffer, WellKnownObject.ArrayBuffer);
                }
                if (srcArray.ArrayKind == kind)
                {
                    ArrayBuffer buffer = srcArray.Buffer.Clone(srcArray.ByteOffset, bytesPerElement * srcArray.Length, bufferConstructor);
                    array.Init(buffer);
                }
                else
                {
                    ArrayBuffer buffer = ArrayBuffer.AllocateArrayBuffer(bufferConstructor, bytesPerElement * srcArray.Length);
                    Guard.BufferNotDetached(srcArray);
                    array.Init(buffer);
                    for (int i = 0, j = 0, count = srcArray.Length; i < count; i++, j++)
                    {
                        array.SetValueInBuffer(j, srcArray.GetValueFromBuffer(i));
                    }
                }
                return(thisValue);
            }
            if (obj is ArrayBuffer srcBuffer)
            {
                long offset = args.Length > 1 ? args[1].ToIndex() : 0;
                if ((offset % bytesPerElement) != 0)
                {
                    throw new EcmaRangeErrorException(InternalString.Error.TypedArrayInvalidOffset, TypedArrayInfo.GetTypedArrayName(array.ArrayKind), bytesPerElement);
                }
                long length;
                if (args.Length <= 2 || args[2] == default)
                {
                    Guard.BufferNotDetached(srcBuffer);
                    if ((srcBuffer.ByteLength % bytesPerElement) != 0)
                    {
                        throw new EcmaRangeErrorException(InternalString.Error.TypedArrayInvalidByteLength, TypedArrayInfo.GetTypedArrayName(array.ArrayKind), bytesPerElement);
                    }
                    if (srcBuffer.ByteLength < offset)
                    {
                        throw new EcmaRangeErrorException(InternalString.Error.BufferOffsetOutOfBound, offset);
                    }
                    length = srcBuffer.ByteLength - offset;
                }
                else
                {
                    length = args[2].ToIndex() * bytesPerElement;
                    Guard.BufferNotDetached(srcBuffer);
                    if (offset + length > srcBuffer.ByteLength)
                    {
                        throw new EcmaRangeErrorException(InternalString.Error.TypedArrayInvalidLength, length);
                    }
                }
                array.Init(srcBuffer, offset, length);
                return(thisValue);
            }
            RuntimeObject iterator = obj.GetMethod(WellKnownSymbol.Iterator);

            if (iterator != null)
            {
                List <EcmaValue> values = new List <EcmaValue>(obj.GetIterator());
                array.Init(values.Count);
                int i = 0;
                foreach (EcmaValue v in values)
                {
                    array.Set(i++, v);
                }
            }
            else
            {
                long length = obj[WellKnownProperty.Length].ToLength();
                array.Init((int)length);
                for (int i = 0; i < length; i++)
                {
                    array.Set(i, obj[i]);
                }
            }
            return(thisValue);
        }