Skip to content

Commit 78eefe1

Browse files
committed
css: add source map entries for generated js names
1 parent 8abb666 commit 78eefe1

File tree

10 files changed

+116
-23
lines changed

10 files changed

+116
-23
lines changed

internal/bundler/bundler.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,21 +2062,19 @@ func (s *scanner) processScannedFiles(entryPointMeta []graph.EntryPoint) []scann
20622062
stubKey.Text = canonicalFileSystemPathForWindows(stubKey.Text)
20632063
}
20642064
sourceIndex := s.allocateSourceIndex(stubKey, cache.SourceIndexJSStubForCSS)
2065-
source := logger.Source{
2066-
Index: sourceIndex,
2067-
PrettyPath: otherFile.inputFile.Source.PrettyPath,
2068-
IdentifierName: otherFile.inputFile.Source.IdentifierName,
2069-
}
2065+
source := otherFile.inputFile.Source
2066+
source.Index = sourceIndex
20702067

20712068
// Export all local CSS names for JavaScript to use
20722069
exports := js_ast.EObject{}
20732070
cssSourceIndex := record.SourceIndex.GetIndex()
20742071
for innerIndex, symbol := range css.AST.Symbols {
20752072
if symbol.Kind == ast.SymbolLocalCSS {
20762073
ref := ast.Ref{SourceIndex: cssSourceIndex, InnerIndex: uint32(innerIndex)}
2074+
loc := css.AST.DefineLocs[ref]
20772075
exports.Properties = append(exports.Properties, js_ast.Property{
2078-
Key: js_ast.Expr{Data: &js_ast.EString{Value: helpers.StringToUTF16(symbol.OriginalName)}},
2079-
ValueOrNil: js_ast.Expr{Data: &js_ast.ENameOfSymbol{Ref: ref}},
2076+
Key: js_ast.Expr{Loc: loc, Data: &js_ast.EString{Value: helpers.StringToUTF16(symbol.OriginalName)}},
2077+
ValueOrNil: js_ast.Expr{Loc: loc, Data: &js_ast.ENameOfSymbol{Ref: ref}},
20802078
})
20812079
}
20822080
}
@@ -2085,6 +2083,7 @@ func (s *scanner) processScannedFiles(entryPointMeta []graph.EntryPoint) []scann
20852083
file: scannerFile{
20862084
inputFile: graph.InputFile{
20872085
Source: source,
2086+
Loader: otherFile.inputFile.Loader,
20882087
Repr: &graph.JSRepr{
20892088
AST: js_parser.LazyExportAST(s.log, source,
20902089
js_parser.OptionsFromConfig(&s.options), js_ast.Expr{Data: &exports}, ""),

internal/bundler_tests/snapshots/snapshots_css.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,13 +1110,13 @@ console.log("file 1", t, l.a);
11101110

11111111
// dir2/style.css
11121112
var e = "n";
1113-
var f = {
1113+
var n = {
11141114
b: "e",
11151115
button: e
11161116
};
11171117

11181118
// b.js
1119-
console.log("file 2", e, f.b);
1119+
console.log("file 2", e, n.b);
11201120

11211121
---------- /out/entry.css ----------
11221122
/* dir1/style.css */
@@ -1154,7 +1154,7 @@ TestImportLocalCSSFromJSMinifyIdentifiersAvoidGlobalNames
11541154

11551155
================================================================================
11561156
TestMetafileCSSBundleTwoToOne
1157-
---------- /out/js/UOATE6K4.js ----------
1157+
---------- /out/js/2PSDKYWE.js ----------
11581158
// foo/entry.js
11591159
console.log("foo");
11601160

@@ -1164,7 +1164,7 @@ body {
11641164
color: red;
11651165
}
11661166

1167-
---------- /out/js/6ZCNL5VY.js ----------
1167+
---------- /out/js/MA6C7ZBK.js ----------
11681168
// bar/entry.js
11691169
console.log("bar");
11701170
---------- metafile.json ----------
@@ -1198,7 +1198,7 @@ console.log("bar");
11981198
}
11991199
},
12001200
"outputs": {
1201-
"out/js/UOATE6K4.js": {
1201+
"out/js/2PSDKYWE.js": {
12021202
"imports": [],
12031203
"exports": [],
12041204
"entryPoint": "foo/entry.js",
@@ -1222,7 +1222,7 @@ console.log("bar");
12221222
},
12231223
"bytes": 40
12241224
},
1225-
"out/js/6ZCNL5VY.js": {
1225+
"out/js/MA6C7ZBK.js": {
12261226
"imports": [],
12271227
"exports": [],
12281228
"entryPoint": "bar/entry.js",

internal/bundler_tests/snapshots/snapshots_default.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,13 +1170,13 @@ console.log((init_types(), __toCommonJS(types_exports)));
11701170

11711171
================================================================================
11721172
TestEntryNamesChunkNamesExtPlaceholder
1173-
---------- /out/main/js/entry1-L7KI5G7A.js ----------
1173+
---------- /out/main/js/entry1-4X3SO762.js ----------
11741174
import "../../common/js/chunk-XHGYOYUR.js";
11751175

11761176
// src/entries/entry1.js
11771177
console.log("entry1");
11781178

1179-
---------- /out/main/js/entry2-KTHKWVT2.js ----------
1179+
---------- /out/main/js/entry2-URQRHZS5.js ----------
11801180
import "../../common/js/chunk-XHGYOYUR.js";
11811181

11821182
// src/entries/entry2.js

internal/config/config.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,17 @@ func (loader Loader) IsTypeScript() bool {
229229
switch loader {
230230
case LoaderTS, LoaderTSNoAmbiguousLessThan, LoaderTSX:
231231
return true
232-
default:
233-
return false
234232
}
233+
return false
234+
}
235+
236+
func (loader Loader) IsCSS() bool {
237+
switch loader {
238+
case
239+
LoaderCSS, LoaderGlobalCSS, LoaderLocalCSS:
240+
return true
241+
}
242+
return false
235243
}
236244

237245
func (loader Loader) CanHaveSourceMap() bool {
@@ -242,9 +250,8 @@ func (loader Loader) CanHaveSourceMap() bool {
242250
LoaderCSS, LoaderGlobalCSS, LoaderLocalCSS,
243251
LoaderJSON, LoaderText:
244252
return true
245-
default:
246-
return false
247253
}
254+
return false
248255
}
249256

250257
type Format uint8

internal/css_ast/css_ast.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type AST struct {
3030
Rules []Rule
3131
SourceMapComment logger.Span
3232
ApproximateLineCount int32
33+
DefineLocs map[ast.Ref]logger.Loc
3334
}
3435

3536
// We create a lot of tokens, so make sure this layout is memory-efficient.

internal/css_lexer/css_lexer.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,54 @@ func WouldStartIdentifierWithoutEscapes(text string) bool {
598598
return false
599599
}
600600

601+
func RangeOfIdentifier(source logger.Source, loc logger.Loc) logger.Range {
602+
text := source.Contents[loc.Start:]
603+
if len(text) == 0 {
604+
return logger.Range{Loc: loc, Len: 0}
605+
}
606+
607+
i := 0
608+
n := len(text)
609+
610+
for {
611+
c, width := utf8.DecodeRuneInString(text[i:])
612+
if IsNameContinue(c) {
613+
i += width
614+
continue
615+
}
616+
617+
// Handle an escape
618+
if c == '\\' && i+1 < n && !isNewline(rune(text[i+1])) {
619+
i += width // Skip the backslash
620+
c, width = utf8.DecodeRuneInString(text[i:])
621+
if _, ok := isHex(c); ok {
622+
i += width
623+
c, width = utf8.DecodeRuneInString(text[i:])
624+
for j := 0; j < 5; j++ {
625+
if _, ok := isHex(c); !ok {
626+
break
627+
}
628+
i += width
629+
c, width = utf8.DecodeRuneInString(text[i:])
630+
}
631+
if isWhitespace(c) {
632+
i += width
633+
}
634+
}
635+
continue
636+
}
637+
638+
break
639+
}
640+
641+
// Don't end with a whitespace
642+
if i > 0 && isWhitespace(rune(text[i-1])) {
643+
i--
644+
}
645+
646+
return logger.Range{Loc: loc, Len: int32(i)}
647+
}
648+
601649
func (lexer *lexer) wouldStartNumber() bool {
602650
if lexer.codePoint >= '0' && lexer.codePoint <= '9' {
603651
return true

internal/css_parser/css_parser.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type parser struct {
2424
stack []css_lexer.T
2525
importRecords []ast.ImportRecord
2626
symbols []ast.Symbol
27+
defineLocs map[ast.Ref]logger.Loc
2728
localSymbolMap map[string]ast.Ref
2829
globalSymbolMap map[string]ast.Ref
2930
nestingWarnings map[logger.Loc]struct{}
@@ -125,6 +126,7 @@ func Parse(log logger.Log, source logger.Source, options Options) css_ast.AST {
125126
allComments: result.AllComments,
126127
legalComments: result.LegalComments,
127128
prevError: logger.Loc{Start: -1},
129+
defineLocs: make(map[ast.Ref]logger.Loc),
128130
localSymbolMap: make(map[string]ast.Ref),
129131
globalSymbolMap: make(map[string]ast.Ref),
130132
makeLocalSymbols: options.symbolMode == symbolModeLocal,
@@ -142,6 +144,7 @@ func Parse(log logger.Log, source logger.Source, options Options) css_ast.AST {
142144
ImportRecords: p.importRecords,
143145
ApproximateLineCount: result.ApproximateLineCount,
144146
SourceMapComment: result.SourceMapComment,
147+
DefineLocs: p.defineLocs,
145148
}
146149
}
147150

@@ -301,7 +304,7 @@ func (p *parser) unexpected() {
301304
}
302305
}
303306

304-
func (p *parser) symbolForName(name string) ast.Ref {
307+
func (p *parser) symbolForName(loc logger.Loc, name string) ast.Ref {
305308
var kind ast.SymbolKind
306309
var scope map[string]ast.Ref
307310

@@ -325,6 +328,7 @@ func (p *parser) symbolForName(name string) ast.Ref {
325328
Link: ast.InvalidRef,
326329
})
327330
scope[name] = ref
331+
p.defineLocs[ref] = loc
328332
}
329333

330334
p.symbols[ref.InnerIndex].UseCountEstimate++

internal/css_parser/css_parser_selector.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ subclassSelectors:
366366
sel.SubclassSelectors = append(sel.SubclassSelectors, css_ast.SubclassSelector{
367367
Loc: subclassToken.Range.Loc,
368368
Data: &css_ast.SSHash{
369-
Name: ast.LocRef{Loc: nameLoc, Ref: p.symbolForName(name)},
369+
Name: ast.LocRef{Loc: nameLoc, Ref: p.symbolForName(nameLoc, name)},
370370
},
371371
})
372372
p.advance()
@@ -378,7 +378,7 @@ subclassSelectors:
378378
sel.SubclassSelectors = append(sel.SubclassSelectors, css_ast.SubclassSelector{
379379
Loc: subclassToken.Range.Loc,
380380
Data: &css_ast.SSClass{
381-
Name: ast.LocRef{Loc: nameLoc, Ref: p.symbolForName(name)},
381+
Name: ast.LocRef{Loc: nameLoc, Ref: p.symbolForName(nameLoc, name)},
382382
},
383383
})
384384
if !p.expect(css_lexer.TIdent) {

internal/linker/linker.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/evanw/esbuild/internal/compat"
2525
"github.com/evanw/esbuild/internal/config"
2626
"github.com/evanw/esbuild/internal/css_ast"
27+
"github.com/evanw/esbuild/internal/css_lexer"
2728
"github.com/evanw/esbuild/internal/css_parser"
2829
"github.com/evanw/esbuild/internal/css_printer"
2930
"github.com/evanw/esbuild/internal/fs"
@@ -2672,7 +2673,12 @@ func (c *linkerContext) maybeCorrectObviousTypo(repr *graph.JSRepr, name string,
26722673
// happen with automatically-generated exports from non-JavaScript files.
26732674
note.Text = text
26742675
} else {
2675-
r := js_lexer.RangeOfIdentifier(importedFile.InputFile.Source, export.NameLoc)
2676+
var r logger.Range
2677+
if importedFile.InputFile.Loader.IsCSS() {
2678+
r = css_lexer.RangeOfIdentifier(importedFile.InputFile.Source, export.NameLoc)
2679+
} else {
2680+
r = js_lexer.RangeOfIdentifier(importedFile.InputFile.Source, export.NameLoc)
2681+
}
26762682
note = importedFile.LineColumnTracker().MsgData(r, text)
26772683
}
26782684
msg.Notes = append(msg.Notes, note)

scripts/end-to-end-tests.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7845,6 +7845,34 @@ tests.push(
78457845
}),
78467846
)
78477847

7848+
// Test CSS-related warning ranges
7849+
tests.push(
7850+
test(['in.js', '--outfile=node.js', '--bundle', '--loader:.css=local-css'], {
7851+
'in.js': `
7852+
import * as ns from './styles.css'
7853+
if (ns.buton !== void 0) throw 'fail'
7854+
`,
7855+
'styles.css': `
7856+
.bu\\74 ton { color: red }
7857+
`,
7858+
}, {
7859+
expectedStderr: `▲ [WARNING] Import "buton" will always be undefined because there is no matching export in "styles.css" [import-is-undefined]
7860+
7861+
in.js:3:13:
7862+
3 │ if (ns.buton !== void 0) throw 'fail'
7863+
│ ~~~~~
7864+
╵ button
7865+
7866+
Did you mean to import "button" instead?
7867+
7868+
styles.css:2:7:
7869+
2 │ .bu\\74 ton { color: red }
7870+
╵ ~~~~~~~~~
7871+
7872+
`,
7873+
}),
7874+
)
7875+
78487876
// Test writing to stdout
78497877
tests.push(
78507878
// These should succeed

0 commit comments

Comments
 (0)