Skip to content

Commit

Permalink
feat(ecmascript): constant eval null to number (#6879)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Oct 25, 2024
1 parent 0d0bb17 commit 4429754
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 8 deletions.
7 changes: 4 additions & 3 deletions crates/oxc_ecmascript/src/constant_evaluation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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())))
}
Expand Down Expand Up @@ -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
Expand Down
19 changes: 18 additions & 1 deletion crates/oxc_ecmascript/src/constant_evaluation/value.rs
Original file line number Diff line number Diff line change
@@ -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> {
Expand All @@ -11,6 +12,7 @@ pub enum ConstantValue<'a> {
String(Cow<'a, str>),
Boolean(bool),
Undefined,
Null,
}

impl<'a> ConstantValue<'a> {
Expand Down Expand Up @@ -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),
}
}
}
9 changes: 5 additions & 4 deletions crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1174,26 +1174,27 @@ 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");
test("x = (null - 1) * 2", "x = -2");
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]
Expand Down
1 change: 1 addition & 0 deletions crates/oxc_minifier/src/node_util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}

Expand Down

0 comments on commit 4429754

Please sign in to comment.