Пример #1
0
        public static EcmaValue From([This] EcmaValue thisValue, EcmaValue source, EcmaValue mapFn, EcmaValue thisArg)
        {
            if (!thisValue.IsCallable || !thisValue.ToObject().IsConstructor)
            {
                throw new EcmaTypeErrorException(InternalString.Error.NotConstructor);
            }
            if (mapFn != default)
            {
                Guard.ArgumentIsCallable(mapFn);
            }
            if (source.IsNullOrUndefined)
            {
                return(thisValue.Construct(0));
            }
            RuntimeObject obj      = source.ToObject();
            RuntimeObject iterator = obj.GetMethod(WellKnownSymbol.Iterator);
            TypedArray    array;

            if (iterator != null)
            {
                List <EcmaValue> values = new List <EcmaValue>(obj.GetIterator());
                array = thisValue.Construct(values.Count).GetUnderlyingObject <TypedArray>();
                if (array.Length < values.Count)
                {
                    throw new EcmaTypeErrorException(InternalString.Error.TypedArrayBufferTooSmall);
                }
                int i = 0;
                foreach (EcmaValue v in values)
                {
                    EcmaValue value = v;
                    if (mapFn != default)
                    {
                        value = mapFn.Call(thisArg, value, i);
                    }
                    array.Set(i++, value);
                }
            }
            else
            {
                long length = source[WellKnownProperty.Length].ToLength();
                array = thisValue.Construct(length).GetUnderlyingObject <TypedArray>();
                if (array.Length < length)
                {
                    throw new EcmaTypeErrorException(InternalString.Error.TypedArrayBufferTooSmall);
                }
                for (int i = 0; i < length; i++)
                {
                    EcmaValue value = obj.Get(i);
                    if (mapFn != default)
                    {
                        value = mapFn.Call(thisArg, value, i);
                    }
                    array.Set(i, value);
                }
            }
            return(array);
        }
Пример #2
0
        public static EcmaValue From([This] EcmaValue thisValue, EcmaValue arrayLike, EcmaValue mapFn, EcmaValue thisArg)
        {
            RuntimeObject items = arrayLike.ToObject();

            if (mapFn != default)
            {
                Guard.ArgumentIsCallable(mapFn);
            }
            bool          usingIterator = items.GetMethod(WellKnownSymbol.Iterator) != null;
            long          initialLen    = usingIterator ? 0 : arrayLike[WellKnownProperty.Length].ToLength();
            RuntimeObject arr;

            if (thisValue.IsCallable && thisValue.ToObject().IsConstructor)
            {
                arr = thisValue.Construct(usingIterator ? EcmaValue.EmptyArray : new EcmaValue[] { initialLen }).ToObject();
            }
            else
            {
                arr = new EcmaArray(initialLen);
            }

            if (usingIterator)
            {
                foreach (EcmaValue value in items.GetIterator())
                {
                    ArrayPrototype.ThrowIfLengthExceeded(initialLen + 1);
                    EcmaValue value1 = value;
                    if (mapFn != default)
                    {
                        value1 = mapFn.Call(thisArg, value, initialLen);
                    }
                    arr.CreateDataPropertyOrThrow(initialLen++, value1);
                }
            }
            else
            {
                for (long i = 0; i < initialLen; i++)
                {
                    EcmaValue value = items[i];
                    if (mapFn != default)
                    {
                        value = mapFn.Call(thisArg, value, i);
                    }
                    arr.CreateDataPropertyOrThrow(i, value);
                }
            }
            arr.SetOrThrow(WellKnownProperty.Length, initialLen);
            return(arr);
        }
Пример #3
0
        public static bool InstanceOf(this EcmaValue thisValue, EcmaValue constructor)
        {
            if (constructor.Type != EcmaValueType.Object)
            {
                throw new EcmaTypeErrorException(InternalString.Error.NotFunction);
            }
            RuntimeObject obj           = constructor.ToObject();
            RuntimeObject instOfHandler = obj.GetMethod(Symbol.HasInstance);

            if (instOfHandler != null)
            {
                return(instOfHandler.Call(constructor, thisValue).ToBoolean());
            }
            if (!constructor.IsCallable)
            {
                throw new EcmaTypeErrorException(InternalString.Error.NotFunction);
            }
            return(obj.HasInstance(thisValue.ToObject()));
        }
Пример #4
0
 private void ResolveSelf(EcmaValue value, bool finalize)
 {
     if (value.Type == EcmaValueType.Object)
     {
         RuntimeObject obj = value.ToObject();
         if (obj == this)
         {
             SetStateFinalize(PromiseState.Rejected, new EcmaTypeErrorException(InternalString.Error.PromiseSelfResolution).ToValue());
             return;
         }
         try {
             RuntimeObject then = obj.GetMethod(WellKnownProperty.Then);
             if (then != null)
             {
                 then.Call(value, (PromiseResolver)ResolveSelf, (PromiseResolver)RejectSelf);
                 return;
             }
         } catch (Exception ex) {
             SetStateFinalize(PromiseState.Rejected, EcmaValueUtility.GetValueFromException(ex));
             return;
         }
     }
     SetState(PromiseState.Fulfilled, value, finalize);
 }
Пример #5
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);
        }