From d074f1c514cadced4f7414ef54325f76ff258529 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 01:01:46 -0400 Subject: [PATCH 01/17] Distinguish between a ExistingRawSourceMap and ExistingDecodedSourceMap --- src/Chunk.ts | 10 ++++++++-- src/Module.ts | 8 ++++---- src/rollup/types.d.ts | 27 ++++++++++++++++++--------- src/utils/collapseSourcemaps.ts | 10 ++++------ src/utils/getOriginalLocation.ts | 8 ++++---- src/utils/renderChunk.ts | 17 ++++++++++++----- src/utils/transform.ts | 12 ++++-------- typings/declarations.d.ts | 4 +++- 8 files changed, 57 insertions(+), 39 deletions(-) diff --git a/src/Chunk.ts b/src/Chunk.ts index c64bd6e1fd1..493ec35b8b1 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -14,7 +14,13 @@ import ExternalModule from './ExternalModule'; import finalisers from './finalisers/index'; import Graph from './Graph'; import Module from './Module'; -import { GlobalsOption, OutputOptions, RawSourceMap, RenderedChunk, RenderedModule } from './rollup/types'; +import { + ExistingRawSourceMap, + GlobalsOption, + OutputOptions, + RenderedChunk, + RenderedModule +} from './rollup/types'; import { Addons } from './utils/addons'; import { toBase64 } from './utils/base64'; import collapseSourcemaps from './utils/collapseSourcemaps'; @@ -676,7 +682,7 @@ export default class Chunk { timeEnd('render format', 3); let map: SourceMap = null as any; - const chunkSourcemapChain: RawSourceMap[] = []; + const chunkSourcemapChain: ExistingRawSourceMap[] = []; return renderChunk({ chunk: this, diff --git a/src/Module.ts b/src/Module.ts index acf5541094d..63d12235c4b 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -33,8 +33,8 @@ import Graph from './Graph'; import { Asset, EmittedChunk, + ExistingRawSourceMap, ModuleJSON, - RawSourceMap, ResolvedIdMap, RollupError, RollupWarning, @@ -199,11 +199,11 @@ export default class Module { manualChunkAlias: string = null as any; moduleSideEffects: boolean; originalCode!: string; - originalSourcemap!: RawSourceMap | null; + originalSourcemap!: ExistingRawSourceMap | null; reexports: { [name: string]: ReexportDescription } = Object.create(null); resolvedIds!: ResolvedIdMap; scope!: ModuleScope; - sourcemapChain!: RawSourceMap[]; + sourcemapChain!: ExistingRawSourceMap[]; sources: string[] = []; transformAssets?: Asset[]; transformChunks?: EmittedChunk[]; @@ -540,7 +540,7 @@ export default class Module { this.code = code; this.originalCode = originalCode; this.originalSourcemap = originalSourcemap; - this.sourcemapChain = sourcemapChain as RawSourceMap[]; + this.sourcemapChain = sourcemapChain; if (transformAssets) { this.transformAssets = transformAssets; } diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index f4c84280b70..6a06894475b 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -38,6 +38,16 @@ export interface RollupLogProps { url?: string; } +export interface ExistingDecodedSourceMap { + file?: string; + mappings: number[][][]; + names: string[]; + sourceRoot?: string; + sources: string[]; + sourcesContent?: string[]; + version: number; +} + export interface ExistingRawSourceMap { file?: string; mappings: string; @@ -48,8 +58,6 @@ export interface ExistingRawSourceMap { version: number; } -export type RawSourceMap = { mappings: '' } | ExistingRawSourceMap; - export interface SourceMap { file: string; mappings: string; @@ -64,7 +72,7 @@ export interface SourceMap { export interface SourceDescription { ast?: ESTree.Program; code: string; - map?: string | RawSourceMap; + map?: string | ExistingRawSourceMap; moduleSideEffects?: boolean | null; } @@ -79,9 +87,10 @@ export interface TransformModuleJSON { customTransformCache: boolean; moduleSideEffects: boolean | null; originalCode: string; - originalSourcemap: RawSourceMap | null; + originalSourcemap: ExistingDecodedSourceMap | null; resolvedIds?: ResolvedIdMap; - sourcemapChain: (RawSourceMap | { missing: true; plugin: string })[]; + // TODO + sourcemapChain: (ExistingDecodedSourceMap | { missing: true; plugin: string })[]; transformDependencies: string[] | null; } @@ -207,8 +216,8 @@ export type TransformChunkHook = ( code: string, options: OutputOptions ) => - | Promise<{ code: string; map: RawSourceMap } | null | undefined> - | { code: string; map: RawSourceMap } + | Promise<{ code: string; map: ExistingRawSourceMap } | null | undefined> + | { code: string; map: ExistingRawSourceMap } | null | undefined; @@ -218,8 +227,8 @@ export type RenderChunkHook = ( chunk: RenderedChunk, options: OutputOptions ) => - | Promise<{ code: string; map: RawSourceMap } | null> - | { code: string; map: RawSourceMap } + | Promise<{ code: string; map: ExistingRawSourceMap } | null> + | { code: string; map: ExistingRawSourceMap } | string | null; diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index dfde40ddc7c..9c7d683e61f 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -1,7 +1,7 @@ import { DecodedSourceMap, SourceMap } from 'magic-string'; import Chunk from '../Chunk'; import Module from '../Module'; -import { ExistingRawSourceMap, RawSourceMap } from '../rollup/types'; +import { ExistingRawSourceMap, ExistingRawSourceMap } from '../rollup/types'; import { error } from './error'; import { basename, dirname, relative, resolve } from './path'; @@ -77,9 +77,7 @@ class Link { sourcesContent[sourceIndex] !== traced.source.content ) { error({ - message: `Multiple conflicting contents for sourcemap source ${ - traced.source.filename - }` + message: `Multiple conflicting contents for sourcemap source ${traced.source.filename}` }); } @@ -148,7 +146,7 @@ export default function collapseSourcemaps( file: string, map: DecodedSourceMap, modules: Module[], - bundleSourcemapChain: RawSourceMap[], + bundleSourcemapChain: ExistingRawSourceMap[], excludeContent: boolean ) { function linkMap(source: Source, map: any) { @@ -186,7 +184,7 @@ export default function collapseSourcemaps( if (sources == null || (sources.length <= 1 && sources[0] == null)) { source = new Source(module.id, sourcesContent[0]); - sourcemapChain = [originalSourcemap as RawSourceMap].concat(sourcemapChain); + sourcemapChain = [originalSourcemap].concat(sourcemapChain); } else { // TODO indiscriminately treating IDs and sources as normal paths is probably bad. const directory = dirname(module.id) || '.'; diff --git a/src/utils/getOriginalLocation.ts b/src/utils/getOriginalLocation.ts index 358cc70a3ab..39c41576dd3 100644 --- a/src/utils/getOriginalLocation.ts +++ b/src/utils/getOriginalLocation.ts @@ -1,13 +1,13 @@ -import { ExistingRawSourceMap, RawSourceMap } from '../rollup/types'; +import { ExistingRawSourceMap, ExistingRawSourceMap } from '../rollup/types'; export function getOriginalLocation( - sourcemapChain: RawSourceMap[], + sourcemapChain: ExistingRawSourceMap[], location: { column: number; line: number; name?: string; source?: string } ) { - const filteredSourcemapChain = sourcemapChain.filter(sourcemap => sourcemap.mappings); + const filteredSourcemapChain = sourcemapChain.filter(sourcemap => sourcemap.mappings.length); while (filteredSourcemapChain.length > 0) { - const sourcemap = filteredSourcemapChain.pop() as ExistingRawSourceMap; + const sourcemap = filteredSourcemapChain.pop(); const line: any = sourcemap.mappings[location.line - 1]; let locationFound = false; diff --git a/src/utils/renderChunk.ts b/src/utils/renderChunk.ts index 74c3511a3ee..4dad769f395 100644 --- a/src/utils/renderChunk.ts +++ b/src/utils/renderChunk.ts @@ -1,7 +1,7 @@ import { decode } from 'sourcemap-codec'; import Chunk from '../Chunk'; import Graph from '../Graph'; -import { OutputOptions, Plugin, RawSourceMap, RenderedChunk } from '../rollup/types'; +import { ExistingRawSourceMap, OutputOptions, Plugin, RenderedChunk } from '../rollup/types'; import { error } from './error'; export default function renderChunk({ @@ -17,9 +17,13 @@ export default function renderChunk({ graph: Graph; options: OutputOptions; renderChunk: RenderedChunk; - sourcemapChain: RawSourceMap[]; + sourcemapChain: ExistingRawSourceMap[]; }): Promise { - const renderChunkReducer = (code: string, result: any, plugin: Plugin): string => { + const renderChunkReducer = ( + code: string, + result: { code: string; map?: ExistingRawSourceMap | string }, + plugin: Plugin + ): string => { if (result == null) return code; if (typeof result === 'string') @@ -28,11 +32,14 @@ export default function renderChunk({ map: undefined }; - const map = typeof result.map === 'string' ? JSON.parse(result.map) : result.map; + const map = + typeof result.map === 'string' + ? (JSON.parse(result.map) as ExistingRawSourceMap) + : result.map || null; if (map && typeof map.mappings === 'string') map.mappings = decode(map.mappings); // strict null check allows 'null' maps to not be pushed to the chain, while 'undefined' gets the missing map warning - if (map !== null) sourcemapChain.push(map || { missing: true, plugin: plugin.name }); + sourcemapChain.push(map || { missing: true, plugin: plugin.name }); return result.code; }; diff --git a/src/utils/transform.ts b/src/utils/transform.ts index 05fc9123202..4ec4a75d37a 100644 --- a/src/utils/transform.ts +++ b/src/utils/transform.ts @@ -9,7 +9,6 @@ import { Plugin, PluginCache, PluginContext, - RawSourceMap, RollupError, RollupWarning, TransformModuleJSON, @@ -27,9 +26,10 @@ export default function transform( module: Module ): Promise { const id = module.id; - const sourcemapChain: (RawSourceMap | { missing: true; plugin: string })[] = []; + const sourcemapChain: (ExistingRawSourceMap | { missing: true; plugin: string })[] = []; - const originalSourcemap = typeof source.map === 'string' ? JSON.parse(source.map) : source.map; + const originalSourcemap = + typeof source.map === 'string' ? (JSON.parse(source.map) as ExistingRawSourceMap) : source.map; if (originalSourcemap && typeof originalSourcemap.mappings === 'string') originalSourcemap.mappings = decode(originalSourcemap.mappings); @@ -103,11 +103,7 @@ export default function transform( } // strict null check allows 'null' maps to not be pushed to the chain, while 'undefined' gets the missing map warning - if (result.map !== null) { - sourcemapChain.push( - (result.map as ExistingRawSourceMap) || { missing: true, plugin: plugin.name } - ); - } + sourcemapChain.push(result.map || { missing: true, plugin: plugin.name }); ast = result.ast; diff --git a/typings/declarations.d.ts b/typings/declarations.d.ts index 71f65898dd6..5a94638f7ee 100644 --- a/typings/declarations.d.ts +++ b/typings/declarations.d.ts @@ -12,7 +12,9 @@ declare module 'signal-exit'; declare module 'date-time'; declare module 'locate-character'; declare module 'is-reference'; -declare module 'sourcemap-codec'; +declare module 'sourcemap-codec' { + export function decode(mappings: string): number[][][]; +} declare module 'require-relative'; declare module 'acorn-dynamic-import'; declare module 'acorn-import-meta'; From c3298494b8d2d1bb2f1558c8f4bf966dfff2c46d Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 01:23:26 -0400 Subject: [PATCH 02/17] Start work on DecodedSourceMapOrMissing type --- src/Chunk.ts | 4 ++-- src/Module.ts | 8 +++++--- src/rollup/types.d.ts | 12 ++++++++++-- src/utils/collapseSourcemaps.ts | 5 +++-- src/utils/getOriginalLocation.ts | 11 +++++++---- src/utils/renderChunk.ts | 10 ++++++++-- src/utils/transform.ts | 3 ++- 7 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/Chunk.ts b/src/Chunk.ts index 493ec35b8b1..04e3b0683f0 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -15,7 +15,7 @@ import finalisers from './finalisers/index'; import Graph from './Graph'; import Module from './Module'; import { - ExistingRawSourceMap, + DecodedSourceMapOrMissing, GlobalsOption, OutputOptions, RenderedChunk, @@ -682,7 +682,7 @@ export default class Chunk { timeEnd('render format', 3); let map: SourceMap = null as any; - const chunkSourcemapChain: ExistingRawSourceMap[] = []; + const chunkSourcemapChain: DecodedSourceMapOrMissing[] = []; return renderChunk({ chunk: this, diff --git a/src/Module.ts b/src/Module.ts index 63d12235c4b..1d272f7162c 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -32,8 +32,9 @@ import ExternalModule from './ExternalModule'; import Graph from './Graph'; import { Asset, + DecodedSourceMapOrMissing, EmittedChunk, - ExistingRawSourceMap, + ExistingDecodedSourceMap, ModuleJSON, ResolvedIdMap, RollupError, @@ -199,11 +200,12 @@ export default class Module { manualChunkAlias: string = null as any; moduleSideEffects: boolean; originalCode!: string; - originalSourcemap!: ExistingRawSourceMap | null; + originalSourcemap!: ExistingDecodedSourceMap | null; reexports: { [name: string]: ReexportDescription } = Object.create(null); resolvedIds!: ResolvedIdMap; scope!: ModuleScope; - sourcemapChain!: ExistingRawSourceMap[]; + // TODO(jridgewell) + sourcemapChain!: DecodedSourceMapOrMissing[]; sources: string[] = []; transformAssets?: Asset[]; transformChunks?: EmittedChunk[]; diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 6a06894475b..b90c3bb6df4 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -58,6 +58,14 @@ export interface ExistingRawSourceMap { version: number; } +export type DecodedSourceMapOrMissing = + | { + mappings?: never; + missing: true; + plugin: string; + } + | ExistingDecodedSourceMap; + export interface SourceMap { file: string; mappings: string; @@ -89,8 +97,8 @@ export interface TransformModuleJSON { originalCode: string; originalSourcemap: ExistingDecodedSourceMap | null; resolvedIds?: ResolvedIdMap; - // TODO - sourcemapChain: (ExistingDecodedSourceMap | { missing: true; plugin: string })[]; + // TODO(jridewell) + sourcemapChain: DecodedSourceMapOrMissing[]; transformDependencies: string[] | null; } diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index 9c7d683e61f..d492ad35f53 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -1,7 +1,7 @@ import { DecodedSourceMap, SourceMap } from 'magic-string'; import Chunk from '../Chunk'; import Module from '../Module'; -import { ExistingRawSourceMap, ExistingRawSourceMap } from '../rollup/types'; +import { DecodedSourceMapOrMissing, ExistingRawSourceMap } from '../rollup/types'; import { error } from './error'; import { basename, dirname, relative, resolve } from './path'; @@ -146,10 +146,11 @@ export default function collapseSourcemaps( file: string, map: DecodedSourceMap, modules: Module[], - bundleSourcemapChain: ExistingRawSourceMap[], + bundleSourcemapChain: DecodedSourceMapOrMissing[], excludeContent: boolean ) { function linkMap(source: Source, map: any) { + // TODO(jridgewell): missing if (map.missing) { bundle.graph.warn({ code: 'SOURCEMAP_BROKEN', diff --git a/src/utils/getOriginalLocation.ts b/src/utils/getOriginalLocation.ts index 39c41576dd3..0a84fe71184 100644 --- a/src/utils/getOriginalLocation.ts +++ b/src/utils/getOriginalLocation.ts @@ -1,13 +1,16 @@ -import { ExistingRawSourceMap, ExistingRawSourceMap } from '../rollup/types'; +import { DecodedSourceMapOrMissing, ExistingDecodedSourceMap } from '../rollup/types'; export function getOriginalLocation( - sourcemapChain: ExistingRawSourceMap[], + sourcemapChain: DecodedSourceMapOrMissing[], location: { column: number; line: number; name?: string; source?: string } ) { - const filteredSourcemapChain = sourcemapChain.filter(sourcemap => sourcemap.mappings.length); + // This cast is guaranteed. If it were a missing Map, it wouldn't have a mappings. + const filteredSourcemapChain = sourcemapChain.filter( + sourcemap => sourcemap.mappings + ) as ExistingDecodedSourceMap[]; while (filteredSourcemapChain.length > 0) { - const sourcemap = filteredSourcemapChain.pop(); + const sourcemap = filteredSourcemapChain.pop()!; const line: any = sourcemap.mappings[location.line - 1]; let locationFound = false; diff --git a/src/utils/renderChunk.ts b/src/utils/renderChunk.ts index 4dad769f395..15d44886188 100644 --- a/src/utils/renderChunk.ts +++ b/src/utils/renderChunk.ts @@ -1,7 +1,13 @@ import { decode } from 'sourcemap-codec'; import Chunk from '../Chunk'; import Graph from '../Graph'; -import { ExistingRawSourceMap, OutputOptions, Plugin, RenderedChunk } from '../rollup/types'; +import { + DecodedSourceMapOrMissing, + ExistingRawSourceMap, + OutputOptions, + Plugin, + RenderedChunk +} from '../rollup/types'; import { error } from './error'; export default function renderChunk({ @@ -17,7 +23,7 @@ export default function renderChunk({ graph: Graph; options: OutputOptions; renderChunk: RenderedChunk; - sourcemapChain: ExistingRawSourceMap[]; + sourcemapChain: DecodedSourceMapOrMissing[]; }): Promise { const renderChunkReducer = ( code: string, diff --git a/src/utils/transform.ts b/src/utils/transform.ts index 4ec4a75d37a..fd2a0ce0d85 100644 --- a/src/utils/transform.ts +++ b/src/utils/transform.ts @@ -3,6 +3,7 @@ import Graph from '../Graph'; import Module from '../Module'; import { Asset, + DecodedSourceMapOrMissing, EmitAsset, EmittedChunk, ExistingRawSourceMap, @@ -26,7 +27,7 @@ export default function transform( module: Module ): Promise { const id = module.id; - const sourcemapChain: (ExistingRawSourceMap | { missing: true; plugin: string })[] = []; + const sourcemapChain: DecodedSourceMapOrMissing[] = []; const originalSourcemap = typeof source.map === 'string' ? (JSON.parse(source.map) as ExistingRawSourceMap) : source.map; From ad2671e0003f73902f099da9bc66e3e8a57d4d95 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 01:37:33 -0400 Subject: [PATCH 03/17] Add decodedSourcemap helper --- src/rollup/types.d.ts | 8 ++++---- src/utils/decodedSourcemap.ts | 21 +++++++++++++++++++++ src/utils/renderChunk.ts | 9 ++------- src/utils/transform.ts | 17 ++++------------- 4 files changed, 31 insertions(+), 24 deletions(-) create mode 100644 src/utils/decodedSourcemap.ts diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index b90c3bb6df4..da007f5dd86 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -224,8 +224,8 @@ export type TransformChunkHook = ( code: string, options: OutputOptions ) => - | Promise<{ code: string; map: ExistingRawSourceMap } | null | undefined> - | { code: string; map: ExistingRawSourceMap } + | Promise<{ code: string; map?: ExistingRawSourceMap | string } | null | undefined> + | { code: string; map?: ExistingRawSourceMap | string } | null | undefined; @@ -235,8 +235,8 @@ export type RenderChunkHook = ( chunk: RenderedChunk, options: OutputOptions ) => - | Promise<{ code: string; map: ExistingRawSourceMap } | null> - | { code: string; map: ExistingRawSourceMap } + | Promise<{ code: string; map?: ExistingRawSourceMap | string } | null> + | { code: string; map?: ExistingRawSourceMap | string } | string | null; diff --git a/src/utils/decodedSourcemap.ts b/src/utils/decodedSourcemap.ts new file mode 100644 index 00000000000..3b9316695d8 --- /dev/null +++ b/src/utils/decodedSourcemap.ts @@ -0,0 +1,21 @@ +import { decode } from 'sourcemap-codec'; +import { ExistingDecodedSourceMap, ExistingRawSourceMap } from '../rollup/types'; + +type Input = ExistingRawSourceMap | ExistingDecodedSourceMap | string | undefined; + +export function decodedSourcemap(map: Input): ExistingDecodedSourceMap | null { + if (!map) return null; + + if (typeof map === 'string') { + map = JSON.parse(map) as ExistingRawSourceMap; + } + + let mappings: number[][][]; + if (typeof map.mappings === 'string') { + mappings = decode(map.mappings); + } else { + mappings = map.mappings; + } + + return { ...map, mappings }; +} diff --git a/src/utils/renderChunk.ts b/src/utils/renderChunk.ts index 15d44886188..3b23060d5a7 100644 --- a/src/utils/renderChunk.ts +++ b/src/utils/renderChunk.ts @@ -8,6 +8,7 @@ import { Plugin, RenderedChunk } from '../rollup/types'; +import { decodedSourcemap } from './decodedSourcemap'; import { error } from './error'; export default function renderChunk({ @@ -38,13 +39,7 @@ export default function renderChunk({ map: undefined }; - const map = - typeof result.map === 'string' - ? (JSON.parse(result.map) as ExistingRawSourceMap) - : result.map || null; - if (map && typeof map.mappings === 'string') map.mappings = decode(map.mappings); - - // strict null check allows 'null' maps to not be pushed to the chain, while 'undefined' gets the missing map warning + const map = decodedSourcemap(result.map); sourcemapChain.push(map || { missing: true, plugin: plugin.name }); return result.code; diff --git a/src/utils/transform.ts b/src/utils/transform.ts index fd2a0ce0d85..a13000d12b1 100644 --- a/src/utils/transform.ts +++ b/src/utils/transform.ts @@ -17,6 +17,7 @@ import { TransformSourceDescription } from '../rollup/types'; import { createTransformEmitAsset } from './assetHooks'; +import { decodedSourcemap } from './decodedSourcemap'; import { augmentCodeLocation, error } from './error'; import { dirname, resolve } from './path'; import { trackPluginCache } from './pluginDriver'; @@ -29,11 +30,7 @@ export default function transform( const id = module.id; const sourcemapChain: DecodedSourceMapOrMissing[] = []; - const originalSourcemap = - typeof source.map === 'string' ? (JSON.parse(source.map) as ExistingRawSourceMap) : source.map; - if (originalSourcemap && typeof originalSourcemap.mappings === 'string') - originalSourcemap.mappings = decode(originalSourcemap.mappings); - + const originalSourcemap = decodedSourcemap(source.map); const baseEmitAsset = graph.pluginDriver.emitAsset; const originalCode = source.code; let ast = source.ast; @@ -97,14 +94,8 @@ export default function transform( return code; } - if (result.map && typeof (result.map as ExistingRawSourceMap).mappings === 'string') { - (result.map as ExistingRawSourceMap).mappings = decode( - (result.map as ExistingRawSourceMap).mappings - ); - } - - // strict null check allows 'null' maps to not be pushed to the chain, while 'undefined' gets the missing map warning - sourcemapChain.push(result.map || { missing: true, plugin: plugin.name }); + const map = decodedSourcemap(result.map); + sourcemapChain.push(map || { missing: true, plugin: plugin.name }); ast = result.ast; From 9d54e5ccc3edfa342f0759e00d677a3aa6ba5e1c Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 01:42:58 -0400 Subject: [PATCH 04/17] Fix collapseSourcemaps types --- src/utils/collapseSourcemaps.ts | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index d492ad35f53..d84befd5e24 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -173,33 +173,26 @@ export default function collapseSourcemaps( const moduleSources = modules .filter(module => !module.excludeFromSourcemap) .map(module => { - let sourcemapChain = module.sourcemapChain; - let source: Source; - const originalSourcemap = module.originalSourcemap as ExistingRawSourceMap; + const originalSourcemap = module.originalSourcemap; if (!originalSourcemap) { source = new Source(module.id, module.originalCode); } else { const sources = originalSourcemap.sources; const sourcesContent = originalSourcemap.sourcesContent || []; - if (sources == null || (sources.length <= 1 && sources[0] == null)) { - source = new Source(module.id, sourcesContent[0]); - sourcemapChain = [originalSourcemap].concat(sourcemapChain); - } else { - // TODO indiscriminately treating IDs and sources as normal paths is probably bad. - const directory = dirname(module.id) || '.'; - const sourceRoot = originalSourcemap.sourceRoot || '.'; + // TODO indiscriminately treating IDs and sources as normal paths is probably bad. + const directory = dirname(module.id) || '.'; + const sourceRoot = originalSourcemap.sourceRoot || '.'; - const baseSources = sources.map( - (source, i) => new Source(resolve(directory, sourceRoot, source), sourcesContent[i]) - ); + const baseSources = sources.map( + (source, i) => new Source(resolve(directory, sourceRoot, source), sourcesContent[i]) + ); - source = new Link(originalSourcemap as any, baseSources) as any; - } + source = new Link(originalSourcemap as any, baseSources) as any; } - source = sourcemapChain.reduce(linkMap as any, source); + source = module.sourcemapChain.reduce(linkMap as any, source); return source; }); From 5aa3542810006d4a5ac5555320c2b43fb2afa904 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 01:45:00 -0400 Subject: [PATCH 05/17] Specify Link|Source type --- src/Module.ts | 1 - src/utils/collapseSourcemaps.ts | 15 +++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Module.ts b/src/Module.ts index 1d272f7162c..bf30ec88ff2 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -204,7 +204,6 @@ export default class Module { reexports: { [name: string]: ReexportDescription } = Object.create(null); resolvedIds!: ResolvedIdMap; scope!: ModuleScope; - // TODO(jridgewell) sourcemapChain!: DecodedSourceMapOrMissing[]; sources: string[] = []; transformAssets?: Asset[]; diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index d84befd5e24..fe8f665da98 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -35,9 +35,12 @@ interface SourceMapSegmentObject { class Link { mappings: SourceMapSegmentVector[][]; names: string[]; - sources: Source[]; + sources: (Source | Link)[]; - constructor(map: { mappings: SourceMapSegmentVector[][]; names: string[] }, sources: Source[]) { + constructor( + map: { mappings: SourceMapSegmentVector[][]; names: string[] }, + sources: (Source | Link)[] + ) { this.sources = sources; this.names = map.names; this.mappings = map.mappings; @@ -108,7 +111,7 @@ class Link { return { sources, sourcesContent, names, mappings }; } - traceSegment(line: number, column: number, name: string) { + traceSegment(line: number, column: number, name: string): SourceMapSegmentObject | null { const segments = this.mappings[line]; if (!segments) return null; @@ -149,7 +152,7 @@ export default function collapseSourcemaps( bundleSourcemapChain: DecodedSourceMapOrMissing[], excludeContent: boolean ) { - function linkMap(source: Source, map: any) { + function linkMap(source: Source | Link, map: any) { // TODO(jridgewell): missing if (map.missing) { bundle.graph.warn({ @@ -173,7 +176,7 @@ export default function collapseSourcemaps( const moduleSources = modules .filter(module => !module.excludeFromSourcemap) .map(module => { - let source: Source; + let source: Source | Link; const originalSourcemap = module.originalSourcemap; if (!originalSourcemap) { source = new Source(module.id, module.originalCode); @@ -189,7 +192,7 @@ export default function collapseSourcemaps( (source, i) => new Source(resolve(directory, sourceRoot, source), sourcesContent[i]) ); - source = new Link(originalSourcemap as any, baseSources) as any; + source = new Link(originalSourcemap as any, baseSources); } source = module.sourcemapChain.reduce(linkMap as any, source); From 93ee458890b5eb7e58850b6061102bec9b903a71 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 01:48:53 -0400 Subject: [PATCH 06/17] Handle missing map in collapseSourcemaps --- src/utils/collapseSourcemaps.ts | 43 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index fe8f665da98..48d8fb3e479 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -37,13 +37,10 @@ class Link { names: string[]; sources: (Source | Link)[]; - constructor( - map: { mappings: SourceMapSegmentVector[][]; names: string[] }, - sources: (Source | Link)[] - ) { + constructor(map: { mappings: number[][][]; names: string[] }, sources: (Source | Link)[]) { this.sources = sources; this.names = map.names; - this.mappings = map.mappings; + this.mappings = map.mappings as SourceMapSegmentVector[][]; } traceMappings() { @@ -152,25 +149,27 @@ export default function collapseSourcemaps( bundleSourcemapChain: DecodedSourceMapOrMissing[], excludeContent: boolean ) { - function linkMap(source: Source | Link, map: any) { - // TODO(jridgewell): missing - if (map.missing) { - bundle.graph.warn({ - code: 'SOURCEMAP_BROKEN', - message: `Sourcemap is likely to be incorrect: a plugin${ - map.plugin ? ` ('${map.plugin}')` : `` - } was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, - plugin: map.plugin, - url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` - }); - - map = { - mappings: '', - names: [] - }; + function linkMap(source: Source | Link, map: DecodedSourceMapOrMissing) { + if (map.mappings) { + return new Link(map, [source]); } - return new Link(map, [source]); + bundle.graph.warn({ + code: 'SOURCEMAP_BROKEN', + message: `Sourcemap is likely to be incorrect: a plugin${ + map.plugin ? ` ('${map.plugin}')` : `` + } was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, + plugin: map.plugin, + url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` + }); + + return new Link( + { + mappings: [], + names: [] + }, + [source] + ); } const moduleSources = modules From 2eeed53f661f5521e01a560405c391a6725dcfa9 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 01:50:17 -0400 Subject: [PATCH 07/17] Remove remaining any casts --- src/utils/collapseSourcemaps.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index 48d8fb3e479..097fd3fdffd 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -140,7 +140,6 @@ class Link { } } -// TODO TypeScript: Fix typecasts export default function collapseSourcemaps( bundle: Chunk, file: string, @@ -191,17 +190,17 @@ export default function collapseSourcemaps( (source, i) => new Source(resolve(directory, sourceRoot, source), sourcesContent[i]) ); - source = new Link(originalSourcemap as any, baseSources); + source = new Link(originalSourcemap, baseSources); } - source = module.sourcemapChain.reduce(linkMap as any, source); + source = module.sourcemapChain.reduce(linkMap, source); return source; }); - let source = new Link(map as any, moduleSources); + let source = new Link(map, moduleSources); - source = bundleSourcemapChain.reduce(linkMap as any, source); + source = bundleSourcemapChain.reduce(linkMap, source); let { sources, sourcesContent, names, mappings } = source.traceMappings(); From 9027baf87fb0040c24501d974c7787c7013ffea9 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 01:54:20 -0400 Subject: [PATCH 08/17] Handle single item SourceMapSegmentVector --- src/utils/collapseSourcemaps.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index 097fd3fdffd..8709edb7cf9 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -22,8 +22,9 @@ class Source { } type SourceMapSegmentVector = - | [number, number, number, number, number] - | [number, number, number, number]; + | [number] + | [number, number, number, number] + | [number, number, number, number, number]; interface SourceMapSegmentObject { column: number; @@ -54,6 +55,7 @@ class Link { const tracedLine: SourceMapSegmentVector[] = []; for (const segment of line) { + if (segment.length == 1) continue; const source = this.sources[segment[1]]; if (!source) continue; @@ -120,6 +122,7 @@ class Link { const m = (i + j) >> 1; const segment = segments[m]; if (segment[0] === column) { + if (segment.length == 1) return null; const source = this.sources[segment[1]]; if (!source) return null; From 417e76f2d1c467f69ca959c9789837291622e8b8 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 02:06:04 -0400 Subject: [PATCH 09/17] Fix tests --- .../transform-without-sourcemap/_config.js | 12 ++++++++++++ test/sourcemaps/samples/loaders/_config.js | 4 +--- .../_config.js | 12 ++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js b/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js index 0e08b7d75fc..921c7fcb3f0 100644 --- a/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js +++ b/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js @@ -32,6 +32,18 @@ module.exports = { plugin: 'fake plugin 1', message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 1') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` + }, + { + code: `SOURCEMAP_BROKEN`, + plugin: 'fake plugin 2', + message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 2') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, + url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` + }, + { + code: `SOURCEMAP_BROKEN`, + plugin: 'fake plugin 2', + message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 2') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, + url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` } ] }; diff --git a/test/sourcemaps/samples/loaders/_config.js b/test/sourcemaps/samples/loaders/_config.js index 842e4f55a45..c8169ae1d10 100644 --- a/test/sourcemaps/samples/loaders/_config.js +++ b/test/sourcemaps/samples/loaders/_config.js @@ -24,9 +24,7 @@ module.exports = { source: id }); - if (/main.js$/.test(id)) { - delete out.map.sources; - } else { + if (!/main.js$/.test(id)) { const slash = out.map.sources[0].lastIndexOf('/') + 1; out.map.sources = out.map.sources.map(source => '../' + source.slice(slash)); out.map.sourceRoot = 'fake'; diff --git a/test/sourcemaps/samples/transform-without-sourcemap-render-chunk/_config.js b/test/sourcemaps/samples/transform-without-sourcemap-render-chunk/_config.js index 703d4c85cad..4588f70afe9 100644 --- a/test/sourcemaps/samples/transform-without-sourcemap-render-chunk/_config.js +++ b/test/sourcemaps/samples/transform-without-sourcemap-render-chunk/_config.js @@ -25,6 +25,18 @@ module.exports = { plugin: 'fake plugin 1', message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 1') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` + }, + { + code: `SOURCEMAP_BROKEN`, + plugin: 'fake plugin 2', + message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 2') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, + url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` + }, + { + code: `SOURCEMAP_BROKEN`, + plugin: 'fake plugin 2', + message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 2') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, + url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` } ] }; From 38f52add9edc8fcf15cfc45166da6e92be82f7b1 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 02:11:58 -0400 Subject: [PATCH 10/17] Fix lint issues --- src/utils/collapseSourcemaps.ts | 2 +- src/utils/renderChunk.ts | 1 - src/utils/transform.ts | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index 8709edb7cf9..dabbe02281a 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -1,7 +1,7 @@ import { DecodedSourceMap, SourceMap } from 'magic-string'; import Chunk from '../Chunk'; import Module from '../Module'; -import { DecodedSourceMapOrMissing, ExistingRawSourceMap } from '../rollup/types'; +import { DecodedSourceMapOrMissing } from '../rollup/types'; import { error } from './error'; import { basename, dirname, relative, resolve } from './path'; diff --git a/src/utils/renderChunk.ts b/src/utils/renderChunk.ts index 3b23060d5a7..c5e372f0a67 100644 --- a/src/utils/renderChunk.ts +++ b/src/utils/renderChunk.ts @@ -1,4 +1,3 @@ -import { decode } from 'sourcemap-codec'; import Chunk from '../Chunk'; import Graph from '../Graph'; import { diff --git a/src/utils/transform.ts b/src/utils/transform.ts index a13000d12b1..a96dd3df13d 100644 --- a/src/utils/transform.ts +++ b/src/utils/transform.ts @@ -1,4 +1,3 @@ -import { decode } from 'sourcemap-codec'; import Graph from '../Graph'; import Module from '../Module'; import { @@ -6,7 +5,6 @@ import { DecodedSourceMapOrMissing, EmitAsset, EmittedChunk, - ExistingRawSourceMap, Plugin, PluginCache, PluginContext, From 550dbeecf6bf5a6b24941e2c5ff607b7960561aa Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 02:25:36 -0400 Subject: [PATCH 11/17] Handle null sourcemaps meaning no change in code --- src/rollup/types.d.ts | 12 +++++++----- src/utils/renderChunk.ts | 12 ++++++++---- src/utils/transform.ts | 9 ++++++--- .../transform-without-sourcemap/_config.js | 12 ------------ .../_config.js | 12 ------------ 5 files changed, 21 insertions(+), 36 deletions(-) diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index da007f5dd86..83e5dcdc7f0 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -77,10 +77,12 @@ export interface SourceMap { toUrl(): string; } +export type SourceMapInput = ExistingRawSourceMap | string | null; + export interface SourceDescription { ast?: ESTree.Program; code: string; - map?: string | ExistingRawSourceMap; + map?: SourceMapInput; moduleSideEffects?: boolean | null; } @@ -224,8 +226,8 @@ export type TransformChunkHook = ( code: string, options: OutputOptions ) => - | Promise<{ code: string; map?: ExistingRawSourceMap | string } | null | undefined> - | { code: string; map?: ExistingRawSourceMap | string } + | Promise<{ code: string; map?: SourceMapInput } | null | undefined> + | { code: string; map?: SourceMapInput } | null | undefined; @@ -235,8 +237,8 @@ export type RenderChunkHook = ( chunk: RenderedChunk, options: OutputOptions ) => - | Promise<{ code: string; map?: ExistingRawSourceMap | string } | null> - | { code: string; map?: ExistingRawSourceMap | string } + | Promise<{ code: string; map?: SourceMapInput } | null> + | { code: string; map?: SourceMapInput } | string | null; diff --git a/src/utils/renderChunk.ts b/src/utils/renderChunk.ts index c5e372f0a67..8c2cb96189c 100644 --- a/src/utils/renderChunk.ts +++ b/src/utils/renderChunk.ts @@ -5,7 +5,8 @@ import { ExistingRawSourceMap, OutputOptions, Plugin, - RenderedChunk + RenderedChunk, + SourceMapInput } from '../rollup/types'; import { decodedSourcemap } from './decodedSourcemap'; import { error } from './error'; @@ -27,7 +28,7 @@ export default function renderChunk({ }): Promise { const renderChunkReducer = ( code: string, - result: { code: string; map?: ExistingRawSourceMap | string }, + result: { code: string; map?: SourceMapInput }, plugin: Plugin ): string => { if (result == null) return code; @@ -38,8 +39,11 @@ export default function renderChunk({ map: undefined }; - const map = decodedSourcemap(result.map); - sourcemapChain.push(map || { missing: true, plugin: plugin.name }); + // null means code was not moved by the plugin. + if (result.map !== null) { + const map = decodedSourcemap(result.map); + sourcemapChain.push(map || { missing: true, plugin: plugin.name }); + } return result.code; }; diff --git a/src/utils/transform.ts b/src/utils/transform.ts index a96dd3df13d..2316b0ec37c 100644 --- a/src/utils/transform.ts +++ b/src/utils/transform.ts @@ -28,7 +28,7 @@ export default function transform( const id = module.id; const sourcemapChain: DecodedSourceMapOrMissing[] = []; - const originalSourcemap = decodedSourcemap(source.map); + const originalSourcemap = source.map === null ? null : decodedSourcemap(source.map); const baseEmitAsset = graph.pluginDriver.emitAsset; const originalCode = source.code; let ast = source.ast; @@ -92,8 +92,11 @@ export default function transform( return code; } - const map = decodedSourcemap(result.map); - sourcemapChain.push(map || { missing: true, plugin: plugin.name }); + // null means code was not moved by the plugin. + if (result.map !== null) { + const map = decodedSourcemap(result.map); + sourcemapChain.push(map || { missing: true, plugin: plugin.name }); + } ast = result.ast; diff --git a/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js b/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js index 921c7fcb3f0..0e08b7d75fc 100644 --- a/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js +++ b/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js @@ -32,18 +32,6 @@ module.exports = { plugin: 'fake plugin 1', message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 1') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` - }, - { - code: `SOURCEMAP_BROKEN`, - plugin: 'fake plugin 2', - message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 2') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, - url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` - }, - { - code: `SOURCEMAP_BROKEN`, - plugin: 'fake plugin 2', - message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 2') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, - url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` } ] }; diff --git a/test/sourcemaps/samples/transform-without-sourcemap-render-chunk/_config.js b/test/sourcemaps/samples/transform-without-sourcemap-render-chunk/_config.js index 4588f70afe9..703d4c85cad 100644 --- a/test/sourcemaps/samples/transform-without-sourcemap-render-chunk/_config.js +++ b/test/sourcemaps/samples/transform-without-sourcemap-render-chunk/_config.js @@ -25,18 +25,6 @@ module.exports = { plugin: 'fake plugin 1', message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 1') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` - }, - { - code: `SOURCEMAP_BROKEN`, - plugin: 'fake plugin 2', - message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 2') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, - url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` - }, - { - code: `SOURCEMAP_BROKEN`, - plugin: 'fake plugin 2', - message: `Sourcemap is likely to be incorrect: a plugin ('fake plugin 2') was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, - url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` } ] }; From ae28f186b1cf4ace740e8622c4c051fb75b26898 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 02:48:04 -0400 Subject: [PATCH 12/17] Handle a no-mappings sourcemap --- src/rollup/types.d.ts | 2 +- src/utils/decodedSourcemap.ts | 14 +++++++++++--- .../_config.js | 18 ++++++++++++++++++ .../main.js | 1 + 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 test/function/samples/handles-empty-string-sourcemap-mappings/_config.js create mode 100644 test/function/samples/handles-empty-string-sourcemap-mappings/main.js diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 83e5dcdc7f0..c63653e4b82 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -77,7 +77,7 @@ export interface SourceMap { toUrl(): string; } -export type SourceMapInput = ExistingRawSourceMap | string | null; +export type SourceMapInput = ExistingRawSourceMap | string | null | { mappings: '' }; export interface SourceDescription { ast?: ESTree.Program; diff --git a/src/utils/decodedSourcemap.ts b/src/utils/decodedSourcemap.ts index 3b9316695d8..ecc54f17cab 100644 --- a/src/utils/decodedSourcemap.ts +++ b/src/utils/decodedSourcemap.ts @@ -1,7 +1,7 @@ import { decode } from 'sourcemap-codec'; -import { ExistingDecodedSourceMap, ExistingRawSourceMap } from '../rollup/types'; +import { ExistingDecodedSourceMap, ExistingRawSourceMap, SourceMapInput } from '../rollup/types'; -type Input = ExistingRawSourceMap | ExistingDecodedSourceMap | string | undefined; +type Input = SourceMapInput | ExistingDecodedSourceMap | undefined; export function decodedSourcemap(map: Input): ExistingDecodedSourceMap | null { if (!map) return null; @@ -9,6 +9,14 @@ export function decodedSourcemap(map: Input): ExistingDecodedSourceMap | null { if (typeof map === 'string') { map = JSON.parse(map) as ExistingRawSourceMap; } + if (map.mappings === '') { + return { + mappings: [], + names: [], + sources: [], + version: 3 + }; + } let mappings: number[][][]; if (typeof map.mappings === 'string') { @@ -17,5 +25,5 @@ export function decodedSourcemap(map: Input): ExistingDecodedSourceMap | null { mappings = map.mappings; } - return { ...map, mappings }; + return { ...(map as ExistingRawSourceMap | ExistingDecodedSourceMap), mappings }; } diff --git a/test/function/samples/handles-empty-string-sourcemap-mappings/_config.js b/test/function/samples/handles-empty-string-sourcemap-mappings/_config.js new file mode 100644 index 00000000000..764c77a324a --- /dev/null +++ b/test/function/samples/handles-empty-string-sourcemap-mappings/_config.js @@ -0,0 +1,18 @@ +module.exports = { + description: 'handles transforms that return sourcemap with empty mappings', + + options: { + plugins: [ + { + transform(code) { + return { + code, + map: { mappings: '' } + }; + } + } + ], + // ensure source maps are generated + output: { sourcemap: true } + } +}; diff --git a/test/function/samples/handles-empty-string-sourcemap-mappings/main.js b/test/function/samples/handles-empty-string-sourcemap-mappings/main.js new file mode 100644 index 00000000000..7a4e8a723a4 --- /dev/null +++ b/test/function/samples/handles-empty-string-sourcemap-mappings/main.js @@ -0,0 +1 @@ +export default 42; From 4de681a2f449e4a2b5e3dd7ba14f88e4889d5d47 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 15:48:35 -0400 Subject: [PATCH 13/17] Remove sourcemap-coded declaration It has types now --- src/utils/renderChunk.ts | 1 - typings/declarations.d.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/utils/renderChunk.ts b/src/utils/renderChunk.ts index 8c2cb96189c..c2d98106c41 100644 --- a/src/utils/renderChunk.ts +++ b/src/utils/renderChunk.ts @@ -2,7 +2,6 @@ import Chunk from '../Chunk'; import Graph from '../Graph'; import { DecodedSourceMapOrMissing, - ExistingRawSourceMap, OutputOptions, Plugin, RenderedChunk, diff --git a/typings/declarations.d.ts b/typings/declarations.d.ts index 5a94638f7ee..100ca939fa2 100644 --- a/typings/declarations.d.ts +++ b/typings/declarations.d.ts @@ -12,9 +12,6 @@ declare module 'signal-exit'; declare module 'date-time'; declare module 'locate-character'; declare module 'is-reference'; -declare module 'sourcemap-codec' { - export function decode(mappings: string): number[][][]; -} declare module 'require-relative'; declare module 'acorn-dynamic-import'; declare module 'acorn-import-meta'; From aaa055867497cafffb8344c57c482fe609a3eb2f Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 15:51:45 -0400 Subject: [PATCH 14/17] Undo comment changes --- src/utils/renderChunk.ts | 2 +- src/utils/transform.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/renderChunk.ts b/src/utils/renderChunk.ts index c2d98106c41..d53be7c376b 100644 --- a/src/utils/renderChunk.ts +++ b/src/utils/renderChunk.ts @@ -38,7 +38,7 @@ export default function renderChunk({ map: undefined }; - // null means code was not moved by the plugin. + // strict null check allows 'null' maps to not be pushed to the chain, while 'undefined' gets the missing map warning if (result.map !== null) { const map = decodedSourcemap(result.map); sourcemapChain.push(map || { missing: true, plugin: plugin.name }); diff --git a/src/utils/transform.ts b/src/utils/transform.ts index 2316b0ec37c..3bf570fbd6d 100644 --- a/src/utils/transform.ts +++ b/src/utils/transform.ts @@ -92,7 +92,7 @@ export default function transform( return code; } - // null means code was not moved by the plugin. + // strict null check allows 'null' maps to not be pushed to the chain, while 'undefined' gets the missing map warning if (result.map !== null) { const map = decodedSourcemap(result.map); sourcemapChain.push(map || { missing: true, plugin: plugin.name }); From f936eeb1ac3e5ff753c95082d9ee9996f44cecb8 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 4 Jul 2019 16:12:42 -0400 Subject: [PATCH 15/17] Use sourcemap-codec's types --- src/utils/collapseSourcemaps.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index dabbe02281a..5face4b5eb1 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -1,4 +1,5 @@ import { DecodedSourceMap, SourceMap } from 'magic-string'; +import { SourceMapLine, SourceMapMappings, SourceMapSegment } from 'sourcemap-codec'; import Chunk from '../Chunk'; import Module from '../Module'; import { DecodedSourceMapOrMissing } from '../rollup/types'; @@ -21,11 +22,6 @@ class Source { } } -type SourceMapSegmentVector = - | [number] - | [number, number, number, number] - | [number, number, number, number, number]; - interface SourceMapSegmentObject { column: number; line: number; @@ -34,14 +30,14 @@ interface SourceMapSegmentObject { } class Link { - mappings: SourceMapSegmentVector[][]; + mappings: SourceMapMappings; names: string[]; sources: (Source | Link)[]; constructor(map: { mappings: number[][][]; names: string[] }, sources: (Source | Link)[]) { this.sources = sources; this.names = map.names; - this.mappings = map.mappings as SourceMapSegmentVector[][]; + this.mappings = map.mappings as SourceMapMappings; } traceMappings() { @@ -52,7 +48,7 @@ class Link { const mappings = []; for (const line of this.mappings) { - const tracedLine: SourceMapSegmentVector[] = []; + const tracedLine: SourceMapLine = []; for (const segment of line) { if (segment.length == 1) continue; @@ -83,7 +79,7 @@ class Link { }); } - const tracedSegment: SourceMapSegmentVector = [ + const tracedSegment: SourceMapSegment = [ segment[0], sourceIndex, traced.line, @@ -97,7 +93,7 @@ class Link { names.push(traced.name); } - (tracedSegment as SourceMapSegmentVector)[4] = nameIndex; + (tracedSegment as SourceMapSegment)[4] = nameIndex; } tracedLine.push(tracedSegment); From 597ad003253c5ce4b0bfb48f84835b6a02b88dbd Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Fri, 5 Jul 2019 15:00:11 -0400 Subject: [PATCH 16/17] Get rid of TODO --- src/rollup/types.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index c63653e4b82..987c08f3e59 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -99,7 +99,6 @@ export interface TransformModuleJSON { originalCode: string; originalSourcemap: ExistingDecodedSourceMap | null; resolvedIds?: ResolvedIdMap; - // TODO(jridewell) sourcemapChain: DecodedSourceMapOrMissing[]; transformDependencies: string[] | null; } From 37ac3e97d72f59cfd5803a3febb745480e2d34e6 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Sat, 6 Jul 2019 15:01:37 -0400 Subject: [PATCH 17/17] Use our own SourceMapSegment tuple type --- src/rollup/types.d.ts | 7 ++++++- src/utils/collapseSourcemaps.ts | 26 +++++++++++++++++--------- src/utils/decodedSourcemap.ts | 2 +- src/utils/getOriginalLocation.ts | 6 +++--- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 987c08f3e59..c24a7dded59 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -38,9 +38,14 @@ export interface RollupLogProps { url?: string; } +export type SourceMapSegment = + | [number] + | [number, number, number, number] + | [number, number, number, number, number]; + export interface ExistingDecodedSourceMap { file?: string; - mappings: number[][][]; + mappings: SourceMapSegment[][]; names: string[]; sourceRoot?: string; sources: string[]; diff --git a/src/utils/collapseSourcemaps.ts b/src/utils/collapseSourcemaps.ts index 5face4b5eb1..a240190b501 100644 --- a/src/utils/collapseSourcemaps.ts +++ b/src/utils/collapseSourcemaps.ts @@ -1,8 +1,11 @@ import { DecodedSourceMap, SourceMap } from 'magic-string'; -import { SourceMapLine, SourceMapMappings, SourceMapSegment } from 'sourcemap-codec'; import Chunk from '../Chunk'; import Module from '../Module'; -import { DecodedSourceMapOrMissing } from '../rollup/types'; +import { + DecodedSourceMapOrMissing, + ExistingDecodedSourceMap, + SourceMapSegment +} from '../rollup/types'; import { error } from './error'; import { basename, dirname, relative, resolve } from './path'; @@ -30,14 +33,17 @@ interface SourceMapSegmentObject { } class Link { - mappings: SourceMapMappings; + mappings: SourceMapSegment[][]; names: string[]; sources: (Source | Link)[]; - constructor(map: { mappings: number[][][]; names: string[] }, sources: (Source | Link)[]) { + constructor( + map: { mappings: SourceMapSegment[][]; names: string[] }, + sources: (Source | Link)[] + ) { this.sources = sources; this.names = map.names; - this.mappings = map.mappings as SourceMapMappings; + this.mappings = map.mappings; } traceMappings() { @@ -48,7 +54,7 @@ class Link { const mappings = []; for (const line of this.mappings) { - const tracedLine: SourceMapLine = []; + const tracedLine: SourceMapSegment[] = []; for (const segment of line) { if (segment.length == 1) continue; @@ -58,7 +64,7 @@ class Link { const traced = source.traceSegment( segment[2], segment[3], - this.names[segment[4] as number] + segment.length === 5 ? this.names[segment[4]] : '' ); if (traced) { @@ -125,7 +131,7 @@ class Link { return source.traceSegment( segment[2], segment[3], - this.names[segment[4] as number] || name + segment.length === 5 ? this.names[segment[4]] : name ); } if (segment[0] > column) { @@ -197,7 +203,9 @@ export default function collapseSourcemaps( return source; }); - let source = new Link(map, moduleSources); + // DecodedSourceMap (from magic-string) uses a number[] instead of the more + // correct SourceMapSegment tuples. Cast it here to gain type safety. + let source = new Link(map as ExistingDecodedSourceMap, moduleSources); source = bundleSourcemapChain.reduce(linkMap, source); diff --git a/src/utils/decodedSourcemap.ts b/src/utils/decodedSourcemap.ts index ecc54f17cab..3b4acfcf6a4 100644 --- a/src/utils/decodedSourcemap.ts +++ b/src/utils/decodedSourcemap.ts @@ -18,7 +18,7 @@ export function decodedSourcemap(map: Input): ExistingDecodedSourceMap | null { }; } - let mappings: number[][][]; + let mappings; if (typeof map.mappings === 'string') { mappings = decode(map.mappings); } else { diff --git a/src/utils/getOriginalLocation.ts b/src/utils/getOriginalLocation.ts index 0a84fe71184..1da1d7aa7e5 100644 --- a/src/utils/getOriginalLocation.ts +++ b/src/utils/getOriginalLocation.ts @@ -11,17 +11,17 @@ export function getOriginalLocation( while (filteredSourcemapChain.length > 0) { const sourcemap = filteredSourcemapChain.pop()!; - const line: any = sourcemap.mappings[location.line - 1]; + const line = sourcemap.mappings[location.line - 1]; let locationFound = false; if (line !== undefined) { for (const segment of line) { if (segment[0] >= location.column) { - if (segment.length < 4) break; + if (segment.length === 1) break; location = { column: segment[3], line: segment[2] + 1, - name: sourcemap.names[segment[4]], + name: segment.length === 5 ? sourcemap.names[segment[4]] : undefined, source: sourcemap.sources[segment[1]] }; locationFound = true;