Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions cmd/esbuild/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ import (
"github.com/evanw/esbuild/pkg/cli"
)

type responseCallback func(interface{})
type rebuildCallback func(uint32) []byte
type watchStopCallback func()
type serveStopCallback func()
type pluginResolveCallback func(uint32, map[string]interface{}) []byte
type (
responseCallback func(interface{})
rebuildCallback func(uint32) []byte
watchStopCallback func()
serveStopCallback func()
pluginResolveCallback func(uint32, map[string]interface{}) []byte
)

type activeBuild struct {
rebuild rebuildCallback
Expand Down
9 changes: 4 additions & 5 deletions internal/bundler/bundler_default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5642,11 +5642,10 @@ func TestToESMWrapperOmission(t *testing.T) {

// This is coverage for a past bug in esbuild. We used to generate this, which is wrong:
//
// let x = function(foo) {
// var foo2;
// return foo2;
// };
//
// let x = function(foo) {
// var foo2;
// return foo2;
// };
func TestNamedFunctionExpressionArgumentCollision(t *testing.T) {
loader_suite.expectBundled(t, bundled{
files: map[string]string{
Expand Down
14 changes: 9 additions & 5 deletions internal/bundler/bundler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,16 @@ func (s *suite) expectBundled(t *testing.T, args bundled) {
})
}

const snapshotsDir = "snapshots"
const snapshotSplitter = "\n================================================================================\n"
const (
snapshotsDir = "snapshots"
snapshotSplitter = "\n================================================================================\n"
)

var globalTestMutex sync.Mutex
var globalSuites map[*suite]bool
var globalUpdateSnapshots bool
var (
globalTestMutex sync.Mutex
globalSuites map[*suite]bool
globalUpdateSnapshots bool
)

func (s *suite) compareSnapshot(t *testing.T, testName string, generated string) {
t.Helper()
Expand Down
7 changes: 3 additions & 4 deletions internal/bundler/bundler_ts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1934,10 +1934,9 @@ func TestTSEnumExportClause(t *testing.T) {
// This checks that we don't generate a warning for code that the TypeScript
// compiler generates that looks like this:
//
// var __rest = (this && this.__rest) || function (s, e) {
// ...
// };
//
// var __rest = (this && this.__rest) || function (s, e) {
// ...
// };
func TestTSThisIsUndefinedWarning(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
Expand Down
58 changes: 35 additions & 23 deletions internal/bundler/linker.go
Original file line number Diff line number Diff line change
Expand Up @@ -991,8 +991,7 @@ func (c *linkerContext) computeCrossChunkDependencies(chunks []chunkInfo) {
// Ignore uses that aren't top-level symbols
if otherChunkIndex := c.graph.Symbols.Get(importRef).ChunkIndex; otherChunkIndex.IsValid() {
if otherChunkIndex := otherChunkIndex.GetIndex(); otherChunkIndex != uint32(chunkIndex) {
chunkRepr.importsFromOtherChunks[otherChunkIndex] =
append(chunkRepr.importsFromOtherChunks[otherChunkIndex], crossChunkImportItem{ref: importRef})
chunkRepr.importsFromOtherChunks[otherChunkIndex] = append(chunkRepr.importsFromOtherChunks[otherChunkIndex], crossChunkImportItem{ref: importRef})
chunkMetas[otherChunkIndex].exports[importRef] = true
}
}
Expand Down Expand Up @@ -2644,12 +2643,11 @@ func (c *linkerContext) addExportsForExportStar(
}
} else if existing.SourceIndex != otherSourceIndex {
// Two different re-exports colliding makes it potentially ambiguous
existing.PotentiallyAmbiguousExportStarRefs =
append(existing.PotentiallyAmbiguousExportStarRefs, graph.ImportData{
SourceIndex: otherSourceIndex,
Ref: name.Ref,
NameLoc: name.AliasLoc,
})
existing.PotentiallyAmbiguousExportStarRefs = append(existing.PotentiallyAmbiguousExportStarRefs, graph.ImportData{
SourceIndex: otherSourceIndex,
Ref: name.Ref,
NameLoc: name.AliasLoc,
})
resolvedExports[alias] = existing
}
}
Expand Down Expand Up @@ -2968,11 +2966,11 @@ func sanitizeFilePathForVirtualModulePath(path string) string {
// order that JavaScript modules were evaluated in before the top-level await
// feature was introduced.
//
// A
// / \
// B C
// \ /
// D
// A
// / \
// B C
// \ /
// D
//
// If A imports B and then C, B imports D, and C imports D, then the JavaScript
// traversal order is D B C A.
Expand Down Expand Up @@ -3036,11 +3034,11 @@ func (c *linkerContext) findImportedCSSFilesInJSOrder(entryPoint uint32) (order
// CSS file multiple times is equivalent to evaluating it once at the last
// location. So we drop all but the last evaluation in the order.
//
// A
// / \
// B C
// \ /
// D
// A
// / \
// B C
// \ /
// D
//
// If A imports B and then C, B imports D, and C imports D, then the CSS
// traversal order is B D C A.
Expand Down Expand Up @@ -3657,9 +3655,12 @@ func (c *linkerContext) convertStmtsForChunk(sourceIndex uint32, stmtList *stmtL
} else {
if record.SourceIndex.IsValid() {
if otherRepr := c.graph.Files[record.SourceIndex.GetIndex()].InputFile.Repr.(*graph.JSRepr); otherRepr.Meta.Wrap == graph.WrapESM {
stmtList.insideWrapperPrefix = append(stmtList.insideWrapperPrefix, js_ast.Stmt{Loc: stmt.Loc,
stmtList.insideWrapperPrefix = append(stmtList.insideWrapperPrefix, js_ast.Stmt{
Loc: stmt.Loc,
Data: &js_ast.SExpr{Value: js_ast.Expr{Loc: stmt.Loc, Data: &js_ast.ECall{
Target: js_ast.Expr{Loc: stmt.Loc, Data: &js_ast.EIdentifier{Ref: otherRepr.AST.WrapperRef}}}}}})
Target: js_ast.Expr{Loc: stmt.Loc, Data: &js_ast.EIdentifier{Ref: otherRepr.AST.WrapperRef}},
}}},
})
}
}

Expand Down Expand Up @@ -4349,7 +4350,11 @@ func (c *linkerContext) generateEntryPointTailJS(
Data: &js_ast.SExportDefault{Value: js_ast.Stmt{
Data: &js_ast.SExpr{Value: js_ast.Expr{
Data: &js_ast.ECall{Target: js_ast.Expr{
Data: &js_ast.EIdentifier{Ref: repr.AST.WrapperRef}}}}}}}})
Data: &js_ast.EIdentifier{Ref: repr.AST.WrapperRef},
}},
}},
}},
})
} else {
if repr.Meta.Wrap == graph.WrapESM {
if repr.Meta.IsAsyncOrHasAsyncDependency {
Expand All @@ -4358,13 +4363,20 @@ func (c *linkerContext) generateEntryPointTailJS(
Data: &js_ast.SExpr{Value: js_ast.Expr{
Data: &js_ast.EAwait{Value: js_ast.Expr{
Data: &js_ast.ECall{Target: js_ast.Expr{
Data: &js_ast.EIdentifier{Ref: repr.AST.WrapperRef}}}}}}}})
Data: &js_ast.EIdentifier{Ref: repr.AST.WrapperRef},
}},
}},
}},
})
} else {
// "init_foo();"
stmts = append(stmts, js_ast.Stmt{
Data: &js_ast.SExpr{
Value: js_ast.Expr{Data: &js_ast.ECall{Target: js_ast.Expr{
Data: &js_ast.EIdentifier{Ref: repr.AST.WrapperRef}}}}}})
Data: &js_ast.EIdentifier{Ref: repr.AST.WrapperRef},
}}},
},
})
}
}

