Skip to content

Commit 593fbd4

Browse files
committed
Merge branch 'transforms-transformer-jsx' into transforms-transformer-es7
2 parents 2c9cd2e + 1fdaf74 commit 593fbd4

File tree

4 files changed

+116
-117
lines changed

4 files changed

+116
-117
lines changed

src/compiler/printer.ts

+51-27
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,7 @@ const _super = (function (geti, seti) {
151151
let isEmitNotificationEnabled: (node: Node) => boolean;
152152
let expressionSubstitution: (node: Expression) => Expression;
153153
let identifierSubstitution: (node: Identifier) => Identifier;
154-
let onBeforeEmitNode: (node: Node) => void;
155-
let onAfterEmitNode: (node: Node) => void;
154+
let onEmitNode: (node: Node, emit: (node: Node) => void) => void;
156155
let nodeToGeneratedName: string[];
157156
let generatedNameSet: Map<string>;
158157
let tempFlags: TempFlags;
@@ -213,8 +212,7 @@ const _super = (function (geti, seti) {
213212
isEmitNotificationEnabled = undefined;
214213
expressionSubstitution = undefined;
215214
identifierSubstitution = undefined;
216-
onBeforeEmitNode = undefined;
217-
onAfterEmitNode = undefined;
215+
onEmitNode = undefined;
218216
tempFlags = TempFlags.Auto;
219217
currentSourceFile = undefined;
220218
currentText = undefined;
@@ -234,8 +232,7 @@ const _super = (function (geti, seti) {
234232
isEmitNotificationEnabled = context.isEmitNotificationEnabled;
235233
expressionSubstitution = context.expressionSubstitution;
236234
identifierSubstitution = context.identifierSubstitution;
237-
onBeforeEmitNode = context.onBeforeEmitNode;
238-
onAfterEmitNode = context.onAfterEmitNode;
235+
onEmitNode = context.onEmitNode;
239236
return printSourceFile;
240237
}
241238

@@ -249,46 +246,62 @@ const _super = (function (geti, seti) {
249246
return node;
250247
}
251248

249+
/**
250+
* Emits a node.
251+
*/
252252
function emit(node: Node) {
253-
emitWithWorker(node, emitWorker);
253+
emitNodeWithNotificationOption(node, emitWithoutNotificationOption);
254+
}
255+
256+
/**
257+
* Emits a node without calling onEmitNode.
258+
* NOTE: Do not call this method directly.
259+
*/
260+
function emitWithoutNotificationOption(node: Node) {
261+
emitNodeWithWorker(node, emitWorker);
254262
}
255263

264+
/**
265+
* Emits an expression node.
266+
*/
256267
function emitExpression(node: Expression) {
257-
emitWithWorker(node, emitExpressionWorker);
268+
emitNodeWithNotificationOption(node, emitExpressionWithoutNotificationOption);
269+
}
270+
271+
/**
272+
* Emits an expression without calling onEmitNode.
273+
* NOTE: Do not call this method directly.
274+
*/
275+
function emitExpressionWithoutNotificationOption(node: Expression) {
276+
emitNodeWithWorker(node, emitExpressionWorker);
258277
}
259278

260-
function emitWithWorker(node: Node, emitWorker: (node: Node) => void) {
279+
/**
280+
* Emits a node with emit notification if available.
281+
*/
282+
function emitNodeWithNotificationOption(node: Node, emit: (node: Node) => void) {
261283
if (node) {
262-
const adviseOnEmit = isEmitNotificationEnabled(node);
263-
if (adviseOnEmit && onBeforeEmitNode) {
264-
onBeforeEmitNode(node);
284+
if (isEmitNotificationEnabled(node)) {
285+
onEmitNode(node, emit);
286+
}
287+
else {
288+
emit(node);
265289
}
290+
}
291+
}
266292

293+
function emitNodeWithWorker(node: Node, emitWorker: (node: Node) => void) {
294+
if (node) {
267295
const leadingComments = getLeadingComments(node, getNotEmittedParent);
268296
const trailingComments = getTrailingComments(node, getNotEmittedParent);
269297
emitLeadingComments(node, leadingComments);
270298
emitStart(node);
271299
emitWorker(node);
272300
emitEnd(node);
273301
emitTrailingComments(node, trailingComments);
274-
275-
if (adviseOnEmit && onAfterEmitNode) {
276-
onAfterEmitNode(node);
277-
}
278302
}
279303
}
280304

281-
function getNotEmittedParent(node: Node): Node {
282-
if (getNodeEmitFlags(node) & NodeEmitFlags.EmitCommentsOfNotEmittedParent) {
283-
const parent = getOriginalNode(node).parent;
284-
if (getNodeEmitFlags(parent) & NodeEmitFlags.IsNotEmittedNode) {
285-
return parent;
286-
}
287-
}
288-
289-
return undefined;
290-
}
291-
292305
function emitWorker(node: Node): void {
293306
const kind = node.kind;
294307
switch (kind) {
@@ -2361,6 +2374,17 @@ const _super = (function (geti, seti) {
23612374
&& rangeEndIsOnSameLineAsRangeStart(block, block);
23622375
}
23632376

2377+
function getNotEmittedParent(node: Node): Node {
2378+
if (getNodeEmitFlags(node) & NodeEmitFlags.EmitCommentsOfNotEmittedParent) {
2379+
const parent = getOriginalNode(node).parent;
2380+
if (getNodeEmitFlags(parent) & NodeEmitFlags.IsNotEmittedNode) {
2381+
return parent;
2382+
}
2383+
}
2384+
2385+
return undefined;
2386+
}
2387+
23642388
function isUniqueName(name: string): boolean {
23652389
return !resolver.hasGlobalName(name) &&
23662390
!hasProperty(currentFileIdentifiers, name) &&

src/compiler/transformer.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ namespace ts {
7878
expressionSubstitution: node => node,
7979
enableExpressionSubstitution,
8080
isExpressionSubstitutionEnabled,
81-
onBeforeEmitNode: node => { },
82-
onAfterEmitNode: node => { },
81+
onEmitNode: (node, emit) => emit(node),
8382
enableEmitNotification,
8483
isEmitNotificationEnabled,
8584
};

src/compiler/transformers/ts.ts

+61-79
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,11 @@ namespace ts {
2828
const languageVersion = getEmitScriptTarget(compilerOptions);
2929

3030
// Save the previous transformation hooks.
31-
const previousOnBeforeEmitNode = context.onBeforeEmitNode;
32-
const previousOnAfterEmitNode = context.onAfterEmitNode;
31+
const previousOnEmitNode = context.onEmitNode;
3332
const previousExpressionSubstitution = context.expressionSubstitution;
3433

3534
// Set new transformation hooks.
36-
context.onBeforeEmitNode = onBeforeEmitNode;
37-
context.onAfterEmitNode = onAfterEmitNode;
35+
context.onEmitNode = onEmitNode;
3836
context.expressionSubstitution = substituteExpression;
3937

4038
// These variables contain state that changes as we descend into the tree.
@@ -64,19 +62,16 @@ namespace ts {
6462
let currentDecoratedClassAliases: Map<Identifier>;
6563

6664
/**
67-
* Keeps track of how deeply nested we are within any containing namespaces
68-
* when performing just-in-time substitution while printing an expression identifier.
69-
* If the nest level is greater than zero, then we are performing a substitution
70-
* inside of a namespace and we should perform the more costly checks to determine
71-
* whether the identifier points to an exported declaration.
65+
* Keeps track of whether we are within any containing namespaces when performing
66+
* just-in-time substitution while printing an expression identifier.
7267
*/
73-
let namespaceNestLevel: number;
68+
let isEnclosedInNamespace: boolean;
7469

7570
/**
76-
* This array keeps track of containers where `super` is valid, for use with
71+
* This keeps track of containers where `super` is valid, for use with
7772
* just-in-time substitution for `super` expressions inside of async methods.
7873
*/
79-
let superContainerStack: SuperContainer[];
74+
let currentSuperContainer: SuperContainer;
8075

8176
return transformSourceFile;
8277

@@ -2378,21 +2373,24 @@ namespace ts {
23782373
// x_1.y = ...;
23792374
// })(x || (x = {}));
23802375
statements.push(
2381-
setOriginalNode(
2382-
createStatement(
2383-
createCall(
2384-
createParen(
2385-
createFunctionExpression(
2386-
/*asteriskToken*/ undefined,
2387-
/*name*/ undefined,
2388-
[createParameter(currentNamespaceLocalName)],
2389-
transformModuleBody(node)
2390-
)
2391-
),
2392-
[moduleParam]
2393-
)
2376+
setNodeEmitFlags(
2377+
setOriginalNode(
2378+
createStatement(
2379+
createCall(
2380+
createParen(
2381+
createFunctionExpression(
2382+
/*asteriskToken*/ undefined,
2383+
/*name*/ undefined,
2384+
[createParameter(currentNamespaceLocalName)],
2385+
transformModuleBody(node)
2386+
)
2387+
),
2388+
[moduleParam]
2389+
)
2390+
),
2391+
node
23942392
),
2395-
node
2393+
NodeEmitFlags.AdviseOnEmitNode
23962394
)
23972395
);
23982396

@@ -2594,62 +2592,51 @@ namespace ts {
25942592
: getClassPrototype(node);
25952593
}
25962594

2597-
function onBeforeEmitNode(node: Node): void {
2598-
previousOnBeforeEmitNode(node);
2595+
function isClassWithDecorators(node: Node): node is ClassDeclaration {
2596+
return node.kind === SyntaxKind.ClassDeclaration && node.decorators !== undefined;
2597+
}
25992598

2599+
function isSuperContainer(node: Node): node is SuperContainer {
26002600
const kind = node.kind;
2601-
if (enabledSubstitutions & TypeScriptSubstitutionFlags.DecoratedClasses
2602-
&& kind === SyntaxKind.ClassDeclaration
2603-
&& node.decorators) {
2604-
currentDecoratedClassAliases[getOriginalNodeId(node)] = decoratedClassAliases[getOriginalNodeId(node)];
2605-
}
2601+
return kind === SyntaxKind.ClassDeclaration
2602+
|| kind === SyntaxKind.Constructor
2603+
|| kind === SyntaxKind.MethodDeclaration
2604+
|| kind === SyntaxKind.GetAccessor
2605+
|| kind === SyntaxKind.SetAccessor;
2606+
}
26062607

2607-
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports
2608-
&& (kind === SyntaxKind.ClassDeclaration
2609-
|| kind === SyntaxKind.Constructor
2610-
|| kind === SyntaxKind.MethodDeclaration
2611-
|| kind === SyntaxKind.GetAccessor
2612-
|| kind === SyntaxKind.SetAccessor)) {
2608+
function isTransformedModuleDeclaration(node: Node): boolean {
2609+
return getOriginalNode(node).kind === SyntaxKind.ModuleDeclaration;
2610+
}
26132611

2614-
if (!superContainerStack) {
2615-
superContainerStack = [];
2616-
}
2612+
function onEmitNode(node: Node, emit: (node: Node) => void): void {
2613+
const savedIsEnclosedInNamespace = isEnclosedInNamespace;
2614+
const savedCurrentSuperContainer = currentSuperContainer;
26172615

2618-
superContainerStack.push(<SuperContainer>node);
2616+
// If we need support substitutions for aliases for decorated classes,
2617+
// we should enable it here.
2618+
if (enabledSubstitutions & TypeScriptSubstitutionFlags.DecoratedClasses && isClassWithDecorators(node)) {
2619+
currentDecoratedClassAliases[getOriginalNodeId(node)] = decoratedClassAliases[getOriginalNodeId(node)];
26192620
}
26202621

2621-
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports
2622-
&& kind === SyntaxKind.ModuleDeclaration) {
2623-
namespaceNestLevel++;
2622+
// If we need to support substitutions for `super` in an async method,
2623+
// we should track it here.
2624+
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
2625+
currentSuperContainer = node;
26242626
}
2625-
}
26262627

2627-
function onAfterEmitNode(node: Node): void {
2628-
previousOnAfterEmitNode(node);
2629-
2630-
const kind = node.kind;
2631-
if (enabledSubstitutions & TypeScriptSubstitutionFlags.DecoratedClasses
2632-
&& kind === SyntaxKind.ClassDeclaration
2633-
&& node.decorators) {
2634-
currentDecoratedClassAliases[getOriginalNodeId(node)] = undefined;
2628+
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node)) {
2629+
isEnclosedInNamespace = true;
26352630
}
26362631

2637-
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports
2638-
&& (kind === SyntaxKind.ClassDeclaration
2639-
|| kind === SyntaxKind.Constructor
2640-
|| kind === SyntaxKind.MethodDeclaration
2641-
|| kind === SyntaxKind.GetAccessor
2642-
|| kind === SyntaxKind.SetAccessor)) {
2632+
previousOnEmitNode(node, emit);
26432633

2644-
if (superContainerStack) {
2645-
superContainerStack.pop();
2646-
}
2634+
if (enabledSubstitutions & TypeScriptSubstitutionFlags.DecoratedClasses && isClassWithDecorators(node)) {
2635+
currentDecoratedClassAliases[getOriginalNodeId(node)] = undefined;
26472636
}
26482637

2649-
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports
2650-
&& kind === SyntaxKind.ModuleDeclaration) {
2651-
namespaceNestLevel--;
2652-
}
2638+
isEnclosedInNamespace = savedIsEnclosedInNamespace;
2639+
currentSuperContainer = savedCurrentSuperContainer;
26532640
}
26542641

26552642
function substituteExpression(node: Expression): Expression {
@@ -2660,7 +2647,7 @@ namespace ts {
26602647
return substituteExpressionIdentifier(<Identifier>node);
26612648
}
26622649

2663-
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports) {
2650+
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) {
26642651
switch (node.kind) {
26652652
case SyntaxKind.CallExpression:
26662653
return substituteCallExpression(<CallExpression>node);
@@ -2691,8 +2678,7 @@ namespace ts {
26912678
}
26922679
}
26932680

2694-
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports
2695-
&& namespaceNestLevel > 0) {
2681+
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isEnclosedInNamespace) {
26962682
// If we are nested within a namespace declaration, we may need to qualifiy
26972683
// an identifier that is exported from a merged namespace.
26982684
const original = getOriginalNode(node);
@@ -2758,8 +2744,8 @@ namespace ts {
27582744
}
27592745

27602746
function enableExpressionSubstitutionForAsyncMethodsWithSuper() {
2761-
if ((enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports) === 0) {
2762-
enabledSubstitutions |= TypeScriptSubstitutionFlags.NamespaceExports;
2747+
if ((enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) === 0) {
2748+
enabledSubstitutions |= TypeScriptSubstitutionFlags.AsyncMethodsWithSuper;
27632749

27642750
// We need to enable substitutions for call, property access, and element access
27652751
// if we need to rewrite super calls.
@@ -2800,9 +2786,6 @@ namespace ts {
28002786

28012787
// We need to be notified when entering and exiting namespaces.
28022788
context.enableEmitNotification(SyntaxKind.ModuleDeclaration);
2803-
2804-
// Keep track of namespace nesting depth
2805-
namespaceNestLevel = 0;
28062789
}
28072790
}
28082791

@@ -2827,9 +2810,8 @@ namespace ts {
28272810
}
28282811

28292812
function getSuperContainerAsyncMethodFlags() {
2830-
const container = lastOrUndefined(superContainerStack);
2831-
return container !== undefined
2832-
&& resolver.getNodeCheckFlags(getOriginalNode(container)) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
2813+
return currentSuperContainer !== undefined
2814+
&& resolver.getNodeCheckFlags(getOriginalNode(currentSuperContainer)) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
28332815
}
28342816
}
28352817
}

src/compiler/types.ts

+3-9
Original file line numberDiff line numberDiff line change
@@ -2865,16 +2865,10 @@ namespace ts {
28652865
isEmitNotificationEnabled(node: Node): boolean;
28662866

28672867
/**
2868-
* Hook used to notify transformers immediately before the pretty printer
2869-
* emits a node.
2868+
* Hook used to allow transformers to capture state before or after
2869+
* the printer emits a node.
28702870
*/
2871-
onBeforeEmitNode?: (node: Node) => void;
2872-
2873-
/**
2874-
* Hook used to notify transformers immediately after the pretty printer
2875-
* emits a node.
2876-
*/
2877-
onAfterEmitNode?: (node: Node) => void;
2871+
onEmitNode?: (node: Node, emit: (node: Node) => void) => void;
28782872
}
28792873

28802874
/* @internal */

0 commit comments

Comments
 (0)