Revise return control flow graph construction logic

This commit is contained in:
Anders Hejlsberg 2017-11-17 09:05:46 -08:00
parent 190f99e460
commit 041d04577e

View File

@ -506,16 +506,14 @@ namespace ts {
const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !hasModifier(node, ModifierFlags.Async) && !!getImmediatelyInvokedFunctionExpression(node);
// A non-async IIFE is considered part of the containing control flow. Return statements behave
// similarly to break statements that exit to a label just past the statement body.
if (isIIFE) {
currentReturnTarget = createBranchLabel();
}
else {
if (!isIIFE) {
currentFlow = { flags: FlowFlags.Start };
if (containerFlags & (ContainerFlags.IsFunctionExpression | ContainerFlags.IsObjectLiteralOrClassExpressionMethod)) {
(<FlowStart>currentFlow).container = <FunctionExpression | ArrowFunction | MethodDeclaration>node;
}
currentReturnTarget = node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined;
}
// We create a return control flow graph for IIFEs and constructors. For constructors
// we use the return control flow graph in strict property intialization checks.
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor ? createBranchLabel() : undefined;
currentBreakTarget = undefined;
currentContinueTarget = undefined;
@ -531,15 +529,14 @@ namespace ts {
if (node.kind === SyntaxKind.SourceFile) {
node.flags |= emitFlags;
}
if (isIIFE) {
if (currentReturnTarget) {
addAntecedent(currentReturnTarget, currentFlow);
currentFlow = finishFlowLabel(currentReturnTarget);
}
else {
if (node.kind === SyntaxKind.Constructor) {
addAntecedent(currentReturnTarget, currentFlow);
(<ConstructorDeclaration>node).returnFlowNode = currentFlow;
}
}
if (!isIIFE) {
currentFlow = saveCurrentFlow;
}
currentBreakTarget = saveBreakTarget;