Merge pull request #27629 from Microsoft/sourceMapGenerator
Simplify source map generation
This commit is contained in:
commit
50a0174582
|
@ -1,6 +1,7 @@
|
|||
// @ts-check
|
||||
const path = require("path");
|
||||
const child_process = require("child_process");
|
||||
const fs = require("fs");
|
||||
const tsc = require("gulp-typescript");
|
||||
const Vinyl = require("vinyl");
|
||||
const { Duplex, Readable } = require("stream");
|
||||
|
@ -42,7 +43,10 @@ function createProject(tsConfigFileName, settings, options) {
|
|||
getVinyl(path) { return inputs.get(path); },
|
||||
getSourceFile(fileName) { return sourceFiles.get(fileName); },
|
||||
createSourceFile(fileName, text, languageVersion) {
|
||||
if (text === undefined) throw new Error("File not cached.");
|
||||
if (text === undefined) {
|
||||
text = fs.readFileSync(fileName, "utf8");
|
||||
}
|
||||
|
||||
/** @type {protocol.SourceFile} */
|
||||
let file;
|
||||
if (options.parse) {
|
||||
|
|
|
@ -450,7 +450,7 @@ namespace ts {
|
|||
assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile);
|
||||
if (!targetSourceFile) {
|
||||
// Emit and report any errors we ran into.
|
||||
let sourceMaps: SourceMapData[] = [];
|
||||
let sourceMaps: SourceMapEmitResult[] = [];
|
||||
let emitSkipped = false;
|
||||
let diagnostics: Diagnostic[] | undefined;
|
||||
let emittedFiles: string[] = [];
|
||||
|
|
|
@ -3141,7 +3141,7 @@ namespace ts {
|
|||
const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName);
|
||||
const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true });
|
||||
const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
|
||||
printer.writeNode(EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, writer); // TODO: GH#18217
|
||||
printer.writeNode(EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, getTrailingSemicolonOmittingWriter(writer)); // TODO: GH#18217
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,431 +0,0 @@
|
|||
/* @internal */
|
||||
namespace ts {
|
||||
export interface CommentWriter {
|
||||
reset(): void;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
setWriter(writer: EmitTextWriter | undefined): void;
|
||||
emitNodeWithComments(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node) => void): void;
|
||||
emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void;
|
||||
emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean): void;
|
||||
emitLeadingCommentsOfPosition(pos: number): void;
|
||||
}
|
||||
|
||||
export function createCommentWriter(printerOptions: PrinterOptions, emitPos: ((pos: number) => void) | undefined): CommentWriter {
|
||||
const extendedDiagnostics = printerOptions.extendedDiagnostics;
|
||||
const newLine = getNewLineCharacter(printerOptions);
|
||||
let writer: EmitTextWriter;
|
||||
let containerPos = -1;
|
||||
let containerEnd = -1;
|
||||
let declarationListContainerEnd = -1;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentText: string;
|
||||
let currentLineMap: ReadonlyArray<number>;
|
||||
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[] | undefined;
|
||||
let hasWrittenComment = false;
|
||||
let disabled: boolean = !!printerOptions.removeComments;
|
||||
|
||||
return {
|
||||
reset,
|
||||
setWriter,
|
||||
setSourceFile,
|
||||
emitNodeWithComments,
|
||||
emitBodyWithDetachedComments,
|
||||
emitTrailingCommentsOfPosition,
|
||||
emitLeadingCommentsOfPosition,
|
||||
};
|
||||
|
||||
function emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
if (disabled) {
|
||||
emitCallback(hint, node);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
hasWrittenComment = false;
|
||||
|
||||
const emitNode = node.emitNode;
|
||||
const emitFlags = emitNode && emitNode.flags || 0;
|
||||
const { pos, end } = emitNode && emitNode.commentRange || node;
|
||||
if ((pos < 0 && end < 0) || (pos === end)) {
|
||||
// Both pos and end are synthesized, so just emit the node without comments.
|
||||
emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback);
|
||||
}
|
||||
else {
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("preEmitNodeWithComment");
|
||||
}
|
||||
|
||||
const isEmittedNode = node.kind !== SyntaxKind.NotEmittedStatement;
|
||||
// We have to explicitly check that the node is JsxText because if the compilerOptions.jsx is "preserve" we will not do any transformation.
|
||||
// It is expensive to walk entire tree just to set one kind of node to have no comments.
|
||||
const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0 || node.kind === SyntaxKind.JsxText;
|
||||
const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0 || node.kind === SyntaxKind.JsxText;
|
||||
|
||||
// Emit leading comments if the position is not synthesized and the node
|
||||
// has not opted out from emitting leading comments.
|
||||
if (!skipLeadingComments) {
|
||||
emitLeadingComments(pos, isEmittedNode);
|
||||
}
|
||||
|
||||
// Save current container state on the stack.
|
||||
const savedContainerPos = containerPos;
|
||||
const savedContainerEnd = containerEnd;
|
||||
const savedDeclarationListContainerEnd = declarationListContainerEnd;
|
||||
|
||||
if (!skipLeadingComments || (pos >= 0 && (emitFlags & EmitFlags.NoLeadingComments) !== 0)) {
|
||||
// Advance the container position of comments get emitted or if they've been disabled explicitly using NoLeadingComments.
|
||||
containerPos = pos;
|
||||
}
|
||||
|
||||
if (!skipTrailingComments || (end >= 0 && (emitFlags & EmitFlags.NoTrailingComments) !== 0)) {
|
||||
// As above.
|
||||
containerEnd = end;
|
||||
|
||||
// To avoid invalid comment emit in a down-level binding pattern, we
|
||||
// keep track of the last declaration list container's end
|
||||
if (node.kind === SyntaxKind.VariableDeclarationList) {
|
||||
declarationListContainerEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "preEmitNodeWithComment");
|
||||
}
|
||||
|
||||
emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("postEmitNodeWithComment");
|
||||
}
|
||||
|
||||
// Restore previous container state.
|
||||
containerPos = savedContainerPos;
|
||||
containerEnd = savedContainerEnd;
|
||||
declarationListContainerEnd = savedDeclarationListContainerEnd;
|
||||
|
||||
// Emit trailing comments if the position is not synthesized and the node
|
||||
// has not opted out from emitting leading comments and is an emitted node.
|
||||
if (!skipTrailingComments && isEmittedNode) {
|
||||
emitTrailingComments(end);
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "postEmitNodeWithComment");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitNodeWithSynthesizedComments(hint: EmitHint, node: Node, emitNode: EmitNode | undefined, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
const leadingComments = emitNode && emitNode.leadingComments;
|
||||
if (some(leadingComments)) {
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("preEmitNodeWithSynthesizedComments");
|
||||
}
|
||||
|
||||
forEach(leadingComments, emitLeadingSynthesizedComment);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "preEmitNodeWithSynthesizedComments");
|
||||
}
|
||||
}
|
||||
|
||||
emitNodeWithNestedComments(hint, node, emitFlags, emitCallback);
|
||||
|
||||
const trailingComments = emitNode && emitNode.trailingComments;
|
||||
if (some(trailingComments)) {
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("postEmitNodeWithSynthesizedComments");
|
||||
}
|
||||
|
||||
forEach(trailingComments, emitTrailingSynthesizedComment);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "postEmitNodeWithSynthesizedComments");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitLeadingSynthesizedComment(comment: SynthesizedComment) {
|
||||
if (comment.kind === SyntaxKind.SingleLineCommentTrivia) {
|
||||
writer.writeLine();
|
||||
}
|
||||
writeSynthesizedComment(comment);
|
||||
if (comment.hasTrailingNewLine || comment.kind === SyntaxKind.SingleLineCommentTrivia) {
|
||||
writer.writeLine();
|
||||
}
|
||||
else {
|
||||
writer.write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function emitTrailingSynthesizedComment(comment: SynthesizedComment) {
|
||||
if (!writer.isAtStartOfLine()) {
|
||||
writer.write(" ");
|
||||
}
|
||||
writeSynthesizedComment(comment);
|
||||
if (comment.hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
function writeSynthesizedComment(comment: SynthesizedComment) {
|
||||
const text = formatSynthesizedComment(comment);
|
||||
const lineMap = comment.kind === SyntaxKind.MultiLineCommentTrivia ? computeLineStarts(text) : undefined;
|
||||
writeCommentRange(text, lineMap!, writer, 0, text.length, newLine);
|
||||
}
|
||||
|
||||
function formatSynthesizedComment(comment: SynthesizedComment) {
|
||||
return comment.kind === SyntaxKind.MultiLineCommentTrivia
|
||||
? `/*${comment.text}*/`
|
||||
: `//${comment.text}`;
|
||||
}
|
||||
|
||||
function emitNodeWithNestedComments(hint: EmitHint, node: Node, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
if (emitFlags & EmitFlags.NoNestedComments) {
|
||||
disabled = true;
|
||||
emitCallback(hint, node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(hint, node);
|
||||
}
|
||||
}
|
||||
|
||||
function emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) {
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("preEmitBodyWithDetachedComments");
|
||||
}
|
||||
|
||||
const { pos, end } = detachedRange;
|
||||
const emitFlags = getEmitFlags(node);
|
||||
const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0;
|
||||
const skipTrailingComments = disabled || end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0;
|
||||
|
||||
if (!skipLeadingComments) {
|
||||
emitDetachedCommentsAndUpdateCommentsInfo(detachedRange);
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "preEmitBodyWithDetachedComments");
|
||||
}
|
||||
|
||||
if (emitFlags & EmitFlags.NoNestedComments && !disabled) {
|
||||
disabled = true;
|
||||
emitCallback(node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(node);
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("beginEmitBodyWithDetachedComments");
|
||||
}
|
||||
|
||||
if (!skipTrailingComments) {
|
||||
emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true);
|
||||
if (hasWrittenComment && !writer.isAtStartOfLine()) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "beginEmitBodyWithDetachedComments");
|
||||
}
|
||||
}
|
||||
|
||||
function emitLeadingComments(pos: number, isEmittedNode: boolean) {
|
||||
hasWrittenComment = false;
|
||||
|
||||
if (isEmittedNode) {
|
||||
forEachLeadingCommentToEmit(pos, emitLeadingComment);
|
||||
}
|
||||
else if (pos === 0) {
|
||||
// If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node,
|
||||
// unless it is a triple slash comment at the top of the file.
|
||||
// For Example:
|
||||
// /// <reference-path ...>
|
||||
// declare var x;
|
||||
// /// <reference-path ...>
|
||||
// interface F {}
|
||||
// The first /// will NOT be removed while the second one will be removed even though both node will not be emitted
|
||||
forEachLeadingCommentToEmit(pos, emitTripleSlashLeadingComment);
|
||||
}
|
||||
}
|
||||
|
||||
function emitTripleSlashLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) {
|
||||
if (isTripleSlashComment(commentPos, commentEnd)) {
|
||||
emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos);
|
||||
}
|
||||
}
|
||||
|
||||
function shouldWriteComment(text: string, pos: number) {
|
||||
if (printerOptions.onlyPrintJsDocStyle) {
|
||||
return (isJSDocLikeText(text, pos) || isPinnedComment(text, pos));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) {
|
||||
if (!shouldWriteComment(currentText, commentPos)) return;
|
||||
if (!hasWrittenComment) {
|
||||
emitNewLineBeforeLeadingCommentOfPosition(currentLineMap, writer, rangePos, commentPos);
|
||||
hasWrittenComment = true;
|
||||
}
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
if (emitPos) emitPos(commentPos);
|
||||
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
|
||||
if (emitPos) emitPos(commentEnd);
|
||||
|
||||
if (hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
}
|
||||
else if (kind === SyntaxKind.MultiLineCommentTrivia) {
|
||||
writer.write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function emitLeadingCommentsOfPosition(pos: number) {
|
||||
if (disabled || pos === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitLeadingComments(pos, /*isEmittedNode*/ true);
|
||||
}
|
||||
|
||||
function emitTrailingComments(pos: number) {
|
||||
forEachTrailingCommentToEmit(pos, emitTrailingComment);
|
||||
}
|
||||
|
||||
function emitTrailingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
|
||||
if (!shouldWriteComment(currentText, commentPos)) return;
|
||||
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/
|
||||
if (!writer.isAtStartOfLine()) {
|
||||
writer.write(" ");
|
||||
}
|
||||
|
||||
if (emitPos) emitPos(commentPos);
|
||||
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
|
||||
if (emitPos) emitPos(commentEnd);
|
||||
|
||||
if (hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
function emitTrailingCommentsOfPosition(pos: number, prefixSpace?: boolean) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("beforeEmitTrailingCommentsOfPosition");
|
||||
}
|
||||
|
||||
forEachTrailingCommentToEmit(pos, prefixSpace ? emitTrailingComment : emitTrailingCommentOfPosition);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "beforeEmitTrailingCommentsOfPosition");
|
||||
}
|
||||
}
|
||||
|
||||
function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
|
||||
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
|
||||
|
||||
if (emitPos) emitPos(commentPos);
|
||||
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
|
||||
if (emitPos) emitPos(commentEnd);
|
||||
|
||||
if (hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
}
|
||||
else {
|
||||
writer.write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function forEachLeadingCommentToEmit(pos: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) {
|
||||
// Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments
|
||||
if (containerPos === -1 || pos !== containerPos) {
|
||||
if (hasDetachedComments(pos)) {
|
||||
forEachLeadingCommentWithoutDetachedComments(cb);
|
||||
}
|
||||
else {
|
||||
forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function forEachTrailingCommentToEmit(end: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) => void) {
|
||||
// Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments
|
||||
if (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) {
|
||||
forEachTrailingCommentRange(currentText, end, cb);
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
currentSourceFile = undefined!;
|
||||
currentText = undefined!;
|
||||
currentLineMap = undefined!;
|
||||
detachedCommentsInfo = undefined;
|
||||
}
|
||||
|
||||
function setWriter(output: EmitTextWriter): void {
|
||||
writer = output;
|
||||
}
|
||||
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
currentSourceFile = sourceFile;
|
||||
currentText = currentSourceFile.text;
|
||||
currentLineMap = getLineStarts(currentSourceFile);
|
||||
detachedCommentsInfo = undefined;
|
||||
}
|
||||
|
||||
function hasDetachedComments(pos: number) {
|
||||
return detachedCommentsInfo !== undefined && last(detachedCommentsInfo).nodePos === pos;
|
||||
}
|
||||
|
||||
function forEachLeadingCommentWithoutDetachedComments(cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) {
|
||||
// get the leading comments from detachedPos
|
||||
const pos = last(detachedCommentsInfo!).detachedCommentEndPos;
|
||||
if (detachedCommentsInfo!.length - 1) {
|
||||
detachedCommentsInfo!.pop();
|
||||
}
|
||||
else {
|
||||
detachedCommentsInfo = undefined;
|
||||
}
|
||||
|
||||
forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos);
|
||||
}
|
||||
|
||||
function emitDetachedCommentsAndUpdateCommentsInfo(range: TextRange) {
|
||||
const currentDetachedCommentInfo = emitDetachedComments(currentText, currentLineMap, writer, writeComment, range, newLine, disabled);
|
||||
if (currentDetachedCommentInfo) {
|
||||
if (detachedCommentsInfo) {
|
||||
detachedCommentsInfo.push(currentDetachedCommentInfo);
|
||||
}
|
||||
else {
|
||||
detachedCommentsInfo = [currentDetachedCommentInfo];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) {
|
||||
if (!shouldWriteComment(currentText, commentPos)) return;
|
||||
if (emitPos) emitPos(commentPos);
|
||||
writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine);
|
||||
if (emitPos) emitPos(commentEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given comment is a triple-slash
|
||||
*
|
||||
* @return true if the comment is a triple-slash comment else false
|
||||
*/
|
||||
function isTripleSlashComment(commentPos: number, commentEnd: number) {
|
||||
return isRecognizedTripleSlashComment(currentText, commentPos, commentEnd);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1061,10 +1061,10 @@ namespace ts {
|
|||
/**
|
||||
* Stable sort of an array. Elements equal to each other maintain their relative position in the array.
|
||||
*/
|
||||
export function stableSort<T>(array: ReadonlyArray<T>, comparer: Comparer<T>) {
|
||||
export function stableSort<T>(array: ReadonlyArray<T>, comparer: Comparer<T>): SortedReadonlyArray<T> {
|
||||
const indices = array.map((_, i) => i);
|
||||
stableSortIndices(array, indices, comparer);
|
||||
return indices.map(i => array[i]);
|
||||
return indices.map(i => array[i]) as SortedArray<T> as SortedReadonlyArray<T>;
|
||||
}
|
||||
|
||||
export function rangeEquals<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>, pos: number, end: number) {
|
||||
|
@ -1156,13 +1156,26 @@ namespace ts {
|
|||
* @param offset An offset into `array` at which to start the search.
|
||||
*/
|
||||
export function binarySearch<T, U>(array: ReadonlyArray<T>, value: T, keySelector: (v: T) => U, keyComparer: Comparer<U>, offset?: number): number {
|
||||
if (!array || array.length === 0) {
|
||||
return binarySearchKey(array, keySelector(value), keySelector, keyComparer, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a binary search, finding the index at which an object with `key` occurs in `array`.
|
||||
* If no such index is found, returns the 2's-complement of first index at which
|
||||
* `array[index]` exceeds `key`.
|
||||
* @param array A sorted array whose first element must be no larger than number
|
||||
* @param key The key to be searched for in the array.
|
||||
* @param keySelector A callback used to select the search key from each element of `array`.
|
||||
* @param keyComparer A callback used to compare two keys in a sorted array.
|
||||
* @param offset An offset into `array` at which to start the search.
|
||||
*/
|
||||
export function binarySearchKey<T, U>(array: ReadonlyArray<T>, key: U, keySelector: (v: T) => U, keyComparer: Comparer<U>, offset?: number): number {
|
||||
if (!some(array)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let low = offset || 0;
|
||||
let high = array.length - 1;
|
||||
const key = keySelector(value);
|
||||
while (low <= high) {
|
||||
const middle = low + ((high - low) >> 1);
|
||||
const midKey = keySelector(array[middle]);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,6 +19,41 @@ namespace ts.performance {
|
|||
let marks: Map<number>;
|
||||
let measures: Map<number>;
|
||||
|
||||
export interface Timer {
|
||||
enter(): void;
|
||||
exit(): void;
|
||||
}
|
||||
|
||||
export function createTimerIf(condition: boolean, measureName: string, startMarkName: string, endMarkName: string) {
|
||||
return condition ? createTimer(measureName, startMarkName, endMarkName) : nullTimer;
|
||||
}
|
||||
|
||||
export function createTimer(measureName: string, startMarkName: string, endMarkName: string): Timer {
|
||||
let enterCount = 0;
|
||||
return {
|
||||
enter,
|
||||
exit
|
||||
};
|
||||
|
||||
function enter() {
|
||||
if (++enterCount === 1) {
|
||||
mark(startMarkName);
|
||||
}
|
||||
}
|
||||
|
||||
function exit() {
|
||||
if (--enterCount === 0) {
|
||||
mark(endMarkName);
|
||||
measure(measureName, startMarkName, endMarkName);
|
||||
}
|
||||
else if (enterCount < 0) {
|
||||
Debug.fail("enter/exit count does not match.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const nullTimer: Timer = { enter: noop, exit: noop };
|
||||
|
||||
/**
|
||||
* Marks a performance event.
|
||||
*
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,376 +0,0 @@
|
|||
/* @internal */
|
||||
namespace ts {
|
||||
export interface SourceFileLikeCache {
|
||||
get(path: Path): SourceFileLike | undefined;
|
||||
}
|
||||
|
||||
export function createSourceFileLikeCache(host: { readFile?: (path: string) => string | undefined, fileExists?: (path: string) => boolean }): SourceFileLikeCache {
|
||||
const cached = createMap<SourceFileLike>();
|
||||
return {
|
||||
get(path: Path) {
|
||||
if (cached.has(path)) {
|
||||
return cached.get(path);
|
||||
}
|
||||
if (!host.fileExists || !host.readFile || !host.fileExists(path)) return;
|
||||
// And failing that, check the disk
|
||||
const text = host.readFile(path)!; // TODO: GH#18217
|
||||
const file = {
|
||||
text,
|
||||
lineMap: undefined,
|
||||
getLineAndCharacterOfPosition(pos: number) {
|
||||
return computeLineAndCharacterOfPosition(getLineStarts(this), pos);
|
||||
}
|
||||
} as SourceFileLike;
|
||||
cached.set(path, file);
|
||||
return file;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
namespace ts.sourcemaps {
|
||||
export interface SourceMapData {
|
||||
version?: number;
|
||||
file?: string;
|
||||
sourceRoot?: string;
|
||||
sources: string[];
|
||||
sourcesContent?: (string | null)[];
|
||||
names?: string[];
|
||||
mappings: string;
|
||||
}
|
||||
|
||||
export interface SourceMappableLocation {
|
||||
fileName: string;
|
||||
position: number;
|
||||
}
|
||||
|
||||
export interface SourceMapper {
|
||||
getOriginalPosition(input: SourceMappableLocation): SourceMappableLocation;
|
||||
getGeneratedPosition(input: SourceMappableLocation): SourceMappableLocation;
|
||||
}
|
||||
|
||||
export const identitySourceMapper = { getOriginalPosition: identity, getGeneratedPosition: identity };
|
||||
|
||||
export interface SourceMapDecodeHost {
|
||||
readFile(path: string): string | undefined;
|
||||
fileExists(path: string): boolean;
|
||||
getCanonicalFileName(path: string): string;
|
||||
log(text: string): void;
|
||||
useCaseSensitiveFileNames: boolean;
|
||||
}
|
||||
|
||||
export function decode(host: SourceMapDecodeHost, mapPath: string, map: SourceMapData, program?: Program, fallbackCache = createSourceFileLikeCache(host)): SourceMapper {
|
||||
const currentDirectory = getDirectoryPath(mapPath);
|
||||
const sourceRoot = map.sourceRoot ? getNormalizedAbsolutePath(map.sourceRoot, currentDirectory) : currentDirectory;
|
||||
let decodedMappings: ProcessedSourceMapPosition[];
|
||||
let generatedOrderedMappings: ProcessedSourceMapPosition[];
|
||||
let sourceOrderedMappings: ProcessedSourceMapPosition[];
|
||||
|
||||
return {
|
||||
getOriginalPosition,
|
||||
getGeneratedPosition
|
||||
};
|
||||
|
||||
function getGeneratedPosition(loc: SourceMappableLocation): SourceMappableLocation {
|
||||
const maps = getSourceOrderedMappings();
|
||||
if (!length(maps)) return loc;
|
||||
let targetIndex = binarySearch(maps, { sourcePath: loc.fileName, sourcePosition: loc.position }, identity, compareProcessedPositionSourcePositions);
|
||||
if (targetIndex < 0 && maps.length > 0) {
|
||||
// if no exact match, closest is 2's compliment of result
|
||||
targetIndex = ~targetIndex;
|
||||
}
|
||||
if (!maps[targetIndex] || comparePaths(loc.fileName, maps[targetIndex].sourcePath, sourceRoot, !host.useCaseSensitiveFileNames) !== 0) {
|
||||
return loc;
|
||||
}
|
||||
return { fileName: getNormalizedAbsolutePath(map.file!, sourceRoot), position: maps[targetIndex].emittedPosition }; // Closest pos
|
||||
}
|
||||
|
||||
function getOriginalPosition(loc: SourceMappableLocation): SourceMappableLocation {
|
||||
const maps = getGeneratedOrderedMappings();
|
||||
if (!length(maps)) return loc;
|
||||
let targetIndex = binarySearch(maps, { emittedPosition: loc.position }, identity, compareProcessedPositionEmittedPositions);
|
||||
if (targetIndex < 0 && maps.length > 0) {
|
||||
// if no exact match, closest is 2's compliment of result
|
||||
targetIndex = ~targetIndex;
|
||||
}
|
||||
return { fileName: getNormalizedAbsolutePath(maps[targetIndex].sourcePath, sourceRoot), position: maps[targetIndex].sourcePosition }; // Closest pos
|
||||
}
|
||||
|
||||
function getSourceFileLike(fileName: string, location: string): SourceFileLike | undefined {
|
||||
// Lookup file in program, if provided
|
||||
const path = toPath(fileName, location, host.getCanonicalFileName);
|
||||
const file = program && program.getSourceFileByPath(path);
|
||||
// file returned here could be .d.ts when asked for .ts file if projectReferences and module resolution created this source file
|
||||
if (!file || file.resolvedPath !== path) {
|
||||
// Otherwise check the cache (which may hit disk)
|
||||
return fallbackCache.get(path);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
function getPositionOfLineAndCharacterUsingName(fileName: string, directory: string, line: number, character: number) {
|
||||
const file = getSourceFileLike(fileName, directory);
|
||||
if (!file) {
|
||||
return -1;
|
||||
}
|
||||
return getPositionOfLineAndCharacter(file, line, character);
|
||||
}
|
||||
|
||||
function getDecodedMappings() {
|
||||
return decodedMappings || (decodedMappings = calculateDecodedMappings(map, processPosition, host));
|
||||
}
|
||||
|
||||
function getSourceOrderedMappings() {
|
||||
return sourceOrderedMappings || (sourceOrderedMappings = getDecodedMappings().slice().sort(compareProcessedPositionSourcePositions));
|
||||
}
|
||||
|
||||
function getGeneratedOrderedMappings() {
|
||||
return generatedOrderedMappings || (generatedOrderedMappings = getDecodedMappings().slice().sort(compareProcessedPositionEmittedPositions));
|
||||
}
|
||||
|
||||
function compareProcessedPositionSourcePositions(a: ProcessedSourceMapPosition, b: ProcessedSourceMapPosition) {
|
||||
return comparePaths(a.sourcePath, b.sourcePath, sourceRoot, !host.useCaseSensitiveFileNames) ||
|
||||
compareValues(a.sourcePosition, b.sourcePosition);
|
||||
}
|
||||
|
||||
function compareProcessedPositionEmittedPositions(a: ProcessedSourceMapPosition, b: ProcessedSourceMapPosition) {
|
||||
return compareValues(a.emittedPosition, b.emittedPosition);
|
||||
}
|
||||
|
||||
function processPosition(position: RawSourceMapPosition): ProcessedSourceMapPosition {
|
||||
const sourcePath = map.sources[position.sourceIndex];
|
||||
return {
|
||||
emittedPosition: getPositionOfLineAndCharacterUsingName(map.file!, currentDirectory, position.emittedLine, position.emittedColumn),
|
||||
sourcePosition: getPositionOfLineAndCharacterUsingName(sourcePath, sourceRoot, position.sourceLine, position.sourceColumn),
|
||||
sourcePath,
|
||||
// TODO: Consider using `name` field to remap the expected identifier to scan for renames to handle another tool renaming oout output
|
||||
// name: position.nameIndex ? map.names[position.nameIndex] : undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface MappingsDecoder extends Iterator<SourceMapSpan> {
|
||||
readonly decodingIndex: number;
|
||||
readonly error: string | undefined;
|
||||
readonly lastSpan: SourceMapSpan;
|
||||
}
|
||||
|
||||
export function decodeMappings(map: SourceMapData): MappingsDecoder {
|
||||
const state: DecoderState = {
|
||||
encodedText: map.mappings,
|
||||
currentNameIndex: undefined,
|
||||
sourceMapNamesLength: map.names ? map.names.length : undefined,
|
||||
currentEmittedColumn: 0,
|
||||
currentEmittedLine: 0,
|
||||
currentSourceColumn: 0,
|
||||
currentSourceLine: 0,
|
||||
currentSourceIndex: 0,
|
||||
decodingIndex: 0
|
||||
};
|
||||
function captureSpan(): SourceMapSpan {
|
||||
return {
|
||||
emittedColumn: state.currentEmittedColumn,
|
||||
emittedLine: state.currentEmittedLine,
|
||||
sourceColumn: state.currentSourceColumn,
|
||||
sourceIndex: state.currentSourceIndex,
|
||||
sourceLine: state.currentSourceLine,
|
||||
nameIndex: state.currentNameIndex
|
||||
};
|
||||
}
|
||||
return {
|
||||
get decodingIndex() { return state.decodingIndex; },
|
||||
get error() { return state.error; },
|
||||
get lastSpan() { return captureSpan(); },
|
||||
next() {
|
||||
if (hasCompletedDecoding(state) || state.error) return { done: true, value: undefined as never };
|
||||
if (!decodeSinglePosition(state)) return { done: true, value: undefined as never };
|
||||
return { done: false, value: captureSpan() };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function calculateDecodedMappings<T>(map: SourceMapData, processPosition: (position: RawSourceMapPosition) => T, host?: { log?(s: string): void }): T[] {
|
||||
const decoder = decodeMappings(map);
|
||||
const positions = arrayFrom(decoder, processPosition);
|
||||
if (decoder.error) {
|
||||
if (host && host.log) {
|
||||
host.log(`Encountered error while decoding sourcemap: ${decoder.error}`);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
return positions;
|
||||
}
|
||||
|
||||
interface ProcessedSourceMapPosition {
|
||||
emittedPosition: number;
|
||||
sourcePosition: number;
|
||||
sourcePath: string;
|
||||
}
|
||||
|
||||
interface RawSourceMapPosition {
|
||||
emittedLine: number;
|
||||
emittedColumn: number;
|
||||
sourceLine: number;
|
||||
sourceColumn: number;
|
||||
sourceIndex: number;
|
||||
nameIndex?: number;
|
||||
}
|
||||
|
||||
interface DecoderState {
|
||||
decodingIndex: number;
|
||||
currentEmittedLine: number;
|
||||
currentEmittedColumn: number;
|
||||
currentSourceLine: number;
|
||||
currentSourceColumn: number;
|
||||
currentSourceIndex: number;
|
||||
currentNameIndex: number | undefined;
|
||||
encodedText: string;
|
||||
sourceMapNamesLength?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
function hasCompletedDecoding(state: DecoderState) {
|
||||
return state.decodingIndex === state.encodedText.length;
|
||||
}
|
||||
|
||||
function decodeSinglePosition(state: DecoderState): boolean {
|
||||
while (state.decodingIndex < state.encodedText.length) {
|
||||
const char = state.encodedText.charCodeAt(state.decodingIndex);
|
||||
if (char === CharacterCodes.semicolon) {
|
||||
// New line
|
||||
state.currentEmittedLine++;
|
||||
state.currentEmittedColumn = 0;
|
||||
state.decodingIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (char === CharacterCodes.comma) {
|
||||
// Next entry is on same line - no action needed
|
||||
state.decodingIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read the current position
|
||||
// 1. Column offset from prev read jsColumn
|
||||
state.currentEmittedColumn += base64VLQFormatDecode();
|
||||
// Incorrect emittedColumn dont support this map
|
||||
if (createErrorIfCondition(state.currentEmittedColumn < 0, "Invalid emittedColumn found")) {
|
||||
return false;
|
||||
}
|
||||
// Dont support reading mappings that dont have information about original source and its line numbers
|
||||
if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after emitted column")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Relative sourceIndex
|
||||
state.currentSourceIndex += base64VLQFormatDecode();
|
||||
// Incorrect sourceIndex dont support this map
|
||||
if (createErrorIfCondition(state.currentSourceIndex < 0, "Invalid sourceIndex found")) {
|
||||
return false;
|
||||
}
|
||||
// Dont support reading mappings that dont have information about original source position
|
||||
if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after sourceIndex")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. Relative sourceLine 0 based
|
||||
state.currentSourceLine += base64VLQFormatDecode();
|
||||
// Incorrect sourceLine dont support this map
|
||||
if (createErrorIfCondition(state.currentSourceLine < 0, "Invalid sourceLine found")) {
|
||||
return false;
|
||||
}
|
||||
// Dont support reading mappings that dont have information about original source and its line numbers
|
||||
if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after emitted Line")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. Relative sourceColumn 0 based
|
||||
state.currentSourceColumn += base64VLQFormatDecode();
|
||||
// Incorrect sourceColumn dont support this map
|
||||
if (createErrorIfCondition(state.currentSourceColumn < 0, "Invalid sourceLine found")) {
|
||||
return false;
|
||||
}
|
||||
// 5. Check if there is name:
|
||||
if (!isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex)) {
|
||||
if (state.currentNameIndex === undefined) {
|
||||
state.currentNameIndex = 0;
|
||||
}
|
||||
state.currentNameIndex += base64VLQFormatDecode();
|
||||
// Incorrect nameIndex dont support this map
|
||||
// TODO: If we start using `name`s, issue errors when they aren't correct in the sourcemap
|
||||
// if (createErrorIfCondition(state.currentNameIndex < 0 || state.currentNameIndex >= state.sourceMapNamesLength, "Invalid name index for the source map entry")) {
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
// Dont support reading mappings that dont have information about original source and its line numbers
|
||||
if (createErrorIfCondition(!isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: There are more entries after " + (state.currentNameIndex === undefined ? "sourceColumn" : "nameIndex"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Entry should be complete
|
||||
return true;
|
||||
}
|
||||
|
||||
createErrorIfCondition(/*condition*/ true, "No encoded entry found");
|
||||
return false;
|
||||
|
||||
function createErrorIfCondition(condition: boolean, errormsg: string) {
|
||||
if (state.error) {
|
||||
// An error was already reported
|
||||
return true;
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
state.error = errormsg;
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
function base64VLQFormatDecode(): number {
|
||||
let moreDigits = true;
|
||||
let shiftCount = 0;
|
||||
let value = 0;
|
||||
|
||||
for (; moreDigits; state.decodingIndex++) {
|
||||
if (createErrorIfCondition(state.decodingIndex >= state.encodedText.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) {
|
||||
return undefined!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
// 6 digit number
|
||||
const currentByte = base64FormatDecode(state.encodedText.charAt(state.decodingIndex));
|
||||
|
||||
// If msb is set, we still have more bits to continue
|
||||
moreDigits = (currentByte & 32) !== 0;
|
||||
|
||||
// least significant 5 bits are the next msbs in the final value.
|
||||
value = value | ((currentByte & 31) << shiftCount);
|
||||
shiftCount += 5;
|
||||
}
|
||||
|
||||
// Least significant bit if 1 represents negative and rest of the msb is actual absolute value
|
||||
if ((value & 1) === 0) {
|
||||
// + number
|
||||
value = value >> 1;
|
||||
}
|
||||
else {
|
||||
// - number
|
||||
value = value >> 1;
|
||||
value = -value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function base64FormatDecode(char: string) {
|
||||
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(char);
|
||||
}
|
||||
|
||||
function isSourceMappingSegmentEnd(encodedText: string, pos: number) {
|
||||
return (pos === encodedText.length ||
|
||||
encodedText.charCodeAt(pos) === CharacterCodes.comma ||
|
||||
encodedText.charCodeAt(pos) === CharacterCodes.semicolon);
|
||||
}
|
||||
}
|
|
@ -68,6 +68,14 @@ namespace ts {
|
|||
return transformers;
|
||||
}
|
||||
|
||||
export function noEmitSubstitution(_hint: EmitHint, node: Node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function noEmitNotification(hint: EmitHint, node: Node, callback: (hint: EmitHint, node: Node) => void) {
|
||||
callback(hint, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an array of SourceFiles by passing them through each transformer.
|
||||
*
|
||||
|
@ -87,8 +95,8 @@ namespace ts {
|
|||
let lexicalEnvironmentStackOffset = 0;
|
||||
let lexicalEnvironmentSuspended = false;
|
||||
let emitHelpers: EmitHelper[] | undefined;
|
||||
let onSubstituteNode: TransformationContext["onSubstituteNode"] = (_, node) => node;
|
||||
let onEmitNode: TransformationContext["onEmitNode"] = (hint, node, callback) => callback(hint, node);
|
||||
let onSubstituteNode: TransformationContext["onSubstituteNode"] = noEmitSubstitution;
|
||||
let onEmitNode: TransformationContext["onEmitNode"] = noEmitNotification;
|
||||
let state = TransformationState.Uninitialized;
|
||||
const diagnostics: DiagnosticWithLocation[] = [];
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"checker.ts",
|
||||
"factory.ts",
|
||||
"visitor.ts",
|
||||
"sourcemapDecoder.ts",
|
||||
"sourcemap.ts",
|
||||
"transformers/utilities.ts",
|
||||
"transformers/destructuring.ts",
|
||||
"transformers/ts.ts",
|
||||
|
@ -42,8 +42,6 @@
|
|||
"transformers/declarations/diagnostics.ts",
|
||||
"transformers/declarations.ts",
|
||||
"transformer.ts",
|
||||
"sourcemap.ts",
|
||||
"comments.ts",
|
||||
"emitter.ts",
|
||||
"watchUtilities.ts",
|
||||
"program.ts",
|
||||
|
|
|
@ -2963,16 +2963,10 @@ namespace ts {
|
|||
sourceIndex: number;
|
||||
}
|
||||
|
||||
export interface SourceMapData {
|
||||
sourceMapFilePath: string; // Where the sourcemap file is written
|
||||
jsSourceMappingURL: string; // source map URL written in the .js file
|
||||
sourceMapFile: string; // Source map's file field - .js file name
|
||||
sourceMapSourceRoot: string; // Source map's sourceRoot field - location where the sources will be present if not ""
|
||||
sourceMapSources: string[]; // Source map's sources field - list of sources that can be indexed in this source map
|
||||
sourceMapSourcesContent?: (string | null)[]; // Source map's sourcesContent field - list of the sources' text to be embedded in the source map
|
||||
inputSourceFileNames: string[]; // Input source file (which one can use on program to get the file), 1:1 mapping with the sourceMapSources list
|
||||
sourceMapNames?: string[]; // Source map's names field - list of names that can be indexed in this source map
|
||||
sourceMapMappings: string; // Source map's mapping field - encoded source map spans
|
||||
/* @internal */
|
||||
export interface SourceMapEmitResult {
|
||||
inputSourceFileNames: ReadonlyArray<string>; // Input source file (which one can use on program to get the file), 1:1 mapping with the sourceMap.sources list
|
||||
sourceMap: RawSourceMap;
|
||||
}
|
||||
|
||||
/** Return code used by getEmitOutput function to indicate status of the function */
|
||||
|
@ -2994,7 +2988,7 @@ namespace ts {
|
|||
/** Contains declaration emit diagnostics */
|
||||
diagnostics: ReadonlyArray<Diagnostic>;
|
||||
emittedFiles?: string[]; // Array of files the compiler wrote to disk
|
||||
/* @internal */ sourceMaps?: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
|
||||
/* @internal */ sourceMaps?: SourceMapEmitResult[]; // Array of sourceMapData if compiler emitted sourcemaps
|
||||
/* @internal */ exportedModulesFromDeclarationEmit?: ExportedModulesFromDeclarationEmit;
|
||||
}
|
||||
|
||||
|
@ -5217,6 +5211,7 @@ namespace ts {
|
|||
IdentifierName, // Emitting an IdentifierName
|
||||
MappedTypeParameter, // Emitting a TypeParameterDeclaration inside of a MappedTypeNode
|
||||
Unspecified, // Emitting an otherwise unspecified node
|
||||
EmbeddedStatement, // Emitting an embedded statement
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
@ -5386,8 +5381,8 @@ namespace ts {
|
|||
printBundle(bundle: Bundle): string;
|
||||
/*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
|
||||
/*@internal*/ writeList<T extends Node>(format: ListFormat, list: NodeArray<T> | undefined, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
|
||||
/*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void;
|
||||
/*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter, info?: BundleInfo): void;
|
||||
/*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void;
|
||||
/*@internal*/ writeBundle(bundle: Bundle, info: BundleInfo | undefined, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined): void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5467,15 +5462,90 @@ namespace ts {
|
|||
/*@internal*/ target?: CompilerOptions["target"];
|
||||
/*@internal*/ sourceMap?: boolean;
|
||||
/*@internal*/ inlineSourceMap?: boolean;
|
||||
/*@internal*/ inlineSources?: boolean;
|
||||
/*@internal*/ extendedDiagnostics?: boolean;
|
||||
/*@internal*/ onlyPrintJsDocStyle?: boolean;
|
||||
/*@internal*/ neverAsciiEscape?: boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface RawSourceMap {
|
||||
version: 3;
|
||||
file: string;
|
||||
sourceRoot?: string | null;
|
||||
sources: string[];
|
||||
sourcesContent?: (string | null)[] | null;
|
||||
mappings: string;
|
||||
names?: string[] | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a source map.
|
||||
*/
|
||||
/* @internal */
|
||||
export interface SourceMapGenerator {
|
||||
getSources(): ReadonlyArray<string>;
|
||||
/**
|
||||
* Adds a source to the source map.
|
||||
*/
|
||||
addSource(fileName: string): number;
|
||||
/**
|
||||
* Set the content for a source.
|
||||
*/
|
||||
setSourceContent(sourceIndex: number, content: string | null): void;
|
||||
/**
|
||||
* Adds a name.
|
||||
*/
|
||||
addName(name: string): number;
|
||||
/**
|
||||
* Adds a mapping without source information.
|
||||
*/
|
||||
addMapping(generatedLine: number, generatedCharacter: number): void;
|
||||
/**
|
||||
* Adds a mapping with source information.
|
||||
*/
|
||||
addMapping(generatedLine: number, generatedCharacter: number, sourceIndex: number, sourceLine: number, sourceCharacter: number, nameIndex?: number): void;
|
||||
/**
|
||||
* Appends a source map.
|
||||
*/
|
||||
appendSourceMap(generatedLine: number, generatedCharacter: number, sourceMap: RawSourceMap, sourceMapPath: string): void;
|
||||
/**
|
||||
* Gets the source map as a `RawSourceMap` object.
|
||||
*/
|
||||
toJSON(): RawSourceMap;
|
||||
/**
|
||||
* Gets the string representation of the source map.
|
||||
*/
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface DocumentPositionMapperHost {
|
||||
getSourceFileLike(path: Path): SourceFileLike | undefined;
|
||||
getCanonicalFileName(path: string): string;
|
||||
log?(text: string): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps positions between source and generated files.
|
||||
*/
|
||||
/* @internal */
|
||||
export interface DocumentPositionMapper {
|
||||
getSourcePosition(input: DocumentPosition): DocumentPosition;
|
||||
getGeneratedPosition(input: DocumentPosition): DocumentPosition;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface DocumentPosition {
|
||||
fileName: string;
|
||||
pos: number;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface EmitTextWriter extends SymbolWriter {
|
||||
write(s: string): void;
|
||||
writeTextOfNode(text: string, node: Node): void;
|
||||
writeTrailingSemicolon(text: string): void;
|
||||
writeComment(text: string): void;
|
||||
getText(): string;
|
||||
rawWrite(s: string): void;
|
||||
writeLiteral(s: string): void;
|
||||
|
|
|
@ -64,7 +64,6 @@ namespace ts {
|
|||
getText: () => str,
|
||||
write: writeText,
|
||||
rawWrite: writeText,
|
||||
writeTextOfNode: writeText,
|
||||
writeKeyword: writeText,
|
||||
writeOperator: writeText,
|
||||
writePunctuation: writeText,
|
||||
|
@ -73,7 +72,9 @@ namespace ts {
|
|||
writeLiteral: writeText,
|
||||
writeParameter: writeText,
|
||||
writeProperty: writeText,
|
||||
writeSymbol: writeText,
|
||||
writeSymbol: (s, _) => writeText(s),
|
||||
writeTrailingSemicolon: writeText,
|
||||
writeComment: writeText,
|
||||
getTextPos: () => str.length,
|
||||
getLine: () => 0,
|
||||
getColumn: () => 0,
|
||||
|
@ -3201,18 +3202,11 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function writeTextOfNode(text: string, node: Node) {
|
||||
const s = getTextOfNodeFromSourceText(text, node);
|
||||
write(s);
|
||||
updateLineCountAndPosFor(s);
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
return {
|
||||
write,
|
||||
rawWrite,
|
||||
writeTextOfNode,
|
||||
writeLiteral,
|
||||
writeLine,
|
||||
increaseIndent: () => { indent++; },
|
||||
|
@ -3235,7 +3229,79 @@ namespace ts {
|
|||
writePunctuation: write,
|
||||
writeSpace: write,
|
||||
writeStringLiteral: write,
|
||||
writeSymbol: write
|
||||
writeSymbol: (s, _) => write(s),
|
||||
writeTrailingSemicolon: write,
|
||||
writeComment: write
|
||||
};
|
||||
}
|
||||
|
||||
export function getTrailingSemicolonOmittingWriter(writer: EmitTextWriter): EmitTextWriter {
|
||||
let pendingTrailingSemicolon = false;
|
||||
|
||||
function commitPendingTrailingSemicolon() {
|
||||
if (pendingTrailingSemicolon) {
|
||||
writer.writeTrailingSemicolon(";");
|
||||
pendingTrailingSemicolon = false;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...writer,
|
||||
writeTrailingSemicolon() {
|
||||
pendingTrailingSemicolon = true;
|
||||
},
|
||||
writeLiteral(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeLiteral(s);
|
||||
},
|
||||
writeStringLiteral(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeStringLiteral(s);
|
||||
},
|
||||
writeSymbol(s, sym) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeSymbol(s, sym);
|
||||
},
|
||||
writePunctuation(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writePunctuation(s);
|
||||
},
|
||||
writeKeyword(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeKeyword(s);
|
||||
},
|
||||
writeOperator(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeOperator(s);
|
||||
},
|
||||
writeParameter(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeParameter(s);
|
||||
},
|
||||
writeSpace(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeSpace(s);
|
||||
},
|
||||
writeProperty(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeProperty(s);
|
||||
},
|
||||
writeComment(s) {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeComment(s);
|
||||
},
|
||||
writeLine() {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.writeLine();
|
||||
},
|
||||
increaseIndent() {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.increaseIndent();
|
||||
},
|
||||
decreaseIndent() {
|
||||
commitPendingTrailingSemicolon();
|
||||
writer.decreaseIndent();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3515,13 +3581,13 @@ namespace ts {
|
|||
writeComment: (text: string, lineMap: ReadonlyArray<number>, writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) => void) {
|
||||
if (comments && comments.length > 0) {
|
||||
if (leadingSeparator) {
|
||||
writer.write(" ");
|
||||
writer.writeSpace(" ");
|
||||
}
|
||||
|
||||
let emitInterveningSeparator = false;
|
||||
for (const comment of comments) {
|
||||
if (emitInterveningSeparator) {
|
||||
writer.write(" ");
|
||||
writer.writeSpace(" ");
|
||||
emitInterveningSeparator = false;
|
||||
}
|
||||
|
||||
|
@ -3535,7 +3601,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
if (emitInterveningSeparator && trailingSeparator) {
|
||||
writer.write(" ");
|
||||
writer.writeSpace(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3669,7 +3735,7 @@ namespace ts {
|
|||
}
|
||||
else {
|
||||
// Single line comment of style //....
|
||||
writer.write(text.substring(commentPos, commentEnd));
|
||||
writer.writeComment(text.substring(commentPos, commentEnd));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3678,14 +3744,14 @@ namespace ts {
|
|||
const currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, "");
|
||||
if (currentLineText) {
|
||||
// trimmed forward and ending spaces text
|
||||
writer.write(currentLineText);
|
||||
writer.writeComment(currentLineText);
|
||||
if (end !== commentEnd) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Empty string - make sure we write empty line
|
||||
writer.writeLiteral(newLine);
|
||||
writer.rawWrite(newLine);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1646,6 +1646,7 @@ namespace Harness {
|
|||
else {
|
||||
sourceMapCode = "";
|
||||
result.maps.forEach(sourceMap => {
|
||||
if (sourceMapCode) sourceMapCode += "\r\n";
|
||||
sourceMapCode += fileOutput(sourceMap, harnessSettings);
|
||||
});
|
||||
}
|
||||
|
@ -1671,6 +1672,9 @@ namespace Harness {
|
|||
|
||||
let jsCode = "";
|
||||
result.js.forEach(file => {
|
||||
if (jsCode.length && jsCode.charCodeAt(jsCode.length - 1) !== ts.CharacterCodes.lineFeed) {
|
||||
jsCode += "\r\n";
|
||||
}
|
||||
jsCode += fileOutput(file, harnessSettings);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,44 +1,36 @@
|
|||
namespace Harness.SourceMapRecorder {
|
||||
|
||||
interface SourceMapSpanWithDecodeErrors {
|
||||
sourceMapSpan: ts.SourceMapSpan;
|
||||
sourceMapSpan: ts.Mapping;
|
||||
decodeErrors: string[] | undefined;
|
||||
}
|
||||
|
||||
namespace SourceMapDecoder {
|
||||
let sourceMapMappings: string;
|
||||
let decodingIndex: number;
|
||||
let mappings: ts.sourcemaps.MappingsDecoder | undefined;
|
||||
let mappings: ts.MappingsDecoder | undefined;
|
||||
|
||||
export interface DecodedMapping {
|
||||
sourceMapSpan: ts.SourceMapSpan;
|
||||
sourceMapSpan: ts.Mapping;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export function initializeSourceMapDecoding(sourceMapData: ts.SourceMapData) {
|
||||
export function initializeSourceMapDecoding(sourceMapData: ts.SourceMapEmitResult) {
|
||||
decodingIndex = 0;
|
||||
sourceMapMappings = sourceMapData.sourceMapMappings;
|
||||
mappings = ts.sourcemaps.decodeMappings({
|
||||
version: 3,
|
||||
file: sourceMapData.sourceMapFile,
|
||||
sources: sourceMapData.sourceMapSources,
|
||||
sourceRoot: sourceMapData.sourceMapSourceRoot,
|
||||
sourcesContent: sourceMapData.sourceMapSourcesContent,
|
||||
mappings: sourceMapData.sourceMapMappings,
|
||||
names: sourceMapData.sourceMapNames
|
||||
});
|
||||
sourceMapMappings = sourceMapData.sourceMap.mappings;
|
||||
mappings = ts.decodeMappings(sourceMapData.sourceMap.mappings);
|
||||
}
|
||||
|
||||
export function decodeNextEncodedSourceMapSpan(): DecodedMapping {
|
||||
if (!mappings) return ts.Debug.fail("not initialized");
|
||||
const result = mappings.next();
|
||||
if (result.done) return { error: mappings.error || "No encoded entry found", sourceMapSpan: mappings.lastSpan };
|
||||
if (result.done) return { error: mappings.error || "No encoded entry found", sourceMapSpan: mappings.state };
|
||||
return { sourceMapSpan: result.value };
|
||||
}
|
||||
|
||||
export function hasCompletedDecoding() {
|
||||
if (!mappings) return ts.Debug.fail("not initialized");
|
||||
return mappings.decodingIndex === sourceMapMappings.length;
|
||||
return mappings.pos === sourceMapMappings.length;
|
||||
}
|
||||
|
||||
export function getRemainingDecodeString() {
|
||||
|
@ -49,7 +41,7 @@ namespace Harness.SourceMapRecorder {
|
|||
namespace SourceMapSpanWriter {
|
||||
let sourceMapRecorder: Compiler.WriterAggregator;
|
||||
let sourceMapSources: string[];
|
||||
let sourceMapNames: string[] | undefined;
|
||||
let sourceMapNames: string[] | null | undefined;
|
||||
|
||||
let jsFile: documents.TextDocument;
|
||||
let jsLineMap: ReadonlyArray<number>;
|
||||
|
@ -61,10 +53,10 @@ namespace Harness.SourceMapRecorder {
|
|||
let nextJsLineToWrite: number;
|
||||
let spanMarkerContinues: boolean;
|
||||
|
||||
export function initializeSourceMapSpanWriter(sourceMapRecordWriter: Compiler.WriterAggregator, sourceMapData: ts.SourceMapData, currentJsFile: documents.TextDocument) {
|
||||
export function initializeSourceMapSpanWriter(sourceMapRecordWriter: Compiler.WriterAggregator, sourceMapData: ts.SourceMapEmitResult, currentJsFile: documents.TextDocument) {
|
||||
sourceMapRecorder = sourceMapRecordWriter;
|
||||
sourceMapSources = sourceMapData.sourceMapSources;
|
||||
sourceMapNames = sourceMapData.sourceMapNames;
|
||||
sourceMapSources = sourceMapData.sourceMap.sources;
|
||||
sourceMapNames = sourceMapData.sourceMap.names;
|
||||
|
||||
jsFile = currentJsFile;
|
||||
jsLineMap = jsFile.lineStarts;
|
||||
|
@ -75,43 +67,39 @@ namespace Harness.SourceMapRecorder {
|
|||
spanMarkerContinues = false;
|
||||
|
||||
SourceMapDecoder.initializeSourceMapDecoding(sourceMapData);
|
||||
|
||||
sourceMapRecorder.WriteLine("===================================================================");
|
||||
sourceMapRecorder.WriteLine("JsFile: " + sourceMapData.sourceMapFile);
|
||||
sourceMapRecorder.WriteLine("mapUrl: " + sourceMapData.jsSourceMappingURL);
|
||||
sourceMapRecorder.WriteLine("sourceRoot: " + sourceMapData.sourceMapSourceRoot);
|
||||
sourceMapRecorder.WriteLine("sources: " + sourceMapData.sourceMapSources);
|
||||
if (sourceMapData.sourceMapSourcesContent) {
|
||||
sourceMapRecorder.WriteLine("sourcesContent: " + JSON.stringify(sourceMapData.sourceMapSourcesContent));
|
||||
sourceMapRecorder.WriteLine("JsFile: " + sourceMapData.sourceMap.file);
|
||||
sourceMapRecorder.WriteLine("mapUrl: " + ts.tryGetSourceMappingURL(jsFile.text, jsLineMap));
|
||||
sourceMapRecorder.WriteLine("sourceRoot: " + sourceMapData.sourceMap.sourceRoot);
|
||||
sourceMapRecorder.WriteLine("sources: " + sourceMapData.sourceMap.sources);
|
||||
if (sourceMapData.sourceMap.sourcesContent) {
|
||||
sourceMapRecorder.WriteLine("sourcesContent: " + JSON.stringify(sourceMapData.sourceMap.sourcesContent));
|
||||
}
|
||||
sourceMapRecorder.WriteLine("===================================================================");
|
||||
}
|
||||
|
||||
function getSourceMapSpanString(mapEntry: ts.SourceMapSpan, getAbsentNameIndex?: boolean) {
|
||||
let mapString = "Emitted(" + (mapEntry.emittedLine + 1) + ", " + (mapEntry.emittedColumn + 1) + ") Source(" + (mapEntry.sourceLine + 1) + ", " + (mapEntry.sourceColumn + 1) + ") + SourceIndex(" + mapEntry.sourceIndex + ")";
|
||||
if (mapEntry.nameIndex! >= 0 && mapEntry.nameIndex! < sourceMapNames!.length) {
|
||||
mapString += " name (" + sourceMapNames![mapEntry.nameIndex!] + ")";
|
||||
}
|
||||
else {
|
||||
if ((mapEntry.nameIndex && mapEntry.nameIndex !== -1) || getAbsentNameIndex) {
|
||||
mapString += " nameIndex (" + mapEntry.nameIndex + ")";
|
||||
function getSourceMapSpanString(mapEntry: ts.Mapping, getAbsentNameIndex?: boolean) {
|
||||
let mapString = "Emitted(" + (mapEntry.generatedLine + 1) + ", " + (mapEntry.generatedCharacter + 1) + ")";
|
||||
if (ts.isSourceMapping(mapEntry)) {
|
||||
mapString += " Source(" + (mapEntry.sourceLine + 1) + ", " + (mapEntry.sourceCharacter + 1) + ") + SourceIndex(" + mapEntry.sourceIndex + ")";
|
||||
if (mapEntry.nameIndex! >= 0 && mapEntry.nameIndex! < sourceMapNames!.length) {
|
||||
mapString += " name (" + sourceMapNames![mapEntry.nameIndex!] + ")";
|
||||
}
|
||||
else {
|
||||
if ((mapEntry.nameIndex && mapEntry.nameIndex !== -1) || getAbsentNameIndex) {
|
||||
mapString += " nameIndex (" + mapEntry.nameIndex + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mapString;
|
||||
}
|
||||
|
||||
export function recordSourceMapSpan(sourceMapSpan: ts.SourceMapSpan) {
|
||||
export function recordSourceMapSpan(sourceMapSpan: ts.Mapping) {
|
||||
// verify the decoded span is same as the new span
|
||||
const decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan();
|
||||
let decodeErrors: string[] | undefined;
|
||||
if (typeof decodeResult.error === "string"
|
||||
|| decodeResult.sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine
|
||||
|| decodeResult.sourceMapSpan.emittedColumn !== sourceMapSpan.emittedColumn
|
||||
|| decodeResult.sourceMapSpan.sourceLine !== sourceMapSpan.sourceLine
|
||||
|| decodeResult.sourceMapSpan.sourceColumn !== sourceMapSpan.sourceColumn
|
||||
|| decodeResult.sourceMapSpan.sourceIndex !== sourceMapSpan.sourceIndex
|
||||
|| decodeResult.sourceMapSpan.nameIndex !== sourceMapSpan.nameIndex) {
|
||||
if (typeof decodeResult.error === "string" || !ts.sameMapping(decodeResult.sourceMapSpan, sourceMapSpan)) {
|
||||
if (decodeResult.error) {
|
||||
decodeErrors = ["!!^^ !!^^ There was decoding error in the sourcemap at this location: " + decodeResult.error];
|
||||
}
|
||||
|
@ -121,7 +109,7 @@ namespace Harness.SourceMapRecorder {
|
|||
decodeErrors.push("!!^^ !!^^ Decoded span from sourcemap's mappings entry: " + getSourceMapSpanString(decodeResult.sourceMapSpan, /*getAbsentNameIndex*/ true) + " Span encoded by the emitter:" + getSourceMapSpanString(sourceMapSpan, /*getAbsentNameIndex*/ true));
|
||||
}
|
||||
|
||||
if (spansOnSingleLine.length && spansOnSingleLine[0].sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine) {
|
||||
if (spansOnSingleLine.length && spansOnSingleLine[0].sourceMapSpan.generatedLine !== sourceMapSpan.generatedLine) {
|
||||
// On different line from the one that we have been recording till now,
|
||||
writeRecordedSpans();
|
||||
spansOnSingleLine = [];
|
||||
|
@ -129,14 +117,21 @@ namespace Harness.SourceMapRecorder {
|
|||
spansOnSingleLine.push({ sourceMapSpan, decodeErrors });
|
||||
}
|
||||
|
||||
export function recordNewSourceFileSpan(sourceMapSpan: ts.SourceMapSpan, newSourceFileCode: string) {
|
||||
assert.isTrue(spansOnSingleLine.length === 0 || spansOnSingleLine[0].sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine, "new file source map span should be on new line. We currently handle only that scenario");
|
||||
export function recordNewSourceFileSpan(sourceMapSpan: ts.Mapping, newSourceFileCode: string) {
|
||||
let continuesLine = false;
|
||||
if (spansOnSingleLine.length > 0 && spansOnSingleLine[0].sourceMapSpan.generatedCharacter === sourceMapSpan.generatedLine) {
|
||||
writeRecordedSpans();
|
||||
spansOnSingleLine = [];
|
||||
nextJsLineToWrite--; // walk back one line to reprint the line
|
||||
continuesLine = true;
|
||||
}
|
||||
|
||||
recordSourceMapSpan(sourceMapSpan);
|
||||
|
||||
assert.isTrue(spansOnSingleLine.length === 1);
|
||||
sourceMapRecorder.WriteLine("-------------------------------------------------------------------");
|
||||
sourceMapRecorder.WriteLine("emittedFile:" + jsFile.file);
|
||||
sourceMapRecorder.WriteLine("sourceFile:" + sourceMapSources[spansOnSingleLine[0].sourceMapSpan.sourceIndex]);
|
||||
sourceMapRecorder.WriteLine("emittedFile:" + jsFile.file + (continuesLine ? ` (${sourceMapSpan.generatedLine + 1}, ${sourceMapSpan.generatedCharacter + 1})` : ""));
|
||||
sourceMapRecorder.WriteLine("sourceFile:" + sourceMapSources[spansOnSingleLine[0].sourceMapSpan.sourceIndex!]);
|
||||
sourceMapRecorder.WriteLine("-------------------------------------------------------------------");
|
||||
|
||||
tsLineMap = ts.computeLineStarts(newSourceFileCode);
|
||||
|
@ -195,7 +190,7 @@ namespace Harness.SourceMapRecorder {
|
|||
prevEmittedCol = 0;
|
||||
for (let i = 0; i < spansOnSingleLine.length; i++) {
|
||||
fn(spansOnSingleLine[i], i);
|
||||
prevEmittedCol = spansOnSingleLine[i].sourceMapSpan.emittedColumn;
|
||||
prevEmittedCol = spansOnSingleLine[i].sourceMapSpan.generatedCharacter;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,7 +201,7 @@ namespace Harness.SourceMapRecorder {
|
|||
}
|
||||
}
|
||||
|
||||
function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues = false) {
|
||||
function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.generatedCharacter, endContinues = false) {
|
||||
const markerId = getMarkerId(index);
|
||||
markerIds.push(markerId);
|
||||
|
||||
|
@ -223,7 +218,7 @@ namespace Harness.SourceMapRecorder {
|
|||
}
|
||||
|
||||
function writeSourceMapSourceText(currentSpan: SourceMapSpanWithDecodeErrors, index: number) {
|
||||
const sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine] + (currentSpan.sourceMapSpan.sourceColumn);
|
||||
const sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine!] + (currentSpan.sourceMapSpan.sourceCharacter!);
|
||||
let sourceText = "";
|
||||
if (prevWrittenSourcePos < sourcePos) {
|
||||
// Position that goes forward, get text
|
||||
|
@ -255,7 +250,7 @@ namespace Harness.SourceMapRecorder {
|
|||
}
|
||||
|
||||
if (spansOnSingleLine.length) {
|
||||
const currentJsLine = spansOnSingleLine[0].sourceMapSpan.emittedLine;
|
||||
const currentJsLine = spansOnSingleLine[0].sourceMapSpan.generatedLine;
|
||||
|
||||
// Write js line
|
||||
writeJsFileLines(currentJsLine + 1);
|
||||
|
@ -280,14 +275,14 @@ namespace Harness.SourceMapRecorder {
|
|||
}
|
||||
}
|
||||
|
||||
export function getSourceMapRecord(sourceMapDataList: ReadonlyArray<ts.SourceMapData>, program: ts.Program, jsFiles: ReadonlyArray<documents.TextDocument>, declarationFiles: ReadonlyArray<documents.TextDocument>) {
|
||||
export function getSourceMapRecord(sourceMapDataList: ReadonlyArray<ts.SourceMapEmitResult>, program: ts.Program, jsFiles: ReadonlyArray<documents.TextDocument>, declarationFiles: ReadonlyArray<documents.TextDocument>) {
|
||||
const sourceMapRecorder = new Compiler.WriterAggregator();
|
||||
|
||||
for (let i = 0; i < sourceMapDataList.length; i++) {
|
||||
const sourceMapData = sourceMapDataList[i];
|
||||
let prevSourceFile: ts.SourceFile | undefined;
|
||||
let currentFile: documents.TextDocument;
|
||||
if (ts.endsWith(sourceMapData.sourceMapFile, ts.Extension.Dts)) {
|
||||
if (ts.endsWith(sourceMapData.sourceMap.file, ts.Extension.Dts)) {
|
||||
if (sourceMapDataList.length > jsFiles.length) {
|
||||
currentFile = declarationFiles[Math.floor(i / 2)]; // When both kinds of source map are present, they alternate js/dts
|
||||
}
|
||||
|
@ -305,11 +300,15 @@ namespace Harness.SourceMapRecorder {
|
|||
}
|
||||
|
||||
SourceMapSpanWriter.initializeSourceMapSpanWriter(sourceMapRecorder, sourceMapData, currentFile);
|
||||
const mapper = ts.sourcemaps.decodeMappings({ mappings: sourceMapData.sourceMapMappings, sources: sourceMapData.sourceMapSources });
|
||||
const mapper = ts.decodeMappings(sourceMapData.sourceMap.mappings);
|
||||
for (let { value: decodedSourceMapping, done } = mapper.next(); !done; { value: decodedSourceMapping, done } = mapper.next()) {
|
||||
const currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex])!;
|
||||
const currentSourceFile = ts.isSourceMapping(decodedSourceMapping)
|
||||
? program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex])
|
||||
: undefined;
|
||||
if (currentSourceFile !== prevSourceFile) {
|
||||
SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text);
|
||||
if (currentSourceFile) {
|
||||
SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text);
|
||||
}
|
||||
prevSourceFile = currentSourceFile;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -2367,8 +2367,8 @@ namespace ts.server {
|
|||
}
|
||||
|
||||
/*@internal*/
|
||||
getOriginalLocationEnsuringConfiguredProject(project: Project, location: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined {
|
||||
const originalLocation = project.getSourceMapper().tryGetOriginalLocation(location);
|
||||
getOriginalLocationEnsuringConfiguredProject(project: Project, location: DocumentPosition): DocumentPosition | undefined {
|
||||
const originalLocation = project.getSourceMapper().tryGetSourcePosition(location);
|
||||
if (!originalLocation) return undefined;
|
||||
|
||||
const { fileName } = originalLocation;
|
||||
|
|
|
@ -290,7 +290,7 @@ namespace ts.server {
|
|||
projects: Projects,
|
||||
defaultProject: Project,
|
||||
action: (project: Project) => ReadonlyArray<T>,
|
||||
getLocation: (t: T) => sourcemaps.SourceMappableLocation,
|
||||
getLocation: (t: T) => DocumentPosition,
|
||||
resultsEqual: (a: T, b: T) => boolean,
|
||||
): T[] {
|
||||
const outputs: T[] = [];
|
||||
|
@ -312,18 +312,18 @@ namespace ts.server {
|
|||
function combineProjectOutputForRenameLocations(
|
||||
projects: Projects,
|
||||
defaultProject: Project,
|
||||
initialLocation: sourcemaps.SourceMappableLocation,
|
||||
initialLocation: DocumentPosition,
|
||||
findInStrings: boolean,
|
||||
findInComments: boolean
|
||||
): ReadonlyArray<RenameLocation> {
|
||||
const outputs: RenameLocation[] = [];
|
||||
|
||||
combineProjectOutputWorker<sourcemaps.SourceMappableLocation>(
|
||||
combineProjectOutputWorker<DocumentPosition>(
|
||||
projects,
|
||||
defaultProject,
|
||||
initialLocation,
|
||||
({ project, location }, tryAddToTodo) => {
|
||||
for (const output of project.getLanguageService().findRenameLocations(location.fileName, location.position, findInStrings, findInComments) || emptyArray) {
|
||||
for (const output of project.getLanguageService().findRenameLocations(location.fileName, location.pos, findInStrings, findInComments) || emptyArray) {
|
||||
if (!contains(outputs, output, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(output))) {
|
||||
outputs.push(output);
|
||||
}
|
||||
|
@ -335,29 +335,29 @@ namespace ts.server {
|
|||
return outputs;
|
||||
}
|
||||
|
||||
function getDefinitionLocation(defaultProject: Project, initialLocation: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined {
|
||||
const infos = defaultProject.getLanguageService().getDefinitionAtPosition(initialLocation.fileName, initialLocation.position);
|
||||
function getDefinitionLocation(defaultProject: Project, initialLocation: DocumentPosition): DocumentPosition | undefined {
|
||||
const infos = defaultProject.getLanguageService().getDefinitionAtPosition(initialLocation.fileName, initialLocation.pos);
|
||||
const info = infos && firstOrUndefined(infos);
|
||||
return info && { fileName: info.fileName, position: info.textSpan.start };
|
||||
return info && { fileName: info.fileName, pos: info.textSpan.start };
|
||||
}
|
||||
|
||||
function combineProjectOutputForReferences(
|
||||
projects: Projects,
|
||||
defaultProject: Project,
|
||||
initialLocation: sourcemaps.SourceMappableLocation
|
||||
initialLocation: DocumentPosition
|
||||
): ReadonlyArray<ReferencedSymbol> {
|
||||
const outputs: ReferencedSymbol[] = [];
|
||||
|
||||
combineProjectOutputWorker<sourcemaps.SourceMappableLocation>(
|
||||
combineProjectOutputWorker<DocumentPosition>(
|
||||
projects,
|
||||
defaultProject,
|
||||
initialLocation,
|
||||
({ project, location }, getMappedLocation) => {
|
||||
for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.position) || emptyArray) {
|
||||
for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.pos) || emptyArray) {
|
||||
const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition));
|
||||
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? outputReferencedSymbol.definition : {
|
||||
...outputReferencedSymbol.definition,
|
||||
textSpan: createTextSpan(mappedDefinitionFile.position, outputReferencedSymbol.definition.textSpan.length),
|
||||
textSpan: createTextSpan(mappedDefinitionFile.pos, outputReferencedSymbol.definition.textSpan.length),
|
||||
fileName: mappedDefinitionFile.fileName,
|
||||
};
|
||||
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, definition));
|
||||
|
@ -380,7 +380,7 @@ namespace ts.server {
|
|||
return outputs.filter(o => o.references.length !== 0);
|
||||
}
|
||||
|
||||
interface ProjectAndLocation<TLocation extends sourcemaps.SourceMappableLocation | undefined> {
|
||||
interface ProjectAndLocation<TLocation extends DocumentPosition | undefined> {
|
||||
readonly project: Project;
|
||||
readonly location: TLocation;
|
||||
}
|
||||
|
@ -398,24 +398,24 @@ namespace ts.server {
|
|||
}
|
||||
}
|
||||
|
||||
type CombineProjectOutputCallback<TLocation extends sourcemaps.SourceMappableLocation | undefined> = (
|
||||
type CombineProjectOutputCallback<TLocation extends DocumentPosition | undefined> = (
|
||||
where: ProjectAndLocation<TLocation>,
|
||||
getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => sourcemaps.SourceMappableLocation | undefined,
|
||||
getMappedLocation: (project: Project, location: DocumentPosition) => DocumentPosition | undefined,
|
||||
) => void;
|
||||
|
||||
function combineProjectOutputWorker<TLocation extends sourcemaps.SourceMappableLocation | undefined>(
|
||||
function combineProjectOutputWorker<TLocation extends DocumentPosition | undefined>(
|
||||
projects: Projects,
|
||||
defaultProject: Project,
|
||||
initialLocation: TLocation,
|
||||
cb: CombineProjectOutputCallback<TLocation>,
|
||||
getDefinition: (() => sourcemaps.SourceMappableLocation | undefined) | undefined,
|
||||
getDefinition: (() => DocumentPosition | undefined) | undefined,
|
||||
): void {
|
||||
const projectService = defaultProject.projectService;
|
||||
let toDo: ProjectAndLocation<TLocation>[] | undefined;
|
||||
const seenProjects = createMap<true>();
|
||||
forEachProjectInProjects(projects, initialLocation && initialLocation.fileName, (project, path) => {
|
||||
// TLocation shoud be either `sourcemaps.SourceMappableLocation` or `undefined`. Since `initialLocation` is `TLocation` this cast should be valid.
|
||||
const location = (initialLocation ? { fileName: path, position: initialLocation.position } : undefined) as TLocation;
|
||||
// TLocation shoud be either `DocumentPosition` or `undefined`. Since `initialLocation` is `TLocation` this cast should be valid.
|
||||
const location = (initialLocation ? { fileName: path, pos: initialLocation.pos } : undefined) as TLocation;
|
||||
toDo = callbackProjectAndLocation({ project, location }, projectService, toDo, seenProjects, cb);
|
||||
});
|
||||
|
||||
|
@ -436,13 +436,13 @@ namespace ts.server {
|
|||
}
|
||||
}
|
||||
|
||||
function getDefinitionInProject(definition: sourcemaps.SourceMappableLocation | undefined, definingProject: Project, project: Project): sourcemaps.SourceMappableLocation | undefined {
|
||||
function getDefinitionInProject(definition: DocumentPosition | undefined, definingProject: Project, project: Project): DocumentPosition | undefined {
|
||||
if (!definition || project.containsFile(toNormalizedPath(definition.fileName))) return definition;
|
||||
const mappedDefinition = definingProject.getLanguageService().getSourceMapper().tryGetGeneratedLocation(definition);
|
||||
const mappedDefinition = definingProject.getLanguageService().getSourceMapper().tryGetGeneratedPosition(definition);
|
||||
return mappedDefinition && project.containsFile(toNormalizedPath(mappedDefinition.fileName)) ? mappedDefinition : undefined;
|
||||
}
|
||||
|
||||
function callbackProjectAndLocation<TLocation extends sourcemaps.SourceMappableLocation | undefined>(
|
||||
function callbackProjectAndLocation<TLocation extends DocumentPosition | undefined>(
|
||||
projectAndLocation: ProjectAndLocation<TLocation>,
|
||||
projectService: ProjectService,
|
||||
toDo: ProjectAndLocation<TLocation>[] | undefined,
|
||||
|
@ -472,16 +472,16 @@ namespace ts.server {
|
|||
return toDo;
|
||||
}
|
||||
|
||||
function addToTodo<TLocation extends sourcemaps.SourceMappableLocation | undefined>(projectAndLocation: ProjectAndLocation<TLocation>, toDo: Push<ProjectAndLocation<TLocation>>, seenProjects: Map<true>): void {
|
||||
function addToTodo<TLocation extends DocumentPosition | undefined>(projectAndLocation: ProjectAndLocation<TLocation>, toDo: Push<ProjectAndLocation<TLocation>>, seenProjects: Map<true>): void {
|
||||
if (addToSeen(seenProjects, projectAndLocation.project.projectName)) toDo.push(projectAndLocation);
|
||||
}
|
||||
|
||||
function documentSpanLocation({ fileName, textSpan }: DocumentSpan): sourcemaps.SourceMappableLocation {
|
||||
return { fileName, position: textSpan.start };
|
||||
function documentSpanLocation({ fileName, textSpan }: DocumentSpan): DocumentPosition {
|
||||
return { fileName, pos: textSpan.start };
|
||||
}
|
||||
|
||||
function getMappedLocation(location: sourcemaps.SourceMappableLocation, projectService: ProjectService, project: Project): sourcemaps.SourceMappableLocation | undefined {
|
||||
const mapsTo = project.getSourceMapper().tryGetOriginalLocation(location);
|
||||
function getMappedLocation(location: DocumentPosition, projectService: ProjectService, project: Project): DocumentPosition | undefined {
|
||||
const mapsTo = project.getSourceMapper().tryGetSourcePosition(location);
|
||||
return mapsTo && projectService.fileExists(toNormalizedPath(mapsTo.fileName)) ? mapsTo : undefined;
|
||||
}
|
||||
|
||||
|
@ -941,7 +941,7 @@ namespace ts.server {
|
|||
kind: info.kind,
|
||||
name: info.name,
|
||||
textSpan: {
|
||||
start: newLoc.position,
|
||||
start: newLoc.pos,
|
||||
length: info.textSpan.length
|
||||
},
|
||||
originalFileName: info.fileName,
|
||||
|
@ -1038,7 +1038,7 @@ namespace ts.server {
|
|||
kind: info.kind,
|
||||
displayParts: info.displayParts,
|
||||
textSpan: {
|
||||
start: newLoc.position,
|
||||
start: newLoc.pos,
|
||||
length: info.textSpan.length
|
||||
},
|
||||
originalFileName: info.fileName,
|
||||
|
@ -1229,7 +1229,7 @@ namespace ts.server {
|
|||
const locations = combineProjectOutputForRenameLocations(
|
||||
projects,
|
||||
this.getDefaultProject(args),
|
||||
{ fileName: args.file, position },
|
||||
{ fileName: args.file, pos: position },
|
||||
!!args.findInStrings,
|
||||
!!args.findInComments
|
||||
);
|
||||
|
@ -1269,7 +1269,7 @@ namespace ts.server {
|
|||
const references = combineProjectOutputForReferences(
|
||||
projects,
|
||||
this.getDefaultProject(args),
|
||||
{ fileName: args.file, position },
|
||||
{ fileName: args.file, pos: position },
|
||||
);
|
||||
|
||||
if (simplifiedResult) {
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace ts {
|
|||
export function getPathUpdater(oldFileOrDirPath: string, newFileOrDirPath: string, getCanonicalFileName: GetCanonicalFileName, sourceMapper: SourceMapper | undefined): PathUpdater {
|
||||
const canonicalOldPath = getCanonicalFileName(oldFileOrDirPath);
|
||||
return path => {
|
||||
const originalPath = sourceMapper && sourceMapper.tryGetOriginalLocation({ fileName: path, position: 0 });
|
||||
const originalPath = sourceMapper && sourceMapper.tryGetSourcePosition({ fileName: path, pos: 0 });
|
||||
const updatedPath = getUpdatedPath(originalPath ? originalPath.fileName : path);
|
||||
return originalPath
|
||||
? updatedPath === undefined ? undefined : makeCorrespondingRelativeChange(originalPath.fileName, updatedPath, path, getCanonicalFileName)
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
/* @internal */
|
||||
namespace ts {
|
||||
// Sometimes tools can sometimes see the following line as a source mapping url comment, so we mangle it a bit (the [M])
|
||||
const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\s*$/;
|
||||
const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
|
||||
const base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/;
|
||||
|
||||
export interface SourceMapper {
|
||||
toLineColumnOffset(fileName: string, position: number): LineAndCharacter;
|
||||
tryGetOriginalLocation(info: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined;
|
||||
tryGetGeneratedLocation(info: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined;
|
||||
tryGetSourcePosition(info: DocumentPosition): DocumentPosition | undefined;
|
||||
tryGetGeneratedPosition(info: DocumentPosition): DocumentPosition | undefined;
|
||||
clearCache(): void;
|
||||
}
|
||||
|
||||
|
@ -21,7 +18,7 @@ namespace ts {
|
|||
): SourceMapper {
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
let sourcemappedFileCache: SourceFileLikeCache;
|
||||
return { tryGetOriginalLocation, tryGetGeneratedLocation, toLineColumnOffset, clearCache };
|
||||
return { tryGetSourcePosition, tryGetGeneratedPosition, toLineColumnOffset, clearCache };
|
||||
|
||||
function toPath(fileName: string) {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
|
@ -32,44 +29,36 @@ namespace ts {
|
|||
if (!mappedFile) {
|
||||
return;
|
||||
}
|
||||
const starts = getLineStarts(mappedFile);
|
||||
for (let index = starts.length - 1; index >= 0; index--) {
|
||||
const lineText = mappedFile.text.substring(starts[index], starts[index + 1]);
|
||||
const comment = sourceMapCommentRegExp.exec(lineText);
|
||||
if (comment) {
|
||||
return comment[1];
|
||||
}
|
||||
// If we see a non-whitespace/map comment-like line, break, to avoid scanning up the entire file
|
||||
else if (!lineText.match(whitespaceOrMapCommentRegExp)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return tryGetSourceMappingURL(mappedFile.text, getLineStarts(mappedFile));
|
||||
}
|
||||
|
||||
function convertDocumentToSourceMapper(file: { sourceMapper?: sourcemaps.SourceMapper }, contents: string, mapFileName: string) {
|
||||
let maps: sourcemaps.SourceMapData | undefined;
|
||||
try {
|
||||
maps = JSON.parse(contents);
|
||||
}
|
||||
catch {
|
||||
// swallow error
|
||||
}
|
||||
if (!maps || !maps.sources || !maps.file || !maps.mappings) {
|
||||
function convertDocumentToSourceMapper(file: { sourceMapper?: DocumentPositionMapper }, contents: string, mapFileName: string) {
|
||||
const map = tryParseRawSourceMap(contents);
|
||||
if (!map || !map.sources || !map.file || !map.mappings) {
|
||||
// obviously invalid map
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
return file.sourceMapper = identitySourceMapConsumer;
|
||||
}
|
||||
return file.sourceMapper = sourcemaps.decode({
|
||||
readFile: s => host.readFile!(s), // TODO: GH#18217
|
||||
fileExists: s => host.fileExists!(s), // TODO: GH#18217
|
||||
useCaseSensitiveFileNames,
|
||||
const program = getProgram();
|
||||
return file.sourceMapper = createDocumentPositionMapper({
|
||||
getSourceFileLike: s => {
|
||||
// Lookup file in program, if provided
|
||||
const file = program && program.getSourceFileByPath(s);
|
||||
// file returned here could be .d.ts when asked for .ts file if projectReferences and module resolution created this source file
|
||||
if (file === undefined || file.resolvedPath !== s) {
|
||||
// Otherwise check the cache (which may hit disk)
|
||||
return sourcemappedFileCache.get(s);
|
||||
}
|
||||
return file;
|
||||
},
|
||||
getCanonicalFileName,
|
||||
log,
|
||||
}, mapFileName, maps, getProgram(), sourcemappedFileCache);
|
||||
}, map, mapFileName);
|
||||
}
|
||||
|
||||
function getSourceMapper(fileName: string, file: SourceFileLike): sourcemaps.SourceMapper {
|
||||
function getSourceMapper(fileName: string, file: SourceFileLike): DocumentPositionMapper {
|
||||
if (!host.readFile || !host.fileExists) {
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
return file.sourceMapper = identitySourceMapConsumer;
|
||||
}
|
||||
if (file.sourceMapper) {
|
||||
return file.sourceMapper;
|
||||
|
@ -97,19 +86,19 @@ namespace ts {
|
|||
return convertDocumentToSourceMapper(file, host.readFile(mapPath)!, mapPath); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
return file.sourceMapper = identitySourceMapConsumer;
|
||||
}
|
||||
|
||||
function tryGetOriginalLocation(info: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined {
|
||||
function tryGetSourcePosition(info: DocumentPosition): DocumentPosition | undefined {
|
||||
if (!isDeclarationFileName(info.fileName)) return undefined;
|
||||
|
||||
const file = getFile(info.fileName);
|
||||
if (!file) return undefined;
|
||||
const newLoc = getSourceMapper(info.fileName, file).getOriginalPosition(info);
|
||||
return newLoc === info ? undefined : tryGetOriginalLocation(newLoc) || newLoc;
|
||||
const newLoc = getSourceMapper(info.fileName, file).getSourcePosition(info);
|
||||
return newLoc === info ? undefined : tryGetSourcePosition(newLoc) || newLoc;
|
||||
}
|
||||
|
||||
function tryGetGeneratedLocation(info: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined {
|
||||
function tryGetGeneratedPosition(info: DocumentPosition): DocumentPosition | undefined {
|
||||
const program = getProgram();
|
||||
const options = program.getCompilerOptions();
|
||||
const outPath = options.outFile || options.out;
|
||||
|
@ -141,4 +130,31 @@ namespace ts {
|
|||
sourcemappedFileCache = createSourceFileLikeCache(host);
|
||||
}
|
||||
}
|
||||
|
||||
interface SourceFileLikeCache {
|
||||
get(path: Path): SourceFileLike | undefined;
|
||||
}
|
||||
|
||||
function createSourceFileLikeCache(host: { readFile?: (path: string) => string | undefined, fileExists?: (path: string) => boolean }): SourceFileLikeCache {
|
||||
const cached = createMap<SourceFileLike>();
|
||||
return {
|
||||
get(path: Path) {
|
||||
if (cached.has(path)) {
|
||||
return cached.get(path);
|
||||
}
|
||||
if (!host.fileExists || !host.readFile || !host.fileExists(path)) return;
|
||||
// And failing that, check the disk
|
||||
const text = host.readFile(path)!; // TODO: GH#18217
|
||||
const file = {
|
||||
text,
|
||||
lineMap: undefined,
|
||||
getLineAndCharacterOfPosition(pos: number) {
|
||||
return computeLineAndCharacterOfPosition(getLineStarts(this), pos);
|
||||
}
|
||||
} as SourceFileLike;
|
||||
cached.set(path, file);
|
||||
return file;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -925,6 +925,9 @@ namespace ts.textChanges {
|
|||
this.writer.write(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeComment(s: string): void {
|
||||
this.writer.writeComment(s);
|
||||
}
|
||||
writeKeyword(s: string): void {
|
||||
this.writer.writeKeyword(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
|
@ -937,6 +940,10 @@ namespace ts.textChanges {
|
|||
this.writer.writePunctuation(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeTrailingSemicolon(s: string): void {
|
||||
this.writer.writeTrailingSemicolon(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeParameter(s: string): void {
|
||||
this.writer.writeParameter(s);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
|
@ -957,9 +964,6 @@ namespace ts.textChanges {
|
|||
this.writer.writeSymbol(s, sym);
|
||||
this.setLastNonTriviaPosition(s, /*force*/ false);
|
||||
}
|
||||
writeTextOfNode(text: string, node: Node): void {
|
||||
this.writer.writeTextOfNode(text, node);
|
||||
}
|
||||
writeLine(): void {
|
||||
this.writer.writeLine();
|
||||
}
|
||||
|
|
|
@ -86,12 +86,12 @@ namespace ts {
|
|||
getPositionOfLineAndCharacter(line: number, character: number): number;
|
||||
update(newText: string, textChangeRange: TextChangeRange): SourceFile;
|
||||
|
||||
/* @internal */ sourceMapper?: sourcemaps.SourceMapper;
|
||||
/* @internal */ sourceMapper?: DocumentPositionMapper;
|
||||
}
|
||||
|
||||
export interface SourceFileLike {
|
||||
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
|
||||
/*@internal*/ sourceMapper?: sourcemaps.SourceMapper;
|
||||
/*@internal*/ sourceMapper?: DocumentPositionMapper;
|
||||
}
|
||||
|
||||
export interface SourceMapSource {
|
||||
|
|
|
@ -1459,6 +1459,7 @@ namespace ts {
|
|||
writeKeyword: text => writeKind(text, SymbolDisplayPartKind.keyword),
|
||||
writeOperator: text => writeKind(text, SymbolDisplayPartKind.operator),
|
||||
writePunctuation: text => writeKind(text, SymbolDisplayPartKind.punctuation),
|
||||
writeTrailingSemicolon: text => writeKind(text, SymbolDisplayPartKind.punctuation),
|
||||
writeSpace: text => writeKind(text, SymbolDisplayPartKind.space),
|
||||
writeStringLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral),
|
||||
writeParameter: text => writeKind(text, SymbolDisplayPartKind.parameterName),
|
||||
|
@ -1467,7 +1468,7 @@ namespace ts {
|
|||
writeSymbol,
|
||||
writeLine,
|
||||
write: unknownWrite,
|
||||
writeTextOfNode: unknownWrite,
|
||||
writeComment: unknownWrite,
|
||||
getText: () => "",
|
||||
getTextPos: () => 0,
|
||||
getColumn: () => 0,
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace project {
|
|||
program?: ts.Program;
|
||||
compilerOptions?: ts.CompilerOptions;
|
||||
errors: ReadonlyArray<ts.Diagnostic>;
|
||||
sourceMapData?: ReadonlyArray<ts.SourceMapData>;
|
||||
sourceMapData?: ReadonlyArray<ts.SourceMapEmitResult>;
|
||||
}
|
||||
|
||||
interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult {
|
||||
|
@ -315,11 +315,11 @@ namespace project {
|
|||
// Clean up source map data that will be used in baselining
|
||||
if (sourceMapData) {
|
||||
for (const data of sourceMapData) {
|
||||
for (let j = 0; j < data.sourceMapSources.length; j++) {
|
||||
data.sourceMapSources[j] = this.cleanProjectUrl(data.sourceMapSources[j]);
|
||||
}
|
||||
data.jsSourceMappingURL = this.cleanProjectUrl(data.jsSourceMappingURL);
|
||||
data.sourceMapSourceRoot = this.cleanProjectUrl(data.sourceMapSourceRoot);
|
||||
data.sourceMap = {
|
||||
...data.sourceMap,
|
||||
sources: data.sourceMap.sources.map(source => this.cleanProjectUrl(source)),
|
||||
sourceRoot: data.sourceMap.sourceRoot && this.cleanProjectUrl(data.sourceMap.sourceRoot)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,6 +425,7 @@ namespace project {
|
|||
skipDefaultLibCheck: false,
|
||||
moduleResolution: ts.ModuleResolutionKind.Classic,
|
||||
module: moduleKind,
|
||||
newLine: ts.NewLineKind.CarriageReturnLineFeed,
|
||||
mapRoot: testCase.resolveMapRoot && testCase.mapRoot
|
||||
? vpath.resolve(vfs.srcFolder, testCase.mapRoot)
|
||||
: testCase.mapRoot,
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace ts {
|
|||
writeFile: (fileName, text) => outputs.set(fileName, text),
|
||||
};
|
||||
|
||||
const program = createProgram(arrayFrom(fileMap.keys()), options, host);
|
||||
const program = createProgram(arrayFrom(fileMap.keys()), { newLine: NewLineKind.LineFeed, ...options }, host);
|
||||
program.emit(/*targetSourceFile*/ undefined, host.writeFile, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ false, customTransformers);
|
||||
let content = "";
|
||||
for (const [file, text] of arrayFrom(outputs.entries())) {
|
||||
|
|
|
@ -10058,7 +10058,7 @@ declare class TestLib {
|
|||
const configContent = JSON.stringify({ compilerOptions });
|
||||
const aTsconfig: File = { path: "/a/tsconfig.json", content: configContent };
|
||||
|
||||
const aDtsMapContent: SourceMapSection = {
|
||||
const aDtsMapContent: RawSourceMap = {
|
||||
version: 3,
|
||||
file: "a.d.ts",
|
||||
sourceRoot: "",
|
||||
|
@ -10082,7 +10082,7 @@ declare class TestLib {
|
|||
};
|
||||
const bTsconfig: File = { path: "/b/tsconfig.json", content: configContent };
|
||||
|
||||
const bDtsMapContent: SourceMapSection = {
|
||||
const bDtsMapContent: RawSourceMap = {
|
||||
version: 3,
|
||||
file: "b.d.ts",
|
||||
sourceRoot: "",
|
||||
|
|
|
@ -1849,17 +1849,6 @@ declare namespace ts {
|
|||
/** .ts file (index into sources array) associated with this span */
|
||||
sourceIndex: number;
|
||||
}
|
||||
interface SourceMapData {
|
||||
sourceMapFilePath: string;
|
||||
jsSourceMappingURL: string;
|
||||
sourceMapFile: string;
|
||||
sourceMapSourceRoot: string;
|
||||
sourceMapSources: string[];
|
||||
sourceMapSourcesContent?: (string | null)[];
|
||||
inputSourceFileNames: string[];
|
||||
sourceMapNames?: string[];
|
||||
sourceMapMappings: string;
|
||||
}
|
||||
/** Return code used by getEmitOutput function to indicate status of the function */
|
||||
enum ExitStatus {
|
||||
Success = 0,
|
||||
|
@ -2764,7 +2753,8 @@ declare namespace ts {
|
|||
Expression = 1,
|
||||
IdentifierName = 2,
|
||||
MappedTypeParameter = 3,
|
||||
Unspecified = 4
|
||||
Unspecified = 4,
|
||||
EmbeddedStatement = 5
|
||||
}
|
||||
interface TransformationContext {
|
||||
/** Gets the compiler options supplied to the transformer. */
|
||||
|
|
14
tests/baselines/reference/api/typescript.d.ts
vendored
14
tests/baselines/reference/api/typescript.d.ts
vendored
|
@ -1849,17 +1849,6 @@ declare namespace ts {
|
|||
/** .ts file (index into sources array) associated with this span */
|
||||
sourceIndex: number;
|
||||
}
|
||||
interface SourceMapData {
|
||||
sourceMapFilePath: string;
|
||||
jsSourceMappingURL: string;
|
||||
sourceMapFile: string;
|
||||
sourceMapSourceRoot: string;
|
||||
sourceMapSources: string[];
|
||||
sourceMapSourcesContent?: (string | null)[];
|
||||
inputSourceFileNames: string[];
|
||||
sourceMapNames?: string[];
|
||||
sourceMapMappings: string;
|
||||
}
|
||||
/** Return code used by getEmitOutput function to indicate status of the function */
|
||||
enum ExitStatus {
|
||||
Success = 0,
|
||||
|
@ -2764,7 +2753,8 @@ declare namespace ts {
|
|||
Expression = 1,
|
||||
IdentifierName = 2,
|
||||
MappedTypeParameter = 3,
|
||||
Unspecified = 4
|
||||
Unspecified = 4,
|
||||
EmbeddedStatement = 5
|
||||
}
|
||||
interface TransformationContext {
|
||||
/** Gets the compiler options supplied to the transformer. */
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//// [a.d.ts.map]
|
||||
{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["a.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,OAAO,CAAC,CAAC,EAAE;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd"}//// [index.d.ts.map]
|
||||
{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["a.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,OAAO,CAAC,CAAC,EAAE;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd"}
|
||||
//// [index.d.ts.map]
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,eAAO,IAAI,CAAC;;CAAqB,CAAC;AAClC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC"}
|
|
@ -1,3 +1,4 @@
|
|||
//// [bundle.js.map]
|
||||
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IAAA;IAOA,CAAC;IANG,qBAAO,GAAP,UAAQ,CAAc;QAClB,OAAO,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAC,CAAC;IACpB,CAAC;IACM,QAAI,GAAX;QACI,OAAO,IAAI,GAAG,EAAE,CAAC;IACrB,CAAC;IACL,UAAC;AAAD,CAAC,AAPD,IAOC;ACPD,IAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;AACpB,CAAC,CAAC,OAAO,CAAC,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC;AAEnB,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC"}//// [bundle.d.ts.map]
|
||||
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IAAA;IAOA,CAAC;IANG,qBAAO,GAAP,UAAQ,CAAc;QAClB,OAAO,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAC,CAAC;IACpB,CAAC;IACM,QAAI,GAAX;QACI,OAAO,IAAI,GAAG,EAAE,CAAC;IACrB,CAAC;IACL,UAAC;AAAD,CAAC,AAPD,IAOC;ACPD,IAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;AACpB,CAAC,CAAC,OAAO,CAAC,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC;AAEnB,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC"}
|
||||
//// [bundle.d.ts.map]
|
||||
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA,cAAM,GAAG;IACL,OAAO,CAAC,GAAG;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"}
|
|
@ -68,7 +68,8 @@ exports.createElement = Element.createElement;
|
|||
function toCamelCase(text) {
|
||||
return text[0].toLowerCase() + text.substring(1);
|
||||
}
|
||||
//# sourceMappingURL=Element.js.map//// [test.js]
|
||||
//# sourceMappingURL=Element.js.map
|
||||
//// [test.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Element_1 = require("./Element");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//// [Element.js.map]
|
||||
{"version":3,"file":"Element.js","sourceRoot":"","sources":["Element.ts"],"names":[],"mappings":";;AAYA,IAAiB,OAAO,CAUvB;AAVD,WAAiB,OAAO;IACpB,SAAgB,SAAS,CAAC,EAAO;QAC7B,OAAO,EAAE,CAAC,wBAAwB,KAAK,SAAS,CAAC;IACrD,CAAC;IAFe,iBAAS,YAExB,CAAA;IAED,SAAgB,aAAa,CAAC,IAAW;QAErC,OAAO,EACN,CAAA;IACL,CAAC;IAJe,qBAAa,gBAI5B,CAAA;AACL,CAAC,EAVgB,OAAO,GAAP,eAAO,KAAP,eAAO,QAUvB;AAEU,QAAA,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;AAEjD,SAAS,WAAW,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC"}//// [test.js.map]
|
||||
{"version":3,"file":"Element.js","sourceRoot":"","sources":["Element.ts"],"names":[],"mappings":";;AAYA,IAAiB,OAAO,CAUvB;AAVD,WAAiB,OAAO;IACpB,SAAgB,SAAS,CAAC,EAAO;QAC7B,OAAO,EAAE,CAAC,wBAAwB,KAAK,SAAS,CAAC;IACrD,CAAC;IAFe,iBAAS,YAExB,CAAA;IAED,SAAgB,aAAa,CAAC,IAAW;QAErC,OAAO,EACN,CAAA;IACL,CAAC;IAJe,qBAAa,gBAI5B,CAAA;AACL,CAAC,EAVgB,OAAO,GAAP,eAAO,KAAP,eAAO,QAUvB;AAEU,QAAA,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;AAEjD,SAAS,WAAW,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC"}
|
||||
//// [test.js.map]
|
||||
{"version":3,"file":"test.js","sourceRoot":"","sources":["test.tsx"],"names":[],"mappings":";;AAAA,uCAAmC;AACnC,IAAI,aAAa,GAAG,iBAAO,CAAC,aAAa,CAAC;AAC1C,IAAI,CAIH,CAAC;AAEF,MAAM,CAAC;IACN,IAAI;QACH,OAAO;YACN,wBAAM,OAAO,EAAC,YAAY,GAAQ;YAClC,wBAAM,OAAO,EAAE,CAAC,CAAC,CAAE,CAAC,CAAC,GAAS;SAC9B,CAAC;IACH,CAAC;CACD"}
|
|
@ -67,7 +67,8 @@ exports.createElement = Element.createElement;
|
|||
function toCamelCase(text) {
|
||||
return text[0].toLowerCase() + text.substring(1);
|
||||
}
|
||||
//# sourceMappingURL=Element.js.map//// [test.js]
|
||||
//# sourceMappingURL=Element.js.map
|
||||
//// [test.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Element_1 = require("./Element");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//// [Element.js.map]
|
||||
{"version":3,"file":"Element.js","sourceRoot":"","sources":["Element.ts"],"names":[],"mappings":";;AAYA,IAAiB,OAAO,CAUvB;AAVD,WAAiB,OAAO;IACpB,SAAgB,SAAS,CAAC,EAAO;QAC7B,OAAO,EAAE,CAAC,wBAAwB,KAAK,SAAS,CAAC;IACrD,CAAC;IAFe,iBAAS,YAExB,CAAA;IAED,SAAgB,aAAa,CAAC,IAAW;QAErC,OAAO,EACN,CAAA;IACL,CAAC;IAJe,qBAAa,gBAI5B,CAAA;AACL,CAAC,EAVgB,OAAO,GAAP,eAAO,KAAP,eAAO,QAUvB;AAEU,QAAA,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;AAEjD,SAAS,WAAW,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC"}//// [test.js.map]
|
||||
{"version":3,"file":"Element.js","sourceRoot":"","sources":["Element.ts"],"names":[],"mappings":";;AAYA,IAAiB,OAAO,CAUvB;AAVD,WAAiB,OAAO;IACpB,SAAgB,SAAS,CAAC,EAAO;QAC7B,OAAO,EAAE,CAAC,wBAAwB,KAAK,SAAS,CAAC;IACrD,CAAC;IAFe,iBAAS,YAExB,CAAA;IAED,SAAgB,aAAa,CAAC,IAAW;QAErC,OAAO,EACN,CAAA;IACL,CAAC;IAJe,qBAAa,gBAI5B,CAAA;AACL,CAAC,EAVgB,OAAO,GAAP,eAAO,KAAP,eAAO,QAUvB;AAEU,QAAA,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;AAEjD,SAAS,WAAW,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC"}
|
||||
//// [test.js.map]
|
||||
{"version":3,"file":"test.js","sourceRoot":"","sources":["test.tsx"],"names":[],"mappings":";;AAAA,uCAAmC;AAEnC,IAAI,CAIH,CAAC;AAEF,MAAM,CAAC;IACN,IAAI;QACH,OAAO;YACN,0CAAM,OAAO,EAAC,YAAY,GAAQ;YAClC,0CAAM,OAAO,EAAE,CAAC,CAAC,CAAE,CAAC,CAAC,GAAS;SAC9B,CAAC;IACH,CAAC;CACD"}
|
|
@ -18,7 +18,8 @@ var c = /** @class */ (function () {
|
|||
}
|
||||
return c;
|
||||
}());
|
||||
//# sourceMappingURL=app.js.map//// [app2.js]
|
||||
//# sourceMappingURL=app.js.map
|
||||
//// [app2.js]
|
||||
var d = /** @class */ (function () {
|
||||
function d() {
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//// [app.js.map]
|
||||
{"version":3,"file":"app.js","sourceRoot":"","sources":["../testFiles/app.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,wIAAwI;AACxI;IAAA;IACA,CAAC;IAAD,QAAC;AAAD,CAAC,AADD,IACC"}//// [app2.js.map]
|
||||
{"version":3,"file":"app.js","sourceRoot":"","sources":["../testFiles/app.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,wIAAwI;AACxI;IAAA;IACA,CAAC;IAAD,QAAC;AAAD,CAAC,AADD,IACC"}
|
||||
//// [app2.js.map]
|
||||
{"version":3,"file":"app2.js","sourceRoot":"","sources":["../testFiles/app2.ts"],"names":[],"mappings":"AAAA;IAAA;IACA,CAAC;IAAD,QAAC;AAAD,CAAC,AADD,IACC"}
|
|
@ -18,7 +18,8 @@ var c = /** @class */ (function () {
|
|||
}
|
||||
return c;
|
||||
}());
|
||||
//# sourceMappingURL=app.js.map//// [app2.js]
|
||||
//# sourceMappingURL=app.js.map
|
||||
//// [app2.js]
|
||||
var d = /** @class */ (function () {
|
||||
function d() {
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//// [app.js.map]
|
||||
{"version":3,"file":"app.js","sourceRoot":"","sources":["app.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,0GAA0G;AAC1G;IAAA;IACA,CAAC;IAAD,QAAC;AAAD,CAAC,AADD,IACC"}//// [app2.js.map]
|
||||
{"version":3,"file":"app.js","sourceRoot":"","sources":["app.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,0GAA0G;AAC1G;IAAA;IACA,CAAC;IAAD,QAAC;AAAD,CAAC,AADD,IACC"}
|
||||
//// [app2.js.map]
|
||||
{"version":3,"file":"app2.js","sourceRoot":"","sources":["app2.ts"],"names":[],"mappings":"AAAA;IAAA;IACA,CAAC;IAAD,QAAC;AAAD,CAAC,AADD,IACC"}
|
Loading…
Reference in a new issue