Skip to content

Commit 097bc77

Browse files
author
Kanchalai Tanglertsampan
committed
Emit unique prologue directives at the top of bundle output file
1 parent d219f8a commit 097bc77

File tree

1 file changed

+47
-10
lines changed

1 file changed

+47
-10
lines changed

src/compiler/emitter.ts

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ namespace ts {
212212
} = comments;
213213

214214
let currentSourceFile: SourceFile;
215+
let statementOffset: number; // We cache the index of first non prologue so we don't have to recalculate it multiple times like in emitBodyInDirect
215216
let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes.
216217
let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables.
217218
let generatedNames: Map<string>; // Set of names generated by the NameGenerator.
@@ -275,6 +276,7 @@ namespace ts {
275276
const previousWriter = writer;
276277
setWriter(output);
277278
emitShebangIfNeeded(bundle);
279+
emitPrologueDirectivesIfNeeded(bundle);
278280
emitHelpersIndirect(bundle);
279281
for (const sourceFile of bundle.sourceFiles) {
280282
print(EmitHint.SourceFile, sourceFile, sourceFile);
@@ -287,6 +289,7 @@ namespace ts {
287289
const previousWriter = writer;
288290
setWriter(output);
289291
emitShebangIfNeeded(sourceFile);
292+
emitPrologueDirectivesIfNeeded(sourceFile);
290293
print(EmitHint.SourceFile, sourceFile, sourceFile);
291294
reset();
292295
writer = previousWriter;
@@ -309,6 +312,7 @@ namespace ts {
309312

310313
function setSourceFile(sourceFile: SourceFile) {
311314
currentSourceFile = sourceFile;
315+
statementOffset = getIndexOfFirstNonPrologueDirectives(sourceFile.statements);
312316
comments.setSourceFile(sourceFile);
313317
if (onSetSourceFile) {
314318
onSetSourceFile(sourceFile);
@@ -733,7 +737,11 @@ namespace ts {
733737
}
734738

735739
function emitBodyIndirect(node: Node, elements: NodeArray<Node>, emitCallback: (node: Node) => void): void {
736-
if (emitBodyWithDetachedComments) {
740+
// If the node is a sourceFile and it has prologueDirective (statmentOffSet is not zero) that is synthesize
741+
// We will need to emit detached comment here because emitPrologueDirective will not emit comments of such prologue directive
742+
const shouldEmitDetachedComment = node.kind !== SyntaxKind.SourceFile ? true :
743+
statementOffset === 0 || nodeIsSynthesized((node as SourceFile).statements[statementOffset - 1]);
744+
if (emitBodyWithDetachedComments && shouldEmitDetachedComment) {
737745
emitBodyWithDetachedComments(node, elements, emitCallback);
738746
}
739747
else {
@@ -2058,7 +2066,6 @@ namespace ts {
20582066

20592067
function emitSourceFileWorker(node: SourceFile) {
20602068
const statements = node.statements;
2061-
const statementOffset = emitPrologueDirectives(statements);
20622069
pushNameGenerationScope();
20632070
emitHelpersIndirect(node);
20642071
emitList(node, statements, ListFormat.MultiLine, statementOffset);
@@ -2075,13 +2082,20 @@ namespace ts {
20752082
* Emits any prologue directives at the start of a Statement list, returning the
20762083
* number of prologue directives written to the output.
20772084
*/
2078-
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean): number {
2085+
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean, seenPrologueDirectives?: Map<String>): number {
20792086
for (let i = 0; i < statements.length; i++) {
2080-
if (isPrologueDirective(statements[i])) {
2081-
if (startWithNewLine || i > 0) {
2082-
writeLine();
2087+
const statement = statements[i];
2088+
if (isPrologueDirective(statement)) {
2089+
const shouldEmitPrologueDirective = seenPrologueDirectives ? !seenPrologueDirectives.has(statement.expression.text) : true;
2090+
if (shouldEmitPrologueDirective) {
2091+
if (startWithNewLine || i > 0) {
2092+
writeLine();
2093+
}
2094+
emit(statement);
2095+
if (seenPrologueDirectives) {
2096+
seenPrologueDirectives.set(statement.expression.text, statement.expression.text);
2097+
}
20832098
}
2084-
emit(statements[i]);
20852099
}
20862100
else {
20872101
// return index of the first non prologue directive
@@ -2092,9 +2106,19 @@ namespace ts {
20922106
return statements.length;
20932107
}
20942108

2095-
//
2096-
// Helpers
2097-
//
2109+
function emitPrologueDirectivesIfNeeded(sourceFileOrBundle: Bundle | SourceFile) {
2110+
if (sourceFileOrBundle.kind === SyntaxKind.SourceFile) {
2111+
setSourceFile(sourceFileOrBundle as SourceFile);
2112+
emitPrologueDirectives((sourceFileOrBundle as SourceFile).statements);
2113+
}
2114+
else {
2115+
const seenProgolueDirectives = createMap<String>();
2116+
for (const sourceFile of (sourceFileOrBundle as Bundle).sourceFiles) {
2117+
setSourceFile(sourceFile);
2118+
emitPrologueDirectives(sourceFile.statements, /*startWithNewLine*/ true, seenProgolueDirectives);
2119+
}
2120+
}
2121+
}
20982122

20992123
function emitShebangIfNeeded(sourceFileOrBundle: Bundle | SourceFile) {
21002124
if (sourceFileOrBundle.kind === SyntaxKind.SourceFile) {
@@ -2119,6 +2143,19 @@ namespace ts {
21192143
}
21202144
}
21212145

2146+
//
2147+
// Helpers
2148+
//
2149+
2150+
function getIndexOfFirstNonPrologueDirectives(statements: Statement[]): number {
2151+
for (let i = 0; i < statements.length; i++) {
2152+
if (!isPrologueDirective(statements[i])) {
2153+
return i;
2154+
}
2155+
}
2156+
return statements.length;
2157+
}
2158+
21222159
function emitModifiers(node: Node, modifiers: NodeArray<Modifier>) {
21232160
if (modifiers && modifiers.length) {
21242161
emitList(node, modifiers, ListFormat.Modifiers);

0 commit comments

Comments
 (0)