diff --git a/CHANGELOG.md b/CHANGELOG.md index 77d2d987971..7b3105f120c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ Care was taken to still parallelize as much as possible despite parts of the code having to block. Each input file in a chunk is still printed to a string fully in parallel. Waiting was only introduced in the chunk assembly stage where input file strings are joined together. In practice, this change doesn't appear to have slowed down esbuild by a noticeable amount. +* Fix an off-by-one error with source map generation ([#289](https://github.com/evanw/esbuild/issues/289)) + + The nested source map support added in version 0.6.5 contained a bug. Input files that were included in the bundle but that didn't themselves contain any generated code caused the source index to shift by one, throwing off the source names of all files after it. This could happen with files consisting only of re-export statements (e.g. `export {name} from 'path'`). This bug has been fixed and this specific scenario now has test coverage. + ## 0.6.10 * Revert the binary operator chain change diff --git a/internal/bundler/linker.go b/internal/bundler/linker.go index 2c6e1c83851..f3ba06b90a3 100644 --- a/internal/bundler/linker.go +++ b/internal/bundler/linker.go @@ -2959,11 +2959,11 @@ func (c *linkerContext) generateChunk(chunk *chunkMeta) func([]ast.ImportRecord) prevOffset.advanceBytes(compileResult.JS) } else { prevOffset = lineColumnOffset{} - } - // Include this file in the source map - if c.options.SourceMap != config.SourceMapNone { - compileResultsForSourceMap = append(compileResultsForSourceMap, compileResult) + // Include this file in the source map + if c.options.SourceMap != config.SourceMapNone { + compileResultsForSourceMap = append(compileResultsForSourceMap, compileResult) + } } // Include this file in the metadata diff --git a/scripts/verify-source-map.js b/scripts/verify-source-map.js index 448cc69d8ee..3700a62bc88 100644 --- a/scripts/verify-source-map.js +++ b/scripts/verify-source-map.js @@ -89,6 +89,35 @@ const testCaseStdin = { `, } +const testCaseEmptyFile = { + 'entry.js': ` + import './before' + import {fn} from './re-export' + import './after' + fn() + `, + 're-export.js': ` + // This file will be empty in the generated code, which was causing + // an off-by-one error with the source index in the source map + export {default as fn} from './test' + `, + 'test.js': ` + export default function() { + console.log("test") + } + `, + 'before.js': ` + console.log("before") + `, + 'after.js': ` + console.log("after") + `, +} + +const toSearchEmptyFile = [ + 'before', 'test', 'after', +] + async function check(kind, testCase, toSearch, flags) { let failed = 0 @@ -230,6 +259,7 @@ async function main() { check('es6' + suffix, testCaseES6, toSearchBundle, flags.concat('--outfile=out.js', '--bundle')), check('ts' + suffix, testCaseTypeScriptRuntime, toSearchNoBundle, flags.concat('--outfile=out.js')), check('stdin-stdout' + suffix, testCaseStdin, toSearchNoBundle, flags.concat('--sourcefile=')), + check('empty' + suffix, testCaseEmptyFile, toSearchEmptyFile, flags.concat('--outfile=out.js', '--bundle')), ) }