diff --git a/Jint.Tests/Runtime/NumberTests.cs b/Jint.Tests/Runtime/NumberTests.cs index 63e82052b..b43ae7fb5 100644 --- a/Jint.Tests/Runtime/NumberTests.cs +++ b/Jint.Tests/Runtime/NumberTests.cs @@ -137,11 +137,33 @@ public void ToLocaleString(string parseNumber, string culture, string result) } [Theory] - // Does not add extra zeros of there is no cuture argument. + // Does not add extra zeros of there is no culture argument. [InlineData("123456")] public void ToLocaleStringNoArg(string parseNumber) { var value = _engine.Evaluate($"({parseNumber}).toLocaleString()").AsString(); Assert.DoesNotContain(".0", value); } -} \ No newline at end of file + + [Fact] + public void CoercingOverflowFromString() + { + var engine = new Engine(); + + Assert.Equal(double.PositiveInfinity, engine.Evaluate("Number(1e1000)").ToObject()); + Assert.Equal(double.PositiveInfinity, engine.Evaluate("+1e1000").ToObject()); + Assert.Equal("Infinity", engine.Evaluate("(+1e1000).toString()").ToObject()); + + Assert.Equal(double.PositiveInfinity, engine.Evaluate("Number('1e1000')").ToObject()); + Assert.Equal(double.PositiveInfinity, engine.Evaluate("+'1e1000'").ToObject()); + Assert.Equal("Infinity", engine.Evaluate("(+'1e1000').toString()").ToObject()); + + Assert.Equal(double.NegativeInfinity, engine.Evaluate("Number(-1e1000)").ToObject()); + Assert.Equal(double.NegativeInfinity, engine.Evaluate("-1e1000").ToObject()); + Assert.Equal("-Infinity", engine.Evaluate("(-1e1000).toString()").ToObject()); + + Assert.Equal(double.NegativeInfinity, engine.Evaluate("Number('-1e1000')").ToObject()); + Assert.Equal(double.NegativeInfinity, engine.Evaluate("-'1e1000'").ToObject()); + Assert.Equal("-Infinity", engine.Evaluate("(-'1e1000').toString()").ToObject()); + } +} diff --git a/Jint/Runtime/TypeConverter.cs b/Jint/Runtime/TypeConverter.cs index f11ec3d98..bbca3b175 100644 --- a/Jint/Runtime/TypeConverter.cs +++ b/Jint/Runtime/TypeConverter.cs @@ -274,12 +274,37 @@ private static double ToNumber(string input) } } +#if NETFRAMEWORK + // if we are on full framework, one extra check for whether it was actually over the bounds of double + // in modern NET parsing was fixed to be IEEE 754 compliant, full framework is not and cannot detect positive infinity + try + { + var targetString = firstChar == '-' ? input.Substring(1) : input; + var n = double.Parse(targetString, NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture); + + if (n == 0 && firstChar == '-') + { + return -0.0; + } + + return firstChar == '-' ? - 1 * n : n; + } + catch (Exception e) when (e is OverflowException) + { + return firstChar == '-' ? double.NegativeInfinity : double.PositiveInfinity; + } + catch + { + return double.NaN; + } +#else if (double.TryParse(input, NumberStyles, CultureInfo.InvariantCulture, out var n)) { return n == 0 && firstChar == '-' ? -0.0 : n; } return double.NaN; +#endif } /// @@ -1014,4 +1039,4 @@ public static void CheckObjectCoercible(Engine engine, JsValue o) ExceptionHelper.ThrowTypeError(engine.Realm, "Cannot call method on " + o); } } -} \ No newline at end of file +}