mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
refactor(ecmascript): avoid redundant checks by splitting up match arms (#12782)
Makes code a lot easier to understand and avoids some redundant checks in runtime.
This commit is contained in:
1 parent
3f37ed1aff
commit
f3f601235d
1 file changed
+87
-79
@@ -233,51 +233,60 @@ fn binary_operation_evaluate_value_to<'a>(
|
||||
}
|
||||
None
|
||||
}
|
||||
BinaryOperator::Subtraction
|
||||
| BinaryOperator::Division
|
||||
| BinaryOperator::Remainder
|
||||
| BinaryOperator::Multiplication
|
||||
| BinaryOperator::Exponential => {
|
||||
BinaryOperator::Subtraction => {
|
||||
let lval = left.evaluate_value_to_number(ctx)?;
|
||||
let rval = right.evaluate_value_to_number(ctx)?;
|
||||
let val = match operator {
|
||||
BinaryOperator::Subtraction => lval - rval,
|
||||
BinaryOperator::Division => lval / rval,
|
||||
BinaryOperator::Remainder => {
|
||||
if rval.is_zero() {
|
||||
f64::NAN
|
||||
} else {
|
||||
lval % rval
|
||||
}
|
||||
}
|
||||
BinaryOperator::Multiplication => lval * rval,
|
||||
BinaryOperator::Exponential => {
|
||||
let result = lval.powf(rval);
|
||||
// For now, ignore the result if it large or has a decimal part
|
||||
// so that the output does not become bigger than the input.
|
||||
if result.is_finite() && (result.fract() != 0.0 || result.log10() > 4.0) {
|
||||
return None;
|
||||
}
|
||||
result
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Some(ConstantValue::Number(val))
|
||||
Some(ConstantValue::Number(lval - rval))
|
||||
}
|
||||
BinaryOperator::Division => {
|
||||
let lval = left.evaluate_value_to_number(ctx)?;
|
||||
let rval = right.evaluate_value_to_number(ctx)?;
|
||||
Some(ConstantValue::Number(lval / rval))
|
||||
}
|
||||
BinaryOperator::Remainder => {
|
||||
let lval = left.evaluate_value_to_number(ctx)?;
|
||||
let rval = right.evaluate_value_to_number(ctx)?;
|
||||
Some(ConstantValue::Number(if rval.is_zero() { f64::NAN } else { lval % rval }))
|
||||
}
|
||||
BinaryOperator::Multiplication => {
|
||||
let lval = left.evaluate_value_to_number(ctx)?;
|
||||
let rval = right.evaluate_value_to_number(ctx)?;
|
||||
Some(ConstantValue::Number(lval * rval))
|
||||
}
|
||||
BinaryOperator::Exponential => {
|
||||
let lval = left.evaluate_value_to_number(ctx)?;
|
||||
let rval = right.evaluate_value_to_number(ctx)?;
|
||||
let result = lval.powf(rval);
|
||||
// For now, ignore the result if it large or has a decimal part
|
||||
// so that the output does not become bigger than the input.
|
||||
if result.is_finite() && (result.fract() != 0.0 || result.log10() > 4.0) {
|
||||
return None;
|
||||
}
|
||||
Some(ConstantValue::Number(result))
|
||||
}
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
BinaryOperator::ShiftLeft
|
||||
| BinaryOperator::ShiftRight
|
||||
| BinaryOperator::ShiftRightZeroFill => {
|
||||
BinaryOperator::ShiftLeft => {
|
||||
let left = left.evaluate_value_to_number(ctx)?;
|
||||
let right = right.evaluate_value_to_number(ctx)?;
|
||||
let left = left.to_int_32();
|
||||
let right = (right.to_int_32() as u32) & 31;
|
||||
Some(ConstantValue::Number(match operator {
|
||||
BinaryOperator::ShiftLeft => f64::from(left << right),
|
||||
BinaryOperator::ShiftRight => f64::from(left >> right),
|
||||
BinaryOperator::ShiftRightZeroFill => f64::from((left as u32) >> right),
|
||||
_ => unreachable!(),
|
||||
}))
|
||||
Some(ConstantValue::Number(f64::from(left << right)))
|
||||
}
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
BinaryOperator::ShiftRight => {
|
||||
let left = left.evaluate_value_to_number(ctx)?;
|
||||
let right = right.evaluate_value_to_number(ctx)?;
|
||||
let left = left.to_int_32();
|
||||
let right = (right.to_int_32() as u32) & 31;
|
||||
Some(ConstantValue::Number(f64::from(left >> right)))
|
||||
}
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
BinaryOperator::ShiftRightZeroFill => {
|
||||
let left = left.evaluate_value_to_number(ctx)?;
|
||||
let right = right.evaluate_value_to_number(ctx)?;
|
||||
let left = left.to_int_32();
|
||||
let right = (right.to_int_32() as u32) & 31;
|
||||
Some(ConstantValue::Number(f64::from((left as u32) >> right)))
|
||||
}
|
||||
BinaryOperator::LessThan => is_less_than(ctx, left, right).map(|value| match value {
|
||||
ConstantValue::Undefined => ConstantValue::Boolean(false),
|
||||
@@ -303,33 +312,35 @@ fn binary_operation_evaluate_value_to<'a>(
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
BinaryOperator::BitwiseAnd | BinaryOperator::BitwiseOR | BinaryOperator::BitwiseXOR => {
|
||||
BinaryOperator::BitwiseAnd => {
|
||||
if left.value_type(ctx).is_bigint() && right.value_type(ctx).is_bigint() {
|
||||
let left_val = left.evaluate_value_to_bigint(ctx)?;
|
||||
let right_val = right.evaluate_value_to_bigint(ctx)?;
|
||||
let result_val: BigInt = match operator {
|
||||
BinaryOperator::BitwiseAnd => left_val & right_val,
|
||||
BinaryOperator::BitwiseOR => left_val | right_val,
|
||||
BinaryOperator::BitwiseXOR => left_val ^ right_val,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
return Some(ConstantValue::BigInt(result_val));
|
||||
let left_biginit = left.evaluate_value_to_bigint(ctx)?;
|
||||
let right_bigint = right.evaluate_value_to_bigint(ctx)?;
|
||||
return Some(ConstantValue::BigInt(left_biginit & right_bigint));
|
||||
}
|
||||
let left_num = left.evaluate_value_to_number(ctx);
|
||||
let right_num = right.evaluate_value_to_number(ctx);
|
||||
if let (Some(left_val), Some(right_val)) = (left_num, right_num) {
|
||||
let left_val_int = left_val.to_int_32();
|
||||
let right_val_int = right_val.to_int_32();
|
||||
|
||||
let result_val: f64 = match operator {
|
||||
BinaryOperator::BitwiseAnd => f64::from(left_val_int & right_val_int),
|
||||
BinaryOperator::BitwiseOR => f64::from(left_val_int | right_val_int),
|
||||
BinaryOperator::BitwiseXOR => f64::from(left_val_int ^ right_val_int),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
return Some(ConstantValue::Number(result_val));
|
||||
let left_int = left.evaluate_value_to_number(ctx)?.to_int_32();
|
||||
let right_int = right.evaluate_value_to_number(ctx)?.to_int_32();
|
||||
Some(ConstantValue::Number(f64::from(left_int & right_int)))
|
||||
}
|
||||
BinaryOperator::BitwiseOR => {
|
||||
if left.value_type(ctx).is_bigint() && right.value_type(ctx).is_bigint() {
|
||||
let left_biginit = left.evaluate_value_to_bigint(ctx)?;
|
||||
let right_bigint = right.evaluate_value_to_bigint(ctx)?;
|
||||
return Some(ConstantValue::BigInt(left_biginit | right_bigint));
|
||||
}
|
||||
None
|
||||
let left_int = left.evaluate_value_to_number(ctx)?.to_int_32();
|
||||
let right_int = right.evaluate_value_to_number(ctx)?.to_int_32();
|
||||
Some(ConstantValue::Number(f64::from(left_int | right_int)))
|
||||
}
|
||||
BinaryOperator::BitwiseXOR => {
|
||||
if left.value_type(ctx).is_bigint() && right.value_type(ctx).is_bigint() {
|
||||
let left_biginit = left.evaluate_value_to_bigint(ctx)?;
|
||||
let right_bigint = right.evaluate_value_to_bigint(ctx)?;
|
||||
return Some(ConstantValue::BigInt(left_biginit ^ right_bigint));
|
||||
}
|
||||
let left_int = left.evaluate_value_to_number(ctx)?.to_int_32();
|
||||
let right_int = right.evaluate_value_to_number(ctx)?.to_int_32();
|
||||
Some(ConstantValue::Number(f64::from(left_int ^ right_int)))
|
||||
}
|
||||
BinaryOperator::Instanceof => {
|
||||
if let Expression::Identifier(right_ident) = right {
|
||||
@@ -348,24 +359,21 @@ fn binary_operation_evaluate_value_to<'a>(
|
||||
}
|
||||
None
|
||||
}
|
||||
BinaryOperator::StrictEquality
|
||||
| BinaryOperator::StrictInequality
|
||||
| BinaryOperator::Equality
|
||||
| BinaryOperator::Inequality => {
|
||||
let value = match operator {
|
||||
BinaryOperator::StrictEquality | BinaryOperator::StrictInequality => {
|
||||
strict_equality_comparison(ctx, left, right)?
|
||||
}
|
||||
BinaryOperator::Equality | BinaryOperator::Inequality => {
|
||||
abstract_equality_comparison(ctx, left, right)?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
Some(ConstantValue::Boolean(match operator {
|
||||
BinaryOperator::StrictEquality | BinaryOperator::Equality => value,
|
||||
BinaryOperator::StrictInequality | BinaryOperator::Inequality => !value,
|
||||
_ => unreachable!(),
|
||||
}))
|
||||
BinaryOperator::StrictEquality => {
|
||||
let value = strict_equality_comparison(ctx, left, right)?;
|
||||
Some(ConstantValue::Boolean(value))
|
||||
}
|
||||
BinaryOperator::StrictInequality => {
|
||||
let value = strict_equality_comparison(ctx, left, right)?;
|
||||
Some(ConstantValue::Boolean(!value))
|
||||
}
|
||||
BinaryOperator::Equality => {
|
||||
let value = abstract_equality_comparison(ctx, left, right)?;
|
||||
Some(ConstantValue::Boolean(value))
|
||||
}
|
||||
BinaryOperator::Inequality => {
|
||||
let value = abstract_equality_comparison(ctx, left, right)?;
|
||||
Some(ConstantValue::Boolean(!value))
|
||||
}
|
||||
BinaryOperator::In => None,
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user