From 05f4fee09303c65d6558ac83b97be1c2eec04fa2 Mon Sep 17 00:00:00 2001 From: Choongwoo Han Date: Mon, 20 Feb 2023 21:59:33 -0800 Subject: [PATCH] Return Integer for inc/dec of an integer --- boa_engine/src/tests.rs | 40 +++++++++++++++++++ .../src/vm/opcode/unary_ops/decrement.rs | 33 ++++++++++----- .../src/vm/opcode/unary_ops/increment.rs | 33 ++++++++++----- 3 files changed, 86 insertions(+), 20 deletions(-) diff --git a/boa_engine/src/tests.rs b/boa_engine/src/tests.rs index 189122a0f51..57498fae5ba 100644 --- a/boa_engine/src/tests.rs +++ b/boa_engine/src/tests.rs @@ -541,6 +541,20 @@ fn unary_pre() { --a === 4; "#; assert_eq!(&exec(execs_before_dec), "true"); + + let i32_limit_inc = r#" + let a = 2147483647; + ++a; + a; + "#; + assert_eq!(&exec(i32_limit_inc), "2147483648"); + + let i32_limit_dec = r#" + let a = -2147483648; + --a; + a; + "#; + assert_eq!(&exec(i32_limit_dec), "-2147483649"); } #[test] @@ -683,6 +697,32 @@ fn unary_post() { a-- === 5; "#; assert_eq!(&exec(execs_after_dec), "true"); + + let i32_limit_inc = r#" + let a = 2147483647; + a++; + a; + "#; + assert_eq!(&exec(i32_limit_inc), "2147483648"); + + let i32_limit_dec = r#" + let a = -2147483648; + a--; + a; + "#; + assert_eq!(&exec(i32_limit_dec), "-2147483649"); + + let to_numeric_inc = r#" + let a = {[Symbol.toPrimitive]() { return 123; }}; + a++ + "#; + assert_eq!(&exec(to_numeric_inc), "123"); + + let to_numeric_dec = r#" + let a = {[Symbol.toPrimitive]() { return 123; }}; + a-- + "#; + assert_eq!(&exec(to_numeric_dec), "123"); } #[test] diff --git a/boa_engine/src/vm/opcode/unary_ops/decrement.rs b/boa_engine/src/vm/opcode/unary_ops/decrement.rs index 9cdea744e18..d348b14b994 100644 --- a/boa_engine/src/vm/opcode/unary_ops/decrement.rs +++ b/boa_engine/src/vm/opcode/unary_ops/decrement.rs @@ -1,5 +1,5 @@ use crate::{ - value::Numeric, + value::{JsValue, Numeric}, vm::{opcode::Operation, ShouldExit}, Context, JsBigInt, JsResult, }; @@ -17,11 +17,16 @@ impl Operation for Dec { fn execute(context: &mut Context<'_>) -> JsResult { let value = context.vm.pop(); - match value.to_numeric(context)? { - Numeric::Number(number) => context.vm.push(number - 1f64), - Numeric::BigInt(bigint) => { - context.vm.push(JsBigInt::sub(&bigint, &JsBigInt::one())); + match value { + JsValue::Integer(number) if number > i32::MIN => { + context.vm.push(number - 1); } + _ => match value.to_numeric(context)? { + Numeric::Number(number) => context.vm.push(number - 1f64), + Numeric::BigInt(bigint) => { + context.vm.push(JsBigInt::sub(&bigint, &JsBigInt::one())); + } + }, } Ok(ShouldExit::False) } @@ -40,14 +45,22 @@ impl Operation for DecPost { fn execute(context: &mut Context<'_>) -> JsResult { let value = context.vm.pop(); - let value = value.to_numeric(context)?; match value { - Numeric::Number(number) => context.vm.push(number - 1f64), - Numeric::BigInt(ref bigint) => { - context.vm.push(JsBigInt::sub(bigint, &JsBigInt::one())); + JsValue::Integer(number) if number > i32::MIN => { + context.vm.push(number - 1); + context.vm.push(value); + } + _ => { + let value = value.to_numeric(context)?; + match value { + Numeric::Number(number) => context.vm.push(number - 1f64), + Numeric::BigInt(ref bigint) => { + context.vm.push(JsBigInt::sub(bigint, &JsBigInt::one())); + } + } + context.vm.push(value); } } - context.vm.push(value); Ok(ShouldExit::False) } } diff --git a/boa_engine/src/vm/opcode/unary_ops/increment.rs b/boa_engine/src/vm/opcode/unary_ops/increment.rs index 669b6e9344f..6d51c9332e7 100644 --- a/boa_engine/src/vm/opcode/unary_ops/increment.rs +++ b/boa_engine/src/vm/opcode/unary_ops/increment.rs @@ -1,5 +1,5 @@ use crate::{ - value::Numeric, + value::{JsValue, Numeric}, vm::{opcode::Operation, ShouldExit}, Context, JsBigInt, JsResult, }; @@ -17,11 +17,16 @@ impl Operation for Inc { fn execute(context: &mut Context<'_>) -> JsResult { let value = context.vm.pop(); - match value.to_numeric(context)? { - Numeric::Number(number) => context.vm.push(number + 1f64), - Numeric::BigInt(bigint) => { - context.vm.push(JsBigInt::add(&bigint, &JsBigInt::one())); + match value { + JsValue::Integer(number) if number < i32::MAX => { + context.vm.push(number + 1); } + _ => match value.to_numeric(context)? { + Numeric::Number(number) => context.vm.push(number + 1f64), + Numeric::BigInt(bigint) => { + context.vm.push(JsBigInt::add(&bigint, &JsBigInt::one())); + } + }, } Ok(ShouldExit::False) } @@ -40,14 +45,22 @@ impl Operation for IncPost { fn execute(context: &mut Context<'_>) -> JsResult { let value = context.vm.pop(); - let value = value.to_numeric(context)?; match value { - Numeric::Number(number) => context.vm.push(number + 1f64), - Numeric::BigInt(ref bigint) => { - context.vm.push(JsBigInt::add(bigint, &JsBigInt::one())); + JsValue::Integer(number) if number < i32::MAX => { + context.vm.push(number + 1); + context.vm.push(value); + } + _ => { + let value = value.to_numeric(context)?; + match value { + Numeric::Number(number) => context.vm.push(number + 1f64), + Numeric::BigInt(ref bigint) => { + context.vm.push(JsBigInt::add(bigint, &JsBigInt::one())); + } + } + context.vm.push(value); } } - context.vm.push(value); Ok(ShouldExit::False) } }