Skip to content

Commit 15d56ca

Browse files
committed
emit null source mappings for empty chunk content
1 parent 8d98f6f commit 15d56ca

File tree

2 files changed

+77
-30
lines changed

2 files changed

+77
-30
lines changed

internal/linker/linker.go

+54-20
Original file line numberDiff line numberDiff line change
@@ -5849,6 +5849,16 @@ func (c *linkerContext) generateChunkJS(chunkIndex int, chunkWaitGroup *sync.Wai
58495849
// Ignore empty source map chunks
58505850
if compileResult.SourceMapChunk.ShouldIgnore {
58515851
prevOffset.AdvanceBytes(compileResult.JS)
5852+
5853+
// Include a null entry in the source map
5854+
if c.options.SourceMap != config.SourceMapNone {
5855+
if n := len(compileResultsForSourceMap); n > 0 && !compileResultsForSourceMap[n-1].isNullEntry {
5856+
compileResultsForSourceMap = append(compileResultsForSourceMap, compileResultForSourceMap{
5857+
sourceIndex: compileResult.sourceIndex,
5858+
isNullEntry: true,
5859+
})
5860+
}
5861+
}
58525862
} else {
58535863
prevOffset = sourcemap.LineColumnOffset{}
58545864

@@ -6330,6 +6340,16 @@ func (c *linkerContext) generateChunkCSS(chunkIndex int, chunkWaitGroup *sync.Wa
63306340
// Ignore empty source map chunks
63316341
if compileResult.SourceMapChunk.ShouldIgnore {
63326342
prevOffset.AdvanceBytes(compileResult.CSS)
6343+
6344+
// Include a null entry in the source map
6345+
if c.options.SourceMap != config.SourceMapNone && compileResult.sourceIndex.IsValid() {
6346+
if n := len(compileResultsForSourceMap); n > 0 && !compileResultsForSourceMap[n-1].isNullEntry {
6347+
compileResultsForSourceMap = append(compileResultsForSourceMap, compileResultForSourceMap{
6348+
sourceIndex: compileResult.sourceIndex.GetIndex(),
6349+
isNullEntry: true,
6350+
})
6351+
}
6352+
}
63336353
} else {
63346354
prevOffset = sourcemap.LineColumnOffset{}
63356355

@@ -6902,6 +6922,7 @@ type compileResultForSourceMap struct {
69026922
sourceMapChunk sourcemap.Chunk
69036923
generatedOffset sourcemap.LineColumnOffset
69046924
sourceIndex uint32
6925+
isNullEntry bool
69056926
}
69066927

69076928
func (c *linkerContext) generateSourceMapForChunk(
@@ -6929,6 +6950,9 @@ func (c *linkerContext) generateSourceMapForChunk(
69296950
continue
69306951
}
69316952
sourceIndexToSourcesIndex[result.sourceIndex] = nextSourcesIndex
6953+
if result.isNullEntry {
6954+
continue
6955+
}
69326956
file := &c.graph.Files[result.sourceIndex]
69336957

69346958
// Simple case: no nested source map
@@ -7044,28 +7068,38 @@ func (c *linkerContext) generateSourceMapForChunk(
70447068
startState.GeneratedColumn += prevColumnOffset
70457069
}
70467070

7047-
// Append the precomputed source map chunk
7048-
sourcemap.AppendSourceMapChunk(&j, prevEndState, startState, chunk.Buffer)
7071+
if result.isNullEntry {
7072+
// Emit a "null" mapping
7073+
chunk.Buffer.Data = []byte("A")
7074+
sourcemap.AppendSourceMapChunk(&j, prevEndState, startState, chunk.Buffer)
70497075

7050-
// Generate the relative offset to start from next time
7051-
prevOriginalName := prevEndState.OriginalName
7052-
prevEndState = chunk.EndState
7053-
prevEndState.SourceIndex += sourcesIndex
7054-
if chunk.Buffer.FirstNameOffset.IsValid() {
7055-
prevEndState.OriginalName += totalQuotedNameLen
7076+
// Only the generated position was advanced
7077+
prevEndState.GeneratedLine = startState.GeneratedLine
7078+
prevEndState.GeneratedColumn = startState.GeneratedColumn
70567079
} else {
7057-
// It's possible for a chunk to have mappings but for none of those
7058-
// mappings to have an associated name. The name is optional and is
7059-
// omitted when the mapping is for a non-name token or if the final
7060-
// and original names are the same. In that case we need to restore
7061-
// the previous original name end state since it wasn't modified after
7062-
// all. If we don't do this, then files after this will adjust their
7063-
// name offsets assuming that the previous generated mapping has this
7064-
// file's offset, which is wrong.
7065-
prevEndState.OriginalName = prevOriginalName
7066-
}
7067-
prevColumnOffset = chunk.FinalGeneratedColumn
7068-
totalQuotedNameLen += len(chunk.QuotedNames)
7080+
// Append the precomputed source map chunk
7081+
sourcemap.AppendSourceMapChunk(&j, prevEndState, startState, chunk.Buffer)
7082+
7083+
// Generate the relative offset to start from next time
7084+
prevOriginalName := prevEndState.OriginalName
7085+
prevEndState = chunk.EndState
7086+
prevEndState.SourceIndex += sourcesIndex
7087+
if chunk.Buffer.FirstNameOffset.IsValid() {
7088+
prevEndState.OriginalName += totalQuotedNameLen
7089+
} else {
7090+
// It's possible for a chunk to have mappings but for none of those
7091+
// mappings to have an associated name. The name is optional and is
7092+
// omitted when the mapping is for a non-name token or if the final
7093+
// and original names are the same. In that case we need to restore
7094+
// the previous original name end state since it wasn't modified after
7095+
// all. If we don't do this, then files after this will adjust their
7096+
// name offsets assuming that the previous generated mapping has this
7097+
// file's offset, which is wrong.
7098+
prevEndState.OriginalName = prevOriginalName
7099+
}
7100+
prevColumnOffset = chunk.FinalGeneratedColumn
7101+
totalQuotedNameLen += len(chunk.QuotedNames)
7102+
}
70697103

70707104
// If this was all one line, include the column offset from the start
70717105
if prevEndState.GeneratedLine == 0 {

internal/sourcemap/sourcemap.go

+23-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sourcemap
22

33
import (
44
"bytes"
5+
"strings"
56
"unicode/utf8"
67

78
"github.com/evanw/esbuild/internal/ast"
@@ -426,20 +427,28 @@ func AppendSourceMapChunk(j *helpers.Joiner, prevEndState SourceMapState, startS
426427
// case below instead. Original names are optional and are often omitted, so
427428
// we handle it uniformly by saving an index to the first original name,
428429
// which may or may not be a part of the first mapping.
430+
var sourceIndex int
431+
var originalLine int
432+
var originalColumn int
433+
omitSource := false
429434
generatedColumn, i := DecodeVLQ(buffer.Data, semicolons)
430-
sourceIndex, i := DecodeVLQ(buffer.Data, i)
431-
originalLine, i := DecodeVLQ(buffer.Data, i)
432-
originalColumn, i := DecodeVLQ(buffer.Data, i)
435+
if i == len(buffer.Data) || strings.IndexByte(",;", buffer.Data[i]) != -1 {
436+
omitSource = true
437+
} else {
438+
sourceIndex, i = DecodeVLQ(buffer.Data, i)
439+
originalLine, i = DecodeVLQ(buffer.Data, i)
440+
originalColumn, i = DecodeVLQ(buffer.Data, i)
441+
}
433442

434443
// Rewrite the first mapping to be relative to the end state of the previous
435444
// chunk. We now know what the end state is because we're in the second pass
436445
// where all chunks have already been generated.
437-
startState.SourceIndex += sourceIndex
438446
startState.GeneratedColumn += generatedColumn
447+
startState.SourceIndex += sourceIndex
439448
startState.OriginalLine += originalLine
440449
startState.OriginalColumn += originalColumn
441450
prevEndState.HasOriginalName = false // This is handled separately below
442-
rewritten, _ := appendMappingToBuffer(nil, j.LastByte(), prevEndState, startState)
451+
rewritten, _ := appendMappingToBuffer(nil, j.LastByte(), prevEndState, startState, omitSource)
443452
j.AddBytes(rewritten)
444453

445454
// Next, if there's an original name, we need to rewrite that as well to be
@@ -458,17 +467,21 @@ func AppendSourceMapChunk(j *helpers.Joiner, prevEndState SourceMapState, startS
458467
j.AddBytes(buffer.Data[i:])
459468
}
460469

461-
func appendMappingToBuffer(buffer []byte, lastByte byte, prevState SourceMapState, currentState SourceMapState) ([]byte, ast.Index32) {
470+
func appendMappingToBuffer(
471+
buffer []byte, lastByte byte, prevState SourceMapState, currentState SourceMapState, omitSource bool,
472+
) ([]byte, ast.Index32) {
462473
// Put commas in between mappings
463474
if lastByte != 0 && lastByte != ';' && lastByte != '"' {
464475
buffer = append(buffer, ',')
465476
}
466477

467478
// Record the mapping (note that the generated line is recorded using ';' elsewhere)
468479
buffer = encodeVLQ(buffer, currentState.GeneratedColumn-prevState.GeneratedColumn)
469-
buffer = encodeVLQ(buffer, currentState.SourceIndex-prevState.SourceIndex)
470-
buffer = encodeVLQ(buffer, currentState.OriginalLine-prevState.OriginalLine)
471-
buffer = encodeVLQ(buffer, currentState.OriginalColumn-prevState.OriginalColumn)
480+
if !omitSource {
481+
buffer = encodeVLQ(buffer, currentState.SourceIndex-prevState.SourceIndex)
482+
buffer = encodeVLQ(buffer, currentState.OriginalLine-prevState.OriginalLine)
483+
buffer = encodeVLQ(buffer, currentState.OriginalColumn-prevState.OriginalColumn)
484+
}
472485

473486
// Record the optional original name
474487
var nameOffset ast.Index32
@@ -820,7 +833,7 @@ func (b *ChunkBuilder) appendMappingWithoutRemapping(currentState SourceMapState
820833
}
821834

822835
var nameOffset ast.Index32
823-
b.sourceMap, nameOffset = appendMappingToBuffer(b.sourceMap, lastByte, b.prevState, currentState)
836+
b.sourceMap, nameOffset = appendMappingToBuffer(b.sourceMap, lastByte, b.prevState, currentState, false)
824837
prevOriginalName := b.prevState.OriginalName
825838
b.prevState = currentState
826839
if !currentState.HasOriginalName {

0 commit comments

Comments
 (0)