mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Candidate sectional sourcemap emit implementation
This commit is contained in:
parent
2cb46407b1
commit
8adbf85e0e
@ -2585,16 +2585,19 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createUnparsedSourceFile(text: string): UnparsedSource {
|
||||
export function createUnparsedSourceFile(text: string, map?: string): UnparsedSource {
|
||||
const node = <UnparsedSource>createNode(SyntaxKind.UnparsedSource);
|
||||
node.text = text;
|
||||
node.sourceMapText = map;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createInputFiles(javascript: string, declaration: string): InputFiles {
|
||||
export function createInputFiles(javascript: string, declaration: string, javascriptMapText?: string, declarationMapText?: string): InputFiles {
|
||||
const node = <InputFiles>createNode(SyntaxKind.InputFiles);
|
||||
node.javascriptText = javascript;
|
||||
node.javascriptMapText = javascriptMapText;
|
||||
node.declarationText = declaration;
|
||||
node.declarationMapText = declarationMapText;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@ -1192,8 +1192,10 @@ namespace ts {
|
||||
|
||||
const dtsFilename = changeExtension(resolvedRefOpts.options.outFile, ".d.ts");
|
||||
const js = host.readFile(resolvedRefOpts.options.outFile) || `/* Input file ${resolvedRefOpts.options.outFile} was missing */\r\n`;
|
||||
const jsMap = host.readFile(resolvedRefOpts.options.outFile + ".map"); // TODO: try to read sourceMappingUrl comment from the js file
|
||||
const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`;
|
||||
const node = createInputFiles(js, dts);
|
||||
const dtsMap = host.readFile(dtsFilename + ".map");
|
||||
const node = createInputFiles(js, dts, jsMap, dtsMap);
|
||||
nodes.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -180,7 +180,7 @@ namespace ts {
|
||||
}
|
||||
), mapDefined(node.prepends, prepend => {
|
||||
if (prepend.kind === SyntaxKind.InputFiles) {
|
||||
return createUnparsedSourceFile(prepend.declarationText);
|
||||
return createUnparsedSourceFile(prepend.declarationText, prepend.declarationMapText);
|
||||
}
|
||||
}));
|
||||
bundle.syntheticFileReferences = [];
|
||||
|
||||
@ -100,7 +100,7 @@ namespace ts {
|
||||
function transformBundle(node: Bundle) {
|
||||
return createBundle(node.sourceFiles.map(transformSourceFile), mapDefined(node.prepends, prepend => {
|
||||
if (prepend.kind === SyntaxKind.InputFiles) {
|
||||
return createUnparsedSourceFile(prepend.javascriptText);
|
||||
return createUnparsedSourceFile(prepend.javascriptText, prepend.javascriptMapText);
|
||||
}
|
||||
return prepend;
|
||||
}));
|
||||
|
||||
@ -2652,12 +2652,15 @@ namespace ts {
|
||||
export interface InputFiles extends Node {
|
||||
kind: SyntaxKind.InputFiles;
|
||||
javascriptText: string;
|
||||
javascriptMapText?: string;
|
||||
declarationText: string;
|
||||
declarationMapText?: string;
|
||||
}
|
||||
|
||||
export interface UnparsedSource extends Node {
|
||||
kind: SyntaxKind.UnparsedSource;
|
||||
text: string;
|
||||
sourceMapText?: string;
|
||||
}
|
||||
|
||||
export interface JsonSourceFile extends SourceFile {
|
||||
|
||||
@ -5454,6 +5454,10 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.Bundle;
|
||||
}
|
||||
|
||||
export function isUnparsedSource(node: Node): node is UnparsedSource {
|
||||
return node.kind === SyntaxKind.UnparsedSource;
|
||||
}
|
||||
|
||||
// JSDoc
|
||||
|
||||
export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression {
|
||||
|
||||
@ -1669,11 +1669,14 @@ declare namespace ts {
|
||||
interface InputFiles extends Node {
|
||||
kind: SyntaxKind.InputFiles;
|
||||
javascriptText: string;
|
||||
javascriptMapText?: string;
|
||||
declarationText: string;
|
||||
declarationMapText?: string;
|
||||
}
|
||||
interface UnparsedSource extends Node {
|
||||
kind: SyntaxKind.UnparsedSource;
|
||||
text: string;
|
||||
sourceMapText?: string;
|
||||
}
|
||||
interface JsonSourceFile extends SourceFile {
|
||||
statements: NodeArray<JsonObjectExpressionStatement>;
|
||||
@ -3371,6 +3374,7 @@ declare namespace ts {
|
||||
function isEnumMember(node: Node): node is EnumMember;
|
||||
function isSourceFile(node: Node): node is SourceFile;
|
||||
function isBundle(node: Node): node is Bundle;
|
||||
function isUnparsedSource(node: Node): node is UnparsedSource;
|
||||
function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression;
|
||||
function isJSDocAllType(node: JSDocAllType): node is JSDocAllType;
|
||||
function isJSDocUnknownType(node: Node): node is JSDocUnknownType;
|
||||
@ -3826,8 +3830,8 @@ declare namespace ts {
|
||||
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
|
||||
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
|
||||
function createBundle(sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource | InputFiles>): Bundle;
|
||||
function createUnparsedSourceFile(text: string): UnparsedSource;
|
||||
function createInputFiles(javascript: string, declaration: string): InputFiles;
|
||||
function createUnparsedSourceFile(text: string, map?: string): UnparsedSource;
|
||||
function createInputFiles(javascript: string, declaration: string, javascriptMapText?: string, declarationMapText?: string): InputFiles;
|
||||
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource>): Bundle;
|
||||
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>): CallExpression;
|
||||
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>, param: ParameterDeclaration, paramValue: Expression): CallExpression;
|
||||
|
||||
@ -1669,11 +1669,14 @@ declare namespace ts {
|
||||
interface InputFiles extends Node {
|
||||
kind: SyntaxKind.InputFiles;
|
||||
javascriptText: string;
|
||||
javascriptMapText?: string;
|
||||
declarationText: string;
|
||||
declarationMapText?: string;
|
||||
}
|
||||
interface UnparsedSource extends Node {
|
||||
kind: SyntaxKind.UnparsedSource;
|
||||
text: string;
|
||||
sourceMapText?: string;
|
||||
}
|
||||
interface JsonSourceFile extends SourceFile {
|
||||
statements: NodeArray<JsonObjectExpressionStatement>;
|
||||
@ -3371,6 +3374,7 @@ declare namespace ts {
|
||||
function isEnumMember(node: Node): node is EnumMember;
|
||||
function isSourceFile(node: Node): node is SourceFile;
|
||||
function isBundle(node: Node): node is Bundle;
|
||||
function isUnparsedSource(node: Node): node is UnparsedSource;
|
||||
function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression;
|
||||
function isJSDocAllType(node: JSDocAllType): node is JSDocAllType;
|
||||
function isJSDocUnknownType(node: Node): node is JSDocUnknownType;
|
||||
@ -3826,8 +3830,8 @@ declare namespace ts {
|
||||
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
|
||||
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
|
||||
function createBundle(sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource | InputFiles>): Bundle;
|
||||
function createUnparsedSourceFile(text: string): UnparsedSource;
|
||||
function createInputFiles(javascript: string, declaration: string): InputFiles;
|
||||
function createUnparsedSourceFile(text: string, map?: string): UnparsedSource;
|
||||
function createInputFiles(javascript: string, declaration: string, javascriptMapText?: string, declarationMapText?: string): InputFiles;
|
||||
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource>): Bundle;
|
||||
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>): CallExpression;
|
||||
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>, param: ParameterDeclaration, paramValue: Expression): CallExpression;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user