Skip to content

Commit 4ebf569

Browse files
committed
Better sourcemaps for destructuring
1 parent e282722 commit 4ebf569

5 files changed

Lines changed: 101 additions & 119 deletions

File tree

src/compiler/emitter.ts

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
464464
const writer = createTextWriter(newLine);
465465
const { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer;
466466

467-
const sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? createSourceMapWriter(host, writer) : getNullSourceMapWriter();
468-
const { setSourceFile, emitStart, emitEnd, emitPos } = sourceMap;
467+
let sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? createSourceMapWriter(host, writer) : getNullSourceMapWriter();
468+
let { setSourceFile, emitStart, emitEnd, emitPos } = sourceMap;
469469

470470
let currentSourceFile: SourceFile;
471471
let currentText: string;
@@ -512,6 +512,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
512512
/** If removeComments is true, no leading-comments needed to be emitted **/
513513
const emitLeadingCommentsOfPosition = compilerOptions.removeComments ? function (pos: number) { } : emitLeadingCommentsOfPositionWorker;
514514

515+
const setSourceMapWriterEmit = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? changeSourceMapEmit : function (writer: SourceMapWriter) { };
516+
515517
const moduleEmitDelegates: Map<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = {
516518
[ModuleKind.ES6]: emitES6Module,
517519
[ModuleKind.AMD]: emitAMDModule,
@@ -2573,7 +2575,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
25732575
leftHandSideExpression.argumentExpression.kind !== SyntaxKind.StringLiteral) {
25742576
const tempArgumentExpression = createAndRecordTempVariable(TempFlags._i);
25752577
(<ElementAccessExpression>synthesizedLHS).argumentExpression = tempArgumentExpression;
2576-
emitAssignment(tempArgumentExpression, leftHandSideExpression.argumentExpression, /*shouldEmitCommaBeforeAssignment*/ true);
2578+
emitAssignment(tempArgumentExpression, leftHandSideExpression.argumentExpression, /*shouldEmitCommaBeforeAssignment*/ true, leftHandSideExpression.expression);
25772579
}
25782580
else {
25792581
(<ElementAccessExpression>synthesizedLHS).argumentExpression = leftHandSideExpression.argumentExpression;
@@ -3728,7 +3730,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
37283730
* @param value an expression as a right-hand-side operand of the assignment
37293731
* @param shouldEmitCommaBeforeAssignment a boolean indicating whether to prefix an assignment with comma
37303732
*/
3731-
function emitAssignment(name: Identifier, value: Expression, shouldEmitCommaBeforeAssignment: boolean) {
3733+
function emitAssignment(name: Identifier, value: Expression, shouldEmitCommaBeforeAssignment: boolean, nodeForSourceMap: TextRange) {
37323734
if (shouldEmitCommaBeforeAssignment) {
37333735
write(", ");
37343736
}
@@ -3744,15 +3746,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
37443746
const isVariableDeclarationOrBindingElement =
37453747
name.parent && (name.parent.kind === SyntaxKind.VariableDeclaration || name.parent.kind === SyntaxKind.BindingElement);
37463748

3747-
if (isVariableDeclarationOrBindingElement) {
3748-
emitModuleMemberName(<Declaration>name.parent);
3749-
}
3750-
else {
3751-
emit(name);
3752-
}
3749+
emitStart(nodeForSourceMap);
3750+
withTemporaryNoSourceMap(() => {
3751+
if (isVariableDeclarationOrBindingElement) {
3752+
emitModuleMemberName(<Declaration>name.parent);
3753+
}
3754+
else {
3755+
emit(name);
3756+
}
37533757

3754-
write(" = ");
3755-
emit(value);
3758+
write(" = ");
3759+
emit(value);
3760+
});
3761+
emitEnd(nodeForSourceMap, /*stopOverridingSpan*/true);
37563762

37573763
if (exportChanged) {
37583764
write(")");
@@ -3770,7 +3776,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
37703776
if (!canDefineTempVariablesInPlace) {
37713777
recordTempDeclaration(identifier);
37723778
}
3773-
emitAssignment(identifier, expression, shouldEmitCommaBeforeAssignment);
3779+
emitAssignment(identifier, expression, shouldEmitCommaBeforeAssignment, expression);
37743780
return identifier;
37753781
}
37763782

@@ -3929,7 +3935,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
39293935
emitArrayLiteralAssignment(<ArrayLiteralExpression>target, value);
39303936
}
39313937
else {
3932-
emitAssignment(<Identifier>target, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0);
3938+
// TODO
3939+
emitAssignment(<Identifier>target, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0, { pos: -1, end: -1 });
39333940
emitCount++;
39343941
}
39353942
}
@@ -3999,7 +4006,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
39994006
}
40004007
}
40014008
else {
4002-
emitAssignment(<Identifier>target.name, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0);
4009+
let nodeForSourceMap: Node;
4010+
// If binding element is part of binding pattern with single element, use binding pattern
4011+
if (target.kind === SyntaxKind.BindingElement && (<BindingPattern>target.parent).elements.length === 1) {
4012+
nodeForSourceMap = (target.parent.parent.kind === SyntaxKind.VariableDeclaration || target.parent.parent.kind === SyntaxKind.Parameter) ?
4013+
target.parent.parent : // Set sourcemap as whole variable declaration
4014+
target.parent; // Only binding Pattern
4015+
}
4016+
else {
4017+
nodeForSourceMap = target; // Binding Element
4018+
}
4019+
emitAssignment(<Identifier>target.name, value, /*shouldEmitCommaBeforeAssignment*/ emitCount > 0, nodeForSourceMap);
40034020
emitCount++;
40044021
}
40054022
}
@@ -7434,6 +7451,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
74347451
}
74357452
}
74367453

