2
0
Эх сурвалжийг харах

Improve infinity detection when parsing numbers on full framework (#2003)

Marko Lahma 8 сар өмнө
parent
commit
a506929f99

+ 24 - 2
Jint.Tests/Runtime/NumberTests.cs

@@ -137,11 +137,33 @@ public class NumberTests
     }
     }
 
 
     [Theory]
     [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")]
     [InlineData("123456")]
     public void ToLocaleStringNoArg(string parseNumber)
     public void ToLocaleStringNoArg(string parseNumber)
     {
     {
         var value = _engine.Evaluate($"({parseNumber}).toLocaleString()").AsString();
         var value = _engine.Evaluate($"({parseNumber}).toLocaleString()").AsString();
         Assert.DoesNotContain(".0", value);
         Assert.DoesNotContain(".0", value);
     }
     }
-}
+
+    [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());
+    }
+}

+ 26 - 1
Jint/Runtime/TypeConverter.cs

@@ -274,12 +274,37 @@ public static class TypeConverter
             }
             }
         }
         }
 
 
+#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))
         if (double.TryParse(input, NumberStyles, CultureInfo.InvariantCulture, out var n))
         {
         {
             return n == 0 && firstChar == '-' ? -0.0 : n;
             return n == 0 && firstChar == '-' ? -0.0 : n;
         }
         }
 
 
         return double.NaN;
         return double.NaN;
+#endif
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -1014,4 +1039,4 @@ public static class TypeConverter
             ExceptionHelper.ThrowTypeError(engine.Realm, "Cannot call method on " + o);
             ExceptionHelper.ThrowTypeError(engine.Realm, "Cannot call method on " + o);
         }
         }
     }
     }
-}
+}