Ejemplo n.º 1
0
        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 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 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);
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
            public ArrayLikeIterator(ArrayOperations obj)
            {
                _obj    = obj;
                _length = obj.GetLength();

                Reset();
            }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
            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;
            }
 public ArrayProtocol(
     Engine engine,
     JsValue thisArg,
     ObjectInstance instance,
     IIterator iterator,
     ICallable callable) : base(engine, iterator, 2)
 {
     _thisArg  = thisArg;
     _instance = ArrayOperations.For(instance);
     _callable = callable;
 }
        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);
        }
Ejemplo n.º 12
0
        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);
            }
Ejemplo n.º 13
0
        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);
        }
Ejemplo n.º 14
0
        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 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);
        }
Ejemplo n.º 16
0
        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);
        }
Ejemplo n.º 17
0
        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);
        }
Ejemplo n.º 18
0
        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);
        }
Ejemplo n.º 19
0
        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);
        }
Ejemplo n.º 20
0
        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);
        }
Ejemplo n.º 21
0
        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);
        }
Ejemplo n.º 24
0
        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 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);
        }
Ejemplo n.º 26
0
        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 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);
        }
Ejemplo n.º 28
0
        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);
        }
Ejemplo n.º 29
0
        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);
        }