1/*@internal*/ 2namespace ts { 3 export function transformES2016(context: TransformationContext) { 4 const { 5 factory, 6 hoistVariableDeclaration 7 } = context; 8 9 return chainBundle(context, transformSourceFile); 10 11 function transformSourceFile(node: SourceFile) { 12 if (node.isDeclarationFile) { 13 return node; 14 } 15 16 return visitEachChild(node, visitor, context); 17 } 18 19 function visitor(node: Node): VisitResult<Node> { 20 if ((node.transformFlags & TransformFlags.ContainsES2016) === 0) { 21 return node; 22 } 23 switch (node.kind) { 24 case SyntaxKind.BinaryExpression: 25 return visitBinaryExpression(node as BinaryExpression); 26 default: 27 return visitEachChild(node, visitor, context); 28 } 29 } 30 31 function visitBinaryExpression(node: BinaryExpression): Expression { 32 switch (node.operatorToken.kind) { 33 case SyntaxKind.AsteriskAsteriskEqualsToken: 34 return visitExponentiationAssignmentExpression(node); 35 case SyntaxKind.AsteriskAsteriskToken: 36 return visitExponentiationExpression(node); 37 default: 38 return visitEachChild(node, visitor, context); 39 } 40 } 41 42 function visitExponentiationAssignmentExpression(node: BinaryExpression) { 43 let target: Expression; 44 let value: Expression; 45 const left = visitNode(node.left, visitor, isExpression); 46 const right = visitNode(node.right, visitor, isExpression); 47 if (isElementAccessExpression(left)) { 48 // Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)` 49 const expressionTemp = factory.createTempVariable(hoistVariableDeclaration); 50 const argumentExpressionTemp = factory.createTempVariable(hoistVariableDeclaration); 51 target = setTextRange( 52 factory.createElementAccessExpression( 53 setTextRange(factory.createAssignment(expressionTemp, left.expression), left.expression), 54 setTextRange(factory.createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression) 55 ), 56 left 57 ); 58 value = setTextRange( 59 factory.createElementAccessExpression( 60 expressionTemp, 61 argumentExpressionTemp 62 ), 63 left 64 ); 65 } 66 else if (isPropertyAccessExpression(left)) { 67 // Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)` 68 const expressionTemp = factory.createTempVariable(hoistVariableDeclaration); 69 target = setTextRange( 70 factory.createPropertyAccessExpression( 71 setTextRange(factory.createAssignment(expressionTemp, left.expression), left.expression), 72 left.name 73 ), 74 left 75 ); 76 value = setTextRange( 77 factory.createPropertyAccessExpression( 78 expressionTemp, 79 left.name 80 ), 81 left 82 ); 83 } 84 else { 85 // Transforms `a **= b` into `a = Math.pow(a, b)` 86 target = left; 87 value = left; 88 } 89 return setTextRange( 90 factory.createAssignment( 91 target, 92 setTextRange(factory.createGlobalMethodCall("Math", "pow", [value, right]), node) 93 ), 94 node 95 ); 96 } 97 98 function visitExponentiationExpression(node: BinaryExpression) { 99 // Transforms `a ** b` into `Math.pow(a, b)` 100 const left = visitNode(node.left, visitor, isExpression); 101 const right = visitNode(node.right, visitor, isExpression); 102 return setTextRange(factory.createGlobalMethodCall("Math", "pow", [left, right]), node); 103 } 104 } 105} 106