feat(ecmascript): constant eval null to number (#6879)

This commit is contained in:
Boshen 2024-10-25 04:23:24 +00:00
parent 0d0bb17ad9
commit 442975408b
4 changed files with 28 additions and 8 deletions

View file

@ -9,7 +9,7 @@ use num_traits::{One, Zero};
use oxc_ast::ast::*;
use crate::{side_effects::MayHaveSideEffects, ToBigInt, ToInt32, ToJsString};
use crate::{side_effects::MayHaveSideEffects, ToBigInt, ToInt32, ToJsString, ToNumber};
pub use self::{is_litral_value::IsLiteralValue, value::ConstantValue, value_type::ValueType};
@ -179,6 +179,7 @@ pub trait ConstantEvaluation<'a> {
Expression::UnaryExpression(e) => self.eval_unary_expression(e),
Expression::Identifier(ident) => self.resolve_binding(ident),
Expression::NumericLiteral(lit) => Some(ConstantValue::Number(lit.value)),
Expression::NullLiteral(_) => Some(ConstantValue::Null),
Expression::StringLiteral(lit) => {
Some(ConstantValue::String(Cow::Borrowed(lit.value.as_str())))
}
@ -206,8 +207,8 @@ pub trait ConstantEvaluation<'a> {
if left_type.is_number() || right_type.is_number() {
let lval = self.eval_expression(left)?;
let rval = self.eval_expression(right)?;
let lnum = lval.into_number()?;
let rnum = rval.into_number()?;
let lnum = lval.to_number()?;
let rnum = rval.to_number()?;
return Some(ConstantValue::Number(lnum + rnum));
}
None

View file

@ -1,8 +1,9 @@
use core::f64;
use std::borrow::Cow;
use num_bigint::BigInt;
use crate::ToJsString;
use crate::{ToJsString, ToNumber};
#[derive(Debug, PartialEq)]
pub enum ConstantValue<'a> {
@ -11,6 +12,7 @@ pub enum ConstantValue<'a> {
String(Cow<'a, str>),
Boolean(bool),
Undefined,
Null,
}
impl<'a> ConstantValue<'a> {
@ -68,6 +70,21 @@ impl<'a> ToJsString<'a> for ConstantValue<'a> {
Self::String(s) => Some(s.clone()),
Self::Boolean(b) => Some(Cow::Borrowed(if *b { "true" } else { "false" })),
Self::Undefined => Some(Cow::Borrowed("undefined")),
Self::Null => Some(Cow::Borrowed("null")),
}
}
}
impl<'a> ToNumber<'a> for ConstantValue<'a> {
fn to_number(&self) -> Option<f64> {
use crate::StringToNumber;
match self {
Self::Number(n) => Some(*n),
Self::BigInt(_) => None,
Self::String(s) => Some(s.as_ref().string_to_number()),
Self::Boolean(true) => Some(1.0),
Self::Boolean(false) | Self::Null => Some(0.0),
Self::Undefined => Some(f64::NAN),
}
}
}

View file

@ -1174,19 +1174,17 @@ mod test {
}
#[test]
#[ignore]
fn test_fold_arithmetic2() {
test_same("x = y + 10 + 20");
test_same("x = y / 2 / 4");
test("x = y * 2.25 * 3", "x = y * 6.75");
// test("x = y * 2.25 * 3", "x = y * 6.75");
test_same("x = y * 2.25 * z * 3");
test_same("z = x * y");
test_same("x = y * 5");
test("x = y + (z * 24 * 60 * 60 * 1000)", "x = y + z * 864E5");
// test("x = y + (z * 24 * 60 * 60 * 1000)", "x = y + z * 864E5");
}
#[test]
#[ignore]
fn test_fold_arithmetic3() {
test("x = null * undefined", "x = NaN");
test("x = null * 1", "x = 0");
@ -1194,6 +1192,9 @@ mod test {
test("x = (null + 1) * 2", "x = 2");
test("x = null ** 0", "x = 1");
test("x = (-0) ** 3", "x = -0");
test("x = 1 + null", "x = 1");
test("x = null + 1", "x = 1");
}
#[test]

View file

@ -43,6 +43,7 @@ impl<'a, 'b> Ctx<'a, 'b> {
ConstantValue::String(s) => self.ast.expression_string_literal(span, s),
ConstantValue::Boolean(b) => self.ast.expression_boolean_literal(span, b),
ConstantValue::Undefined => self.ast.void_0(span),
ConstantValue::Null => self.ast.expression_null_literal(span),
}
}