Candidate sectional sourcemap emit implementation

This commit is contained in:
Wesley Wigham
2018-05-30 17:53:26 -07:00
parent 2cb46407b1
commit 8adbf85e0e
9 changed files with 133 additions and 20 deletions

View File

@@ -99,6 +99,10 @@ namespace ts {
let sourceMapDataList: SourceMapData[] | undefined;
let disabled: boolean = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap);
let completedSections: SourceMapSectionDefinition[];
let sectionStartLine: number;
let sectionStartColumn: number;
return {
initialize,
reset,
@@ -146,6 +150,9 @@ namespace ts {
lastEncodedNameIndex = 0;
// Initialize source map data
completedSections = [];
sectionStartLine = 0;
sectionStartColumn = 0;
sourceMapData = {
sourceMapFilePath,
jsSourceMappingURL: !compilerOptions.inlineSourceMap ? getBaseFileName(normalizeSlashes(sourceMapFilePath)) : undefined!, // TODO: GH#18217
@@ -214,6 +221,68 @@ namespace ts {
lastEncodedNameIndex = undefined;
sourceMapData = undefined!;
sourceMapDataList = undefined!;
completedSections = undefined!;
sectionStartLine = undefined!;
sectionStartColumn = undefined!;
}
interface SourceMapSection {
version: 3;
file: string;
sourceRoot?: string;
sources: string[];
names?: string[];
mappings: string;
sourcesContent?: string[];
sections?: undefined;
}
type SourceMapSectionDefinition =
| { offset: { line: number, column: number }, url: string } // Included for completeness
| { offset: { line: number, column: number }, map: SourceMap };
interface SectionalSourceMap {
version: 3;
file: string;
sections: SourceMapSectionDefinition[];
}
type SourceMap = SectionalSourceMap | SourceMapSection;
function captureSection(): SourceMapSection {
return {
version: 3,
file: sourceMapData.sourceMapFile,
sourceRoot: sourceMapData.sourceMapSourceRoot,
sources: sourceMapData.sourceMapSources,
names: sourceMapData.sourceMapNames,
mappings: sourceMapData.sourceMapMappings,
sourcesContent: sourceMapData.sourceMapSourcesContent,
};
}
function resetSectionalData(): void {
sourceMapData.sourceMapSources = [];
sourceMapData.sourceMapNames = [];
sourceMapData.sourceMapMappings = "";
sourceMapData.sourceMapSourcesContent = compilerOptions.inlineSources ? [] : undefined;
}
function generateMap(): SourceMap {
if (completedSections.length) {
const last = {
offset: { line: sectionStartLine, column: sectionStartColumn },
map: captureSection()
};
return {
version: 3,
file: last.map.file,
sections: [...completedSections, last]
};
}
else {
return captureSection();
}
}
// Encoding for sourcemap span
@@ -284,8 +353,8 @@ namespace ts {
sourceLinePos.line++;
sourceLinePos.character++;
const emittedLine = writer.getLine();
const emittedColumn = writer.getColumn();
const emittedLine = writer.getLine() - sectionStartLine;
const emittedColumn = emittedLine === 0 ? writer.getColumn() - sectionStartColumn : writer.getColumn();
// If this location wasn't recorded or the location in source is going backwards, record the span
if (!lastRecordedSourceMapSpan ||
@@ -333,6 +402,38 @@ namespace ts {
}
if (node) {
if (isUnparsedSource(node) && node.sourceMapText !== undefined) {
if (lastRecordedSourceMapSpan && lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) { // If we've recorded some spans, save them
completedSections.push({ offset: { line: sectionStartLine, column: sectionStartColumn }, map: captureSection() });
resetSectionalData();
}
const text = node.sourceMapText;
let parsed: {} | undefined;
try {
parsed = JSON.parse(text);
}
catch {
// empty
}
const offset = { line: writer.getLine(), column: writer.getColumn() };
completedSections.push(parsed
? {
offset,
map: parsed as SourceMap
}
: {
offset,
// This is just passes the buck on sourcemaps we don't really understand, instead of issuing an error (which would be difficult this late)
url: `data:application/json;charset=utf-8;base64,${base64encode(sys, text)}`
}
);
const emitResult = emitCallback(hint, node);
sectionStartLine = writer.getLine();
sectionStartColumn = writer.getColumn();
lastRecordedSourceMapSpan = undefined!;
lastEncodedSourceMapSpan = undefined!;
return emitResult;
}
const emitNode = node.emitNode;
const emitFlags = emitNode && emitNode.flags || EmitFlags.None;
const range = emitNode && emitNode.sourceMapRange;
@@ -452,15 +553,7 @@ namespace ts {
encodeLastRecordedSourceMapSpan();
return JSON.stringify({
version: 3,
file: sourceMapData.sourceMapFile,
sourceRoot: sourceMapData.sourceMapSourceRoot,
sources: sourceMapData.sourceMapSources,
names: sourceMapData.sourceMapNames,
mappings: sourceMapData.sourceMapMappings,
sourcesContent: sourceMapData.sourceMapSourcesContent,
});
return JSON.stringify(generateMap());
}
/**