feat(minifier): fold NaN comparison (#580)

This commit is contained in:
阿良仔 2023-07-21 11:00:21 +08:00 committed by GitHub
parent 52c3c37b2b
commit 3c76cef11c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 0 deletions

View file

@ -122,6 +122,11 @@ impl<'a> Expression<'a> {
matches!(self, Self::Identifier(ident) if ident.name == "undefined")
}
/// Determines whether the given expr is a `NaN` literal
pub fn is_nan(&self) -> bool {
matches!(self, Self::Identifier(ident) if ident.name == "NaN")
}
/// Determines whether the given expr is a `void 0`
pub fn is_void_0(&self) -> bool {
if let Self::UnaryExpression(expr) = self

View file

@ -483,6 +483,13 @@ impl<'a> Compressor<'a> {
_ => Tri::Unknown,
};
}
// Then, try to evaluate based on the value of the expression.
// 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;
}
Tri::Unknown
}

View file

@ -404,6 +404,43 @@ fn test_string_bigint_comparison() {
test_wcb("'1' !== 1n", "true");
}
#[test]
fn test_nan_comparison() {
test_wcb("NaN < 1", "false");
test_wcb("NaN <= 1", "false");
test_wcb("NaN > 1", "false");
test_wcb("NaN >= 1", "false");
test_wcb("NaN < 1n", "false");
test_wcb("NaN <= 1n", "false");
test_wcb("NaN > 1n", "false");
test_wcb("NaN >= 1n", "false");
test_wcb("NaN < NaN", "false");
test_wcb("NaN >= NaN", "false");
test_wcb("NaN == NaN", "false");
test_wcb("NaN === NaN", "false");
test_wcb("NaN < null", "false");
test_wcb("null >= NaN", "false");
test_wcb("NaN == null", "false");
test_wcb("null != NaN", "true");
test_wcb("null === NaN", "false");
test_wcb("NaN < undefined", "false");
test_wcb("undefined >= NaN", "false");
test_wcb("NaN == undefined", "false");
test_wcb("undefined != NaN", "true");
test_wcb("undefined === NaN", "false");
test_same("NaN<x");
test_same("x>=NaN");
test_same("NaN==x");
test_same("x!=NaN");
test_wcb("NaN === x", "false");
test_wcb("x !== NaN", "true");
test_same("NaN==foo()");
}
#[test]
fn js_typeof() {
test("x = typeof 1", "x='number'");