Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b217c39

Browse filesBrowse files
authored
Merge pull request microsoft#15935 from chuckjaz/external-file-source-map
Add support for external file references in source maps
2 parents 5888804 + ce1d1c8 commit b217c39
Copy full SHA for b217c39

7 files changed

+89-28Lines changed: 89 additions & 28 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/core.ts‎

Copy file name to clipboardExpand all lines: src/compiler/core.ts
+9-1Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2249,6 +2249,7 @@ namespace ts {
22492249
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
22502250
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
22512251
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
2252+
getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
22522253
}
22532254

22542255
function Symbol(this: Symbol, flags: SymbolFlags, name: string) {
@@ -2279,14 +2280,21 @@ namespace ts {
22792280
this.original = undefined;
22802281
}
22812282

2283+
function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number) {
2284+
this.fileName = fileName;
2285+
this.text = text;
2286+
this.skipTrivia = skipTrivia || (pos => pos);
2287+
}
2288+
22822289
export let objectAllocator: ObjectAllocator = {
22832290
getNodeConstructor: () => <any>Node,
22842291
getTokenConstructor: () => <any>Node,
22852292
getIdentifierConstructor: () => <any>Node,
22862293
getSourceFileConstructor: () => <any>Node,
22872294
getSymbolConstructor: () => <any>Symbol,
22882295
getTypeConstructor: () => <any>Type,
2289-
getSignatureConstructor: () => <any>Signature
2296+
getSignatureConstructor: () => <any>Signature,
2297+
getSourceMapSourceConstructor: () => <any>SourceMapSource,
22902298
};
22912299

