private JsValue Reduce(JsValue thisObj, JsValue[] arguments) { var callbackfn = arguments.At(0); var initialValue = arguments.At(1); var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); var callable = GetCallable(callbackfn); if (len == 0 && arguments.Length < 2) { ExceptionHelper.ThrowTypeError(Engine); } var k = 0; JsValue accumulator = Undefined; if (arguments.Length > 1) { accumulator = initialValue; } else { var kPresent = false; while (kPresent == false && k < len) { if (kPresent = o.TryGetValue((uint)k, out var temp)) { accumulator = temp; } k++; } if (kPresent == false) { ExceptionHelper.ThrowTypeError(Engine); } } var args = new JsValue[4]; args[3] = o.Target; while (k < len) { var i = (uint)k; if (o.TryGetValue(i, out var kvalue)) { args[0] = accumulator; args[1] = kvalue; args[2] = i; accumulator = callable.Call(Undefined, args); } k++; } return(accumulator); }
private JsValue Unshift(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); var argCount = (uint)arguments.Length; o.EnsureCapacity(len + argCount); for (var k = len; k > 0; k--) { var from = k - 1; var to = k + argCount - 1; JsValue fromValue; if (o.TryGetValue(from, out fromValue)) { o.Put(to, fromValue, true); } else { o.DeleteAt(to); } } for (uint j = 0; j < argCount; j++) { o.Put(j, arguments[j], true); } o.SetLength(len + argCount); return(len + argCount); }
private JsValue Map(JsValue thisObj, JsValue[] arguments) { if (thisObj is ArrayInstance) { var arrayInstance = thisObj as ArrayInstance; return(arrayInstance.Map(arguments)); } var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); var callbackfn = arguments.At(0); var thisArg = arguments.At(1); var callable = GetCallable(callbackfn); var a = Engine.Array.ConstructFast(len); var args = _engine._jsValueArrayPool.RentArray(3); args[2] = o.Target; for (uint k = 0; k < len; k++) { JsValue kvalue; if (o.TryGetValue(k, out kvalue)) { args[0] = kvalue; args[1] = k; var mappedValue = callable.Call(thisArg, args); a.SetIndexValue(k, mappedValue, updateLength: false); } } _engine._jsValueArrayPool.ReturnArray(args); return(a); }
private JsValue ForEach(JsValue thisObj, JsValue[] arguments) { var callbackfn = arguments.At(0); var thisArg = arguments.At(1); var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); var callable = GetCallable(callbackfn); var args = _engine._jsValueArrayPool.RentArray(3); args[2] = o.Target; for (uint k = 0; k < len; k++) { if (o.TryGetValue(k, out var kvalue)) { args[0] = kvalue; args[1] = k; callable.Call(thisArg, args); } } _engine._jsValueArrayPool.ReturnArray(args); return(Undefined); }
private JsValue Every(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); ulong len = o.GetLongLength(); if (len == 0) { return(JsBoolean.True); } var callbackfn = arguments.At(0); var thisArg = arguments.At(1); var callable = GetCallable(callbackfn); var args = _engine._jsValueArrayPool.RentArray(3); args[2] = o.Target; for (uint k = 0; k < len; k++) { if (o.TryGetValue(k, out var kvalue)) { args[0] = kvalue; args[1] = k; var testResult = callable.Call(thisArg, args); if (false == TypeConverter.ToBoolean(testResult)) { return(JsBoolean.False); } } } _engine._jsValueArrayPool.ReturnArray(args); return(JsBoolean.True); }
private JsValue Shift(JsValue thisObj, JsValue[] arg2) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); if (len == 0) { o.SetLength(0); return(Undefined); } var first = o.Get(0); for (uint k = 1; k < len; k++) { var to = k - 1; JsValue fromVal; if (o.TryGetValue(k, out fromVal)) { o.Put(to, fromVal, true); } else { o.DeleteAt(to); } } o.DeleteAt(len - 1); o.SetLength(len - 1); return(first); }
private JsValue Slice(JsValue thisObj, JsValue[] arguments) { var start = arguments.At(0); var end = arguments.At(1); var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); var relativeStart = TypeConverter.ToInteger(start); uint k; if (relativeStart < 0) { k = (uint)System.Math.Max(len + relativeStart, 0); } else { k = (uint)System.Math.Min(TypeConverter.ToInteger(start), len); } uint final; if (end.IsUndefined()) { final = TypeConverter.ToUint32(len); } else { double relativeEnd = TypeConverter.ToInteger(end); if (relativeEnd < 0) { final = (uint)System.Math.Max(len + relativeEnd, 0); } else { final = (uint)System.Math.Min(TypeConverter.ToInteger(relativeEnd), len); } } var a = Engine.Array.Construct(final - k); uint n = 0; for (; k < final; k++) { JsValue kValue; if (o.TryGetValue(k, out kValue)) { a.SetIndexValue(n, kValue, updateLength: true); } n++; } return(a); }
public ArrayProtocol( Engine engine, JsValue thisArg, ObjectInstance instance, IIterator iterator, ICallable callable) : base(engine, iterator, 2) { _thisArg = thisArg; _instance = ArrayOperations.For(instance); _callable = callable; }
public ArrayLikeIterator(Engine engine, ObjectInstance objectInstance, ArrayIteratorType kind) : base(engine) { _kind = kind; _typedArray = objectInstance as TypedArrayInstance; if (_typedArray is null) { _operations = ArrayOperations.For(objectInstance); } _position = 0; }
private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLongLength(); if (len == 0) { return(-1); } var n = arguments.Length > 1 ? TypeConverter.ToInteger(arguments[1]) : len - 1; double k; if (n >= 0) { k = System.Math.Min(n, len - 1); // min } else { k = len - System.Math.Abs(n); } if (k < 0 || k > uint.MaxValue) { return(-1); } var searchElement = arguments.At(0); var i = (uint)k; for (;; i--) { var kPresent = o.HasProperty(i); if (kPresent) { var elementK = o.Get(i); var same = JintBinaryExpression.StrictlyEqual(elementK, searchElement); if (same) { return(i); } } if (i == 0) { break; } } return(-1); }
internal JsValue Slice(JsValue thisObj, JsValue[] arguments) { var start = arguments.At(0); var end = arguments.At(1); var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLongLength(); var relativeStart = TypeConverter.ToInteger(start); ulong k; if (relativeStart < 0) { k = (ulong)System.Math.Max(len + relativeStart, 0); } else { k = (ulong)System.Math.Min(TypeConverter.ToInteger(start), len); } ulong final; if (end.IsUndefined()) { final = (ulong)TypeConverter.ToNumber(len); } else { double relativeEnd = TypeConverter.ToInteger(end); if (relativeEnd < 0) { final = (ulong)System.Math.Max(len + relativeEnd, 0); } else { final = (ulong)System.Math.Min(TypeConverter.ToInteger(relativeEnd), len); } } if (k < final && final - k > ArrayOperations.MaxArrayLength) { ExceptionHelper.ThrowRangeError(_engine, "Invalid array length");; } var length = (uint)System.Math.Max(0, (long)final - (long)k); var a = Engine.Array.ArraySpeciesCreate(TypeConverter.ToObject(_engine, thisObj), length); if (thisObj is ArrayInstance ai && a is ArrayInstance a2) { a2.CopyValues(ai, (uint)k, 0, length); }
private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); if (len == 0) { return(-1); } var n = arguments.Length > 1 ? TypeConverter.ToInteger(arguments[1]) : len - 1; double k; if (n >= 0) { k = System.Math.Min(n, len - 1); // min } else { k = len - System.Math.Abs(n); } if (k < 0 || k > uint.MaxValue) { return(-1); } var searchElement = arguments.At(0); var i = (uint)k; for (;; i--) { JsValue value; if (o.TryGetValue(i, out value)) { var same = ExpressionInterpreter.StrictlyEqual(value, searchElement); if (same) { return(i); } } if (i == 0) { break; } } return(-1); }
private JsValue Sort(JsValue thisObj, JsValue[] arguments) { if (!thisObj.IsObject()) { ExceptionHelper.ThrowTypeError(_engine, "Array.prorotype.sort can only be applied on objects"); } var obj = ArrayOperations.For(thisObj.AsObject()); var len = obj.GetLength(); if (len <= 1) { return(obj.Target); } var compareArg = arguments.At(0); ICallable compareFn = null; if (!compareArg.IsUndefined()) { compareFn = compareArg.TryCast <ICallable>(x => ExceptionHelper.ThrowTypeError(_engine, "The sort argument must be a function")); } var array = new JsValue[len]; for (uint i = 0; i < len; ++i) { array[i] = obj.Get(i); } // don't eat inner exceptions try { System.Array.Sort(array, new ISortComparer(compareFn)); } catch (InvalidOperationException e) { throw e.InnerException; } for (uint i = 0; i < len; ++i) { obj.Put(i, array[i], false); } return(obj.Target); }
private JsValue ToLocaleString(JsValue thisObj, JsValue[] arguments) { var array = ArrayOperations.For(Engine, thisObj); var len = array.GetLength(); const string separator = ","; if (len == 0) { return(""); } JsValue r; JsValue firstElement; if (!array.TryGetValue(0, out firstElement) || firstElement.IsNull() || firstElement.IsUndefined()) { r = ""; } else { var elementObj = TypeConverter.ToObject(Engine, firstElement); var func = elementObj.Get("toLocaleString") as ICallable ?? ExceptionHelper.ThrowTypeError <ICallable>(_engine); r = func.Call(elementObj, Arguments.Empty); } for (uint k = 1; k < len; k++) { string s = r + separator; JsValue nextElement; if (!array.TryGetValue(k, out nextElement) || nextElement.IsNull()) { r = ""; } else { var elementObj = TypeConverter.ToObject(Engine, nextElement); var func = elementObj.Get("toLocaleString") as ICallable ?? ExceptionHelper.ThrowTypeError <ICallable>(_engine); r = func.Call(elementObj, Arguments.Empty); } r = s + r; } return(r); }
private JsValue Fill(JsValue thisObj, JsValue[] arguments) { if (thisObj.IsNullOrUndefined()) { ExceptionHelper.ThrowTypeError(_engine, "Cannot convert undefined or null to object"); } var operations = ArrayOperations.For(thisObj as ObjectInstance); var length = operations.GetLength(); var value = arguments.At(0); var start = ConvertAndCheckForInfinity(arguments.At(1), 0); var relativeStart = TypeConverter.ToInteger(start); uint actualStart; if (relativeStart < 0) { actualStart = (uint)System.Math.Max(length + relativeStart, 0); } else { actualStart = (uint)System.Math.Min(relativeStart, length); } var end = ConvertAndCheckForInfinity(arguments.At(2), length); var relativeEnd = TypeConverter.ToInteger(end); uint actualEnd; if (relativeEnd < 0) { actualEnd = (uint)System.Math.Max(length + relativeEnd, 0); } else { actualEnd = (uint)System.Math.Min(relativeEnd, length); } for (var i = actualStart; i < actualEnd; ++i) { operations.Set(i, value, updateLength: false, throwOnError: false); } return(thisObj); }
private JsValue Every(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); uint len; if (thisObj is ArrayInstance) { var arrayInstance = thisObj as ArrayInstance; len = arrayInstance.GetLength(); } else { var intValue = ((ArrayOperations.ObjectInstanceOperations)o).GetIntegerLength(); len = intValue < 0 ? 0 : (uint)intValue; } if (len == 0) { return(JsBoolean.True); } var callbackfn = arguments.At(0); var thisArg = arguments.At(1); var callable = GetCallable(callbackfn); var args = _engine._jsValueArrayPool.RentArray(3); args[2] = o.Target; for (uint k = 0; k < len; k++) { JsValue kvalue; if (o.TryGetValue(k, out kvalue)) { args[0] = kvalue; args[1] = k; var testResult = callable.Call(thisArg, args); if (false == TypeConverter.ToBoolean(testResult)) { return(JsBoolean.False); } } } _engine._jsValueArrayPool.ReturnArray(args); return(JsBoolean.True); }
private JsValue Fill(JsValue thisObj, JsValue[] arguments) { var target = thisObj as ObjectInstance; var operations = ArrayOperations.For(target); var length = operations.GetLength(); var value = arguments.At(0); var start = arguments.At(1, 0).AsNumber(); var relativeStart = TypeConverter.ToInteger(start); uint actualStart; if (relativeStart < 0) { actualStart = (uint)System.Math.Max(length + relativeStart, 0); } else { actualStart = (uint)System.Math.Min(relativeStart, length); } var end = arguments.At(2, length).AsNumber(); var relativeEnd = TypeConverter.ToInteger(end); uint actualEnd; if (relativeEnd < 0) { actualEnd = (uint)System.Math.Max(length + relativeEnd, 0); } else { actualEnd = (uint)System.Math.Min(relativeEnd, length); } for (var i = actualStart; i < actualEnd; ++i) { operations.Put(i, value, false); } return(target); }
public JsValue Pop(JsValue thisObject, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObject); var lenVal = TypeConverter.ToNumber(o.Target.Get("length")); uint len = TypeConverter.ToUint32(lenVal); if (len == 0) { o.SetLength(0); return(Undefined); } len = len - 1; string indx = TypeConverter.ToString(len); JsValue element = o.Target.Get(indx); o.Target.Delete(indx, true); o.Target.Put("length", len, true); return(element); }
private JsValue Includes(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLongLength(); if (len == 0) { return(false); } var searchElement = arguments.At(0); var fromIndex = arguments.At(1, 0); var n = TypeConverter.ToNumber(fromIndex); n = n > ArrayOperations.MaxArrayLikeLength ? ArrayOperations.MaxArrayLikeLength : n; var k = (ulong)System.Math.Max( n >= 0 ? n : len - System.Math.Abs(n), 0); bool SameValueZero(JsValue x, JsValue y) { return(x == y || (x is JsNumber xNum && y is JsNumber yNum && double.IsNaN(xNum._value) && double.IsNaN(yNum._value))); } while (k < len) { var value = o.Get(k); if (SameValueZero(value, searchElement)) { return(true); } k++; } return(false); }
private JsValue Join(JsValue thisObj, JsValue[] arguments) { var separator = arguments.At(0); var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); if (separator.IsUndefined()) { separator = ","; } var sep = TypeConverter.ToString(separator); // as per the spec, this has to be called after ToString(separator) if (len == 0) { return(""); } var s = StringFromJsValue(o.Get(0)); if (len == 1) { return(s); } var sb = ArrayExecutionContext.Current.StringBuilder; sb.Clear(); sb.Append(s); for (uint k = 1; k < len; k++) { sb.Append(sep); sb.Append(StringFromJsValue(o.Get(k))); } return(sb.ToString()); }
private JsValue Includes(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLongLength(); if (len == 0) { return(false); } var searchElement = arguments.At(0); var fromIndex = arguments.At(1, 0); var n = TypeConverter.ToNumber(fromIndex); n = n > ArrayOperations.MaxArrayLikeLength ? ArrayOperations.MaxArrayLikeLength : n; var k = (ulong)System.Math.Max( n >= 0 ? n : len - System.Math.Abs(n), 0);
private JsValue Filter(JsValue thisObj, JsValue[] arguments) { var callbackfn = arguments.At(0); var thisArg = arguments.At(1); var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); var callable = GetCallable(callbackfn); var a = Engine.Array.ArraySpeciesCreate(TypeConverter.ToObject(_engine, thisObj), 0); var operations = ArrayOperations.For(a); uint to = 0; var args = _engine._jsValueArrayPool.RentArray(3); args[2] = o.Target; for (uint k = 0; k < len; k++) { if (o.TryGetValue(k, out var kvalue)) { args[0] = kvalue; args[1] = k; var selected = callable.Call(thisArg, args); if (TypeConverter.ToBoolean(selected)) { operations.Set(to, kvalue, updateLength: false, throwOnError: false); to++; } } } operations.SetLength(to); _engine._jsValueArrayPool.ReturnArray(args); return(a); }
private JsValue Reverse(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); var middle = (uint)System.Math.Floor(len / 2.0); uint lower = 0; while (lower != middle) { var upper = len - lower - 1; JsValue lowerValue; JsValue upperValue; var lowerExists = o.TryGetValue(lower, out lowerValue); var upperExists = o.TryGetValue(upper, out upperValue); if (lowerExists && upperExists) { o.Put(lower, upperValue, true); o.Put(upper, lowerValue, true); } if (!lowerExists && upperExists) { o.Put(lower, upperValue, true); o.DeleteAt(upper); } if (lowerExists && !upperExists) { o.DeleteAt(lower); o.Put(upper, lowerValue, true); } lower++; } return(o.Target); }
private JsValue Unshift(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLongLength(); var argCount = (uint)arguments.Length; if (len + argCount > ArrayOperations.MaxArrayLikeLength) { return(ExceptionHelper.ThrowTypeError <JsValue>(_engine, "Invalid array length")); } o.EnsureCapacity(len + argCount); var minIndex = o.GetSmallestIndex(len); for (var k = len; k > minIndex; k--) { var from = k - 1; var to = k + argCount - 1; if (o.TryGetValue(from, out var fromValue)) { o.Set(to, fromValue, false, true); } else { o.DeletePropertyOrThrow(to); } } for (uint j = 0; j < argCount; j++) { o.Set(j, arguments[j], false, true); } o.SetLength(len + argCount); return(len + argCount); }
private JsValue Map(JsValue thisObj, JsValue[] arguments) { if (thisObj is ArrayInstance arrayInstance && !arrayInstance.HasOwnProperty(CommonProperties.Constructor)) { return(arrayInstance.Map(arguments)); } var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLongLength(); if (len > ArrayOperations.MaxArrayLength) { ExceptionHelper.ThrowRangeError(_engine, "Invalid array length");; } var callbackfn = arguments.At(0); var thisArg = arguments.At(1); var callable = GetCallable(callbackfn); var a = ArrayOperations.For(Engine.Array.ArraySpeciesCreate(TypeConverter.ToObject(_engine, thisObj), (uint)len)); var args = _engine._jsValueArrayPool.RentArray(3); args[2] = o.Target; for (uint k = 0; k < len; k++) { if (o.TryGetValue(k, out var kvalue)) { args[0] = kvalue; args[1] = k; var mappedValue = callable.Call(thisArg, args); a.Set(k, mappedValue, updateLength: false, throwOnError: false); } } _engine._jsValueArrayPool.ReturnArray(args); return(a.Target); }
private JsValue Sort(JsValue thisObj, JsValue[] arguments) { if (!thisObj.IsObject()) { ExceptionHelper.ThrowTypeError(_engine, "Array.prorotype.sort can only be applied on objects"); } var obj = ArrayOperations.For(thisObj.AsObject()); var compareArg = arguments.At(0); ICallable compareFn = null; if (!compareArg.IsUndefined()) { if (compareArg.IsNull() || !(compareArg is ICallable)) { ExceptionHelper.ThrowTypeError(_engine, "The comparison function must be either a function or undefined"); } compareFn = (ICallable)compareArg; } var len = obj.GetLength(); if (len <= 1) { return(obj.Target); } int Comparer(JsValue x, JsValue y) { if (ReferenceEquals(x, null)) { return(1); } if (ReferenceEquals(y, null)) { return(-1); } var xUndefined = x.IsUndefined(); var yUndefined = y.IsUndefined(); if (xUndefined && yUndefined) { return(0); } if (xUndefined) { return(1); } if (yUndefined) { return(-1); } if (compareFn != null) { var s = TypeConverter.ToNumber(compareFn.Call(Undefined, new[] { x, y })); if (s < 0) { return(-1); } if (s > 0) { return(1); } return(0); } var xString = TypeConverter.ToString(x); var yString = TypeConverter.ToString(y); var r = CompareOrdinal(xString, yString); return(r); } var array = new JsValue[len]; for (uint i = 0; i < (uint)array.Length; ++i) { var value = obj.TryGetValue(i, out var temp) ? temp : null; array[i] = value; } // don't eat inner exceptions try { System.Array.Sort(array, Comparer); } catch (InvalidOperationException e) { throw e.InnerException; } for (uint i = 0; i < (uint)array.Length; ++i) { if (!ReferenceEquals(array[i], null)) { obj.Set(i, array[i], updateLength: false, throwOnError: false); } else { obj.DeletePropertyOrThrow(i); } } return(obj.Target); }
private JsValue CopyWithin(JsValue thisObj, JsValue[] arguments) { // Steps 1-2. if (thisObj.IsNullOrUndefined()) { return(ExceptionHelper.ThrowTypeError <JsValue>(_engine, "this is null or not defined")); } JsValue target = arguments.At(0); JsValue start = arguments.At(1); JsValue end = arguments.At(2); var operations = ArrayOperations.For(thisObj as ObjectInstance); var initialLength = operations.GetLength(); var len = ConvertAndCheckForInfinity(initialLength, 0); var relativeTarget = ConvertAndCheckForInfinity(target, 0); var to = relativeTarget < 0 ? System.Math.Max(len + relativeTarget, 0) : System.Math.Min(relativeTarget, len); var relativeStart = ConvertAndCheckForInfinity(start, 0); var from = relativeStart < 0 ? System.Math.Max(len + relativeStart, 0) : System.Math.Min(relativeStart, len); var relativeEnd = ConvertAndCheckForInfinity(end, len); var final = relativeEnd < 0 ? System.Math.Max(len + relativeEnd, 0) : System.Math.Min(relativeEnd, len); var count = System.Math.Min(final - from, len - to); var direction = 1; if (from < to && to < from + count) { direction = -1; from += (uint)count - 1; to += (uint)count - 1; } while (count > 0) { var fromPresent = operations.HasProperty((ulong)from); if (fromPresent) { var fromValue = operations.Get((ulong)from); operations.Set((ulong)to, fromValue, updateLength: true, throwOnError: true); } else { operations.DeletePropertyOrThrow((ulong)to); } from = (uint)(from + direction); to = (uint)(to + direction); count--; } return(thisObj); }
private JsValue IndexOf(JsValue thisObj, JsValue[] arguments) { var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); if (len == 0) { return(-1); } var startIndex = arguments.Length > 1 ? TypeConverter.ToInteger(arguments[1]) : 0; if (startIndex > uint.MaxValue) { return(-1); } uint k; if (startIndex < 0) { var abs = System.Math.Abs(startIndex); long temp = len - (uint)abs; if (abs > len || temp < 0) { temp = 0; } k = (uint)temp; } else { k = (uint)startIndex; } if (k >= len) { return(-1); } uint smallestIndex = o.GetSmallestIndex(); if (smallestIndex > k) { k = smallestIndex; } var searchElement = arguments.At(0); for (; k < len; k++) { JsValue elementK; if (o.TryGetValue(k, out elementK)) { var same = ExpressionInterpreter.StrictlyEqual(elementK, searchElement); if (same) { return(k); } } } return(-1); }
private JsValue Splice(JsValue thisObj, JsValue[] arguments) { var start = arguments.At(0); var deleteCount = arguments.At(1); var o = ArrayOperations.For(Engine, thisObj); var len = o.GetLength(); var relativeStart = TypeConverter.ToInteger(start); uint actualStart; if (relativeStart < 0) { actualStart = (uint)System.Math.Max(len + relativeStart, 0); } else { actualStart = (uint)System.Math.Min(relativeStart, len); } var actualDeleteCount = (uint)System.Math.Min(System.Math.Max(TypeConverter.ToInteger(deleteCount), 0), len - actualStart); var a = Engine.Array.ConstructFast(actualDeleteCount); for (uint k = 0; k < actualDeleteCount; k++) { JsValue fromValue; if (o.TryGetValue(actualStart + k, out fromValue)) { a.SetIndexValue(k, fromValue, updateLength: false); } } a.SetLength(actualDeleteCount); var items = System.ArrayExt.Empty <JsValue>(); if (arguments.Length > 2) { items = new JsValue[arguments.Length - 2]; System.Array.Copy(arguments, 2, items, 0, items.Length); } var length = len - actualDeleteCount + (uint)items.Length; o.EnsureCapacity(length); if (items.Length < actualDeleteCount) { for (uint k = actualStart; k < len - actualDeleteCount; k++) { var from = k + actualDeleteCount; var to = (uint)(k + items.Length); JsValue fromValue; if (o.TryGetValue(from, out fromValue)) { o.Put(to, fromValue, true); } else { o.DeleteAt(to); } } for (var k = len; k > len - actualDeleteCount + items.Length; k--) { o.DeleteAt(k - 1); } } else if (items.Length > actualDeleteCount) { for (var k = len - actualDeleteCount; k > actualStart; k--) { var from = k + actualDeleteCount - 1; uint to = (uint)(k + items.Length - 1); JsValue fromValue; if (o.TryGetValue(from, out fromValue)) { o.Put(to, fromValue, true); } else { o.DeleteAt(to); } } } for (uint k = 0; k < items.Length; k++) { var e = items[k]; o.Put(k + actualStart, e, true); } o.SetLength(length); return(a); }
private ObjectInstance ConstructArrayFromArrayLike( JsValue thisObj, ObjectInstance objectInstance, ICallable callable, JsValue thisArg) { var source = ArrayOperations.For(objectInstance); var length = source.GetLength(); ObjectInstance a; if (thisObj is IConstructor constructor) { var argumentsList = objectInstance.Get(GlobalSymbolRegistry.Iterator).IsNullOrUndefined() ? new JsValue[] { length } : null; a = Construct(constructor, argumentsList); } else { a = _engine.Array.ConstructFast(length); } var args = !ReferenceEquals(callable, null) ? _engine._jsValueArrayPool.RentArray(2) : null; var target = ArrayOperations.For(a); uint n = 0; for (uint i = 0; i < length; i++) { JsValue jsValue; source.TryGetValue(i, out var value); if (!ReferenceEquals(callable, null)) { args[0] = value; args[1] = i; jsValue = callable.Call(thisArg, args); // function can alter data length = source.GetLength(); } else { jsValue = value; } target.Set(i, jsValue, updateLength: false, throwOnError: false); n++; } if (!ReferenceEquals(callable, null)) { _engine._jsValueArrayPool.ReturnArray(args); } target.SetLength(length); return(a); }