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