@@ -1202,15 +1202,15 @@ namespace ts {
12021202 function emitWithContext < T extends Node > ( node : T , emitCallback : ( node : T ) => void ) {
12031203 onBeforeEmitNode ?.( node ) ;
12041204
1205+ const emitFlags = getEmitFlags ( node ) ;
12051206 const savedPreserveSourceNewlines = preserveSourceNewlines ;
1206- if ( preserveSourceNewlines && ! ! ( getEmitFlags ( node ) & EmitFlags . IgnoreSourceNewlines ) ) {
1207+ if ( preserveSourceNewlines && ( emitFlags & EmitFlags . IgnoreSourceNewlines ) ) {
12071208 preserveSourceNewlines = false ;
12081209 }
12091210
12101211 const savedContainerPos = containerPos ;
12111212 const savedContainerEnd = containerEnd ;
12121213 const savedDeclarationListContainerEnd = declarationListContainerEnd ;
1213- const emitFlags = getEmitFlags ( node ) ;
12141214 const commentRange = shouldEmitComments ( node ) ? getCommentRange ( node ) : undefined ;
12151215 const sourceMapRange = shouldEmitSourceMaps ( node ) ? getSourceMapRange ( node ) : undefined ;
12161216
@@ -2520,7 +2520,62 @@ namespace ts {
25202520 }
25212521
25222522 function createEmitBinaryExpression ( ) {
2523- return createBinaryExpressionWalker ( noop , maybePipelineEmitExpression , onOperator , maybePipelineEmitExpression , onExit , identity ) ;
2523+ class EmitBinaryExpressionState {
2524+ nested = false ;
2525+ preserveSourceNewlines : boolean | undefined = undefined ;
2526+ containerPos = - 1 ;
2527+ containerEnd = - 1 ;
2528+ declarationListContainerEnd = - 1 ;
2529+ emitFlags = EmitFlags . None ;
2530+ commentRange : TextRange | undefined = undefined ;
2531+ sourceMapRange : SourceMapRange | undefined = undefined ;
2532+ }
2533+
2534+ return createBinaryExpressionWalker ( onEnter , maybeEmitExpression , onOperator , maybeEmitExpression , onExit , identity ) ;
2535+
2536+ function onEnter ( node : BinaryExpression , prev : EmitBinaryExpressionState | undefined ) {
2537+ const state = new EmitBinaryExpressionState ( ) ;
2538+ if ( prev ) {
2539+ // `prev` is only defined when recuring. We can use this fact to indicate
2540+ // we are entering into a nested binary expression and can replicate the
2541+ // leading comment and sourcemap emit performed by `emitWithContext`.
2542+ state . nested = true ;
2543+ onBeforeEmitNode ?.( node ) ;
2544+
2545+ state . emitFlags = getEmitFlags ( node ) ;
2546+ state . preserveSourceNewlines = preserveSourceNewlines ;
2547+ if ( preserveSourceNewlines && ( state . emitFlags & EmitFlags . IgnoreSourceNewlines ) ) {
2548+ preserveSourceNewlines = false ;
2549+ }
2550+
2551+ state . containerPos = containerPos ;
2552+ state . containerEnd = containerEnd ;
2553+ state . declarationListContainerEnd = declarationListContainerEnd ;
2554+ state . commentRange = shouldEmitComments ( node ) ? getCommentRange ( node ) : undefined ;
2555+ state . sourceMapRange = shouldEmitSourceMaps ( node ) ? getSourceMapRange ( node ) : undefined ;
2556+
2557+ // Emit leading comments
2558+ if ( state . commentRange ) {
2559+ emitLeadingCommentsOfNode ( node , state . emitFlags , state . commentRange . pos , state . commentRange . end ) ;
2560+ if ( state . emitFlags & EmitFlags . NoNestedComments ) {
2561+ commentsDisabled = true ;
2562+ }
2563+ }
2564+
2565+ // Emit leading sourcemap
2566+ if ( state . sourceMapRange ) {
2567+ const source = state . sourceMapRange . source || sourceMapSource ;
2568+ if ( ( state . emitFlags & EmitFlags . NoLeadingSourceMap ) === 0
2569+ && state . sourceMapRange . pos >= 0 ) {
2570+ emitSourcePos ( state . sourceMapRange . source || sourceMapSource , skipSourceTrivia ( source , state . sourceMapRange . pos ) ) ;
2571+ }
2572+ if ( state . emitFlags & EmitFlags . NoNestedSourceMaps ) {
2573+ sourceMapsDisabled = true ;
2574+ }
2575+ }
2576+ }
2577+ return state ;
2578+ }
25242579
25252580 function onOperator ( operatorToken : BinaryOperatorToken , _ : unknown , node : BinaryExpression ) {
25262581 const isCommaOperator = operatorToken . kind !== SyntaxKind . CommaToken ;
@@ -2533,25 +2588,48 @@ namespace ts {
25332588 writeLinesAndIndent ( linesAfterOperator , /*writeSpaceIfNotIndenting*/ true ) ;
25342589 }
25352590
2536- function onExit ( node : BinaryExpression ) {
2591+ function onExit ( node : BinaryExpression , state : EmitBinaryExpressionState ) {
25372592 const linesBeforeOperator = getLinesBetweenNodes ( node , node . left , node . operatorToken ) ;
25382593 const linesAfterOperator = getLinesBetweenNodes ( node , node . operatorToken , node . right ) ;
25392594 decreaseIndentIf ( linesBeforeOperator , linesAfterOperator ) ;
2540- }
25412595
2542- function maybePipelineEmitExpression ( next : Expression ) {
2543- // Then actually do the work of emitting the node `next` returned by the prior state
2544- // The following section should be identical to `pipelineEmit` save it assumes EmitHint.Expression and offloads
2545- // binary expression handling, where possible, to the contained work queue
2596+ if ( state . nested ) {
2597+ // If we are marked as nested, we are recurring. We can use this fact to indicate
2598+ // we are exiting from a nested binary expression and can replicate the trailing
2599+ // comment and sourcemap emit performed by `emitWithContext`.
25462600
2547- if ( ! shouldEmitComments ( next ) && ! shouldEmitSourceMaps ( next ) && isBinaryExpression ( next ) ) {
2548- // If the target pipeline phase is emit directly, and the next node's also a binary expression,
2549- // skip all the intermediate indirection and push the expression directly onto the work stack
2550- return next ;
2601+ // Emit trailing sourcemap
2602+ if ( state . sourceMapRange ) {
2603+ if ( state . emitFlags & EmitFlags . NoNestedSourceMaps ) {
2604+ sourceMapsDisabled = false ;
2605+ }
2606+ if ( ( state . emitFlags & EmitFlags . NoTrailingSourceMap ) === 0
2607+ && state . sourceMapRange . end >= 0 ) {
2608+ emitSourcePos ( state . sourceMapRange . source || sourceMapSource , state . sourceMapRange . end ) ;
2609+ }
2610+ }
2611+
2612+ // Emit trailing comments
2613+ if ( state . commentRange ) {
2614+ if ( state . emitFlags & EmitFlags . NoNestedComments ) {
2615+ commentsDisabled = false ;
2616+ }
2617+ emitTrailingCommentsOfNode ( node , state . emitFlags , state . commentRange . pos , state . commentRange . end , state . containerPos , state . containerEnd , state . declarationListContainerEnd ) ;
2618+ }
2619+
2620+ onAfterEmitNode ?.( node ) ;
2621+
2622+ preserveSourceNewlines = state . preserveSourceNewlines ;
25512623 }
2552- else {
2553- emit ( next ) ;
2624+ }
2625+
2626+ function maybeEmitExpression ( next : Expression ) {
2627+ // Push a new frame for binary expressions, otherwise emit all other expressions.
2628+ if ( isBinaryExpression ( next ) ) {
2629+ return next ;
25542630 }
2631+
2632+ emit ( next ) ;
25552633 }
25562634 }
25572635
0 commit comments