mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(minifier): do not fold object comparisons (#8375)
This commit is contained in:
parent
a1752a062c
commit
5516f7fcb9
2 changed files with 38 additions and 37 deletions
|
|
@ -266,20 +266,18 @@ pub trait ConstantEvaluation<'a> {
|
|||
_ => unreachable!(),
|
||||
}))
|
||||
}
|
||||
BinaryOperator::LessThan => {
|
||||
self.is_less_than(left, right, true).map(|value| match value {
|
||||
ConstantValue::Undefined => ConstantValue::Boolean(false),
|
||||
_ => value,
|
||||
})
|
||||
}
|
||||
BinaryOperator::LessThan => self.is_less_than(left, right).map(|value| match value {
|
||||
ConstantValue::Undefined => ConstantValue::Boolean(false),
|
||||
_ => value,
|
||||
}),
|
||||
BinaryOperator::GreaterThan => {
|
||||
self.is_less_than(right, left, false).map(|value| match value {
|
||||
self.is_less_than(right, left).map(|value| match value {
|
||||
ConstantValue::Undefined => ConstantValue::Boolean(false),
|
||||
_ => value,
|
||||
})
|
||||
}
|
||||
BinaryOperator::LessEqualThan => {
|
||||
self.is_less_than(right, left, false).map(|value| match value {
|
||||
self.is_less_than(right, left).map(|value| match value {
|
||||
ConstantValue::Boolean(true) | ConstantValue::Undefined => {
|
||||
ConstantValue::Boolean(false)
|
||||
}
|
||||
|
|
@ -288,7 +286,7 @@ pub trait ConstantEvaluation<'a> {
|
|||
})
|
||||
}
|
||||
BinaryOperator::GreaterEqualThan => {
|
||||
self.is_less_than(left, right, true).map(|value| match value {
|
||||
self.is_less_than(left, right).map(|value| match value {
|
||||
ConstantValue::Boolean(true) | ConstantValue::Undefined => {
|
||||
ConstantValue::Boolean(false)
|
||||
}
|
||||
|
|
@ -444,42 +442,37 @@ pub trait ConstantEvaluation<'a> {
|
|||
}
|
||||
|
||||
/// <https://tc39.es/ecma262/#sec-abstract-relational-comparison>
|
||||
fn is_less_than(
|
||||
&self,
|
||||
left_expr: &Expression<'a>,
|
||||
right_expr: &Expression<'a>,
|
||||
_left_first: bool,
|
||||
) -> Option<ConstantValue<'a>> {
|
||||
let left = ValueType::from(left_expr);
|
||||
let right = ValueType::from(right_expr);
|
||||
|
||||
if left.is_string() && right.is_string() {
|
||||
let left_string = self.get_side_free_string_value(left_expr);
|
||||
let right_string = self.get_side_free_string_value(right_expr);
|
||||
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 None;
|
||||
}
|
||||
return Some(ConstantValue::Boolean(
|
||||
left_string.cmp(&right_string) == Ordering::Less,
|
||||
));
|
||||
}
|
||||
}
|
||||
fn is_less_than(&self, x: &Expression<'a>, y: &Expression<'a>) -> Option<ConstantValue<'a>> {
|
||||
// a. Let px be ? ToPrimitive(x, number).
|
||||
// b. Let py be ? ToPrimitive(y, number).
|
||||
let px = ValueType::from(x);
|
||||
|
||||
// `.toString()` method is called and compared.
|
||||
// TODO: bigint is handled very differently in the spec
|
||||
// See <https://tc39.es/ecma262/#sec-islessthan>
|
||||
if left.is_bigint() || right.is_bigint() {
|
||||
if px.is_object() || px.is_undetermined() || px.is_bigint() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let left_num = self.get_side_free_number_value(left_expr)?;
|
||||
let right_num = self.get_side_free_number_value(right_expr)?;
|
||||
let py = ValueType::from(y);
|
||||
|
||||
if left_num.is_nan() || right_num.is_nan() {
|
||||
return Some(ConstantValue::Undefined);
|
||||
if py.is_object() || py.is_undetermined() || py.is_bigint() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if px.is_string() && py.is_string() {
|
||||
let left_string = self.get_side_free_string_value(x)?;
|
||||
let right_string = self.get_side_free_string_value(y)?;
|
||||
return Some(ConstantValue::Boolean(left_string.cmp(&right_string) == Ordering::Less));
|
||||
}
|
||||
|
||||
let left_num = self.get_side_free_number_value(x)?;
|
||||
if left_num.is_nan() {
|
||||
return Some(ConstantValue::Undefined);
|
||||
}
|
||||
let right_num = self.get_side_free_number_value(y)?;
|
||||
if right_num.is_nan() {
|
||||
return Some(ConstantValue::Undefined);
|
||||
}
|
||||
Some(ConstantValue::Boolean(left_num < right_num))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -715,6 +715,14 @@ mod test {
|
|||
#[test]
|
||||
fn test_comparison() {
|
||||
test("(1, 2) !== 2", "false");
|
||||
test_same("({} <= {})");
|
||||
test_same("({} >= {})");
|
||||
test_same("({} > {})");
|
||||
test_same("({} < {})");
|
||||
test_same("([] <= [])");
|
||||
test_same("([] >= [])");
|
||||
test_same("([] > [])");
|
||||
test_same("([] < [])");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue