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); }