diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index a73d7374b59..ab5e6bfb774 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -464,8 +464,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi const writer = createTextWriter(newLine); const { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer; - const sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? createSourceMapWriter(host, writer) : getNullSourceMapWriter(); - const { setSourceFile, emitStart, emitEnd, emitPos } = sourceMap; + let sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? createSourceMapWriter(host, writer) : getNullSourceMapWriter(); + let { setSourceFile, emitStart, emitEnd, emitPos } = sourceMap; let currentSourceFile: SourceFile; let currentText: string; @@ -512,6 +512,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** If removeComments is true, no leading-comments needed to be emitted **/ const emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos: number) { } : emitLeadingCommentsOfPositionWorker; + const setSourceMapWriterEmit = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? changeSourceMapEmit : function (writer: SourceMapWriter) { }; + const moduleEmitDelegates: Map<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = { [ModuleKind.ES6]: emitES6Module, [ModuleKind.AMD]: emitAMDModule, @@ -2573,7 +2575,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi leftHandSideExpression.argumentExpression.kind !== SyntaxKind.StringLiteral) { const tempArgumentExpression = createAndRecordTempVariable(TempFlags._i); (synthesizedLHS).argumentExpression = tempArgumentExpression; - emitAssignment(tempArgumentExpression, leftHandSideExpression.argumentExpression, /*shouldEmitCommaBeforeAssignment*/ true); + emitAssignment(tempArgumentExpression, leftHandSideExpression.argumentExpression, /*shouldEmitCommaBeforeAssignment*/ true, leftHandSideExpression.expression); } else { (synthesizedLHS).argumentExpression = leftHandSideExpression.argumentExpression; @@ -3728,7 +3730,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi * @param value an expression as a right-hand-side operand of the assignment * @param shouldEmitCommaBeforeAssignment a boolean indicating whether to prefix an assignment with comma */ - function emitAssignment(name: Identifier, value: Expression, shouldEmitCommaBeforeAssignment: boolean) { + function emitAssignment(name: Identifier, value: Expression, shouldEmitCommaBeforeAssignment: boolean, nodeForSourceMap: TextRange) { if (shouldEmitCommaBeforeAssignment) { write(", "); } @@ -3744,15 +3746,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi const isVariableDeclarationOrBindingElement = name.parent && (name.parent.kind === SyntaxKind.VariableDeclaration || name.parent.kind === SyntaxKind.BindingElement); - if (isVariableDeclarationOrBindingElement) { - emitModuleMemberName(name.parent); - } - else { - emit(name); - } + emitStart(nodeForSourceMap); + withTemporaryNoSourceMap(() => { + if (isVariableDeclarationOrBindingElement) { + emitModuleMemberName(name.parent); + } + else { + emit(name); + } - write(" = "); - emit(value); + write(" = "); + emit(value); + }); + emitEnd(nodeForSourceMap, /*stopOverridingSpan*/true); if (exportChanged) { write(")"); @@ -3770,7 +3776,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (!canDefineTempVariablesInPlace) { recordTempDeclaration(identifier); } - emitAssignment(identifier, expression, shouldEmitCommaBeforeAssignment); + emitAssignment(identifier, expression, shouldEmitCommaBeforeAssignment, expression); return identifier; } @@ -3929,7 +3935,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitArrayLiteralAssignment(target, value); } else { - emitAssignment(target, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0); + // TODO + emitAssignment(target, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0, { pos: -1, end: -1 }); emitCount++; } } @@ -3999,7 +4006,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } else { - emitAssignment(target.name, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0); + let nodeForSourceMap: Node; + // If binding element is part of binding pattern with single element, use binding pattern + if (target.kind === SyntaxKind.BindingElement && (target.parent).elements.length === 1) { + nodeForSourceMap = (target.parent.parent.kind === SyntaxKind.VariableDeclaration || target.parent.parent.kind === SyntaxKind.Parameter) ? + target.parent.parent : // Set sourcemap as whole variable declaration + target.parent; // Only binding Pattern + } + else { + nodeForSourceMap = target; // Binding Element + } + emitAssignment(target.name, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0, nodeForSourceMap); emitCount++; } } @@ -7434,6 +7451,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } + function changeSourceMapEmit(writer: SourceMapWriter) { + sourceMap = writer; + emitStart = writer.emitStart; + emitEnd = writer.emitEnd; + emitPos = writer.emitPos; + setSourceFile = writer.setSourceFile; + } + + function withTemporaryNoSourceMap(callback: () => void) { + const prevSourceMap = sourceMap; + setSourceMapWriterEmit(getNullSourceMapWriter()); + callback(); + setSourceMapWriterEmit(prevSourceMap); + } + function isSpecializedCommentHandling(node: Node): boolean { switch (node.kind) { // All of these entities are emitted in a specialized fashion. As such, we allow diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index d98dc233c16..982c37e3fe8 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -7,7 +7,7 @@ namespace ts { setSourceFile(sourceFile: SourceFile): void; emitPos(pos: number): void; emitStart(range: TextRange): void; - emitEnd(range: TextRange): void; + emitEnd(range: TextRange, stopOverridingSpan?: boolean): void; getText(): string; getSourceMappingURL(): string; initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void; @@ -23,7 +23,7 @@ namespace ts { getSourceMapData(): SourceMapData { return undefined; }, setSourceFile(sourceFile: SourceFile): void { }, emitStart(range: TextRange): void { }, - emitEnd(range: TextRange): void { }, + emitEnd(range: TextRange, stopOverridingSpan?: boolean): void { }, emitPos(pos: number): void { }, getText(): string { return undefined; }, getSourceMappingURL(): string { return undefined; }, @@ -39,6 +39,7 @@ namespace ts { const compilerOptions = host.getCompilerOptions(); let currentSourceFile: SourceFile; let sourceMapDir: string; // The directory in which sourcemap will be + let stopOverridingSpan = false; // Current source map file and its index in the sources list let sourceMapSourceIndex: number; @@ -220,8 +221,10 @@ namespace ts { sourceColumn: sourceLinePos.character, sourceIndex: sourceMapSourceIndex }; + + stopOverridingSpan = false; } - else { + else if (!stopOverridingSpan) { // Take the new pos instead since there is no change in emittedLine and column since last location lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line; lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character; @@ -234,8 +237,9 @@ namespace ts { emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1); } - function emitEnd(range: TextRange) { + function emitEnd(range: TextRange, stopOverridingEnd?: boolean) { emitPos(range.end); + stopOverridingSpan = stopOverridingEnd; } function setSourceFile(sourceFile: SourceFile) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 95bf4ff7fa3..0f0f50719c1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1616,7 +1616,7 @@ namespace ts { return node.kind === SyntaxKind.QualifiedName; } - export function nodeIsSynthesized(node: Node): boolean { + export function nodeIsSynthesized(node: Node | TextRange): boolean { return node.pos === -1; } diff --git a/tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.js.map b/tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.js.map index e46d89596d2..b70ebc3bc1d 100644 --- a/tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.js.map +++ b/tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.js.map @@ -1,2 +1,2 @@ //// [sourceMapValidationDestructuringVariableStatement.js.map] -{"version":3,"file":"sourceMapValidationDestructuringVariableStatement.js","sourceRoot":"","sources":["sourceMapValidationDestructuringVariableStatement.ts"],"names":[],"mappings":"AAOA,IAAI,KAAK,GAAG,OAAO,CAAC;AACpB,IAAI,MAAM,GAAU,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACvD,IAAI,MAAM,GAAU,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC3D,IAAY,KAAK,GAAK,MAAM,KAAA,CAAC;AAC7B,IAAY,KAAK,GAAoB,MAAM,OAAjB,MAAM,GAAK,MAAM,MAAA,CAAC;AAC5C,IAAI,KAAiC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,EAAlE,KAAK,YAAS,MAAM,WAA8C,CAAC;AAC/E,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC;IACjB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC;AACD,IAAI,CAAC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"} \ No newline at end of file +{"version":3,"file":"sourceMapValidationDestructuringVariableStatement.js","sourceRoot":"","sources":["sourceMapValidationDestructuringVariableStatement.ts"],"names":[],"mappings":"AAOA,IAAI,KAAK,GAAG,OAAO,CAAC;AACpB,IAAI,MAAM,GAAU,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACvD,IAAI,MAAM,GAAU,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC3D,IAAI,mBAAwB,CAAC;AAC7B,IAAM,mBAAW,EAAE,qBAAa,CAAY;AAC5C,IAAqC,8CAAyC,EAAxE,eAAW,EAAE,iBAAa,CAA+C;AAC/E,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC;IACjB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC;AACD,IAAI,CAAC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.sourcemap.txt b/tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.sourcemap.txt index ff8d54e5e6a..36f31e00216 100644 --- a/tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.sourcemap.txt +++ b/tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.sourcemap.txt @@ -130,121 +130,67 @@ sourceFile:sourceMapValidationDestructuringVariableStatement.ts >>>var nameA = robotA.name; 1 > 2 >^^^^ -3 > ^^^^^ -4 > ^^^ -5 > ^^^^^^ -6 > ^^^^^ -7 > ^ -8 > ^^^^^^^^^^^^^^^^^^^^^^^^-> +3 > ^^^^^^^^^^^^^^^^^^^ +4 > ^ +5 > ^^^^^^^^^^^^^^^^^^^^^^^^-> 1 > > -2 >var { name: -3 > nameA -4 > } = -5 > robotA -6 > -7 > ; +2 >var +3 > { name: nameA } = robotA +4 > ; 1 >Emitted(4, 1) Source(11, 1) + SourceIndex(0) -2 >Emitted(4, 5) Source(11, 13) + SourceIndex(0) -3 >Emitted(4, 10) Source(11, 18) + SourceIndex(0) -4 >Emitted(4, 13) Source(11, 23) + SourceIndex(0) -5 >Emitted(4, 19) Source(11, 29) + SourceIndex(0) -6 >Emitted(4, 24) Source(11, 29) + SourceIndex(0) -7 >Emitted(4, 25) Source(11, 30) + SourceIndex(0) +2 >Emitted(4, 5) Source(11, 5) + SourceIndex(0) +3 >Emitted(4, 24) Source(11, 29) + SourceIndex(0) +4 >Emitted(4, 25) Source(11, 30) + SourceIndex(0) --- >>>var nameB = robotB.name, skillB = robotB.skill; 1-> 2 >^^^^ -3 > ^^^^^ -4 > ^^^ -5 > ^^^^^^ -6 > ^^^^^^^ -7 > ^^^^^^ -8 > ^^^ -9 > ^^^^^^ -10> ^^^^^^ -11> ^ -12> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> +3 > ^^^^^^^^^^^^^^^^^^^ +4 > ^^ +5 > ^^^^^^^^^^^^^^^^^^^^^ +6 > ^ +7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> 1-> > -2 >var { name: -3 > nameB -4 > , skill: skillB } = -5 > robotB -6 > -7 > skillB -8 > } = -9 > robotB -10> -11> ; +2 >var { +3 > name: nameB +4 > , +5 > skill: skillB +6 > } = robotB; 1->Emitted(5, 1) Source(12, 1) + SourceIndex(0) -2 >Emitted(5, 5) Source(12, 13) + SourceIndex(0) -3 >Emitted(5, 10) Source(12, 18) + SourceIndex(0) -4 >Emitted(5, 13) Source(12, 38) + SourceIndex(0) -5 >Emitted(5, 19) Source(12, 44) + SourceIndex(0) -6 >Emitted(5, 26) Source(12, 27) + SourceIndex(0) -7 >Emitted(5, 32) Source(12, 33) + SourceIndex(0) -8 >Emitted(5, 35) Source(12, 38) + SourceIndex(0) -9 >Emitted(5, 41) Source(12, 44) + SourceIndex(0) -10>Emitted(5, 47) Source(12, 44) + SourceIndex(0) -11>Emitted(5, 48) Source(12, 45) + SourceIndex(0) +2 >Emitted(5, 5) Source(12, 7) + SourceIndex(0) +3 >Emitted(5, 24) Source(12, 18) + SourceIndex(0) +4 >Emitted(5, 26) Source(12, 20) + SourceIndex(0) +5 >Emitted(5, 47) Source(12, 33) + SourceIndex(0) +6 >Emitted(5, 48) Source(12, 45) + SourceIndex(0) --- >>>var _a = { name: "Edger", skill: "cutting edges" }, nameC = _a.name, skillC = _a.skill; 1-> 2 >^^^^ -3 > ^^^^^ -4 > ^^ -5 > ^^^^ -6 > ^^ -7 > ^^^^^^^ -8 > ^^ -9 > ^^^^^ -10> ^^ -11> ^^^^^^^^^^^^^^^ -12> ^^ -13> ^^ -14> ^^^^^ -15> ^^^^^^^^^^^^ -16> ^^^^^^ -17> ^^^^^^^^^^^ -18> ^ +3 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +4 > ^^ +5 > ^^^^^^^^^^^^^^^ +6 > ^^ +7 > ^^^^^^^^^^^^^^^^^ +8 > ^ 1-> > -2 >var -3 > { name: nameC, skill: skillC } = -4 > { -5 > name -6 > : -7 > "Edger" -8 > , -9 > skill -10> : -11> "cutting edges" -12> } -13> -14> nameC -15> , skill: -16> skillC -17> } = { name: "Edger", skill: "cutting edges" } -18> ; +2 >var { name: nameC, skill: skillC } = +3 > { name: "Edger", skill: "cutting edges" } +4 > +5 > name: nameC +6 > , +7 > skill: skillC +8 > } = { name: "Edger", skill: "cutting edges" }; 1->Emitted(6, 1) Source(13, 1) + SourceIndex(0) -2 >Emitted(6, 5) Source(13, 5) + SourceIndex(0) -3 >Emitted(6, 10) Source(13, 38) + SourceIndex(0) -4 >Emitted(6, 12) Source(13, 40) + SourceIndex(0) -5 >Emitted(6, 16) Source(13, 44) + SourceIndex(0) -6 >Emitted(6, 18) Source(13, 46) + SourceIndex(0) -7 >Emitted(6, 25) Source(13, 53) + SourceIndex(0) -8 >Emitted(6, 27) Source(13, 55) + SourceIndex(0) -9 >Emitted(6, 32) Source(13, 60) + SourceIndex(0) -10>Emitted(6, 34) Source(13, 62) + SourceIndex(0) -11>Emitted(6, 49) Source(13, 77) + SourceIndex(0) -12>Emitted(6, 51) Source(13, 79) + SourceIndex(0) -13>Emitted(6, 53) Source(13, 13) + SourceIndex(0) -14>Emitted(6, 58) Source(13, 18) + SourceIndex(0) -15>Emitted(6, 70) Source(13, 27) + SourceIndex(0) -16>Emitted(6, 76) Source(13, 33) + SourceIndex(0) -17>Emitted(6, 87) Source(13, 79) + SourceIndex(0) -18>Emitted(6, 88) Source(13, 80) + SourceIndex(0) +2 >Emitted(6, 5) Source(13, 38) + SourceIndex(0) +3 >Emitted(6, 51) Source(13, 79) + SourceIndex(0) +4 >Emitted(6, 53) Source(13, 7) + SourceIndex(0) +5 >Emitted(6, 68) Source(13, 18) + SourceIndex(0) +6 >Emitted(6, 70) Source(13, 20) + SourceIndex(0) +7 >Emitted(6, 87) Source(13, 33) + SourceIndex(0) +8 >Emitted(6, 88) Source(13, 80) + SourceIndex(0) --- >>>if (nameA == nameB) { 1 >