From 442975408b88376868d832d9a06e6f090b90ea00 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Fri, 25 Oct 2024 04:23:24 +0000 Subject: [PATCH] feat(ecmascript): constant eval `null` to number (#6879) --- .../src/constant_evaluation/mod.rs | 7 ++++--- .../src/constant_evaluation/value.rs | 19 ++++++++++++++++++- .../src/ast_passes/peephole_fold_constants.rs | 9 +++++---- crates/oxc_minifier/src/node_util/mod.rs | 1 + 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/crates/oxc_ecmascript/src/constant_evaluation/mod.rs b/crates/oxc_ecmascript/src/constant_evaluation/mod.rs index 79c47522e3125..7b345a0200793 100644 --- a/crates/oxc_ecmascript/src/constant_evaluation/mod.rs +++ b/crates/oxc_ecmascript/src/constant_evaluation/mod.rs @@ -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 diff --git a/crates/oxc_ecmascript/src/constant_evaluation/value.rs b/crates/oxc_ecmascript/src/constant_evaluation/value.rs index 4f4f60a4e7b0e..f8d32c5ab0cb1 100644 --- a/crates/oxc_ecmascript/src/constant_evaluation/value.rs +++ b/crates/oxc_ecmascript/src/constant_evaluation/value.rs @@ -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 { + 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), } } } diff --git a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs index b6ea13a32fd55..32bda00442e36 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs @@ -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] diff --git a/crates/oxc_minifier/src/node_util/mod.rs b/crates/oxc_minifier/src/node_util/mod.rs index f48c1a1f0dc74..810e6f5ce5f4e 100644 --- a/crates/oxc_minifier/src/node_util/mod.rs +++ b/crates/oxc_minifier/src/node_util/mod.rs @@ -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), } }