Skip to content

Commit c739def

Browse files
committed
Handle prologues in prepend outputs
1 parent a90ff10 commit c739def

11 files changed

Lines changed: 649 additions & 587 deletions

src/compiler/emitter.ts

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,9 @@ namespace ts {
727727
case SyntaxKind.UnparsedSource:
728728
return emitUnparsedSource(<UnparsedSource>node);
729729

730+
case SyntaxKind.UnparsedPrologue:
731+
return emitUnparsedPrologue(<UnparsedPrologue>node);
732+
730733
// Identifiers
731734
case SyntaxKind.Identifier:
732735
return emitIdentifier(<Identifier>node);
@@ -1211,6 +1214,11 @@ namespace ts {
12111214
writer.rawWrite(unparsed.text.substr(unparsed.pos));
12121215
}
12131216

1217+
// SyntaxKind.UnparsedPrologue
1218+
function emitUnparsedPrologue(unparsed: UnparsedPrologue) {
1219+
writer.rawWrite(unparsed.parent.text.substring(unparsed.pos, unparsed.end));
1220+
}
1221+
12141222
//
12151223
// Identifiers
12161224
//
@@ -3005,13 +3013,27 @@ namespace ts {
30053013
return statements.length;
30063014
}
30073015

3016+
function emitUnparsedPrologues(prologues: ReadonlyArray<UnparsedPrologue>, seenPrologueDirectives: Map<true>) {
3017+
for (const prologue of prologues) {
3018+
if (!seenPrologueDirectives.has(prologue.text)) {
3019+
emit(prologue);
3020+
if (seenPrologueDirectives) {
3021+
seenPrologueDirectives.set(prologue.text, true);
3022+
}
3023+
}
3024+
}
3025+
}
3026+
30083027
function emitPrologueDirectivesIfNeeded(sourceFileOrBundle: Bundle | SourceFile) {
30093028
if (isSourceFile(sourceFileOrBundle)) {
30103029
setSourceFile(sourceFileOrBundle);
30113030
emitPrologueDirectives(sourceFileOrBundle.statements);
30123031
}
30133032
else {
30143033
const seenPrologueDirectives = createMap<true>();
3034+
for (const prepend of sourceFileOrBundle.prepends) {
3035+
emitUnparsedPrologues((prepend as UnparsedSource).prologues, seenPrologueDirectives);
3036+
}
30153037
for (const sourceFile of sourceFileOrBundle.sourceFiles) {
30163038
setSourceFile(sourceFile);
30173039
emitPrologueDirectives(sourceFile.statements, /*startWithNewLine*/ true, seenPrologueDirectives);
@@ -4343,17 +4365,38 @@ namespace ts {
43434365

43444366
// Source Maps
43454367

4368+
function getParsedSourceMap(node: UnparsedSource) {
4369+
if (node.parsedSourceMap === undefined && node.sourceMapText !== undefined) {
4370+
node.parsedSourceMap = tryParseRawSourceMap(node.sourceMapText) || false;
4371+
}
4372+
return node.parsedSourceMap || undefined;
4373+
}
4374+
43464375
function pipelineEmitWithSourceMap(hint: EmitHint, node: Node) {
43474376
const pipelinePhase = getNextPipelinePhase(PipelinePhase.SourceMaps, node);
4348-
if (isUnparsedSource(node) && node.sourceMapText !== undefined) {
4349-
const parsed = tryParseRawSourceMap(node.sourceMapText);
4377+
if (isUnparsedSource(node)) {
4378+
const parsed = getParsedSourceMap(node);
43504379
if (parsed) {
43514380
sourceMapGenerator!.appendSourceMap(
43524381
writer.getLine(),
43534382
writer.getColumn(),
43544383
parsed,
43554384
node.sourceMapPath!,
4356-
node.pos && node.getLineAndCharacterOfPosition(node.pos).line);
4385+
node.pos ? node.getLineAndCharacterOfPosition(node.pos) : undefined);
4386+
}
4387+
pipelinePhase(hint, node);
4388+
}
4389+
else if (isUnparsedPrologue(node)) {
4390+
const parsed = getParsedSourceMap(node.parent);
4391+
if (parsed) {
4392+
sourceMapGenerator!.appendSourceMap(
4393+
writer.getLine(),
4394+
writer.getColumn(),
4395+
parsed,
4396+
node.parent.sourceMapPath!,
4397+
node.parent.getLineAndCharacterOfPosition(node.pos),
4398+
node.parent.getLineAndCharacterOfPosition(node.end)
4399+
);
43574400
}
43584401
pipelinePhase(hint, node);
43594402
}

src/compiler/factory.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2649,7 +2649,22 @@ namespace ts {
26492649
node.sourceMapText = map;
26502650
}
26512651
const text = node.text;
2652-
node.pos = isShebangTrivia(text, 0) ? skipTrivia(text, 0, /*stopAfterLineBreak*/ true) : 0;
2652+
let pos = isShebangTrivia(text, 0) ? skipTrivia(text, 0, /*stopAfterLineBreak*/ true) : 0;
2653+
const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true, /*languageVariant*/ undefined, text, /*onError*/ undefined, pos);
2654+
let prologues: UnparsedPrologue[] | undefined;
2655+
while (scanner.scan() === SyntaxKind.StringLiteral) {
2656+
const start = pos;
2657+
const prologueText = scanner.getTokenValue();
2658+
scanner.tryScan(() => scanner.scan() === SyntaxKind.SemicolonToken);
2659+
pos = skipTrivia(text, scanner.getTextPos(), /*stopAfterLineBreak*/ true);
2660+
2661+
const prologue = <UnparsedPrologue>createNode(SyntaxKind.UnparsedPrologue, start, pos);
2662+
prologue.parent = node;
2663+
prologue.text = prologueText;
2664+
(prologues || (prologues = [])).push(prologue);
2665+
}
2666+
node.pos = pos;
2667+
node.prologues = prologues || emptyArray;
26532668
node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos);
26542669
return node;
26552670
}

src/compiler/sourcemap.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ namespace ts {
140140
exit();
141141
}
142142

143-
function appendSourceMap(generatedLine: number, generatedCharacter: number, map: RawSourceMap, sourceMapPath: string, startLine: number) {
143+
function appendSourceMap(generatedLine: number, generatedCharacter: number, map: RawSourceMap, sourceMapPath: string, start?: LineAndCharacter, end?: LineAndCharacter) {
144144
Debug.assert(generatedLine >= pendingGeneratedLine, "generatedLine cannot backtrack");
145145
Debug.assert(generatedCharacter >= 0, "generatedCharacter cannot be negative");
146146
enter();
@@ -149,7 +149,15 @@ namespace ts {
149149
let nameIndexToNewNameIndexMap: number[] | undefined;
150150
const mappingIterator = decodeMappings(map.mappings);
151151
for (let { value: raw, done } = mappingIterator.next(); !done; { value: raw, done } = mappingIterator.next()) {
152-
if (raw.generatedLine < startLine) {
152+
if (end && (
153+
raw.generatedLine > end.line ||
154+
(raw.generatedLine === end.line && raw.generatedCharacter > end.character))) {
155+
break;
156+
}
157+
158+
if (start && (
159+
raw.generatedLine < start.line ||
160+
(start.line === raw.generatedLine && raw.generatedCharacter < start.character))) {
153161
continue;
154162
}
155163
// Then reencode all the updated mappings into the overall map
@@ -181,9 +189,10 @@ namespace ts {
181189
}
182190
}
183191

184-
const rawGeneratedLine = raw.generatedLine - startLine;
192+
const rawGeneratedLine = raw.generatedLine - (start ? start.line : 0);
185193
const newGeneratedLine = rawGeneratedLine + generatedLine;
186-
const newGeneratedCharacter = rawGeneratedLine === 0 ? raw.generatedCharacter + generatedCharacter : raw.generatedCharacter;
194+
const rawGeneratedCharacter = start && start.line === raw.generatedLine ? raw.generatedCharacter - start.character : raw.generatedCharacter;
195+
const newGeneratedCharacter = rawGeneratedLine === 0 ? rawGeneratedCharacter + generatedCharacter : rawGeneratedCharacter;
187196
addMapping(newGeneratedLine, newGeneratedCharacter, newSourceIndex, newSourceLine, newSourceCharacter, newNameIndex);
188197
}
189198
exit();

src/compiler/types.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ namespace ts {
428428

429429
// Enum
430430
EnumMember,
431+
UnparsedPrologue,
431432
// Top-level nodes
432433
SourceFile,
433434
Bundle,
@@ -2775,13 +2776,21 @@ namespace ts {
27752776
kind: SyntaxKind.UnparsedSource;
27762777
fileName?: string;
27772778
text: string;
2779+
prologues: ReadonlyArray<UnparsedPrologue>;
27782780
sourceMapPath?: string;
27792781
sourceMapText?: string;
2782+
/*@internal*/ parsedSourceMap?: RawSourceMap | false | undefined;
27802783
// Adding this to satisfy services, fix later
27812784
/*@internal*/
27822785
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
27832786
}
27842787

2788+
export interface UnparsedPrologue extends Node {
2789+
kind: SyntaxKind.UnparsedSource;
2790+
text: string;
2791+
parent: UnparsedSource;
2792+
}
2793+
27852794
export interface JsonSourceFile extends SourceFile {
27862795
statements: NodeArray<JsonObjectExpressionStatement>;
27872796
}
@@ -5531,7 +5540,7 @@ namespace ts {
55315540
/**
55325541
* Appends a source map.
55335542
*/
5534-
appendSourceMap(generatedLine: number, generatedCharacter: number, sourceMap: RawSourceMap, sourceMapPath: string, startLine: number): void;
5543+
appendSourceMap(generatedLine: number, generatedCharacter: number, sourceMap: RawSourceMap, sourceMapPath: string, start?: LineAndCharacter, end?: LineAndCharacter): void;
55355544
/**
55365545
* Gets the source map as a `RawSourceMap` object.
55375546
*/

src/compiler/utilities.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5979,6 +5979,10 @@ namespace ts {
59795979
return node.kind === SyntaxKind.UnparsedSource;
59805980
}
59815981

5982+
export function isUnparsedPrologue(node: Node): node is UnparsedPrologue {
5983+
return node.kind === SyntaxKind.UnparsedPrologue;
5984+
}
5985+
59825986
// JSDoc
59835987

59845988
export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression {

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -355,40 +355,41 @@ declare namespace ts {
355355
ShorthandPropertyAssignment = 276,
356356
SpreadAssignment = 277,
357357
EnumMember = 278,
358-
SourceFile = 279,
359-
Bundle = 280,
360-
UnparsedSource = 281,
361-
InputFiles = 282,
362-
JSDocTypeExpression = 283,
363-
JSDocAllType = 284,
364-
JSDocUnknownType = 285,
365-
JSDocNullableType = 286,
366-
JSDocNonNullableType = 287,
367-
JSDocOptionalType = 288,
368-
JSDocFunctionType = 289,
369-
JSDocVariadicType = 290,
370-
JSDocComment = 291,
371-
JSDocTypeLiteral = 292,
372-
JSDocSignature = 293,
373-
JSDocTag = 294,
374-
JSDocAugmentsTag = 295,
375-
JSDocClassTag = 296,
376-
JSDocCallbackTag = 297,
377-
JSDocEnumTag = 298,
378-
JSDocParameterTag = 299,
379-
JSDocReturnTag = 300,
380-
JSDocThisTag = 301,
381-
JSDocTypeTag = 302,
382-
JSDocTemplateTag = 303,
383-
JSDocTypedefTag = 304,
384-
JSDocPropertyTag = 305,
385-
SyntaxList = 306,
386-
NotEmittedStatement = 307,
387-
PartiallyEmittedExpression = 308,
388-
CommaListExpression = 309,
389-
MergeDeclarationMarker = 310,
390-
EndOfDeclarationMarker = 311,
391-
Count = 312,
358+
UnparsedPrologue = 279,
359+
SourceFile = 280,
360+
Bundle = 281,
361+
UnparsedSource = 282,
362+
InputFiles = 283,
363+
JSDocTypeExpression = 284,
364+
JSDocAllType = 285,
365+
JSDocUnknownType = 286,
366+
JSDocNullableType = 287,
367+
JSDocNonNullableType = 288,
368+
JSDocOptionalType = 289,
369+
JSDocFunctionType = 290,
370+
JSDocVariadicType = 291,
371+
JSDocComment = 292,
372+
JSDocTypeLiteral = 293,
373+
JSDocSignature = 294,
374+
JSDocTag = 295,
375+
JSDocAugmentsTag = 296,
376+
JSDocClassTag = 297,
377+
JSDocCallbackTag = 298,
378+
JSDocEnumTag = 299,
379+
JSDocParameterTag = 300,
380+
JSDocReturnTag = 301,
381+
JSDocThisTag = 302,
382+
JSDocTypeTag = 303,
383+
JSDocTemplateTag = 304,
384+
JSDocTypedefTag = 305,
385+
JSDocPropertyTag = 306,
386+
SyntaxList = 307,
387+
NotEmittedStatement = 308,
388+
PartiallyEmittedExpression = 309,
389+
CommaListExpression = 310,
390+
MergeDeclarationMarker = 311,
391+
EndOfDeclarationMarker = 312,
392+
Count = 313,
392393
FirstAssignment = 59,
393394
LastAssignment = 71,
394395
FirstCompoundAssignment = 60,
@@ -414,10 +415,10 @@ declare namespace ts {
414415
FirstBinaryOperator = 28,
415416
LastBinaryOperator = 71,
416417
FirstNode = 148,
417-
FirstJSDocNode = 283,
418-
LastJSDocNode = 305,
419-
FirstJSDocTagNode = 294,
420-
LastJSDocTagNode = 305
418+
FirstJSDocNode = 284,
419+
LastJSDocNode = 306,
420+
FirstJSDocTagNode = 295,
421+
LastJSDocTagNode = 306
421422
}
422423
enum NodeFlags {
423424
None = 0,
@@ -1739,9 +1740,15 @@ declare namespace ts {
17391740
kind: SyntaxKind.UnparsedSource;
17401741
fileName?: string;
17411742
text: string;
1743+
prologues: ReadonlyArray<UnparsedPrologue>;
17421744
sourceMapPath?: string;
17431745
sourceMapText?: string;
17441746
}
1747+
interface UnparsedPrologue extends Node {
1748+
kind: SyntaxKind.UnparsedSource;
1749+
text: string;
1750+
parent: UnparsedSource;
1751+
}
17451752
interface JsonSourceFile extends SourceFile {
17461753
statements: NodeArray<JsonObjectExpressionStatement>;
17471754
}
@@ -3447,6 +3454,7 @@ declare namespace ts {
34473454
function isSourceFile(node: Node): node is SourceFile;
34483455
function isBundle(node: Node): node is Bundle;
34493456
function isUnparsedSource(node: Node): node is UnparsedSource;
3457+
function isUnparsedPrologue(node: Node): node is UnparsedPrologue;
34503458
function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression;
34513459
function isJSDocAllType(node: JSDocAllType): node is JSDocAllType;
34523460
function isJSDocUnknownType(node: Node): node is JSDocUnknownType;

0 commit comments

Comments
 (0)