22922300
export const enum AssertionLevel {
Collapse file

‎src/compiler/factory.ts‎

Copy file name to clipboardExpand all lines: src/compiler/factory.ts
+12-3Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2314,15 +2314,24 @@ namespace ts {
23142314
/**
23152315
* Sets a custom text range to use when emitting source maps.
23162316
*/
2317-
export function setSourceMapRange<T extends Node>(node: T, range: TextRange | undefined) {
2317+
export function setSourceMapRange<T extends Node>(node: T, range: SourceMapRange | undefined) {
23182318
getOrCreateEmitNode(node).sourceMapRange = range;
23192319
return node;
23202320
}
23212321

2322+
let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
2323+
2324+
/**
2325+
* Create an external source map source file reference
2326+
*/
2327+
export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource {
2328+
return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia);
2329+
}
2330+
23222331
/**
23232332
* Gets the TextRange to use for source maps for a token of a node.
23242333
*/
2325-
export function getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange | undefined {
2334+
export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined {
23262335
const emitNode = node.emitNode;
23272336
const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges;
23282337
return tokenSourceMapRanges && tokenSourceMapRanges[token];
@@ -2331,7 +2340,7 @@ namespace ts {
23312340
/**
23322341
* Sets the TextRange to use for source maps for a token of a node.
23332342
*/
2334-
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: TextRange | undefined) {
2343+
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: SourceMapRange | undefined) {
23352344
const emitNode = getOrCreateEmitNode(node);
23362345
const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []);
23372346
tokenSourceMapRanges[token] = range;
Collapse file

‎src/compiler/scanner.ts‎

Copy file name to clipboardExpand all lines: src/compiler/scanner.ts
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ namespace ts {
363363
};
364364
}
365365

366-
export function getLineAndCharacterOfPosition(sourceFile: SourceFile, position: number): LineAndCharacter {
366+
export function getLineAndCharacterOfPosition(sourceFile: SourceFileLike, position: number): LineAndCharacter {
367367
return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
368368
}
369369

Collapse file

‎src/compiler/sourcemap.ts‎

Copy file name to clipboardExpand all lines: src/compiler/sourcemap.ts
+33-14Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace ts {
2222
*
2323
* @param sourceFile The source file.
2424
*/
25-
setSourceFile(sourceFile: SourceFile): void;
25+
setSourceFile(sourceFile: SourceMapSource): void;
2626

2727
/**
2828
* Emits a mapping.
@@ -81,7 +81,7 @@ namespace ts {
8181
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
8282
const compilerOptions = host.getCompilerOptions();
8383
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
84-
let currentSourceFile: SourceFile;
84+
let currentSource: SourceMapSource;
8585
let currentSourceText: string;
8686
let sourceMapDir: string; // The directory in which sourcemap will be
8787

@@ -109,6 +109,13 @@ namespace ts {
109109
getSourceMappingURL,
110110
};
111111

112+
/**
113+
* Skips trivia such as comments and white-space that can optionally overriden by the source map source
114+
*/
115+
function skipSourceTrivia(pos: number): number {
116+
return currentSource.skipTrivia ? currentSource.skipTrivia(pos) : skipTrivia(currentSourceText, pos);
117+
}
118+
112119
/**
113120
* Initialize the SourceMapWriter for a new output file.
114121
*
@@ -125,7 +132,7 @@ namespace ts {
125132
reset();
126133
}
127134

128-
currentSourceFile = undefined;
135+
currentSource = undefined;
129136
currentSourceText = undefined;
130137

131138
// Current source map file and its index in the sources list
@@ -192,7 +199,7 @@ namespace ts {
192199
return;
193200
}
194201

195-
currentSourceFile = undefined;
202+
currentSource = undefined;
196203
sourceMapDir = undefined;
197204
sourceMapSourceIndex = undefined;
198205
lastRecordedSourceMapSpan = undefined;
@@ -263,7 +270,7 @@ namespace ts {
263270
performance.mark("beforeSourcemap");
264271
}
265272

266-
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
273+
const sourceLinePos = getLineAndCharacterOfPosition(currentSource, pos);
267274

268275
// Convert the location to be one-based.
269276
sourceLinePos.line++;
@@ -320,14 +327,22 @@ namespace ts {
320327
if (node) {
321328
const emitNode = node.emitNode;
322329
const emitFlags = emitNode && emitNode.flags;
323-
const { pos, end } = emitNode && emitNode.sourceMapRange || node;
330+
const range = emitNode && emitNode.sourceMapRange;
331+
const { pos, end } = range || node;
332+
let source = range && range.source;
333+
const oldSource = currentSource;
334+
if (source === oldSource) source = undefined;
335+
336+
if (source) setSourceFile(source);
324337

325338
if (node.kind !== SyntaxKind.NotEmittedStatement
326339
&& (emitFlags & EmitFlags.NoLeadingSourceMap) === 0
327340
&& pos >= 0) {
328-
emitPos(skipTrivia(currentSourceText, pos));
341+
emitPos(skipSourceTrivia(pos));
329342
}
330343

344+
if (source) setSourceFile(oldSource);
345+
331346
if (emitFlags & EmitFlags.NoNestedSourceMaps) {
332347
disabled = true;
333348
emitCallback(hint, node);
@@ -337,11 +352,15 @@ namespace ts {
337352
emitCallback(hint, node);
338353
}
339354

355+
if (source) setSourceFile(source);
356+
340357
if (node.kind !== SyntaxKind.NotEmittedStatement
341358
&& (emitFlags & EmitFlags.NoTrailingSourceMap) === 0
342359
&& end >= 0) {
343360
emitPos(end);
344361
}
362+
363+
if (source) setSourceFile(oldSource);
345364
}
346365
}
347366

@@ -362,7 +381,7 @@ namespace ts {
362381
const emitFlags = emitNode && emitNode.flags;
363382
const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token];
364383

365-
tokenPos = skipTrivia(currentSourceText, range ? range.pos : tokenPos);
384+
tokenPos = skipSourceTrivia(range ? range.pos : tokenPos);
366385
if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) {
367386
emitPos(tokenPos);
368387
}
@@ -382,21 +401,21 @@ namespace ts {
382401
*
383402
* @param sourceFile The source file.
384403
*/
385-
function setSourceFile(sourceFile: SourceFile) {
404+
function setSourceFile(sourceFile: SourceMapSource) {
386405
if (disabled) {
387406
return;
388407
}
389408

390-
currentSourceFile = sourceFile;
391-
currentSourceText = currentSourceFile.text;
409+
currentSource = sourceFile;
410+
currentSourceText = currentSource.text;
392411

393412
// Add the file to tsFilePaths
394413
// If sourceroot option: Use the relative path corresponding to the common directory path
395414
// otherwise source locations relative to map file location
396415
const sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
397416

398417
const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
399-
currentSourceFile.fileName,
418+
currentSource.fileName,
400419
host.getCurrentDirectory(),
401420
host.getCanonicalFileName,
402421
/*isAbsolutePathAnUrl*/ true);
@@ -407,10 +426,10 @@ namespace ts {
407426
sourceMapData.sourceMapSources.push(source);
408427

409428
// The one that can be used from program to get the actual source file
410-
sourceMapData.inputSourceFileNames.push(currentSourceFile.fileName);
429+
sourceMapData.inputSourceFileNames.push(currentSource.fileName);
411430

412431
if (compilerOptions.inlineSources) {
413-
sourceMapData.sourceMapSourcesContent.push(currentSourceFile.text);
432+
sourceMapData.sourceMapSourcesContent.push(currentSource.text);
414433
}
415434
}
416435
}
Collapse file

‎src/compiler/types.ts‎

Copy file name to clipboardExpand all lines: src/compiler/types.ts
+20-9Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4013,18 +4013,29 @@ namespace ts {
40134013
ES2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments,
40144014
}
40154015

4016+
export interface SourceMapRange extends TextRange {
4017+
source?: SourceMapSource;
4018+
}
4019+
4020+
export interface SourceMapSource {
4021+
fileName: string;
4022+
text: string;
4023+
/* @internal */ lineMap: number[];
4024+
skipTrivia?: (pos: number) => number;
4025+
}
4026+
40164027
/* @internal */
40174028
export interface EmitNode {
4018-
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
4019-
flags?: EmitFlags; // Flags that customize emit
4020-
leadingComments?: SynthesizedComment[]; // Synthesized leading comments
4029+
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
4030+
flags?: EmitFlags; // Flags that customize emit
4031+
leadingComments?: SynthesizedComment[]; // Synthesized leading comments
40214032
trailingComments?: SynthesizedComment[]; // Synthesized trailing comments
4022-
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
4023-
sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings
4024-
tokenSourceMapRanges?: TextRange[]; // The text range to use when emitting source mappings for tokens
4025-
constantValue?: string | number; // The constant value of an expression
4026-
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
4027-
helpers?: EmitHelper[]; // Emit helpers for the node
4033+
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
4034+
sourceMapRange?: SourceMapRange; // The text range to use when emitting leading or trailing source mappings
4035+
tokenSourceMapRanges?: SourceMapRange[]; // The text range to use when emitting source mappings for tokens
4036+
constantValue?: string | number; // The constant value of an expression
4037+
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
4038+
helpers?: EmitHelper[]; // Emit helpers for the node
40284039
}
40294040

40304041
export const enum EmitFlags {
Collapse file

‎src/services/services.ts‎

Copy file name to clipboardExpand all lines: src/services/services.ts
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,15 @@ namespace ts {
732732
}
733733
}
734734

735+
class SourceMapSourceObject implements SourceMapSource {
736+
lineMap: number[];
737+
constructor (public fileName: string, public text: string, public skipTrivia?: (pos: number) => number) {}
738+
739+
public getLineAndCharacterOfPosition(pos: number): LineAndCharacter {
740+
return ts.getLineAndCharacterOfPosition(this, pos);
741+
}
742+
}
743+
735744
function getServicesObjectAllocator(): ObjectAllocator {
736745
return {
737746
getNodeConstructor: () => NodeObject,
@@ -742,6 +751,7 @@ namespace ts {
742751
getSymbolConstructor: () => SymbolObject,
743752
getTypeConstructor: () => TypeObject,
744753
getSignatureConstructor: () => SignatureObject,
754+
getSourceMapSourceConstructor: () => SourceMapSourceObject,
745755
};
746756
}
747757

Collapse file

‎src/services/types.ts‎

Copy file name to clipboardExpand all lines: src/services/types.ts
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ namespace ts {
7171
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
7272
}
7373

74+
export interface SourceMapSource {
75+
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
76+
}
77+
7478
/**
7579
* Represents an immutable snapshot of a script at a specified time.Once acquired, the
7680
* snapshot is observably immutable. i.e. the same calls with the same parameters will return

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.