(node, trueTarget, falseTarget)
| 46121 | } |
| 46122 | } |
| 46123 | function bindOptionalChain(node, trueTarget, falseTarget) { |
| 46124 | // For an optional chain, we emulate the behavior of a logical expression: |
| 46125 | // |
| 46126 | // a?.b -> a && a.b |
| 46127 | // a?.b.c -> a && a.b.c |
| 46128 | // a?.b?.c -> a && a.b && a.b.c |
| 46129 | // a?.[x = 1] -> a && a[x = 1] |
| 46130 | // |
| 46131 | // To do this we descend through the chain until we reach the root of a chain (the expression with a `?.`) |
| 46132 | // and build it's CFA graph as if it were the first condition (`a && ...`). Then we bind the rest |
| 46133 | // of the node as part of the "true" branch, and continue to do so as we ascend back up to the outermost |
| 46134 | // chain node. We then treat the entire node as the right side of the expression. |
| 46135 | var preChainLabel = ts.isOptionalChainRoot(node) ? createBranchLabel() : undefined; |
| 46136 | bindOptionalExpression(node.expression, preChainLabel || trueTarget, falseTarget); |
| 46137 | if (preChainLabel) { |
| 46138 | currentFlow = finishFlowLabel(preChainLabel); |
| 46139 | } |
| 46140 | doWithConditionalBranches(bindOptionalChainRest, node, trueTarget, falseTarget); |
| 46141 | if (ts.isOutermostOptionalChain(node)) { |
| 46142 | addAntecedent(trueTarget, createFlowCondition(32 /* FlowFlags.TrueCondition */, currentFlow, node)); |
| 46143 | addAntecedent(falseTarget, createFlowCondition(64 /* FlowFlags.FalseCondition */, currentFlow, node)); |
| 46144 | } |
| 46145 | } |
| 46146 | function bindOptionalChainFlow(node) { |
| 46147 | if (isTopLevelLogicalExpression(node)) { |
| 46148 | var postExpressionLabel = createBranchLabel(); |
no test coverage detected