From 90a517f0302373d7d10c840597b414b5d0e6f017 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Tue, 16 Sep 2025 20:25:17 +0300 Subject: [PATCH] Fix BigInt modulo assignment --- Jint.Tests/Runtime/BigIntTests.cs | 2 + .../Expressions/JintAssignmentExpression.cs | 10 +-- .../Expressions/JintBinaryExpression.cs | 76 +----------------- .../Interpreter/Expressions/JintExpression.cs | 77 +++++++++++++++++++ 4 files changed, 81 insertions(+), 84 deletions(-) diff --git a/Jint.Tests/Runtime/BigIntTests.cs b/Jint.Tests/Runtime/BigIntTests.cs index 8953b048ba..83631fa644 100644 --- a/Jint.Tests/Runtime/BigIntTests.cs +++ b/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(); diff --git a/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs index db9517ac14..51b5bf4d31 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs @@ -170,15 +170,7 @@ protected override object EvaluateInternal(EvaluationContext context) 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; } diff --git a/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs index 1d49437fc0..319ef640cf 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs @@ -6,7 +6,6 @@ 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 @@ protected override object EvaluateInternal(EvaluationContext context) 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); } } diff --git a/Jint/Runtime/Interpreter/Expressions/JintExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintExpression.cs index 0bb4e8bf58..e5993fccd8 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintExpression.cs @@ -142,6 +142,83 @@ protected internal static JintExpression Build(Expression expression) 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) {