fix CFA for BindingElement. #49759 (#49836)

* fix CFA for BindingElement. #49759

* fix Parameter

* fix controlFlowBindingPatternOrder

* fix bindParameterFlow

* add tests

* refactor

* refactor

* refactor
This commit is contained in:
Zzzen
2022-08-10 07:37:39 +08:00
committed by GitHub
parent dd98c17b10
commit b94b299a11
13 changed files with 1046 additions and 24 deletions

View File

@@ -850,6 +850,9 @@ namespace ts {
case SyntaxKind.BindingElement:
bindBindingElementFlow(node as BindingElement);
break;
case SyntaxKind.Parameter:
bindParameterFlow(node as ParameterDeclaration);
break;
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.PropertyAssignment:
@@ -1655,20 +1658,40 @@ namespace ts {
}
function bindBindingElementFlow(node: BindingElement) {
if (isBindingPattern(node.name)) {
// When evaluating a binding pattern, the initializer is evaluated before the binding pattern, per:
// - https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-iteratorbindinginitialization
// - `BindingElement: BindingPattern Initializer?`
// - https://tc39.es/ecma262/#sec-runtime-semantics-keyedbindinginitialization
// - `BindingElement: BindingPattern Initializer?`
bind(node.dotDotDotToken);
bind(node.propertyName);
bind(node.initializer);
bind(node.name);
// When evaluating a binding pattern, the initializer is evaluated before the binding pattern, per:
// - https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-iteratorbindinginitialization
// - `BindingElement: BindingPattern Initializer?`
// - https://tc39.es/ecma262/#sec-runtime-semantics-keyedbindinginitialization
// - `BindingElement: BindingPattern Initializer?`
bind(node.dotDotDotToken);
bind(node.propertyName);
bindInitializer(node.initializer);
bind(node.name);
}
function bindParameterFlow(node: ParameterDeclaration) {
bindEach(node.modifiers);
bind(node.dotDotDotToken);
bind(node.questionToken);
bind(node.type);
bindInitializer(node.initializer);
bind(node.name);
}
// a BindingElement/Parameter does not have side effects if initializers are not evaluated and used. (see GH#49759)
function bindInitializer(node: Expression | undefined) {
if (!node) {
return;
}
else {
bindEachChild(node);
const entryFlow = currentFlow;
bind(node);
if (entryFlow === unreachableFlow || entryFlow === currentFlow) {
return;
}
const exitFlow = createBranchLabel();
addAntecedent(exitFlow, entryFlow);
addAntecedent(exitFlow, currentFlow);
currentFlow = finishFlowLabel(exitFlow);
}
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag) {