Skip to content

Commit

Permalink
split "debug" log level into "debug" and "verbose"
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Apr 17, 2021
1 parent d0ab9aa commit e2a461f
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 90 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@

The TypeScript-to-JavaScript transform in esbuild has been updated to match the TypeScript compiler's output in both of these cases.

* Separate the `debug` log level into `debug` and `verbose`

You can now use `--log-level=debug` to get some additional information that might indicate some problems with your build, but that has a high-enough false-positive rate that it isn't appropriate for warnings, which are on by default. Enabling the `debug` log level no longer generates a torrent of debug information like it did in the past; that behavior is now reserved for the `verbose` log level instead.

## 0.11.11

* Initial support for Deno ([#936](https://github.com/evanw/esbuild/issues/936))
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,7 @@ READMIN_ESBUILD_FLAGS += --define:global=window
READMIN_ESBUILD_FLAGS += --loader:.js=jsx
READMIN_ESBUILD_FLAGS += --minify
READMIN_ESBUILD_FLAGS += --sourcemap
READMIN_ESBUILD_FLAGS += --log-level=debug

bench-readmin-esbuild: esbuild | bench/readmin
rm -fr bench/readmin/esbuild
Expand Down
4 changes: 2 additions & 2 deletions cmd/esbuild/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ var helpText = func(colors logger.Colors) string {
--jsx-factory=... What to use for JSX instead of React.createElement
--jsx-fragment=... What to use for JSX instead of React.Fragment
--keep-names Preserve "name" on functions and classes
--log-level=... Disable logging (debug | info | warning | error |
silent, default info)
--log-level=... Disable logging (verbose | debug | info | warning |
error | silent, default info)
--log-limit=... Maximum message count or 0 to disable (default 10)
--main-fields=... Override the main file order in package.json
(default "browser,module,main" when platform is
Expand Down
30 changes: 17 additions & 13 deletions internal/bundler/bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,10 @@ func parseFile(args parseArgs) {
hint = fmt.Sprintf(" (the plugin %q didn't set a resolve directory)", pluginName)
}
debug.LogErrorMsg(args.log, &source, record.Range, fmt.Sprintf("Could not resolve %q%s", record.Path.Text, hint))
} else if args.log.Level <= logger.LevelDebug && !didLogError && record.HandlesImportErrors {
args.log.AddRangeDebug(&source, record.Range,
fmt.Sprintf("Importing %q was allowed even though it could not be resolved because dynamic import failures appear to be handled here",
record.Path.Text))
}
continue
}
Expand Down Expand Up @@ -538,15 +542,15 @@ func extractSourceMapFromComment(
absPath := fs.Join(absResolveDir, comment.Text)
path := logger.Path{Text: absPath, Namespace: "file"}
contents, err, originalError := fsCache.ReadFile(fs, absPath)
if log.Debug && originalError != nil {
log.AddDebug(nil, logger.Loc{}, fmt.Sprintf("Failed to read file %q: %s", absPath, originalError.Error()))
if log.Level <= logger.LevelDebug && originalError != nil {
log.AddRangeDebug(source, comment.Range, fmt.Sprintf("Failed to read file %q: %s", res.PrettyPath(path), originalError.Error()))
}
if err != nil {
if err == syscall.ENOENT {
// Don't report a warning because this is likely unactionable
return logger.Path{}, nil
}
log.AddRangeError(source, comment.Range, fmt.Sprintf("Cannot read file %q: %s", res.PrettyPath(path), err.Error()))
log.AddRangeWarning(source, comment.Range, fmt.Sprintf("Cannot read file %q: %s", res.PrettyPath(path), err.Error()))
return logger.Path{}, nil
}
return path, &contents
Expand Down Expand Up @@ -833,7 +837,7 @@ func runOnLoadPlugins(
absResolveDir: fs.Dir(source.KeyPath.Text),
}, true
} else {
if log.Debug && originalError != nil {
if log.Level <= logger.LevelDebug && originalError != nil {
log.AddDebug(nil, logger.Loc{}, fmt.Sprintf("Failed to read file %q: %s", source.KeyPath.Text, originalError.Error()))
}
if err == syscall.ENOENT {
Expand Down Expand Up @@ -935,8 +939,8 @@ func ScanBundle(
options config.Options,
) Bundle {
start := time.Now()
if log.Debug {
log.AddDebug(nil, logger.Loc{}, "Started the scan phase")
if log.Level <= logger.LevelVerbose {
log.AddVerbose(nil, logger.Loc{}, "Started the scan phase")
}

applyOptionDefaults(&options)
Expand Down Expand Up @@ -973,8 +977,8 @@ func ScanBundle(
s.scanAllDependencies()
files := s.processScannedFiles()

if log.Debug {
log.AddDebug(nil, logger.Loc{}, fmt.Sprintf("Ended the scan phase (%dms)", time.Since(start).Milliseconds()))
if log.Level <= logger.LevelVerbose {
log.AddVerbose(nil, logger.Loc{}, fmt.Sprintf("Ended the scan phase (%dms)", time.Since(start).Milliseconds()))
}

return Bundle{
Expand Down Expand Up @@ -1262,7 +1266,7 @@ func (s *scanner) addEntryPoints(entryPoints []EntryPoint) []graph.EntryPoint {
entryPoint.InputPath = "./" + entryPoint.InputPath
}
}
} else if s.log.Debug && originalError != nil {
} else if s.log.Level <= logger.LevelDebug && originalError != nil {
s.log.AddDebug(nil, logger.Loc{}, fmt.Sprintf("Failed to read directory %q: %s", absPath, originalError.Error()))
}
}
Expand Down Expand Up @@ -1828,8 +1832,8 @@ func applyOptionDefaults(options *config.Options) {

func (b *Bundle) Compile(log logger.Log, options config.Options) ([]graph.OutputFile, string) {
start := time.Now()
if log.Debug {
log.AddDebug(nil, logger.Loc{}, "Started the compile phase")
if log.Level <= logger.LevelVerbose {
log.AddVerbose(nil, logger.Loc{}, "Started the compile phase")
}

applyOptionDefaults(&options)
Expand Down Expand Up @@ -1936,8 +1940,8 @@ func (b *Bundle) Compile(log logger.Log, options config.Options) ([]graph.Output
outputFiles = outputFiles[:end]
}

if log.Debug {
log.AddDebug(nil, logger.Loc{}, fmt.Sprintf("Ended the compile phase (%dms)", time.Since(start).Milliseconds()))
if log.Level <= logger.LevelVerbose {
log.AddVerbose(nil, logger.Loc{}, fmt.Sprintf("Ended the compile phase (%dms)", time.Since(start).Milliseconds()))
}

return outputFiles, metafileJSON
Expand Down
11 changes: 0 additions & 11 deletions internal/bundler/bundler_default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,6 @@ func TestRequireAndDynamicImportInvalidTemplate(t *testing.T) {
require(tag` + "`./b`" + `)
require(` + "`./${b}`" + `)
// Try/catch should silence this warning for require()
try {
require(tag` + "`./b`" + `)
require(` + "`./${b}`" + `)
Expand All @@ -803,7 +802,6 @@ func TestRequireAndDynamicImportInvalidTemplate(t *testing.T) {
await import(tag` + "`./b`" + `)
await import(` + "`./${b}`" + `)
// Try/catch should silence this warning for await import()
try {
import(tag` + "`./b`" + `)
import(` + "`./${b}`" + `)
Expand All @@ -819,9 +817,6 @@ func TestRequireAndDynamicImportInvalidTemplate(t *testing.T) {
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
},
expectedScanLog: `entry.js: warning: This call to "require" will not be bundled because the argument is not a string literal (surround with a try/catch to silence this warning)
entry.js: warning: This call to "require" will not be bundled because the argument is not a string literal (surround with a try/catch to silence this warning)
`,
})
}

Expand Down Expand Up @@ -905,8 +900,6 @@ func TestConditionalRequire(t *testing.T) {
},
},
},
expectedScanLog: `a.js: warning: This call to "require" will not be bundled because the argument is not a string literal (surround with a try/catch to silence this warning)
`,
})
}

Expand Down Expand Up @@ -944,7 +937,6 @@ func TestRequireBadArgumentCount(t *testing.T) {
require()
require("a", "b")
// Try/catch should silence this warning
try {
require()
require("a", "b")
Expand All @@ -957,9 +949,6 @@ func TestRequireBadArgumentCount(t *testing.T) {
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
},
expectedScanLog: `entry.js: warning: This call to "require" will not be bundled because it has 0 arguments (surround with a try/catch to silence this warning)
entry.js: warning: This call to "require" will not be bundled because it has 2 arguments (surround with a try/catch to silence this warning)
`,
})
}

Expand Down
107 changes: 70 additions & 37 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,10 +474,6 @@ func (dc *duplicateCaseChecker) reset() {
}

func (dc *duplicateCaseChecker) check(p *parser, expr js_ast.Expr) {
if p.options.suppressWarningsAboutWeirdCode {
return
}

if hash, ok := duplicateCaseHash(expr); ok {
bucket := hash % bloomFilterSize
entry := &dc.bloomFilter[bucket/8]
Expand All @@ -489,12 +485,14 @@ func (dc *duplicateCaseChecker) check(p *parser, expr js_ast.Expr) {
if c.hash == hash {
if equals, couldBeIncorrect := duplicateCaseEquals(c.value, expr); equals {
r := p.source.RangeOfOperatorBefore(expr.Loc, "case")
text := "This case clause will never be evaluated because it duplicates an earlier case clause"
if couldBeIncorrect {
p.log.AddRangeWarning(&p.source, r,
"This case clause may never be evaluated because it likely duplicates an earlier case clause")
text = "This case clause may never be evaluated because it likely duplicates an earlier case clause"
}
if !p.options.suppressWarningsAboutWeirdCode {
p.log.AddRangeWarning(&p.source, r, text)
} else {
p.log.AddRangeWarning(&p.source, r,
"This case clause will never be evaluated because it duplicates an earlier case clause")
p.log.AddRangeDebug(&p.source, r, text)
}
}
return
Expand Down Expand Up @@ -9320,9 +9318,12 @@ func (p *parser) warnAboutTypeofAndString(a js_ast.Expr, b js_ast.Expr) {
// Warn about typeof comparisons with values that will never be
// returned. Here's an example of code with this problem:
// https://github.com/olifolkerd/tabulator/issues/2962
r := p.source.RangeOfString(b.Loc)
text := fmt.Sprintf("The \"typeof\" operator will never evaluate to %q", value)
if !p.options.suppressWarningsAboutWeirdCode {
r := p.source.RangeOfString(b.Loc)
p.log.AddRangeWarning(&p.source, r, fmt.Sprintf("The \"typeof\" operator will never evaluate to %q", value))
p.log.AddRangeWarning(&p.source, r, text)
} else {
p.log.AddRangeDebug(&p.source, r, text)
}
}
}
Expand Down Expand Up @@ -9352,10 +9353,6 @@ func maybeSimplifyEqualityComparison(e *js_ast.EBinary, isNotEqual bool) (js_ast
}

func (p *parser) warnAboutEqualityCheck(op string, value js_ast.Expr, afterOpLoc logger.Loc) bool {
if p.options.suppressWarningsAboutWeirdCode {
return false
}

switch e := value.Data.(type) {
case *js_ast.ENumber:
// "0 === -0" is true in JavaScript. Here's an example of code with this
Expand All @@ -9370,7 +9367,11 @@ func (p *parser) warnAboutEqualityCheck(op string, value js_ast.Expr, afterOpLoc
if op == "case" {
text = "Comparison with -0 using a case clause will also match 0"
}
p.log.AddRangeWarning(&p.source, r, text)
if !p.options.suppressWarningsAboutWeirdCode {
p.log.AddRangeWarning(&p.source, r, text)
} else {
p.log.AddRangeDebug(&p.source, r, text)
}
return true
}

Expand All @@ -9380,7 +9381,12 @@ func (p *parser) warnAboutEqualityCheck(op string, value js_ast.Expr, afterOpLoc
if op == "case" {
text = "This case clause will never be evaluated because equality with NaN is always false"
}
p.log.AddRangeWarning(&p.source, p.source.RangeOfOperatorBefore(afterOpLoc, op), text)
r := p.source.RangeOfOperatorBefore(afterOpLoc, op)
if !p.options.suppressWarningsAboutWeirdCode {
p.log.AddRangeWarning(&p.source, r, text)
} else {
p.log.AddRangeDebug(&p.source, r, text)
}
return true
}

Expand All @@ -9395,7 +9401,12 @@ func (p *parser) warnAboutEqualityCheck(op string, value js_ast.Expr, afterOpLoc
if op == "case" {
text = "This case clause will never be evaluated because the comparison is always false"
}
p.log.AddRangeWarning(&p.source, p.source.RangeOfOperatorBefore(afterOpLoc, op), text)
r := p.source.RangeOfOperatorBefore(afterOpLoc, op)
if !p.options.suppressWarningsAboutWeirdCode {
p.log.AddRangeWarning(&p.source, r, text)
} else {
p.log.AddRangeDebug(&p.source, r, text)
}
return true
}
}
Expand Down Expand Up @@ -10531,16 +10542,25 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
if !kind.IsPrivate() {
r := logger.Range{Loc: e.Index.Loc, Len: int32(len(name))}
p.log.AddRangeError(&p.source, r, fmt.Sprintf("Private name %q must be declared in an enclosing class", name))
} else if !p.options.suppressWarningsAboutWeirdCode {
} else {
var r logger.Range
var text string
if in.assignTarget != js_ast.AssignTargetNone && (kind == js_ast.SymbolPrivateMethod || kind == js_ast.SymbolPrivateStaticMethod) {
r := logger.Range{Loc: e.Index.Loc, Len: int32(len(name))}
p.log.AddRangeWarning(&p.source, r, fmt.Sprintf("Writing to read-only method %q will throw", name))
r = logger.Range{Loc: e.Index.Loc, Len: int32(len(name))}
text = fmt.Sprintf("Writing to read-only method %q will throw", name)
} else if in.assignTarget != js_ast.AssignTargetNone && (kind == js_ast.SymbolPrivateGet || kind == js_ast.SymbolPrivateStaticGet) {
r := logger.Range{Loc: e.Index.Loc, Len: int32(len(name))}
p.log.AddRangeWarning(&p.source, r, fmt.Sprintf("Writing to getter-only property %q will throw", name))
r = logger.Range{Loc: e.Index.Loc, Len: int32(len(name))}
text = fmt.Sprintf("Writing to getter-only property %q will throw", name)
} else if in.assignTarget != js_ast.AssignTargetReplace && (kind == js_ast.SymbolPrivateSet || kind == js_ast.SymbolPrivateStaticSet) {
r := logger.Range{Loc: e.Index.Loc, Len: int32(len(name))}
p.log.AddRangeWarning(&p.source, r, fmt.Sprintf("Reading from setter-only property %q will throw", name))
r = logger.Range{Loc: e.Index.Loc, Len: int32(len(name))}
text = fmt.Sprintf("Reading from setter-only property %q will throw", name)
}
if text != "" {
if !p.options.suppressWarningsAboutWeirdCode {
p.log.AddRangeWarning(&p.source, r, text)
} else {
p.log.AddRangeDebug(&p.source, r, text)
}
}
}

Expand Down Expand Up @@ -10630,9 +10650,14 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
case *js_ast.EIdentifier:
p.markStrictModeFeature(deleteBareName, js_lexer.RangeOfIdentifier(p.source, e.Value.Loc), "")
}
if !p.options.suppressWarningsAboutWeirdCode && superPropLoc.Start != 0 {
if superPropLoc.Start != 0 {
r := js_lexer.RangeOfIdentifier(p.source, superPropLoc)
p.log.AddRangeWarning(&p.source, r, "Attempting to delete a property of \"super\" will throw a ReferenceError")
text := "Attempting to delete a property of \"super\" will throw a ReferenceError"
if !p.options.suppressWarningsAboutWeirdCode {
p.log.AddRangeWarning(&p.source, r, text)
} else {
p.log.AddRangeDebug(&p.source, r, text)
}
}

p.deleteTarget = e.Value.Data
Expand Down Expand Up @@ -11099,6 +11124,11 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
}}
}

// Use a debug log so people can see this if they want to
r := js_lexer.RangeOfIdentifier(p.source, expr.Loc)
p.log.AddRangeDebug(&p.source, r,
"This \"import\" expression will not be bundled because the argument is not a string literal")

// We need to convert this into a call to "require()" if ES6 syntax is
// not supported in the current output format. The full conversion:
//
Expand Down Expand Up @@ -11264,9 +11294,13 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
// and exported symbols due to scope hoisting. Except don't warn when
// this code is in a 3rd-party library because there's nothing people
// will be able to do about the warning.
if p.options.mode == config.ModeBundle && p.hasESModuleSyntax && !p.options.suppressWarningsAboutWeirdCode {
p.log.AddRangeWarning(&p.source, js_lexer.RangeOfIdentifier(p.source, e.Target.Loc),
"Using direct eval with a bundler is not recommended and may cause problems (more info: https://esbuild.github.io/link/direct-eval)")
if p.options.mode == config.ModeBundle {
text := "Using direct eval with a bundler is not recommended and may cause problems (more info: https://esbuild.github.io/link/direct-eval)"
if p.hasESModuleSyntax && !p.options.suppressWarningsAboutWeirdCode {
p.log.AddRangeWarning(&p.source, js_lexer.RangeOfIdentifier(p.source, e.Target.Loc), text)
} else {
p.log.AddRangeDebug(&p.source, js_lexer.RangeOfIdentifier(p.source, e.Target.Loc), text)
}
}
}
}
Expand Down Expand Up @@ -11344,22 +11378,21 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
return js_ast.Expr{Loc: expr.Loc, Data: &js_ast.ERequire{ImportRecordIndex: importRecordIndex}}
}

if !omitWarnings {
r := js_lexer.RangeOfIdentifier(p.source, e.Target.Loc)
p.log.AddRangeWarning(&p.source, r,
"This call to \"require\" will not be bundled because the argument is not a string literal (surround with a try/catch to silence this warning)")
}
// Use a debug log so people can see this if they want to
r := js_lexer.RangeOfIdentifier(p.source, e.Target.Loc)
p.log.AddRangeDebug(&p.source, r,
"This call to \"require\" will not be bundled because the argument is not a string literal")

// Otherwise just return a clone of the "require()" call
return js_ast.Expr{Loc: expr.Loc, Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: e.Target.Loc, Data: &js_ast.EIdentifier{Ref: id.Ref}},
Args: []js_ast.Expr{arg},
}}
}), exprOut{}
} else if !omitWarnings {
} else {
r := js_lexer.RangeOfIdentifier(p.source, e.Target.Loc)
p.log.AddRangeWarning(&p.source, r, fmt.Sprintf(
"This call to \"require\" will not be bundled because it has %d arguments (surround with a try/catch to silence this warning)", len(e.Args)))
text := fmt.Sprintf("This call to \"require\" will not be bundled because it has %d arguments", len(e.Args))
p.log.AddRangeDebug(&p.source, r, text)
}
} else if p.options.outputFormat == config.FormatESModule && !omitWarnings {
r := js_lexer.RangeOfIdentifier(p.source, e.Target.Loc)
Expand Down
Loading

0 comments on commit e2a461f

Please sign in to comment.