Skip to content

Commit d500061

Browse files
committed
fix #2322: a log message for ambiguous re-exports
1 parent 4f73331 commit d500061

File tree

5 files changed

+92
-2
lines changed

5 files changed

+92
-2
lines changed

CHANGELOG.md

+22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
* Add a log message for ambiguous re-exports ([#2322](https://github.com/evanw/esbuild/issues/2322))
6+
7+
In JavaScript, you can re-export symbols from another file using `export * from './another-file'`. When you do this from multiple files that export different symbols with the same name, this creates an ambiguous export which is causes that name to not be exported. This is harmless if you don't plan on using the ambiguous export name, so esbuild doesn't have a warning for this. But if you do want a warning for this (or if you want to make it an error), you can now opt-in to seeing this log message with `--log-override:ambiguous-import=warning` or `--log-override:ambiguous-import=error`. The log message looks like this:
8+
9+
```
10+
▲ [WARNING] Re-export of "common" in "example.js" is ambiguous and has been removed [ambiguous-import]
11+
12+
One definition of "common" comes from "a.js" here:
13+
14+
a.js:2:11:
15+
2 │ export let common = 2
16+
╵ ~~~~~~
17+
18+
Another definition of "common" comes from "b.js" here:
19+
20+
b.js:3:14:
21+
3 │ export { b as common }
22+
╵ ~~~~~~
23+
```
24+
325
## 0.14.44
426

527
* Add a `copy` loader ([#2255](https://github.com/evanw/esbuild/issues/2255))

internal/bundler/bundler_default_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -6397,3 +6397,28 @@ ident.js: DEBUG: Indirect calls to "require" will not be bundled
63976397
`,
63986398
})
63996399
}
6400+
6401+
func TestAmbiguousReexportMsg(t *testing.T) {
6402+
loader_suite.expectBundled(t, bundled{
6403+
files: map[string]string{
6404+
"/entry.js": `
6405+
export * from './a'
6406+
export * from './b'
6407+
export * from './c'
6408+
`,
6409+
"/a.js": `export let a = 1, x = 2`,
6410+
"/b.js": `export let b = 3; export { b as x }`,
6411+
"/c.js": `export let c = 4, x = 5`,
6412+
},
6413+
entryPaths: []string{"/entry.js"},
6414+
options: config.Options{
6415+
Mode: config.ModeBundle,
6416+
AbsOutputDir: "/out",
6417+
},
6418+
debugLogs: true,
6419+
expectedCompileLog: `DEBUG: Re-export of "x" in "entry.js" is ambiguous and has been removed
6420+
a.js: NOTE: One definition of "x" comes from "a.js" here:
6421+
b.js: NOTE: Another definition of "x" comes from "b.js" here:
6422+
`,
6423+
})
6424+
}

internal/bundler/linker.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -1443,21 +1443,42 @@ func (c *linkerContext) scanImportsAndExports() {
14431443
aliases := make([]string, 0, len(repr.Meta.ResolvedExports))
14441444
nextAlias:
14451445
for alias, export := range repr.Meta.ResolvedExports {
1446+
otherFile := &c.graph.Files[export.SourceIndex].InputFile
1447+
otherRepr := otherFile.Repr.(*graph.JSRepr)
1448+
14461449
// Re-exporting multiple symbols with the same name causes an ambiguous
14471450
// export. These names cannot be used and should not end up in generated code.
1448-
otherRepr := c.graph.Files[export.SourceIndex].InputFile.Repr.(*graph.JSRepr)
14491451
if len(export.PotentiallyAmbiguousExportStarRefs) > 0 {
14501452
mainRef := export.Ref
1453+
mainLoc := export.NameLoc
14511454
if imported, ok := otherRepr.Meta.ImportsToBind[export.Ref]; ok {
14521455
mainRef = imported.Ref
1456+
mainLoc = imported.NameLoc
14531457
}
1458+
14541459
for _, ambiguousExport := range export.PotentiallyAmbiguousExportStarRefs {
1455-
ambiguousRepr := c.graph.Files[ambiguousExport.SourceIndex].InputFile.Repr.(*graph.JSRepr)
1460+
ambiguousFile := &c.graph.Files[ambiguousExport.SourceIndex].InputFile
1461+
ambiguousRepr := ambiguousFile.Repr.(*graph.JSRepr)
14561462
ambiguousRef := ambiguousExport.Ref
1463+
ambiguousLoc := ambiguousExport.NameLoc
14571464
if imported, ok := ambiguousRepr.Meta.ImportsToBind[ambiguousExport.Ref]; ok {
14581465
ambiguousRef = imported.Ref
1466+
ambiguousLoc = imported.NameLoc
14591467
}
1468+
14601469
if mainRef != ambiguousRef {
1470+
file := &c.graph.Files[sourceIndex].InputFile
1471+
otherTracker := logger.MakeLineColumnTracker(&otherFile.Source)
1472+
ambiguousTracker := logger.MakeLineColumnTracker(&ambiguousFile.Source)
1473+
c.log.AddIDWithNotes(logger.MsgID_Bundler_AmbiguousReexport, logger.Debug, nil, logger.Range{},
1474+
fmt.Sprintf("Re-export of %q in %q is ambiguous and has been removed", alias, file.Source.PrettyPath),
1475+
[]logger.MsgData{
1476+
otherTracker.MsgData(js_lexer.RangeOfIdentifier(otherFile.Source, mainLoc),
1477+
fmt.Sprintf("One definition of %q comes from %q here:", alias, otherFile.Source.PrettyPath)),
1478+
ambiguousTracker.MsgData(js_lexer.RangeOfIdentifier(ambiguousFile.Source, ambiguousLoc),
1479+
fmt.Sprintf("Another definition of %q comes from %q here:", alias, ambiguousFile.Source.PrettyPath)),
1480+
},
1481+
)
14611482
continue nextAlias
14621483
}
14631484
}

internal/bundler/snapshots/snapshots_loader.txt

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
TestAmbiguousReexportMsg
2+
---------- /out/entry.js ----------
3+
// a.js
4+
var a = 1;
5+
6+
// b.js
7+
var b = 3;
8+
9+
// c.js
10+
var c = 4;
11+
export {
12+
a,
13+
b,
14+
c
15+
};
16+
17+
================================================================================
118
TestAutoDetectMimeTypeFromExtension
219
---------- /out.js ----------
320
// test.svg

internal/logger/msg_ids.go

+5
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const (
4949
MsgID_CSS_UnsupportedCSSProperty
5050

5151
// Bundler
52+
MsgID_Bundler_AmbiguousReexport
5253
MsgID_Bundler_DifferentPathCase
5354
MsgID_Bundler_IgnoredBareImport
5455
MsgID_Bundler_IgnoredDynamicImport
@@ -156,6 +157,8 @@ func StringToMsgIDs(str string, logLevel LogLevel, overrides map[MsgID]LogLevel)
156157
overrides[MsgID_CSS_UnsupportedCSSProperty] = logLevel
157158

158159
// Bundler
160+
case "ambiguous-reexport":
161+
overrides[MsgID_Bundler_AmbiguousReexport] = logLevel
159162
case "different-path-case":
160163
overrides[MsgID_Bundler_DifferentPathCase] = logLevel
161164
case "ignored-bare-import":
@@ -266,6 +269,8 @@ func MsgIDToString(id MsgID) string {
266269
return "unsupported-css-property"
267270

268271
// Bundler
272+
case MsgID_Bundler_AmbiguousReexport:
273+
return "ambiguous-reexport"
269274
case MsgID_Bundler_DifferentPathCase:
270275
return "different-path-case"
271276
case MsgID_Bundler_IgnoredBareImport:

0 commit comments

Comments
 (0)