(node)
| 45668 | } |
| 45669 | } |
| 45670 | function bindTryStatement(node) { |
| 45671 | // We conservatively assume that *any* code in the try block can cause an exception, but we only need |
| 45672 | // to track code that causes mutations (because only mutations widen the possible control flow type of |
| 45673 | // a variable). The exceptionLabel is the target label for control flows that result from exceptions. |
| 45674 | // We add all mutation flow nodes as antecedents of this label such that we can analyze them as possible |
| 45675 | // antecedents of the start of catch or finally blocks. Furthermore, we add the current control flow to |
| 45676 | // represent exceptions that occur before any mutations. |
| 45677 | var saveReturnTarget = currentReturnTarget; |
| 45678 | var saveExceptionTarget = currentExceptionTarget; |
| 45679 | var normalExitLabel = createBranchLabel(); |
| 45680 | var returnLabel = createBranchLabel(); |
| 45681 | var exceptionLabel = createBranchLabel(); |
| 45682 | if (node.finallyBlock) { |
| 45683 | currentReturnTarget = returnLabel; |
| 45684 | } |
| 45685 | addAntecedent(exceptionLabel, currentFlow); |
| 45686 | currentExceptionTarget = exceptionLabel; |
| 45687 | bind(node.tryBlock); |
| 45688 | addAntecedent(normalExitLabel, currentFlow); |
| 45689 | if (node.catchClause) { |
| 45690 | // Start of catch clause is the target of exceptions from try block. |
| 45691 | currentFlow = finishFlowLabel(exceptionLabel); |
| 45692 | // The currentExceptionTarget now represents control flows from exceptions in the catch clause. |
| 45693 | // Effectively, in a try-catch-finally, if an exception occurs in the try block, the catch block |
| 45694 | // acts like a second try block. |
| 45695 | exceptionLabel = createBranchLabel(); |
| 45696 | addAntecedent(exceptionLabel, currentFlow); |
| 45697 | currentExceptionTarget = exceptionLabel; |
| 45698 | bind(node.catchClause); |
| 45699 | addAntecedent(normalExitLabel, currentFlow); |
| 45700 | } |
| 45701 | currentReturnTarget = saveReturnTarget; |
| 45702 | currentExceptionTarget = saveExceptionTarget; |
| 45703 | if (node.finallyBlock) { |
| 45704 | // Possible ways control can reach the finally block: |
| 45705 | // 1) Normal completion of try block of a try-finally or try-catch-finally |
| 45706 | // 2) Normal completion of catch block (following exception in try block) of a try-catch-finally |
| 45707 | // 3) Return in try or catch block of a try-finally or try-catch-finally |
| 45708 | // 4) Exception in try block of a try-finally |
| 45709 | // 5) Exception in catch block of a try-catch-finally |
| 45710 | // When analyzing a control flow graph that starts inside a finally block we want to consider all |
| 45711 | // five possibilities above. However, when analyzing a control flow graph that starts outside (past) |
| 45712 | // the finally block, we only want to consider the first two (if we're past a finally block then it |
| 45713 | // must have completed normally). Likewise, when analyzing a control flow graph from return statements |
| 45714 | // in try or catch blocks in an IIFE, we only want to consider the third. To make this possible, we |
| 45715 | // inject a ReduceLabel node into the control flow graph. This node contains an alternate reduced |
| 45716 | // set of antecedents for the pre-finally label. As control flow analysis passes by a ReduceLabel |
| 45717 | // node, the pre-finally label is temporarily switched to the reduced antecedent set. |
| 45718 | var finallyLabel = createBranchLabel(); |
| 45719 | finallyLabel.antecedents = ts.concatenate(ts.concatenate(normalExitLabel.antecedents, exceptionLabel.antecedents), returnLabel.antecedents); |
| 45720 | currentFlow = finallyLabel; |
| 45721 | bind(node.finallyBlock); |
| 45722 | if (currentFlow.flags & 1 /* FlowFlags.Unreachable */) { |
| 45723 | // If the end of the finally block is unreachable, the end of the entire try statement is unreachable. |
| 45724 | currentFlow = unreachableFlow; |
| 45725 | } |
| 45726 | else { |
| 45727 | // If we have an IIFE return target and return statements in the try or catch blocks, add a control |
no test coverage detected