mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(minifier): remove Tri, use Option<bool> instead (#6912)
This commit is contained in:
parent
d3c5c78cba
commit
2c7ac29ece
3 changed files with 30 additions and 74 deletions
|
|
@ -10,7 +10,7 @@ use oxc_syntax::{
|
|||
};
|
||||
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
|
||||
|
||||
use crate::{node_util::Ctx, tri::Tri, CompressorPass};
|
||||
use crate::{node_util::Ctx, CompressorPass};
|
||||
|
||||
/// Constant Folding
|
||||
///
|
||||
|
|
@ -270,20 +270,20 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
}
|
||||
BinaryOperator::Equality => Self::try_abstract_equality_comparison(left, right, ctx),
|
||||
BinaryOperator::Inequality => {
|
||||
Self::try_abstract_equality_comparison(left, right, ctx).not()
|
||||
Self::try_abstract_equality_comparison(left, right, ctx).map(|b| !b)
|
||||
}
|
||||
BinaryOperator::StrictEquality => {
|
||||
Self::try_strict_equality_comparison(left, right, ctx)
|
||||
}
|
||||
BinaryOperator::StrictInequality => {
|
||||
Self::try_strict_equality_comparison(left, right, ctx).not()
|
||||
Self::try_strict_equality_comparison(left, right, ctx).map(|b| !b)
|
||||
}
|
||||
_ => Tri::Unknown,
|
||||
_ => None,
|
||||
};
|
||||
let value = match value {
|
||||
Tri::True => true,
|
||||
Tri::False => false,
|
||||
Tri::Unknown => return None,
|
||||
Some(true) => true,
|
||||
Some(false) => false,
|
||||
None => return None,
|
||||
};
|
||||
Some(ctx.ast.expression_boolean_literal(e.span, value))
|
||||
}
|
||||
|
|
@ -293,7 +293,7 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
left_expr: &'b Expression<'a>,
|
||||
right_expr: &'b Expression<'a>,
|
||||
ctx: Ctx<'a, 'b>,
|
||||
) -> Tri {
|
||||
) -> Option<bool> {
|
||||
let left = ValueType::from(left_expr);
|
||||
let right = ValueType::from(right_expr);
|
||||
if left != ValueType::Undetermined && right != ValueType::Undetermined {
|
||||
|
|
@ -304,7 +304,7 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
(left, right),
|
||||
(ValueType::Null, ValueType::Undefined) | (ValueType::Undefined, ValueType::Null)
|
||||
) {
|
||||
return Tri::True;
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
if matches!((left, right), (ValueType::Number, ValueType::String))
|
||||
|
|
@ -327,7 +327,7 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
);
|
||||
}
|
||||
|
||||
return Tri::Unknown;
|
||||
return None;
|
||||
}
|
||||
|
||||
if matches!((left, right), (ValueType::String, ValueType::Number))
|
||||
|
|
@ -350,7 +350,7 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
);
|
||||
}
|
||||
|
||||
return Tri::Unknown;
|
||||
return None;
|
||||
}
|
||||
|
||||
if matches!(left, ValueType::BigInt) || matches!(right, ValueType::BigInt) {
|
||||
|
|
@ -358,25 +358,25 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
let right_bigint = ctx.get_side_free_bigint_value(right_expr);
|
||||
|
||||
if let (Some(l_big), Some(r_big)) = (left_bigint, right_bigint) {
|
||||
return Tri::from(l_big.eq(&r_big));
|
||||
return Some(l_big.eq(&r_big));
|
||||
}
|
||||
}
|
||||
|
||||
if matches!(left, ValueType::String | ValueType::Number)
|
||||
&& matches!(right, ValueType::Object)
|
||||
{
|
||||
return Tri::Unknown;
|
||||
return None;
|
||||
}
|
||||
|
||||
if matches!(left, ValueType::Object)
|
||||
&& matches!(right, ValueType::String | ValueType::Number)
|
||||
{
|
||||
return Tri::Unknown;
|
||||
return None;
|
||||
}
|
||||
|
||||
return Tri::False;
|
||||
return Some(false);
|
||||
}
|
||||
Tri::Unknown
|
||||
None
|
||||
}
|
||||
|
||||
/// <https://tc39.es/ecma262/#sec-strict-equality-comparison>
|
||||
|
|
@ -385,13 +385,13 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
left_expr: &'b Expression<'a>,
|
||||
right_expr: &'b Expression<'a>,
|
||||
ctx: Ctx<'a, 'b>,
|
||||
) -> Tri {
|
||||
) -> Option<bool> {
|
||||
let left = ValueType::from(left_expr);
|
||||
let right = ValueType::from(right_expr);
|
||||
if left != ValueType::Undetermined && right != ValueType::Undetermined {
|
||||
// Strict equality can only be true for values of the same type.
|
||||
if left != right {
|
||||
return Tri::False;
|
||||
return Some(false);
|
||||
}
|
||||
return match left {
|
||||
ValueType::Number => {
|
||||
|
|
@ -400,13 +400,13 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
|
||||
if let (Some(l_num), Some(r_num)) = (left_number, right_number) {
|
||||
if l_num.is_nan() || r_num.is_nan() {
|
||||
return Tri::False;
|
||||
return Some(false);
|
||||
}
|
||||
|
||||
return Tri::from(l_num == r_num);
|
||||
return Some(l_num == r_num);
|
||||
}
|
||||
|
||||
Tri::Unknown
|
||||
None
|
||||
}
|
||||
ValueType::String => {
|
||||
let left_string = ctx.get_side_free_string_value(left_expr);
|
||||
|
|
@ -414,28 +414,28 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
if let (Some(left_string), Some(right_string)) = (left_string, right_string) {
|
||||
// In JS, browsers parse \v differently. So do not compare strings if one contains \v.
|
||||
if left_string.contains('\u{000B}') || right_string.contains('\u{000B}') {
|
||||
return Tri::Unknown;
|
||||
return None;
|
||||
}
|
||||
|
||||
return Tri::from(left_string == right_string);
|
||||
return Some(left_string == right_string);
|
||||
}
|
||||
|
||||
Tri::Unknown
|
||||
None
|
||||
}
|
||||
ValueType::Undefined | ValueType::Null => Tri::True,
|
||||
ValueType::Undefined | ValueType::Null => Some(true),
|
||||
ValueType::Boolean if right.is_boolean() => {
|
||||
let left = ctx.get_boolean_value(left_expr);
|
||||
let right = ctx.get_boolean_value(right_expr);
|
||||
if let (Some(left_bool), Some(right_bool)) = (left, right) {
|
||||
return Tri::from(left_bool == right_bool);
|
||||
return Some(left_bool == right_bool);
|
||||
}
|
||||
Tri::Unknown
|
||||
None
|
||||
}
|
||||
// TODO
|
||||
ValueType::BigInt
|
||||
| ValueType::Object
|
||||
| ValueType::Boolean
|
||||
| ValueType::Undetermined => Tri::Unknown,
|
||||
| ValueType::Undetermined => None,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -443,9 +443,9 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
// There's only one special case:
|
||||
// Any strict equality comparison against NaN returns false.
|
||||
if left_expr.is_nan() || right_expr.is_nan() {
|
||||
return Tri::False;
|
||||
return Some(false);
|
||||
}
|
||||
Tri::Unknown
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ mod compressor;
|
|||
mod keep_var;
|
||||
mod node_util;
|
||||
mod options;
|
||||
mod tri;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tester;
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
/// Tri state
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Tri {
|
||||
True,
|
||||
False,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<bool> for Tri {
|
||||
fn from(value: bool) -> Self {
|
||||
if value {
|
||||
Tri::True
|
||||
} else {
|
||||
Tri::False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Option<bool>> for Tri {
|
||||
fn from(value: Option<bool>) -> Self {
|
||||
value.map_or(Tri::Unknown, From::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i8> for Tri {
|
||||
fn from(value: i8) -> Self {
|
||||
match value {
|
||||
-1 => Self::False,
|
||||
1 => Self::True,
|
||||
_ => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tri {
|
||||
pub fn not(self) -> Self {
|
||||
match self {
|
||||
Self::True => Self::False,
|
||||
Self::False => Self::True,
|
||||
Self::Unknown => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue