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