Expand Down
35 changes: 17 additions & 18 deletions internal/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,25 @@ import (
// able to reuse the results of parsing between builds and make subsequent
// builds faster by avoiding redundant parsing work. This only works if:
//
// * The AST information in the cache must be considered immutable. There is
// no way to enforce this in Go, but please be disciplined about this. The
// ASTs are shared in between builds. Any information that must be mutated
// in the AST during a build must be done on a shallow clone of the data if
// the mutation happens after parsing (i.e. a clone that clones everything
// that will be mutated and shares only the parts that won't be mutated).
// - The AST information in the cache must be considered immutable. There is
// no way to enforce this in Go, but please be disciplined about this. The
// ASTs are shared in between builds. Any information that must be mutated
// in the AST during a build must be done on a shallow clone of the data if
// the mutation happens after parsing (i.e. a clone that clones everything
// that will be mutated and shares only the parts that won't be mutated).
//
// * The information in the cache must not depend at all on the contents of
// any file other than the file being cached. Invalidating an entry in the
// cache does not also invalidate any entries that depend on that file, so
// caching information that depends on other files can result in incorrect
// results due to reusing stale data. For example, do not "bake in" some
// value imported from another file.
//
// * Cached ASTs must only be reused if the parsing options are identical
// between builds. For example, it would be bad if the AST parser depended
// on options inherited from a nearby "package.json" file but those options
// were not part of the cache key. Then the cached AST could incorrectly be
// reused even if the contents of that "package.json" file have changed.
// - The information in the cache must not depend at all on the contents of
// any file other than the file being cached. Invalidating an entry in the
// cache does not also invalidate any entries that depend on that file, so
// caching information that depends on other files can result in incorrect
// results due to reusing stale data. For example, do not "bake in" some
// value imported from another file.
//
// - Cached ASTs must only be reused if the parsing options are identical
// between builds. For example, it would be bad if the AST parser depended
// on options inherited from a nearby "package.json" file but those options
// were not part of the cache key. Then the cached AST could incorrectly be
// reused even if the contents of that "package.json" file have changed.
type CacheSet struct {
FSCache FSCache
CSSCache CSSCache
Expand Down
39 changes: 20 additions & 19 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,32 +309,31 @@ type UnusedImportFlagsTS uint8

// With !UnusedImportKeepStmt && !UnusedImportKeepValues:
//
// "import 'foo'" => "import 'foo'"
// "import * as unused from 'foo'" => ""
// "import { unused } from 'foo'" => ""
// "import { type unused } from 'foo'" => ""
// "import 'foo'" => "import 'foo'"
// "import * as unused from 'foo'" => ""
// "import { unused } from 'foo'" => ""
// "import { type unused } from 'foo'" => ""
//
// With UnusedImportKeepStmt && !UnusedImportKeepValues:
//
// "import 'foo'" => "import 'foo'"
// "import * as unused from 'foo'" => "import 'foo'"
// "import { unused } from 'foo'" => "import 'foo'"
// "import { type unused } from 'foo'" => "import 'foo'"
// "import 'foo'" => "import 'foo'"
// "import * as unused from 'foo'" => "import 'foo'"
// "import { unused } from 'foo'" => "import 'foo'"
// "import { type unused } from 'foo'" => "import 'foo'"
//
// With !UnusedImportKeepStmt && UnusedImportKeepValues:
//
// "import 'foo'" => "import 'foo'"
// "import * as unused from 'foo'" => "import * as unused from 'foo'"
// "import { unused } from 'foo'" => "import { unused } from 'foo'"
// "import { type unused } from 'foo'" => ""
// "import 'foo'" => "import 'foo'"
// "import * as unused from 'foo'" => "import * as unused from 'foo'"
// "import { unused } from 'foo'" => "import { unused } from 'foo'"
// "import { type unused } from 'foo'" => ""
//
// With UnusedImportKeepStmt && UnusedImportKeepValues:
//
// "import 'foo'" => "import 'foo'"
// "import * as unused from 'foo'" => "import * as unused from 'foo'"
// "import { unused } from 'foo'" => "import { unused } from 'foo'"
// "import { type unused } from 'foo'" => "import {} from 'foo'"
//
// "import 'foo'" => "import 'foo'"
// "import * as unused from 'foo'" => "import * as unused from 'foo'"
// "import { unused } from 'foo'" => "import { unused } from 'foo'"
// "import { type unused } from 'foo'" => "import {} from 'foo'"
const (
UnusedImportKeepStmt UnusedImportFlagsTS = 1 << iota // "importsNotUsedAsValues" != "remove"
UnusedImportKeepValues // "preserveValueImports" == true
Expand Down Expand Up @@ -502,8 +501,10 @@ type InjectableExport struct {
Loc logger.Loc
}

var filterMutex sync.Mutex
var filterCache map[string]*regexp.Regexp
var (
filterMutex sync.Mutex
filterCache map[string]*regexp.Regexp
)

func compileFilter(filter string) (result *regexp.Regexp) {
if filter == "" {
Expand Down
6 changes: 4 additions & 2 deletions internal/config/globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import (
"github.com/evanw/esbuild/internal/js_ast"
)

var processedGlobalsMutex sync.Mutex
var processedGlobals *ProcessedDefines
var (
processedGlobalsMutex sync.Mutex
processedGlobals *ProcessedDefines
)

// If something is in this list, then a direct identifier expression or property
// access chain matching this will be assumed to have no side effects and will
Expand Down
6 changes: 4 additions & 2 deletions internal/css_ast/css_decl_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -648,8 +648,10 @@ var KnownDeclarations = map[string]D{
"zoom": DZoom,
}

var typoDetector *helpers.TypoDetector
var typoDetectorMutex sync.Mutex
var (
typoDetector *helpers.TypoDetector
typoDetectorMutex sync.Mutex
)

func MaybeCorrectDeclarationTypo(text string) (string, bool) {
// Ignore CSS variables, which should not be corrected to CSS properties
Expand Down
15 changes: 7 additions & 8 deletions internal/css_parser/css_decls_box.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,14 @@ const (
// We want to avoid a situation where the browser treats some of the original
// rules as valid and others as invalid.
//
// Safe:
// top: 1px; left: 0; bottom: 1px; right: 0;
// top: 1Q; left: 2Q; bottom: 3Q; right: 4Q;
//
// Unsafe:
// top: 1vh; left: 2vw; bottom: 3vh; right: 4vw;
// top: 1Q; left: 2Q; bottom: 3Q; right: 0;
// inset: 1Q 0 0 0; top: 0;
// Safe:
// top: 1px; left: 0; bottom: 1px; right: 0;
// top: 1Q; left: 2Q; bottom: 3Q; right: 4Q;
//
// Unsafe:
// top: 1vh; left: 2vw; bottom: 3vh; right: 4vw;
// top: 1Q; left: 2Q; bottom: 3Q; right: 0;
// inset: 1Q 0 0 0; top: 0;
type unitSafetyTracker struct {
unit string
status unitSafetyStatus
Expand Down
27 changes: 18 additions & 9 deletions internal/css_parser/css_decls_color.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,12 @@ func (p *parser) lowerColor(token css_ast.Token) css_ast.Token {
token.Text = "rgba"
commaToken := p.commaToken()
token.Children = &[]css_ast.Token{
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexR(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexG(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexB(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexR(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexG(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexB(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: floatToStringForColor(float64(hexA(hex)) / 255)},
}
}
Expand All @@ -305,9 +308,12 @@ func (p *parser) lowerColor(token css_ast.Token) css_ast.Token {
token.Text = "rgba"
commaToken := p.commaToken()
token.Children = &[]css_ast.Token{
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexR(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexG(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexB(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexR(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexG(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexB(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: floatToStringForColor(float64(hexA(hex)) / 255)},
}
}
Expand Down Expand Up @@ -639,9 +645,12 @@ func (p *parser) mangleColor(token css_ast.Token, hex uint32) css_ast.Token {
alpha = alpha[:space]
}
token.Children = &[]css_ast.Token{
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexR(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexG(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexB(hex))}, commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexR(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexG(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: strconv.Itoa(hexB(hex))},
commaToken,
{Kind: css_lexer.TNumber, Text: alpha},
}
}
Expand Down
Loading