• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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