1/*@internal*/ 2namespace ts { 3 export function transformES2021(context: TransformationContext) { 4 const { 5 hoistVariableDeclaration, 6 factory 7 } = context; 8 return chainBundle(context, transformSourceFile); 9 10 function transformSourceFile(node: SourceFile) { 11 if (node.isDeclarationFile) { 12 return node; 13 } 14 15 return visitEachChild(node, visitor, context); 16 } 17 18 function visitor(node: Node): VisitResult<Node> { 19 if ((node.transformFlags & TransformFlags.ContainsES2021) === 0) { 20 return node; 21 } 22 switch (node.kind) { 23 case SyntaxKind.BinaryExpression: 24 const binaryExpression = node as BinaryExpression; 25 if (isLogicalOrCoalescingAssignmentExpression(binaryExpression)) { 26 return transformLogicalAssignment(binaryExpression); 27 } 28 // falls through 29 default: 30 return visitEachChild(node, visitor, context); 31 } 32 } 33 34 function transformLogicalAssignment(binaryExpression: AssignmentExpression<Token<LogicalOrCoalescingAssignmentOperator>>): VisitResult<Node> { 35 const operator = binaryExpression.operatorToken; 36 const nonAssignmentOperator = getNonAssignmentOperatorForCompoundAssignment(operator.kind); 37 let left = skipParentheses(visitNode(binaryExpression.left, visitor, isLeftHandSideExpression)); 38 let assignmentTarget = left; 39 const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression)); 40 41 if (isAccessExpression(left)) { 42 const propertyAccessTargetSimpleCopiable = isSimpleCopiableExpression(left.expression); 43 const propertyAccessTarget = propertyAccessTargetSimpleCopiable ? left.expression : 44 factory.createTempVariable(hoistVariableDeclaration); 45 const propertyAccessTargetAssignment = propertyAccessTargetSimpleCopiable ? left.expression : factory.createAssignment( 46 propertyAccessTarget, 47 left.expression 48 ); 49 50 if (isPropertyAccessExpression(left)) { 51 assignmentTarget = factory.createPropertyAccessExpression( 52 propertyAccessTarget, 53 left.name 54 ); 55 left = factory.createPropertyAccessExpression( 56 propertyAccessTargetAssignment, 57 left.name 58 ); 59 } 60 else { 61 const elementAccessArgumentSimpleCopiable = isSimpleCopiableExpression(left.argumentExpression); 62 const elementAccessArgument = elementAccessArgumentSimpleCopiable ? left.argumentExpression : 63 factory.createTempVariable(hoistVariableDeclaration); 64 65 assignmentTarget = factory.createElementAccessExpression( 66 propertyAccessTarget, 67 elementAccessArgument 68 ); 69 left = factory.createElementAccessExpression( 70 propertyAccessTargetAssignment, 71 elementAccessArgumentSimpleCopiable ? left.argumentExpression : factory.createAssignment( 72 elementAccessArgument, 73 left.argumentExpression 74 ) 75 ); 76 } 77 } 78 79 return factory.createBinaryExpression( 80 left, 81 nonAssignmentOperator, 82 factory.createParenthesizedExpression( 83 factory.createAssignment( 84 assignmentTarget, 85 right 86 ) 87 ) 88 ); 89 } 90 } 91} 92