diff --git a/internal/bundler_tests/bundler_dce_test.go b/internal/bundler_tests/bundler_dce_test.go index 0111241b04f..8167d6acdc9 100644 --- a/internal/bundler_tests/bundler_dce_test.go +++ b/internal/bundler_tests/bundler_dce_test.go @@ -1273,8 +1273,8 @@ func TestTreeShakingReactElements(t *testing.T) { func TestDisableTreeShaking(t *testing.T) { defines := config.ProcessDefines(map[string]config.DefineData{ - "pure": {CallCanBeUnwrappedIfUnused: true}, - "some.fn": {CallCanBeUnwrappedIfUnused: true}, + "pure": {Flags: config.CallCanBeUnwrappedIfUnused}, + "some.fn": {Flags: config.CallCanBeUnwrappedIfUnused}, }) dce_suite.expectBundled(t, bundled{ files: map[string]string{ diff --git a/internal/config/globals.go b/internal/config/globals.go index 97118982fb6..36ffd251ba7 100644 --- a/internal/config/globals.go +++ b/internal/config/globals.go @@ -869,31 +869,35 @@ type DefineExpr struct { type DefineData struct { DefineExpr *DefineExpr + Flags DefineFlags +} + +type DefineFlags uint8 +const ( // True if accessing this value is known to not have any side effects. For // example, a bare reference to "Object.create" can be removed because it // does not have any observable side effects. - CanBeRemovedIfUnused bool + CanBeRemovedIfUnused DefineFlags = 1 << iota // True if a call to this value is known to not have any side effects. For // example, a bare call to "Object()" can be removed because it does not // have any observable side effects. - CallCanBeUnwrappedIfUnused bool + CallCanBeUnwrappedIfUnused // If true, the user has indicated that every direct calls to a property on // this object and all of that call's arguments are to be removed from the // output, even when the arguments have side effects. This is used to // implement the "--drop:console" flag. - MethodCallsMustBeReplacedWithUndefined bool + MethodCallsMustBeReplacedWithUndefined +) + +func (flags DefineFlags) Has(flag DefineFlags) bool { + return (flags & flag) != 0 } func mergeDefineData(old DefineData, new DefineData) DefineData { - if old.CanBeRemovedIfUnused { - new.CanBeRemovedIfUnused = true - } - if old.CallCanBeUnwrappedIfUnused { - new.CallCanBeUnwrappedIfUnused = true - } + new.Flags |= old.Flags return new } @@ -937,9 +941,9 @@ func ProcessDefines(userDefines map[string]DefineData) ProcessedDefines { for _, parts := range knownGlobals { tail := parts[len(parts)-1] if len(parts) == 1 { - result.IdentifierDefines[tail] = DefineData{CanBeRemovedIfUnused: true} + result.IdentifierDefines[tail] = DefineData{Flags: CanBeRemovedIfUnused} } else { - result.DotDefines[tail] = append(result.DotDefines[tail], DotDefine{Parts: parts, Data: DefineData{CanBeRemovedIfUnused: true}}) + result.DotDefines[tail] = append(result.DotDefines[tail], DotDefine{Parts: parts, Data: DefineData{Flags: CanBeRemovedIfUnused}}) } } diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index d37e3cceb71..e15439ad9b5 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -12880,13 +12880,13 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO } // Copy the side effect flags over in case this expression is unused - if data.CanBeRemovedIfUnused { + if data.Flags.Has(config.CanBeRemovedIfUnused) { e.CanBeRemovedIfUnused = true } - if data.CallCanBeUnwrappedIfUnused && !p.options.ignoreDCEAnnotations { + if data.Flags.Has(config.CallCanBeUnwrappedIfUnused) && !p.options.ignoreDCEAnnotations { e.CallCanBeUnwrappedIfUnused = true } - if data.MethodCallsMustBeReplacedWithUndefined { + if data.Flags.Has(config.MethodCallsMustBeReplacedWithUndefined) { methodCallMustBeReplacedWithUndefined = true } } @@ -13406,10 +13406,10 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO } // Copy the side effect flags over in case this expression is unused - if define.Data.CanBeRemovedIfUnused { + if define.Data.Flags.Has(config.CanBeRemovedIfUnused) { e.CanBeRemovedIfUnused = true } - if define.Data.CallCanBeUnwrappedIfUnused && !p.options.ignoreDCEAnnotations { + if define.Data.Flags.Has(config.CallCanBeUnwrappedIfUnused) && !p.options.ignoreDCEAnnotations { e.CallCanBeUnwrappedIfUnused = true } break @@ -13529,10 +13529,10 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO } // Copy the side effect flags over in case this expression is unused - if define.Data.CanBeRemovedIfUnused { + if define.Data.Flags.Has(config.CanBeRemovedIfUnused) { e.CanBeRemovedIfUnused = true } - if define.Data.CallCanBeUnwrappedIfUnused && !p.options.ignoreDCEAnnotations { + if define.Data.Flags.Has(config.CallCanBeUnwrappedIfUnused) && !p.options.ignoreDCEAnnotations { e.CallCanBeUnwrappedIfUnused = true } break diff --git a/pkg/api/api_impl.go b/pkg/api/api_impl.go index 803b771a8ad..021f801f0d6 100644 --- a/pkg/api/api_impl.go +++ b/pkg/api/api_impl.go @@ -694,7 +694,7 @@ func validateDefines( // If we're dropping all console API calls, replace each one with undefined if (drop & DropConsole) != 0 { define := rawDefines["console"] - define.MethodCallsMustBeReplacedWithUndefined = true + define.Flags |= config.MethodCallsMustBeReplacedWithUndefined rawDefines["console"] = define } @@ -709,7 +709,7 @@ func validateDefines( // Merge with any previously-specified defines define := rawDefines[key] - define.CallCanBeUnwrappedIfUnused = true + define.Flags |= config.CallCanBeUnwrappedIfUnused rawDefines[key] = define }