Sfoglia il codice sorgente

Fix BigInt modulo assignment (#2178)

Marko Lahma 3 giorni fa
parent
commit
08ca9cade4

+ 2 - 0
Jint.Tests/Runtime/BigIntTests.cs

@@ -9,10 +9,12 @@ public class BigIntTests
     [InlineData("a = a - b;", "100")]
     [InlineData("a = a * b;", "2829")]
     [InlineData("a = a / b;", "5")]
+    [InlineData("a = a % b;", "8")]
     [InlineData("a += b;", "146")]
     [InlineData("a -= b;", "100")]
     [InlineData("a *= b;", "2829")]
     [InlineData("a /= b;", "5")]
+    [InlineData("a %= b;", "8")]
     public void BasicOperations(string statement, string expected)
     {
         var outputValues = new List<JsValue>();

+ 1 - 9
Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs

@@ -170,15 +170,7 @@ internal sealed class JintAssignmentExpression : JintExpression
                 case Operator.RemainderAssignment:
                     {
                         var rval = _right.GetValue(context);
-                        if (originalLeftValue.IsUndefined() || rval.IsUndefined())
-                        {
-                            newLeftValue = JsValue.Undefined;
-                        }
-                        else
-                        {
-                            newLeftValue = TypeConverter.ToNumber(originalLeftValue) % TypeConverter.ToNumber(rval);
-                        }
-
+                        newLeftValue = Remainder(context, originalLeftValue, rval);
                         break;
                     }
 

+ 1 - 75
Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs

@@ -6,7 +6,6 @@ using System.Reflection;
 using System.Runtime.CompilerServices;
 using Jint.Extensions;
 using Jint.Native;
-using Jint.Native.Number;
 using Jint.Native.Object;
 using Jint.Runtime.Interop;
 
@@ -686,80 +685,7 @@ internal abstract class JintBinaryExpression : JintExpression
                 return JsValue.FromObject(context.Engine, opResult);
             }
 
-            var result = JsValue.Undefined;
-            left = TypeConverter.ToNumeric(left);
-            right = TypeConverter.ToNumeric(right);
-
-            if (AreIntegerOperands(left, right))
-            {
-                var leftInteger = left.AsInteger();
-                var rightInteger = right.AsInteger();
-
-                if (rightInteger == 0)
-                {
-                    result = JsNumber.DoubleNaN;
-                }
-                else
-                {
-                    var modulo = leftInteger % rightInteger;
-                    if (modulo == 0 && leftInteger < 0)
-                    {
-                        result = JsNumber.NegativeZero;
-                    }
-                    else
-                    {
-                        result = JsNumber.Create(modulo);
-                    }
-                }
-            }
-            else if (AreNonBigIntOperands(left, right))
-            {
-                var n = left.AsNumber();
-                var d = right.AsNumber();
-
-                if (double.IsNaN(n) || double.IsNaN(d) || double.IsInfinity(n))
-                {
-                    result = JsNumber.DoubleNaN;
-                }
-                else if (double.IsInfinity(d))
-                {
-                    result = n;
-                }
-                else if (NumberInstance.IsPositiveZero(d) || NumberInstance.IsNegativeZero(d))
-                {
-                    result = JsNumber.DoubleNaN;
-                }
-                else if (NumberInstance.IsPositiveZero(n) || NumberInstance.IsNegativeZero(n))
-                {
-                    result = n;
-                }
-                else
-                {
-                    result = JsNumber.Create(n % d);
-                }
-            }
-            else
-            {
-                AssertValidBigIntArithmeticOperands(left, right);
-
-                var n = TypeConverter.ToBigInt(left);
-                var d = TypeConverter.ToBigInt(right);
-
-                if (d == 0)
-                {
-                    Throw.RangeError(context.Engine.Realm, "Division by zero");
-                }
-                else if (n == 0)
-                {
-                    result = JsBigInt.Zero;
-                }
-                else
-                {
-                    result = JsBigInt.Create(n % d);
-                }
-            }
-
-            return result;
+            return Remainder(context, left, right);
         }
     }
 

+ 77 - 0
Jint/Runtime/Interpreter/Expressions/JintExpression.cs

@@ -142,6 +142,83 @@ internal abstract class JintExpression
         return result;
     }
 
+    protected static JsValue Remainder(EvaluationContext context, JsValue left, JsValue right)
+    {
+        var result = JsValue.Undefined;
+        left = TypeConverter.ToNumeric(left);
+        right = TypeConverter.ToNumeric(right);
+        if (AreIntegerOperands(left, right))
+        {
+            var leftInteger = left.AsInteger();
+            var rightInteger = right.AsInteger();
+
+            if (rightInteger == 0)
+            {
+                result = JsNumber.DoubleNaN;
+            }
+            else
+            {
+                var modulo = leftInteger % rightInteger;
+                if (modulo == 0 && leftInteger < 0)
+                {
+                    result = JsNumber.NegativeZero;
+                }
+                else
+                {
+                    result = JsNumber.Create(modulo);
+                }
+            }
+        }
+        else if (JintBinaryExpression.AreNonBigIntOperands(left, right))
+        {
+            var n = left.AsNumber();
+            var d = right.AsNumber();
+
+            if (double.IsNaN(n) || double.IsNaN(d) || double.IsInfinity(n))
+            {
+                result = JsNumber.DoubleNaN;
+            }
+            else if (double.IsInfinity(d))
+            {
+                result = n;
+            }
+            else if (NumberInstance.IsPositiveZero(d) || NumberInstance.IsNegativeZero(d))
+            {
+                result = JsNumber.DoubleNaN;
+            }
+            else if (NumberInstance.IsPositiveZero(n) || NumberInstance.IsNegativeZero(n))
+            {
+                result = n;
+            }
+            else
+            {
+                result = JsNumber.Create(n % d);
+            }
+        }
+        else
+        {
+            JintBinaryExpression.AssertValidBigIntArithmeticOperands(left, right);
+
+            var n = TypeConverter.ToBigInt(left);
+            var d = TypeConverter.ToBigInt(right);
+
+            if (d == 0)
+            {
+                Throw.RangeError(context.Engine.Realm, "Division by zero");
+            }
+            else if (n == 0)
+            {
+                result = JsBigInt.Zero;
+            }
+            else
+            {
+                result = JsBigInt.Create(n % d);
+            }
+        }
+
+        return result;
+    }
+
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     protected static JsValue Divide(EvaluationContext context, JsValue left, JsValue right)
     {