7454+
function changeSourceMapEmit(writer: SourceMapWriter) {
7455+
sourceMap = writer;
7456+
emitStart = writer.emitStart;
7457+
emitEnd = writer.emitEnd;
7458+
emitPos = writer.emitPos;
7459+
setSourceFile = writer.setSourceFile;
7460+
}
7461+
7462+
function withTemporaryNoSourceMap(callback: () => void) {
7463+
const prevSourceMap = sourceMap;
7464+
setSourceMapWriterEmit(getNullSourceMapWriter());
7465+
callback();
7466+
setSourceMapWriterEmit(prevSourceMap);
7467+
}
7468+
74377469
function isSpecializedCommentHandling(node: Node): boolean {
74387470
switch (node.kind) {
74397471
// All of these entities are emitted in a specialized fashion. As such, we allow

src/compiler/sourcemap.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace ts {
77
setSourceFile(sourceFile: SourceFile): void;
88
emitPos(pos: number): void;
99
emitStart(range: TextRange): void;
10-
emitEnd(range: TextRange): void;
10+
emitEnd(range: TextRange, stopOverridingSpan?: boolean): void;
1111
getText(): string;
1212
getSourceMappingURL(): string;
1313
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
@@ -23,7 +23,7 @@ namespace ts {
2323
getSourceMapData(): SourceMapData { return undefined; },
2424
setSourceFile(sourceFile: SourceFile): void { },
2525
emitStart(range: TextRange): void { },
26-
emitEnd(range: TextRange): void { },
26+
emitEnd(range: TextRange, stopOverridingSpan?: boolean): void { },
2727
emitPos(pos: number): void { },
2828
getText(): string { return undefined; },
2929
getSourceMappingURL(): string { return undefined; },
@@ -39,6 +39,7 @@ namespace ts {
3939
const compilerOptions = host.getCompilerOptions();
4040
let currentSourceFile: SourceFile;
4141
let sourceMapDir: string; // The directory in which sourcemap will be
42+
let stopOverridingSpan = false;
4243

4344
// Current source map file and its index in the sources list
4445
let sourceMapSourceIndex: number;
@@ -220,8 +221,10 @@ namespace ts {
220221
sourceColumn: sourceLinePos.character,
221222
sourceIndex: sourceMapSourceIndex
222223
};
224+
225+
stopOverridingSpan = false;
223226
}
224-
else {
227+
else if (!stopOverridingSpan) {
225228
// Take the new pos instead since there is no change in emittedLine and column since last location
226229
lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
227230
lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
@@ -234,8 +237,9 @@ namespace ts {
234237
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1);
235238
}
236239

237-
function emitEnd(range: TextRange) {
240+
function emitEnd(range: TextRange, stopOverridingEnd?: boolean) {
238241
emitPos(range.end);
242+
stopOverridingSpan = stopOverridingEnd;
239243
}
240244

241245
function setSourceFile(sourceFile: SourceFile) {

src/compiler/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1616,7 +1616,7 @@ namespace ts {
16161616
return node.kind === SyntaxKind.QualifiedName;
16171617
}
16181618

1619-
export function nodeIsSynthesized(node: Node): boolean {
1619+
export function nodeIsSynthesized(node: Node | TextRange): boolean {
16201620
return node.pos === -1;
16211621
}
16221622

tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/baselines/reference/sourceMapValidationDestructuringVariableStatement.sourcemap.txt

Lines changed: 44 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -130,121 +130,67 @@ sourceFile:sourceMapValidationDestructuringVariableStatement.ts
130130
>>>var nameA = robotA.name;
131131
1 >
132132
2 >^^^^
133-
3 > ^^^^^
134-
4 > ^^^
135-
5 > ^^^^^^
136-
6 > ^^^^^
137-
7 > ^
138-
8 > ^^^^^^^^^^^^^^^^^^^^^^^^->
133+
3 > ^^^^^^^^^^^^^^^^^^^
134+
4 > ^
135+
5 > ^^^^^^^^^^^^^^^^^^^^^^^^->
139136
1 >
140137
>
141-
2 >var { name:
142-
3 > nameA
143-
4 > } =
144-
5 > robotA
145-
6 >
146-
7 > ;
138+
2 >var
139+
3 > { name: nameA } = robotA
140+
4 > ;
147141
1 >Emitted(4, 1) Source(11, 1) + SourceIndex(0)
148-
2 >Emitted(4, 5) Source(11, 13) + SourceIndex(0)
149-
3 >Emitted(4, 10) Source(11, 18) + SourceIndex(0)
150-
4 >Emitted(4, 13) Source(11, 23) + SourceIndex(0)
151-
5 >Emitted(4, 19) Source(11, 29) + SourceIndex(0)
152-
6 >Emitted(4, 24) Source(11, 29) + SourceIndex(0)
153-
7 >Emitted(4, 25) Source(11, 30) + SourceIndex(0)
142+
2 >Emitted(4, 5) Source(11, 5) + SourceIndex(0)
143+
3 >Emitted(4, 24) Source(11, 29) + SourceIndex(0)
144+
4 >Emitted(4, 25) Source(11, 30) + SourceIndex(0)
154145
---
155146
>>>var nameB = robotB.name, skillB = robotB.skill;
156147
1->
157148
2 >^^^^
158-
3 > ^^^^^
159-
4 > ^^^
160-
5 > ^^^^^^
161-
6 > ^^^^^^^
162-
7 > ^^^^^^
163-
8 > ^^^
164-
9 > ^^^^^^
165-
10> ^^^^^^
166-
11> ^
167-
12> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
149+
3 > ^^^^^^^^^^^^^^^^^^^
150+
4 > ^^
151+
5 > ^^^^^^^^^^^^^^^^^^^^^
152+
6 > ^
153+
7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
168154
1->
169155
>
170-
2 >var { name:
171-
3 > nameB
172-
4 > , skill: skillB } =
173-
5 > robotB
174-
6 >
175-
7 > skillB
176-
8 > } =
177-
9 > robotB
178-
10>
179-
11> ;
156+
2 >var {
157+
3 > name: nameB
158+
4 > ,
159+
5 > skill: skillB
160+
6 > } = robotB;
180161
1->Emitted(5, 1) Source(12, 1) + SourceIndex(0)
181-
2 >Emitted(5, 5) Source(12, 13) + SourceIndex(0)
182-
3 >Emitted(5, 10) Source(12, 18) + SourceIndex(0)
183-
4 >Emitted(5, 13) Source(12, 38) + SourceIndex(0)
184-
5 >Emitted(5, 19) Source(12, 44) + SourceIndex(0)
185-
6 >Emitted(5, 26) Source(12, 27) + SourceIndex(0)
186-
7 >Emitted(5, 32) Source(12, 33) + SourceIndex(0)
187-
8 >Emitted(5, 35) Source(12, 38) + SourceIndex(0)
188-
9 >Emitted(5, 41) Source(12, 44) + SourceIndex(0)
189-
10>Emitted(5, 47) Source(12, 44) + SourceIndex(0)
190-
11>Emitted(5, 48) Source(12, 45) + SourceIndex(0)
162+
2 >Emitted(5, 5) Source(12, 7) + SourceIndex(0)
163+
3 >Emitted(5, 24) Source(12, 18) + SourceIndex(0)
164+
4 >Emitted(5, 26) Source(12, 20) + SourceIndex(0)
165+
5 >Emitted(5, 47) Source(12, 33) + SourceIndex(0)
166+
6 >Emitted(5, 48) Source(12, 45) + SourceIndex(0)
191167
---
192168
>>>var _a = { name: "Edger", skill: "cutting edges" }, nameC = _a.name, skillC = _a.skill;
193169
1->
194170
2 >^^^^
195-
3 > ^^^^^
196-
4 > ^^
197-
5 > ^^^^
198-
6 > ^^
199-
7 > ^^^^^^^
200-
8 > ^^
201-
9 > ^^^^^
202-
10> ^^
203-
11> ^^^^^^^^^^^^^^^
204-
12> ^^
205-
13> ^^
206-
14> ^^^^^
207-
15> ^^^^^^^^^^^^
208-
16> ^^^^^^
209-
17> ^^^^^^^^^^^
210-
18> ^
171+
3 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
172+
4 > ^^
173+
5 > ^^^^^^^^^^^^^^^
174+
6 > ^^
175+
7 > ^^^^^^^^^^^^^^^^^
176+
8 > ^
211177
1->
212178
>
213-
2 >var
214-
3 > { name: nameC, skill: skillC } =
215-
4 > {
216-
5 > name
217-
6 > :
218-
7 > "Edger"
219-
8 > ,
220-
9 > skill
221-
10> :
222-
11> "cutting edges"
223-
12> }
224-
13>
225-
14> nameC
226-
15> , skill:
227-
16> skillC
228-
17> } = { name: "Edger", skill: "cutting edges" }
229-
18> ;
179+
2 >var { name: nameC, skill: skillC } =
180+
3 > { name: "Edger", skill: "cutting edges" }
181+
4 >
182+
5 > name: nameC
183+
6 > ,
184+
7 > skill: skillC
185+
8 > } = { name: "Edger", skill: "cutting edges" };
230186
1->Emitted(6, 1) Source(13, 1) + SourceIndex(0)
231-
2 >Emitted(6, 5) Source(13, 5) + SourceIndex(0)
232-
3 >Emitted(6, 10) Source(13, 38) + SourceIndex(0)
233-
4 >Emitted(6, 12) Source(13, 40) + SourceIndex(0)
234-
5 >Emitted(6, 16) Source(13, 44) + SourceIndex(0)
235-
6 >Emitted(6, 18) Source(13, 46) + SourceIndex(0)
236-
7 >Emitted(6, 25) Source(13, 53) + SourceIndex(0)
237-
8 >Emitted(6, 27) Source(13, 55) + SourceIndex(0)
238-
9 >Emitted(6, 32) Source(13, 60) + SourceIndex(0)
239-
10>Emitted(6, 34) Source(13, 62) + SourceIndex(0)
240-
11>Emitted(6, 49) Source(13, 77) + SourceIndex(0)
241-
12>Emitted(6, 51) Source(13, 79) + SourceIndex(0)
242-
13>Emitted(6, 53) Source(13, 13) + SourceIndex(0)
243-
14>Emitted(6, 58) Source(13, 18) + SourceIndex(0)
244-
15>Emitted(6, 70) Source(13, 27) + SourceIndex(0)
245-
16>Emitted(6, 76) Source(13, 33) + SourceIndex(0)
246-
17>Emitted(6, 87) Source(13, 79) + SourceIndex(0)
247-
18>Emitted(6, 88) Source(13, 80) + SourceIndex(0)
187+
2 >Emitted(6, 5) Source(13, 38) + SourceIndex(0)
188+
3 >Emitted(6, 51) Source(13, 79) + SourceIndex(0)
189+
4 >Emitted(6, 53) Source(13, 7) + SourceIndex(0)
190+
5 >Emitted(6, 68) Source(13, 18) + SourceIndex(0)
191+
6 >Emitted(6, 70) Source(13, 20) + SourceIndex(0)
192+
7 >Emitted(6, 87) Source(13, 33) + SourceIndex(0)
193+
8 >Emitted(6, 88) Source(13, 80) + SourceIndex(0)
248194
---
249195
>>>if (nameA == nameB) {
250196
1 >

0 commit comments

Comments
 (0)