From 8f1faf7d4a9e5d26768e7b29dc6f5a983be98dbc Mon Sep 17 00:00:00 2001 From: Evan Wallace Date: Fri, 24 May 2024 14:39:41 -0400 Subject: [PATCH] implement late constant-folding for `&& || ??` --- .../bundler_tests/snapshots/snapshots_dce.txt | 18 +++++------ internal/js_ast/js_ast_helpers.go | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/internal/bundler_tests/snapshots/snapshots_dce.txt b/internal/bundler_tests/snapshots/snapshots_dce.txt index 73b16354c78..4d6fd2d544a 100644 --- a/internal/bundler_tests/snapshots/snapshots_dce.txt +++ b/internal/bundler_tests/snapshots/snapshots_dce.txt @@ -291,9 +291,9 @@ console.log([ 7, 5 ], [ - 3 /* a */ && 6 /* b */, - 3 /* a */ || 6 /* b */, - 3 /* a */ ?? 6 /* b */ + 6 /* b */, + 3 /* a */, + 3 /* a */ ]); ---------- /out/const-entry.js ---------- @@ -329,9 +329,9 @@ console.log([ 7, 5 ], [ - 3 && 6, - 3 || 6, - 3 ?? 6 + 6, + 3, + 3 ]); ---------- /out/nested-entry.js ---------- @@ -359,9 +359,9 @@ console.log([ !1, !0 ], [ - "foo" /* a */ && "bar" /* b */, - "foo" /* a */ || "bar" /* b */, - "foo" /* a */ ?? "bar" /* b */ + "bar" /* b */, + "foo" /* a */, + "foo" /* a */ ]); ---------- /out/const-entry.js ---------- diff --git a/internal/js_ast/js_ast_helpers.go b/internal/js_ast/js_ast_helpers.go index dd1d0a8de82..da78ea76919 100644 --- a/internal/js_ast/js_ast_helpers.go +++ b/internal/js_ast/js_ast_helpers.go @@ -1208,6 +1208,11 @@ func ShouldFoldBinaryOperatorWhenMinifying(binary *EBinary) bool { resultLen := approximatePrintedIntCharCount(float64(ToUint32(left) >> (ToUint32(right) & 31))) return resultLen <= leftLen+3+rightLen } + + case BinOpLogicalAnd, BinOpLogicalOr, BinOpNullishCoalescing: + if IsPrimitiveLiteral(binary.Left.Data) { + return true + } } return false } @@ -1326,6 +1331,33 @@ func FoldBinaryOperator(loc logger.Loc, e *EBinary) Expr { if left, right, ok := extractStringValues(e.Left, e.Right); ok { return Expr{Loc: loc, Data: &EBoolean{Value: stringCompareUCS2(left, right) != 0}} } + + case BinOpLogicalAnd: + if boolean, sideEffects, ok := ToBooleanWithSideEffects(e.Left.Data); ok { + if !boolean { + return e.Left + } else if sideEffects == NoSideEffects { + return e.Right + } + } + + case BinOpLogicalOr: + if boolean, sideEffects, ok := ToBooleanWithSideEffects(e.Left.Data); ok { + if boolean { + return e.Left + } else if sideEffects == NoSideEffects { + return e.Right + } + } + + case BinOpNullishCoalescing: + if isNullOrUndefined, sideEffects, ok := ToNullOrUndefinedWithSideEffects(e.Left.Data); ok { + if !isNullOrUndefined { + return e.Left + } else if sideEffects == NoSideEffects { + return e.Right + } + } } return Expr{}