Example #1
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.3
        /// </summary>
        public static JsValue ParseFloat(JsValue thisObject, JsValue[] arguments)
        {
            var inputString   = TypeConverter.ToString(arguments.At(0));
            var trimmedString = StringPrototype.TrimStartEx(inputString);

            var sign = 1;

            if (trimmedString.Length > 0)
            {
                if (trimmedString[0] == '-')
                {
                    sign          = -1;
                    trimmedString = trimmedString.Substring(1);
                }
                else if (trimmedString[0] == '+')
                {
                    trimmedString = trimmedString.Substring(1);
                }
            }

            if (trimmedString.StartsWith("Infinity"))
            {
                return(sign * double.PositiveInfinity);
            }

            if (trimmedString.StartsWith("NaN"))
            {
                return(JsNumber.DoubleNaN);
            }

            var separator = (char)0;

            bool    isNan  = true;
            decimal number = 0;
            var     i      = 0;

            for (; i < trimmedString.Length; i++)
            {
                var c = trimmedString[i];
                if (c == '.')
                {
                    i++;
                    separator = '.';
                    break;
                }

                if (c == 'e' || c == 'E')
                {
                    i++;
                    separator = 'e';
                    break;
                }

                var digit = c - '0';

                if (digit >= 0 && digit <= 9)
                {
                    isNan  = false;
                    number = number * 10 + digit;
                }
                else
                {
                    break;
                }
            }

            decimal pow = 0.1m;

            if (separator == '.')
            {
                for (; i < trimmedString.Length; i++)
                {
                    var c = trimmedString[i];

                    var digit = c - '0';

                    if (digit >= 0 && digit <= 9)
                    {
                        isNan   = false;
                        number += digit * pow;
                        pow    *= 0.1m;
                    }
                    else if (c == 'e' || c == 'E')
                    {
                        i++;
                        separator = 'e';
                        break;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            var exp     = 0;
            var expSign = 1;

            if (separator == 'e')
            {
                if (i < trimmedString.Length)
                {
                    if (trimmedString[i] == '-')
                    {
                        expSign = -1;
                        i++;
                    }
                    else if (trimmedString[i] == '+')
                    {
                        i++;
                    }
                }

                for (; i < trimmedString.Length; i++)
                {
                    var c = trimmedString[i];

                    var digit = c - '0';

                    if (digit >= 0 && digit <= 9)
                    {
                        exp = exp * 10 + digit;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (isNan)
            {
                return(JsNumber.DoubleNaN);
            }

            for (var k = 1; k <= exp; k++)
            {
                if (expSign > 0)
                {
                    number *= 10;
                }
                else
                {
                    number /= 10;
                }
            }

            return((double)(sign * number));
        }
Example #2
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-regexp.prototype-@@split
        /// </summary>
        private JsValue Split(JsValue thisObj, JsValue[] arguments)
        {
            var rx              = AssertThisIsObjectInstance(thisObj, "RegExp.prototype.split");
            var s               = TypeConverter.ToString(arguments.At(0));
            var limit           = arguments.At(1);
            var c               = SpeciesConstructor(rx, _realm.Intrinsics.RegExp);
            var flags           = TypeConverter.ToJsString(rx.Get(PropertyFlags));
            var unicodeMatching = flags.IndexOf('u') > -1;
            var newFlags        = flags.IndexOf('y') > -1 ? flags : new JsString(flags.ToString() + 'y');
            var splitter        = Construct(c, new JsValue[]
            {
                rx,
                newFlags
            });
            uint lengthA = 0;
            var  lim     = limit.IsUndefined() ? NumberConstructor.MaxSafeInteger : TypeConverter.ToUint32(limit);

            if (lim == 0)
            {
                return(_realm.Intrinsics.Array.ArrayCreate(0));
            }

            if (s.Length == 0)
            {
                var a = _realm.Intrinsics.Array.ArrayCreate(0);
                var z = RegExpExec(splitter, s);
                if (!z.IsNull())
                {
                    return(a);
                }

                a.SetIndexValue(0, s, updateLength: true);
                return(a);
            }

            if (!unicodeMatching && rx is RegExpInstance R && R.TryGetDefaultRegExpExec(out _))
            {
                // we can take faster path

                if (R.Source == RegExpInstance.regExpForMatchingAllCharacters)
                {
                    // if empty string, just a string split
                    return(StringPrototype.SplitWithStringSeparator(_realm, "", s, (uint)s.Length));
                }

                var a     = (ArrayInstance)_realm.Intrinsics.Array.Construct(Arguments.Empty);
                var match = R.Value.Match(s, 0);

                if (!match.Success) // No match at all return the string in an array
                {
                    a.SetIndexValue(0, s, updateLength: true);
                    return(a);
                }

                int  lastIndex = 0;
                uint index     = 0;
                while (match.Success && index < lim)
                {
                    if (match.Length == 0 && (match.Index == 0 || match.Index == s.Length || match.Index == lastIndex))
                    {
                        match = match.NextMatch();
                        continue;
                    }

                    // Add the match results to the array.
                    a.SetIndexValue(index++, s.Substring(lastIndex, match.Index - lastIndex), updateLength: true);

                    if (index >= lim)
                    {
                        return(a);
                    }

                    lastIndex = match.Index + match.Length;
                    for (int i = 1; i < match.Groups.Count; i++)
                    {
                        var group = match.Groups[i];
                        var item  = Undefined;
                        if (group.Captures.Count > 0)
                        {
                            item = match.Groups[i].Value;
                        }

                        a.SetIndexValue(index++, item, updateLength: true);

                        if (index >= lim)
                        {
                            return(a);
                        }
                    }

                    match = match.NextMatch();
                    if (!match.Success) // Add the last part of the split
                    {
                        a.SetIndexValue(index++, s.Substring(lastIndex), updateLength: true);
                    }
                }

                return(a);
            }

            return(SplitSlow(s, splitter, unicodeMatching, lengthA, lim));
        }