Skip to content

Commit a295aa8

Browse files
committed
Reduce stack depth due to substitution
1 parent 3b20d82 commit a295aa8

File tree

7 files changed

+27
-42
lines changed

7 files changed

+27
-42
lines changed

src/compiler/emitter.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ namespace ts {
3737

3838
// transform hooks
3939
onEmitNode: transform.emitNodeWithNotification,
40-
onSubstituteNode: transform.emitNodeWithSubstitution,
40+
substituteNode: transform.substituteNode,
4141

4242
// sourcemap hooks
4343
onEmitSourceMapOfNode: sourceMap.emitNodeWithSourceMap,
@@ -198,7 +198,7 @@ namespace ts {
198198
onEmitNode,
199199
onEmitHelpers,
200200
onSetSourceFile,
201-
onSubstituteNode,
201+
substituteNode,
202202
} = handlers;
203203

204204
const newLine = getNewLineCharacter(printerOptions);
@@ -327,8 +327,8 @@ namespace ts {
327327
setWriter(/*output*/ undefined);
328328
}
329329

330-
function emit(node: Node, hint = EmitHint.Unspecified) {
331-
pipelineEmitWithNotification(hint, node);
330+
function emit(node: Node) {
331+
pipelineEmitWithNotification(EmitHint.Unspecified, node);
332332
}
333333

334334
function emitIdentifierName(node: Identifier) {
@@ -349,6 +349,7 @@ namespace ts {
349349
}
350350

351351
function pipelineEmitWithComments(hint: EmitHint, node: Node) {
352+
node = trySubstituteNode(hint, node);
352353
if (emitNodeWithComments && hint !== EmitHint.SourceFile) {
353354
emitNodeWithComments(hint, node, pipelineEmitWithSourceMap);
354355
}
@@ -359,16 +360,7 @@ namespace ts {
359360

360361
function pipelineEmitWithSourceMap(hint: EmitHint, node: Node) {
361362
if (onEmitSourceMapOfNode && hint !== EmitHint.SourceFile && hint !== EmitHint.IdentifierName) {
362-
onEmitSourceMapOfNode(hint, node, pipelineEmitWithSubstitution);
363-
}
364-
else {
365-
pipelineEmitWithSubstitution(hint, node);
366-
}
367-
}
368-
369-
function pipelineEmitWithSubstitution(hint: EmitHint, node: Node) {
370-
if (onSubstituteNode) {
371-
onSubstituteNode(hint, node, pipelineEmitWithHint);
363+
onEmitSourceMapOfNode(hint, node, pipelineEmitWithHint);
372364
}
373365
else {
374366
pipelineEmitWithHint(hint, node);
@@ -634,7 +626,7 @@ namespace ts {
634626
// If the node is an expression, try to emit it as an expression with
635627
// substitution.
636628
if (isExpression(node)) {
637-
return pipelineEmitWithSubstitution(EmitHint.Expression, node);
629+
return pipelineEmitExpression(trySubstituteNode(EmitHint.Expression, node));
638630
}
639631
}
640632

@@ -731,6 +723,10 @@ namespace ts {
731723
}
732724
}
733725

726+
function trySubstituteNode(hint: EmitHint, node: Node) {
727+
return node && substituteNode && substituteNode(hint, node) || node;
728+
}
729+
734730
function emitBodyIndirect(node: Node, elements: NodeArray<Node>, emitCallback: (node: Node) => void): void {
735731
if (emitBodyWithDetachedComments) {
736732
emitBodyWithDetachedComments(node, elements, emitCallback);

src/compiler/transformer.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ namespace ts {
159159

160160
return {
161161
transformed,
162-
emitNodeWithSubstitution,
162+
substituteNode,
163163
emitNodeWithNotification,
164164
dispose
165165
};
@@ -191,14 +191,9 @@ namespace ts {
191191
* @param node The node to emit.
192192
* @param emitCallback The callback used to emit the node or its substitute.
193193
*/
194-
function emitNodeWithSubstitution(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
195-
Debug.assert(state < TransformationState.Disposed, "Cannot invoke TransformationResult callbacks after the result is disposed.");
196-
if (node) {
197-
if (isSubstitutionEnabled(node)) {
198-
node = onSubstituteNode(hint, node) || node;
199-
}
200-
emitCallback(hint, node);
201-
}
194+
function substituteNode(hint: EmitHint, node: Node) {
195+
Debug.assert(state < TransformationState.Disposed, "Cannot substitute a node after the result is disposed.");
196+
return node && isSubstitutionEnabled(node) && onSubstituteNode(hint, node) || node;
202197
}
203198

204199
/**

src/compiler/transformers/es2015.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3549,7 +3549,7 @@ namespace ts {
35493549
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) {
35503550
const original = getParseTreeNode(node, isIdentifier);
35513551
if (original && isNameOfDeclarationWithCollidingName(original)) {
3552-
return getGeneratedNameForNode(original);
3552+
return setTextRange(getGeneratedNameForNode(original), node);
35533553
}
35543554
}
35553555

@@ -3602,7 +3602,7 @@ namespace ts {
36023602
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) {
36033603
const declaration = resolver.getReferencedDeclarationWithCollidingName(node);
36043604
if (declaration) {
3605-
return getGeneratedNameForNode(declaration.name);
3605+
return setTextRange(getGeneratedNameForNode(declaration.name), node);
36063606
}
36073607
}
36083608

src/compiler/transformers/ts.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3322,8 +3322,6 @@ namespace ts {
33223322
: getTextOfNode(node.argumentExpression);
33233323

33243324
addSyntheticTrailingComment(substitute, SyntaxKind.MultiLineCommentTrivia, ` ${propertyName} `);
3325-
// wrap the substituted node so that it emits its own comments.
3326-
return createPartiallyEmittedExpression(substitute);
33273325
}
33283326

33293327
return substitute;

src/compiler/types.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3901,13 +3901,12 @@
39013901
diagnostics?: Diagnostic[];
39023902

39033903
/**
3904-
* Emits the substitute for a node, if one is available; otherwise, emits the node.
3904+
* Gets a substitute for a node, if one is available; otherwise, returns the original node.
39053905
*
39063906
* @param hint A hint as to the intended usage of the node.
39073907
* @param node The node to substitute.
3908-
* @param emitCallback A callback used to emit the node or its substitute.
39093908
*/
3910-
emitNodeWithSubstitution(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
3909+
substituteNode(hint: EmitHint, node: Node): Node;
39113910

39123911
/**
39133912
* Emits a node with possible notification.
@@ -3998,23 +3997,20 @@
39983997
/**
39993998
* A hook used by the Printer to perform just-in-time substitution of a node. This is
40003999
* primarily used by node transformations that need to substitute one node for another,
4001-
* such as replacing `myExportedVar` with `exports.myExportedVar`. A compatible
4002-
* implementation **must** invoke `emitCallback` eith the provided `hint` and either
4003-
* the provided `node`, or its substitute.
4000+
* such as replacing `myExportedVar` with `exports.myExportedVar`.
40044001
* @param hint A hint indicating the intended purpose of the node.
40054002
* @param node The node to emit.
4006-
* @param emitCallback A callback that, when invoked, will emit the node.
40074003
* @example
40084004
* ```ts
40094005
* var printer = createPrinter(printerOptions, {
4010-
* onSubstituteNode(hint, node, emitCallback) {
4006+
* substituteNode(hint, node) {
40114007
* // perform substitution if necessary...
4012-
* emitCallback(hint, node);
4008+
* return node;
40134009
* }
40144010
* });
40154011
* ```
40164012
*/
4017-
onSubstituteNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
4013+
substituteNode?(hint: EmitHint, node: Node): Node;
40184014
/*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
40194015
/*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number;
40204016
/*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void;

src/compiler/visitor.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ namespace ts {
709709
return node ? f(initial, node) : initial;
710710
}
711711

712-
function reduceNodeArray<T>(nodes: Node[], f: (memo: T, nodes: Node[]) => T, initial: T) {
712+
function reduceNodeArray<T>(nodes: NodeArray<Node>, f: (memo: T, nodes: NodeArray<Node>) => T, initial: T) {
713713
return nodes ? f(initial, nodes) : initial;
714714
}
715715

@@ -721,12 +721,12 @@ namespace ts {
721721
* @param initial The initial value to supply to the reduction.
722722
* @param f The callback function
723723
*/
724-
export function reduceEachChild<T>(node: Node, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: Node[]) => T): T {
724+
export function reduceEachChild<T>(node: Node, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: NodeArray<Node>) => T): T {
725725
if (node === undefined) {
726726
return initial;
727727
}
728728

729-
const reduceNodes: (nodes: Node[], f: (memo: T, node: Node | Node[]) => T, initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft;
729+
const reduceNodes: (nodes: NodeArray<Node>, f: (memo: T, node: Node | NodeArray<Node>) => T, initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft;
730730
const cbNodes = cbNodeArray || cbNode;
731731
const kind = node.kind;
732732

src/harness/unittests/transform.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace ts {
99
const transformed = transform(createSourceFile("source.ts", source, ScriptTarget.ES2015), transformers);
1010
const printer = createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed }, {
1111
onEmitNode: transformed.emitNodeWithNotification,
12-
onSubstituteNode: transformed.emitNodeWithSubstitution
12+
substituteNode: transformed.substituteNode
1313
});
1414
const result = printer.printBundle(createBundle(transformed.transformed));
1515
transformed.dispose();

0 commit comments

Comments
 (0)