Skip to content

Commit c4d45e6

Browse files
committed
fix #1448: add source mappings for certain tokens
1 parent b6648af commit c4d45e6

File tree

7 files changed

+186
-124
lines changed

7 files changed

+186
-124
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
* Add source mapping information for some non-executable tokens ([#1448](https://github.com/evanw/esbuild/issues/1448))
6+
7+
Code coverage tools can generate reports that tell you if any code exists that has not been run (or "covered") during your tests. You can use this information to add additional tests for code that isn't currently covered.
8+
9+
Some popular JavaScript code coverage tools have bugs where they incorrectly consider lines without any executable code as uncovered, even though there's no test you could possibly write that would cause those lines to be executed. For example, they apparently complain about the lines that only contain the trailing `}` token of an object literal.
10+
11+
With this release, esbuild now generates source mappings for some of these trailing non-executable tokens. This may not successfully work around bugs in code coverage tools because there are many non-executable tokens in JavaScript and esbuild doesn't map them all (the drawback of mapping these extra tokens is that esbuild will use more memory, build more slowly, and output a bigger source map). The true solution is to fix the bugs in the code coverage tools in the first place.
12+
313
## 0.14.24
414

515
* Allow `es2022` as a target environment ([#2012](https://github.com/evanw/esbuild/issues/2012))

internal/bundler/linker.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,7 +1959,7 @@ func (c *linkerContext) createExportsForFile(sourceIndex uint32) {
19591959

19601960
// Add a getter property
19611961
var getter js_ast.Expr
1962-
body := js_ast.FnBody{Stmts: []js_ast.Stmt{{Loc: value.Loc, Data: &js_ast.SReturn{ValueOrNil: value}}}}
1962+
body := js_ast.FnBody{Block: js_ast.SBlock{Stmts: []js_ast.Stmt{{Loc: value.Loc, Data: &js_ast.SReturn{ValueOrNil: value}}}}}
19631963
if c.options.UnsupportedJSFeatures.Has(compat.Arrow) {
19641964
getter = js_ast.Expr{Data: &js_ast.EFunction{Fn: js_ast.Fn{Body: body}}}
19651965
} else {
@@ -3879,14 +3879,14 @@ func (c *linkerContext) generateCodeForFileInChunkJS(
38793879
cjsArgs = []js_ast.Expr{{Data: &js_ast.EObject{Properties: []js_ast.Property{{
38803880
IsMethod: !c.options.UnsupportedJSFeatures.Has(compat.ObjectExtensions),
38813881
Key: js_ast.Expr{Data: &js_ast.EString{Value: helpers.StringToUTF16(file.InputFile.Source.PrettyPath)}},
3882-
ValueOrNil: js_ast.Expr{Data: &js_ast.EFunction{Fn: js_ast.Fn{Args: args, Body: js_ast.FnBody{Stmts: stmts}}}},
3882+
ValueOrNil: js_ast.Expr{Data: &js_ast.EFunction{Fn: js_ast.Fn{Args: args, Body: js_ast.FnBody{Block: js_ast.SBlock{Stmts: stmts}}}}},
38833883
}}}}}
38843884
} else if c.options.UnsupportedJSFeatures.Has(compat.Arrow) {
38853885
// "__commonJS(function (exports, module) { ... })"
3886-
cjsArgs = []js_ast.Expr{{Data: &js_ast.EFunction{Fn: js_ast.Fn{Args: args, Body: js_ast.FnBody{Stmts: stmts}}}}}
3886+
cjsArgs = []js_ast.Expr{{Data: &js_ast.EFunction{Fn: js_ast.Fn{Args: args, Body: js_ast.FnBody{Block: js_ast.SBlock{Stmts: stmts}}}}}}
38873887
} else {
38883888
// "__commonJS((exports, module) => { ... })"
3889-
cjsArgs = []js_ast.Expr{{Data: &js_ast.EArrow{Args: args, Body: js_ast.FnBody{Stmts: stmts}}}}
3889+
cjsArgs = []js_ast.Expr{{Data: &js_ast.EArrow{Args: args, Body: js_ast.FnBody{Block: js_ast.SBlock{Stmts: stmts}}}}}
38903890
}
38913891
value := js_ast.Expr{Data: &js_ast.ECall{
38923892
Target: js_ast.Expr{Data: &js_ast.EIdentifier{Ref: c.cjsRuntimeRef}},
@@ -3947,14 +3947,14 @@ func (c *linkerContext) generateCodeForFileInChunkJS(
39473947
esmArgs = []js_ast.Expr{{Data: &js_ast.EObject{Properties: []js_ast.Property{{
39483948
IsMethod: !c.options.UnsupportedJSFeatures.Has(compat.ObjectExtensions),
39493949
Key: js_ast.Expr{Data: &js_ast.EString{Value: helpers.StringToUTF16(file.InputFile.Source.PrettyPath)}},
3950-
ValueOrNil: js_ast.Expr{Data: &js_ast.EFunction{Fn: js_ast.Fn{Body: js_ast.FnBody{Stmts: stmts}, IsAsync: isAsync}}},
3950+
ValueOrNil: js_ast.Expr{Data: &js_ast.EFunction{Fn: js_ast.Fn{Body: js_ast.FnBody{Block: js_ast.SBlock{Stmts: stmts}}, IsAsync: isAsync}}},
39513951
}}}}}
39523952
} else if c.options.UnsupportedJSFeatures.Has(compat.Arrow) {
39533953
// "__esm(function () { ... })"
3954-
esmArgs = []js_ast.Expr{{Data: &js_ast.EFunction{Fn: js_ast.Fn{Body: js_ast.FnBody{Stmts: stmts}, IsAsync: isAsync}}}}
3954+
esmArgs = []js_ast.Expr{{Data: &js_ast.EFunction{Fn: js_ast.Fn{Body: js_ast.FnBody{Block: js_ast.SBlock{Stmts: stmts}}, IsAsync: isAsync}}}}
39553955
} else {
39563956
// "__esm(() => { ... })"
3957-
esmArgs = []js_ast.Expr{{Data: &js_ast.EArrow{Body: js_ast.FnBody{Stmts: stmts}, IsAsync: isAsync}}}
3957+
esmArgs = []js_ast.Expr{{Data: &js_ast.EArrow{Body: js_ast.FnBody{Block: js_ast.SBlock{Stmts: stmts}}, IsAsync: isAsync}}}
39583958
}
39593959
value := js_ast.Expr{Data: &js_ast.ECall{
39603960
Target: js_ast.Expr{Data: &js_ast.EIdentifier{Ref: c.esmRuntimeRef}},

internal/js_ast/js_ast.go

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ const (
266266
)
267267

268268
type ClassStaticBlock struct {
269-
Stmts []Stmt
269+
Block SBlock
270270
Loc logger.Loc
271271
}
272272

@@ -334,17 +334,18 @@ type Fn struct {
334334
}
335335

336336
type FnBody struct {
337-
Stmts []Stmt
337+
Block SBlock
338338
Loc logger.Loc
339339
}
340340

341341
type Class struct {
342-
TSDecorators []Expr
343-
Name *LocRef
344-
ExtendsOrNil Expr
345-
Properties []Property
346-
ClassKeyword logger.Range
347-
BodyLoc logger.Loc
342+
TSDecorators []Expr
343+
Name *LocRef
344+
ExtendsOrNil Expr
345+
Properties []Property
346+
ClassKeyword logger.Range
347+
BodyLoc logger.Loc
348+
CloseBraceLoc logger.Loc
348349
}
349350

350351
type ArrayBinding struct {
@@ -432,6 +433,7 @@ func (*EImportCall) isExpr() {}
432433
type EArray struct {
433434
Items []Expr
434435
CommaAfterSpread logger.Loc
436+
CloseBracketLoc logger.Loc
435437
IsSingleLine bool
436438
IsParenthesized bool
437439
}
@@ -476,8 +478,9 @@ var EUndefinedShared = &EUndefined{}
476478
var EThisShared = &EThis{}
477479

478480
type ENew struct {
479-
Target Expr
480-
Args []Expr
481+
Target Expr
482+
Args []Expr
483+
CloseParenLoc logger.Loc
481484

482485
// True if there is a comment containing "@__PURE__" or "#__PURE__" preceding
483486
// this call expression. See the comment inside ECall for more details.
@@ -501,6 +504,7 @@ const (
501504
type ECall struct {
502505
Target Expr
503506
Args []Expr
507+
CloseParenLoc logger.Loc
504508
OptionalChain OptionalChain
505509
IsDirectEval bool
506510

@@ -653,6 +657,7 @@ type EBigInt struct{ Value string }
653657
type EObject struct {
654658
Properties []Property
655659
CommaAfterSpread logger.Loc
660+
CloseBraceLoc logger.Loc
656661
IsSingleLine bool
657662
IsParenthesized bool
658663
}
@@ -1079,7 +1084,8 @@ func (*SBreak) isStmt() {}
10791084
func (*SContinue) isStmt() {}
10801085

10811086
type SBlock struct {
1082-
Stmts []Stmt
1087+
Stmts []Stmt
1088+
CloseBraceLoc logger.Loc
10831089
}
10841090

10851091
type SEmpty struct{}
@@ -1231,21 +1237,21 @@ type SWith struct {
12311237

12321238
type Catch struct {
12331239
BindingOrNil Binding
1234-
Body []Stmt
1240+
Block SBlock
12351241
Loc logger.Loc
1236-
BodyLoc logger.Loc
1242+
BlockLoc logger.Loc
12371243
}
12381244

12391245
type Finally struct {
1240-
Stmts []Stmt
1246+
Block SBlock
12411247
Loc logger.Loc
12421248
}
12431249

12441250
type STry struct {
1245-
Catch *Catch
1246-
Finally *Finally
1247-
Body []Stmt
1248-
BodyLoc logger.Loc
1251+
Catch *Catch
1252+
Finally *Finally
1253+
Block SBlock
1254+
BlockLoc logger.Loc
12491255
}
12501256

12511257
type Case struct {
@@ -2829,7 +2835,7 @@ func SimplifyUnusedExpr(expr Expr, isUnbound func(Ref) bool) Expr {
28292835
}
28302836

28312837
// Just delete "(function() {})()" completely
2832-
if len(target.Fn.Body.Stmts) == 0 {
2838+
if len(target.Fn.Body.Block.Stmts) == 0 {
28332839
return Expr{}
28342840
}
28352841

@@ -2839,19 +2845,19 @@ func SimplifyUnusedExpr(expr Expr, isUnbound func(Ref) bool) Expr {
28392845
}
28402846

28412847
// Just delete "(() => {})()" completely
2842-
if len(target.Body.Stmts) == 0 {
2848+
if len(target.Body.Block.Stmts) == 0 {
28432849
return Expr{}
28442850
}
28452851

2846-
if len(target.Body.Stmts) == 1 {
2847-
switch s := target.Body.Stmts[0].Data.(type) {
2852+
if len(target.Body.Block.Stmts) == 1 {
2853+
switch s := target.Body.Block.Stmts[0].Data.(type) {
28482854
case *SExpr:
28492855
if !target.IsAsync {
28502856
// Replace "(() => { foo() })()" with "foo()"
28512857
return s.Value
28522858
} else {
28532859
// Replace "(async () => { foo() })()" with "(async () => foo())()"
2854-
target.Body.Stmts[0].Data = &SReturn{ValueOrNil: s.Value}
2860+
target.Body.Block.Stmts[0].Data = &SReturn{ValueOrNil: s.Value}
28552861
target.PreferExpr = true
28562862
}
28572863

0 commit comments

Comments
 (0)