@@ -9,44 +9,42 @@ use super::PeepholeOptimizations;
99impl < ' a > PeepholeOptimizations {
1010 pub fn minimize_not (
1111 span : Span ,
12- expr : Expression < ' a > ,
12+ mut expr : Expression < ' a > ,
1313 ctx : & mut TraverseCtx < ' a > ,
14+ boolean_context : bool ,
1415 ) -> Expression < ' a > {
15- let mut unary =
16- Expression :: new_unary_expression ( span, UnaryOperator :: LogicalNot , expr, ctx) ;
17- Self :: minimize_unary ( & mut unary, ctx) ;
18- unary
16+ if Self :: try_negate_expression ( & mut expr, ctx, boolean_context) {
17+ if boolean_context {
18+ Self :: minimize_expression_in_boolean_context ( & mut expr, ctx) ;
19+ }
20+ expr
21+ } else {
22+ Expression :: new_unary_expression ( span, UnaryOperator :: LogicalNot , expr, ctx)
23+ }
1924 }
2025
21- /// `MaybeSimplifyNot`: <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_ast/js_ast_helpers.go#L73>
22- pub fn minimize_unary ( expr : & mut Expression < ' a > , ctx : & mut TraverseCtx < ' a > ) {
23- let Expression :: UnaryExpression ( e) = expr else { return } ;
24- if !e. operator . is_not ( ) {
25- return ;
26- }
27- Self :: minimize_expression_in_boolean_context ( & mut e. argument , ctx) ;
28- match & mut e. argument {
26+ pub fn try_negate_expression (
27+ expr : & mut Expression < ' a > ,
28+ ctx : & mut TraverseCtx < ' a > ,
29+ boolean_context : bool ,
30+ ) -> bool {
31+ match expr {
2932 // `!!true` -> `true`
3033 // `!!false` -> `false`
3134 Expression :: UnaryExpression ( e)
32- if e. operator . is_not ( ) && e. argument . value_type ( ctx) . is_boolean ( ) =>
35+ if e. operator . is_not ( )
36+ && ( boolean_context || e. argument . value_type ( ctx) . is_boolean ( ) ) =>
3337 {
34- // Both discarded `!` wrappers contain no references.
35- ctx. replace_expression_with ( expr, |old, _| {
36- let Expression :: UnaryExpression ( outer) = old else { unreachable ! ( ) } ;
37- let Expression :: UnaryExpression ( inner) = outer. unbox ( ) . argument else {
38- unreachable ! ( )
39- } ;
40- inner. unbox ( ) . argument
41- } ) ;
38+ ctx. replace_expression_with ( expr, Self :: unwrap_unary) ;
39+ true
4240 }
4341 // `!(a == b)` => `a != b`
4442 // `!(a != b)` => `a == b`
4543 // `!(a === b)` => `a !== b`
4644 // `!(a !== b)` => `a === b`
4745 Expression :: BinaryExpression ( binary_expr) if binary_expr. operator . is_equality ( ) => {
4846 binary_expr. operator = binary_expr. operator . equality_inverse_operator ( ) . unwrap ( ) ;
49- ctx . replace_expression_with ( expr , Self :: unwrap_unary ) ;
47+ true
5048 }
5149 // `!(a == b || c == d)` => `a != b && c != d`
5250 // `!(a == b && c == d)` => `a != b || c != d`
@@ -60,18 +58,32 @@ impl<'a> PeepholeOptimizations {
6058 if Self :: de_morgan_paren_delta ( logical_expr) . is_some_and ( |delta| delta <= 0 ) =>
6159 {
6260 Self :: de_morgan_invert_logical ( logical_expr) ;
63- ctx . replace_expression_with ( expr , Self :: unwrap_unary ) ;
61+ true
6462 }
6563 // "!(a, b)" => "a, !b"
6664 Expression :: SequenceExpression ( sequence_expr) => {
6765 if let Some ( last_expr) = sequence_expr. expressions . last_mut ( ) {
6866 ctx. replace_expression_with ( last_expr, |old, ctx| {
69- Self :: minimize_not ( old. span ( ) , old, ctx)
67+ Self :: minimize_not ( old. span ( ) , old, ctx, boolean_context )
7068 } ) ;
71- ctx . replace_expression_with ( expr , Self :: unwrap_unary ) ;
69+ return true ;
7270 }
71+ false
7372 }
74- _ => { }
73+ _ => false ,
74+ }
75+ }
76+
77+ /// `MaybeSimplifyNot`: <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_ast/js_ast_helpers.go#L73>
78+ pub fn minimize_unary ( expr : & mut Expression < ' a > , ctx : & mut TraverseCtx < ' a > ) {
79+ let Expression :: UnaryExpression ( e) = expr else { return } ;
80+ if !e. operator . is_not ( ) {
81+ return ;
82+ }
83+ Self :: minimize_expression_in_boolean_context ( & mut e. argument , ctx) ;
84+
85+ if Self :: try_negate_expression ( & mut e. argument , ctx, false ) {
86+ ctx. replace_expression_with ( expr, Self :: unwrap_unary) ;
7587 }
7688 }
7789
0 commit comments