Browse Source

Fix exponent operator (#2681)

When `abs(base) == 1` and `y == +/- Infinity` result should be `NaN`

Fixes the remaining failing tests in the `exponentiation` test suite
pull/2682/head
Haled Odat 1 year ago
parent
commit
2588aa9f9a
  1. 27
      boa_engine/src/value/operations.rs

27
boa_engine/src/value/operations.rs

@ -195,6 +195,8 @@ impl JsValue {
}
/// Perform the binary `**` operator on the value and return the result.
// NOTE: There are some cases in the spec where we have to compare floats
#[allow(clippy::float_cmp)]
pub fn pow(&self, other: &Self, context: &mut Context<'_>) -> JsResult<Self> {
Ok(match (self, other) {
// Fast path:
@ -202,15 +204,32 @@ impl JsValue {
.ok()
.and_then(|y| x.checked_pow(y))
.map_or_else(|| Self::new(f64::from(*x).powi(*y)), Self::new),
(Self::Rational(x), Self::Rational(y)) => Self::new(x.powf(*y)),
(Self::Integer(x), Self::Rational(y)) => Self::new(f64::from(*x).powf(*y)),
(Self::Rational(x), Self::Rational(y)) => {
if x.abs() == 1.0 && y.is_infinite() {
Self::nan()
} else {
Self::new(x.powf(*y))
}
}
(Self::Integer(x), Self::Rational(y)) => {
if x.wrapping_abs() == 1 && y.is_infinite() {
Self::nan()
} else {
Self::new(f64::from(*x).powf(*y))
}
}
(Self::Rational(x), Self::Integer(y)) => Self::new(x.powi(*y)),
(Self::BigInt(ref a), Self::BigInt(ref b)) => Self::new(JsBigInt::pow(a, b)?),
// Slow path:
(_, _) => match (self.to_numeric(context)?, other.to_numeric(context)?) {
(Numeric::Number(a), Numeric::Number(b)) => Self::new(a.powf(b)),
(Numeric::Number(a), Numeric::Number(b)) => {
if a.abs() == 1.0 && b.is_infinite() {
Self::nan()
} else {
Self::new(a.powf(b))
}
}
(Numeric::BigInt(ref a), Numeric::BigInt(ref b)) => Self::new(JsBigInt::pow(a, b)?),
(_, _) => {
return Err(JsNativeError::typ()

Loading…
Cancel
Save