mirror of
https://github.com/danbulant/oxc
synced 2026-05-22 05:38:54 +00:00
feat(minifier): fold invalid typeof comparisons (#8550)
This commit is contained in:
parent
c479a58718
commit
7cc81ef5ef
1 changed files with 51 additions and 2 deletions
|
|
@ -607,12 +607,12 @@ impl<'a, 'b> PeepholeFoldConstants {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// `typeof a === typeof b` -> `typeof a == typeof b`, `typeof a != typeof b` -> `typeof a != typeof b`,
|
|
||||||
// `typeof a == typeof a` -> `true`, `typeof a != typeof a` -> `false`
|
|
||||||
fn try_fold_binary_typeof_comparison(
|
fn try_fold_binary_typeof_comparison(
|
||||||
bin_expr: &mut BinaryExpression<'a>,
|
bin_expr: &mut BinaryExpression<'a>,
|
||||||
ctx: Ctx<'a, 'b>,
|
ctx: Ctx<'a, 'b>,
|
||||||
) -> Option<Expression<'a>> {
|
) -> Option<Expression<'a>> {
|
||||||
|
// `typeof a === typeof b` -> `typeof a == typeof b`, `typeof a != typeof b` -> `typeof a != typeof b`,
|
||||||
|
// `typeof a == typeof a` -> `true`, `typeof a != typeof a` -> `false`
|
||||||
if bin_expr.operator.is_equality() {
|
if bin_expr.operator.is_equality() {
|
||||||
if let (Expression::UnaryExpression(left), Expression::UnaryExpression(right)) =
|
if let (Expression::UnaryExpression(left), Expression::UnaryExpression(right)) =
|
||||||
(&bin_expr.left, &bin_expr.right)
|
(&bin_expr.left, &bin_expr.right)
|
||||||
|
|
@ -653,6 +653,41 @@ impl<'a, 'b> PeepholeFoldConstants {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `typeof a === 'asd` -> `false``
|
||||||
|
// `typeof a !== 'b'` -> `true``
|
||||||
|
if let Expression::UnaryExpression(left) = &bin_expr.left {
|
||||||
|
if left.operator.is_typeof() && bin_expr.operator.is_equality() {
|
||||||
|
let right_ty = ValueType::from(&bin_expr.right);
|
||||||
|
|
||||||
|
if !right_ty.is_undetermined() && right_ty != ValueType::String {
|
||||||
|
return Some(ctx.ast.expression_boolean_literal(
|
||||||
|
bin_expr.span,
|
||||||
|
bin_expr.operator == BinaryOperator::Inequality
|
||||||
|
|| bin_expr.operator == BinaryOperator::StrictInequality,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if let Expression::StringLiteral(string_lit) = &bin_expr.right {
|
||||||
|
if !matches!(
|
||||||
|
string_lit.value.as_str(),
|
||||||
|
"string"
|
||||||
|
| "number"
|
||||||
|
| "bigint"
|
||||||
|
| "boolean"
|
||||||
|
| "symbol"
|
||||||
|
| "undefined"
|
||||||
|
| "object"
|
||||||
|
| "function"
|
||||||
|
) {
|
||||||
|
return Some(ctx.ast.expression_boolean_literal(
|
||||||
|
bin_expr.span,
|
||||||
|
bin_expr.operator == BinaryOperator::Inequality
|
||||||
|
|| bin_expr.operator == BinaryOperator::StrictInequality,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1736,6 +1771,20 @@ mod test {
|
||||||
test("typeof foo.bar !== typeof foo.bar", "typeof foo.bar != typeof foo.bar");
|
test("typeof foo.bar !== typeof foo.bar", "typeof foo.bar != typeof foo.bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fold_invalid_typeof_comparison() {
|
||||||
|
test("typeof foo == 123", "false");
|
||||||
|
test("typeof foo == '123'", "false");
|
||||||
|
test("typeof foo === null", "false");
|
||||||
|
test("typeof foo === undefined", "false");
|
||||||
|
test("typeof foo !== 123", "true");
|
||||||
|
test("typeof foo !== '123'", "true");
|
||||||
|
test("typeof foo != null", "true");
|
||||||
|
test("typeof foo != undefined", "true");
|
||||||
|
test_same("typeof foo === 'string'");
|
||||||
|
test_same("typeof foo === 'number'");
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: All big ints are rare and difficult to handle.
|
// TODO: All big ints are rare and difficult to handle.
|
||||||
mod bigint {
|
mod bigint {
|
||||||
use super::{
|
use super::{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue