diff --git a/Jint.Tests/Runtime/BigIntTests.cs b/Jint.Tests/Runtime/BigIntTests.cs new file mode 100644 index 0000000000..8953b048ba --- /dev/null +++ b/Jint.Tests/Runtime/BigIntTests.cs @@ -0,0 +1,29 @@ +using Jint.Native; + +namespace Jint.Tests.Runtime; + +public class BigIntTests +{ + [Theory] + [InlineData("a = a + b;", "146")] + [InlineData("a = a - b;", "100")] + [InlineData("a = a * b;", "2829")] + [InlineData("a = a / b;", "5")] + [InlineData("a += b;", "146")] + [InlineData("a -= b;", "100")] + [InlineData("a *= b;", "2829")] + [InlineData("a /= b;", "5")] + public void BasicOperations(string statement, string expected) + { + var outputValues = new List(); + var engine = new Engine() + .SetValue("log", outputValues.Add); + engine.Evaluate("let a = 123n; let b = 23n;"); + + engine.Evaluate(statement); + + engine.Evaluate("log(a)"); + Assert.True(outputValues[0].IsBigInt(), "The type of the value is expected to stay BigInt"); + Assert.Equal(expected, outputValues[0].ToString()); + } +} diff --git a/Jint/Native/JsBigInt.cs b/Jint/Native/JsBigInt.cs index 042784db10..6b6f887521 100644 --- a/Jint/Native/JsBigInt.cs +++ b/Jint/Native/JsBigInt.cs @@ -19,6 +19,7 @@ static JsBigInt() { bigIntegers[i] = new JsBigInt(i); } + _bigIntegerToJsValue = bigIntegers; } @@ -40,12 +41,9 @@ internal static JsBigInt Create(BigInteger bigInt) internal static JsBigInt Create(JsValue value) { - return value is JsBigInt jsBigInt - ? jsBigInt - : Create(TypeConverter.ToBigInt(value)); + return value as JsBigInt ?? Create(TypeConverter.ToBigInt(value)); } - public override object ToObject() => _value; internal override bool ToBoolean() => _value != 0; diff --git a/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs index e04f5cee1a..acf0ef59f0 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs @@ -100,13 +100,14 @@ protected override object EvaluateInternal(EvaluationContext context) newLeftValue = jsString.Append(rprim); } - else if (!AreIntegerOperands(originalLeftValue, rval)) + else if (JintBinaryExpression.AreNonBigIntOperands(originalLeftValue, rval)) { newLeftValue = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim); } else { - newLeftValue = TypeConverter.ToBigInt(lprim) + TypeConverter.ToBigInt(rprim); + JintBinaryExpression.AssertValidBigIntArithmeticOperands(lprim, rprim); + newLeftValue = JsBigInt.Create(TypeConverter.ToBigInt(lprim) + TypeConverter.ToBigInt(rprim)); } } @@ -120,13 +121,14 @@ protected override object EvaluateInternal(EvaluationContext context) { newLeftValue = JsNumber.Create(originalLeftValue.AsInteger() - rval.AsInteger()); } - else if (!AreIntegerOperands(originalLeftValue, rval)) + else if (JintBinaryExpression.AreNonBigIntOperands(originalLeftValue, rval)) { newLeftValue = JsNumber.Create(TypeConverter.ToNumber(originalLeftValue) - TypeConverter.ToNumber(rval)); } else { - newLeftValue = JsNumber.Create(TypeConverter.ToBigInt(originalLeftValue) - TypeConverter.ToBigInt(rval)); + JintBinaryExpression.AssertValidBigIntArithmeticOperands(originalLeftValue, rval); + newLeftValue = JsBigInt.Create(TypeConverter.ToBigInt(originalLeftValue) - TypeConverter.ToBigInt(rval)); } break; @@ -143,13 +145,14 @@ protected override object EvaluateInternal(EvaluationContext context) { newLeftValue = JsValue.Undefined; } - else if (!AreIntegerOperands(originalLeftValue, rval)) + else if (JintBinaryExpression.AreNonBigIntOperands(originalLeftValue, rval)) { newLeftValue = TypeConverter.ToNumber(originalLeftValue) * TypeConverter.ToNumber(rval); } else { - newLeftValue = TypeConverter.ToBigInt(originalLeftValue) * TypeConverter.ToBigInt(rval); + JintBinaryExpression.AssertValidBigIntArithmeticOperands(originalLeftValue, rval); + newLeftValue = JsBigInt.Create(TypeConverter.ToBigInt(originalLeftValue) * TypeConverter.ToBigInt(rval)); } break; diff --git a/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs index 3ca065895d..1570ca8866 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs @@ -355,6 +355,7 @@ protected override object EvaluateInternal(EvaluationContext context) } else { + JintBinaryExpression.AssertValidBigIntArithmeticOperands(left, right); number = JsBigInt.Create(TypeConverter.ToBigInt(left) - TypeConverter.ToBigInt(right)); }