mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Fix control flow analysis for nested try-catch-finally statements (#39399)
* Fix control flow analysis for nested try-catch-finally statements * Add tests
This commit is contained in:
parent
fd8ca520ab
commit
2fe2f88047
@ -1241,6 +1241,11 @@ namespace ts {
|
||||
if (currentReturnTarget && returnLabel.antecedents) {
|
||||
addAntecedent(currentReturnTarget, createReduceLabel(finallyLabel, returnLabel.antecedents, currentFlow));
|
||||
}
|
||||
// If we have an outer exception target (i.e. a containing try-finally or try-catch-finally), add a
|
||||
// control flow that goes back through the finally blok and back through each possible exception source.
|
||||
if (currentExceptionTarget && exceptionLabel.antecedents) {
|
||||
addAntecedent(currentExceptionTarget, createReduceLabel(finallyLabel, exceptionLabel.antecedents, currentFlow));
|
||||
}
|
||||
// If the end of the finally block is reachable, but the end of the try and catch blocks are not,
|
||||
// convert the current flow to unreachable. For example, 'try { return 1; } finally { ... }' should
|
||||
// result in an unreachable current control flow.
|
||||
|
||||
@ -275,4 +275,74 @@ tests/cases/compiler/tryCatchFinallyControlFlow.ts(255,9): error TS7027: Unreach
|
||||
})();
|
||||
x; // Reachable
|
||||
}
|
||||
|
||||
// Repro from #39043
|
||||
|
||||
type State = { tag: "one" } | { tag: "two" } | { tag: "three" };
|
||||
|
||||
function notallowed(arg: number) {
|
||||
let state: State = { tag: "one" };
|
||||
try {
|
||||
state = { tag: "two" };
|
||||
try {
|
||||
state = { tag: "three" };
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
catch (err) {
|
||||
state.tag;
|
||||
if (state.tag !== "one" && state.tag !== "two") {
|
||||
console.log(state.tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function f20() {
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0;
|
||||
try {
|
||||
x = 1;
|
||||
try {
|
||||
x = 2;
|
||||
try {
|
||||
x = 3;
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
}
|
||||
x; // 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 6;
|
||||
}
|
||||
x; // 3 | 4 | 5 | 6
|
||||
}
|
||||
|
||||
function f21() {
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 = 0;
|
||||
try {
|
||||
x = 1;
|
||||
try {
|
||||
x = 2;
|
||||
try {
|
||||
x = 3;
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
}
|
||||
x; // 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
}
|
||||
catch (e) {
|
||||
x; // 0 | 1 | 2 | 3 | 4 | 5
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,6 +257,76 @@ function t1() {
|
||||
})();
|
||||
x; // Reachable
|
||||
}
|
||||
|
||||
// Repro from #39043
|
||||
|
||||
type State = { tag: "one" } | { tag: "two" } | { tag: "three" };
|
||||
|
||||
function notallowed(arg: number) {
|
||||
let state: State = { tag: "one" };
|
||||
try {
|
||||
state = { tag: "two" };
|
||||
try {
|
||||
state = { tag: "three" };
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
catch (err) {
|
||||
state.tag;
|
||||
if (state.tag !== "one" && state.tag !== "two") {
|
||||
console.log(state.tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function f20() {
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0;
|
||||
try {
|
||||
x = 1;
|
||||
try {
|
||||
x = 2;
|
||||
try {
|
||||
x = 3;
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
}
|
||||
x; // 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 6;
|
||||
}
|
||||
x; // 3 | 4 | 5 | 6
|
||||
}
|
||||
|
||||
function f21() {
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 = 0;
|
||||
try {
|
||||
x = 1;
|
||||
try {
|
||||
x = 2;
|
||||
try {
|
||||
x = 3;
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
}
|
||||
x; // 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
}
|
||||
catch (e) {
|
||||
x; // 0 | 1 | 2 | 3 | 4 | 5
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [tryCatchFinallyControlFlow.js]
|
||||
@ -503,3 +573,71 @@ function t1() {
|
||||
})();
|
||||
x; // Reachable
|
||||
}
|
||||
function notallowed(arg) {
|
||||
var state = { tag: "one" };
|
||||
try {
|
||||
state = { tag: "two" };
|
||||
try {
|
||||
state = { tag: "three" };
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
catch (err) {
|
||||
state.tag;
|
||||
if (state.tag !== "one" && state.tag !== "two") {
|
||||
console.log(state.tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
function f20() {
|
||||
var x = 0;
|
||||
try {
|
||||
x = 1;
|
||||
try {
|
||||
x = 2;
|
||||
try {
|
||||
x = 3;
|
||||
}
|
||||
finally {
|
||||
if (!!true)
|
||||
x = 4;
|
||||
}
|
||||
x; // 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true)
|
||||
x = 5;
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
}
|
||||
finally {
|
||||
if (!!true)
|
||||
x = 6;
|
||||
}
|
||||
x; // 3 | 4 | 5 | 6
|
||||
}
|
||||
function f21() {
|
||||
var x = 0;
|
||||
try {
|
||||
x = 1;
|
||||
try {
|
||||
x = 2;
|
||||
try {
|
||||
x = 3;
|
||||
}
|
||||
finally {
|
||||
if (!!true)
|
||||
x = 4;
|
||||
}
|
||||
x; // 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true)
|
||||
x = 5;
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
}
|
||||
catch (e) {
|
||||
x; // 0 | 1 | 2 | 3 | 4 | 5
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,3 +445,139 @@ function t1() {
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 247, 9))
|
||||
}
|
||||
|
||||
// Repro from #39043
|
||||
|
||||
type State = { tag: "one" } | { tag: "two" } | { tag: "three" };
|
||||
>State : Symbol(State, Decl(tryCatchFinallyControlFlow.ts, 257, 1))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 14))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 31))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
|
||||
function notallowed(arg: number) {
|
||||
>notallowed : Symbol(notallowed, Decl(tryCatchFinallyControlFlow.ts, 261, 64))
|
||||
>arg : Symbol(arg, Decl(tryCatchFinallyControlFlow.ts, 263, 20))
|
||||
|
||||
let state: State = { tag: "one" };
|
||||
>state : Symbol(state, Decl(tryCatchFinallyControlFlow.ts, 264, 7))
|
||||
>State : Symbol(State, Decl(tryCatchFinallyControlFlow.ts, 257, 1))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 264, 24))
|
||||
|
||||
try {
|
||||
state = { tag: "two" };
|
||||
>state : Symbol(state, Decl(tryCatchFinallyControlFlow.ts, 264, 7))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 266, 17))
|
||||
|
||||
try {
|
||||
state = { tag: "three" };
|
||||
>state : Symbol(state, Decl(tryCatchFinallyControlFlow.ts, 264, 7))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 268, 21))
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
catch (err) {
|
||||
>err : Symbol(err, Decl(tryCatchFinallyControlFlow.ts, 272, 11))
|
||||
|
||||
state.tag;
|
||||
>state.tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 14), Decl(tryCatchFinallyControlFlow.ts, 261, 31), Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
>state : Symbol(state, Decl(tryCatchFinallyControlFlow.ts, 264, 7))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 14), Decl(tryCatchFinallyControlFlow.ts, 261, 31), Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
|
||||
if (state.tag !== "one" && state.tag !== "two") {
|
||||
>state.tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 14), Decl(tryCatchFinallyControlFlow.ts, 261, 31), Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
>state : Symbol(state, Decl(tryCatchFinallyControlFlow.ts, 264, 7))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 14), Decl(tryCatchFinallyControlFlow.ts, 261, 31), Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
>state.tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 31), Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
>state : Symbol(state, Decl(tryCatchFinallyControlFlow.ts, 264, 7))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 31), Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
|
||||
console.log(state.tag);
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>state.tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
>state : Symbol(state, Decl(tryCatchFinallyControlFlow.ts, 264, 7))
|
||||
>tag : Symbol(tag, Decl(tryCatchFinallyControlFlow.ts, 261, 48))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function f20() {
|
||||
>f20 : Symbol(f20, Decl(tryCatchFinallyControlFlow.ts, 278, 1))
|
||||
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
|
||||
try {
|
||||
x = 1;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
|
||||
try {
|
||||
x = 2;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
|
||||
try {
|
||||
x = 3;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
}
|
||||
x; // 3 | 4
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 6;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
}
|
||||
x; // 3 | 4 | 5 | 6
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 281, 7))
|
||||
}
|
||||
|
||||
function f21() {
|
||||
>f21 : Symbol(f21, Decl(tryCatchFinallyControlFlow.ts, 303, 1))
|
||||
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 = 0;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
|
||||
try {
|
||||
x = 1;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
|
||||
try {
|
||||
x = 2;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
|
||||
try {
|
||||
x = 3;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
}
|
||||
x; // 3 | 4
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
}
|
||||
catch (e) {
|
||||
>e : Symbol(e, Decl(tryCatchFinallyControlFlow.ts, 324, 11))
|
||||
|
||||
x; // 0 | 1 | 2 | 3 | 4 | 5
|
||||
>x : Symbol(x, Decl(tryCatchFinallyControlFlow.ts, 306, 7))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -589,3 +589,191 @@ function t1() {
|
||||
>x : "x" | null
|
||||
}
|
||||
|
||||
// Repro from #39043
|
||||
|
||||
type State = { tag: "one" } | { tag: "two" } | { tag: "three" };
|
||||
>State : State
|
||||
>tag : "one"
|
||||
>tag : "two"
|
||||
>tag : "three"
|
||||
|
||||
function notallowed(arg: number) {
|
||||
>notallowed : (arg: number) => void
|
||||
>arg : number
|
||||
|
||||
let state: State = { tag: "one" };
|
||||
>state : State
|
||||
>{ tag: "one" } : { tag: "one"; }
|
||||
>tag : "one"
|
||||
>"one" : "one"
|
||||
|
||||
try {
|
||||
state = { tag: "two" };
|
||||
>state = { tag: "two" } : { tag: "two"; }
|
||||
>state : State
|
||||
>{ tag: "two" } : { tag: "two"; }
|
||||
>tag : "two"
|
||||
>"two" : "two"
|
||||
|
||||
try {
|
||||
state = { tag: "three" };
|
||||
>state = { tag: "three" } : { tag: "three"; }
|
||||
>state : State
|
||||
>{ tag: "three" } : { tag: "three"; }
|
||||
>tag : "three"
|
||||
>"three" : "three"
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
catch (err) {
|
||||
>err : any
|
||||
|
||||
state.tag;
|
||||
>state.tag : "one" | "two" | "three"
|
||||
>state : State
|
||||
>tag : "one" | "two" | "three"
|
||||
|
||||
if (state.tag !== "one" && state.tag !== "two") {
|
||||
>state.tag !== "one" && state.tag !== "two" : boolean
|
||||
>state.tag !== "one" : boolean
|
||||
>state.tag : "one" | "two" | "three"
|
||||
>state : State
|
||||
>tag : "one" | "two" | "three"
|
||||
>"one" : "one"
|
||||
>state.tag !== "two" : boolean
|
||||
>state.tag : "two" | "three"
|
||||
>state : { tag: "two"; } | { tag: "three"; }
|
||||
>tag : "two" | "three"
|
||||
>"two" : "two"
|
||||
|
||||
console.log(state.tag);
|
||||
>console.log(state.tag) : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>state.tag : "three"
|
||||
>state : { tag: "three"; }
|
||||
>tag : "three"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function f20() {
|
||||
>f20 : () => void
|
||||
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0;
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
>0 : 0
|
||||
|
||||
try {
|
||||
x = 1;
|
||||
>x = 1 : 1
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
>1 : 1
|
||||
|
||||
try {
|
||||
x = 2;
|
||||
>x = 2 : 2
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
>2 : 2
|
||||
|
||||
try {
|
||||
x = 3;
|
||||
>x = 3 : 3
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
>3 : 3
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
>!!true : true
|
||||
>!true : false
|
||||
>true : true
|
||||
>x = 4 : 4
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
>4 : 4
|
||||
}
|
||||
x; // 3 | 4
|
||||
>x : 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
>!!true : true
|
||||
>!true : false
|
||||
>true : true
|
||||
>x = 5 : 5
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
>5 : 5
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
>x : 3 | 4 | 5
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 6;
|
||||
>!!true : true
|
||||
>!true : false
|
||||
>true : true
|
||||
>x = 6 : 6
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||
>6 : 6
|
||||
}
|
||||
x; // 3 | 4 | 5 | 6
|
||||
>x : 3 | 4 | 5 | 6
|
||||
}
|
||||
|
||||
function f21() {
|
||||
>f21 : () => void
|
||||
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 = 0;
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5
|
||||
>0 : 0
|
||||
|
||||
try {
|
||||
x = 1;
|
||||
>x = 1 : 1
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5
|
||||
>1 : 1
|
||||
|
||||
try {
|
||||
x = 2;
|
||||
>x = 2 : 2
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5
|
||||
>2 : 2
|
||||
|
||||
try {
|
||||
x = 3;
|
||||
>x = 3 : 3
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5
|
||||
>3 : 3
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
>!!true : true
|
||||
>!true : false
|
||||
>true : true
|
||||
>x = 4 : 4
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5
|
||||
>4 : 4
|
||||
}
|
||||
x; // 3 | 4
|
||||
>x : 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
>!!true : true
|
||||
>!true : false
|
||||
>true : true
|
||||
>x = 5 : 5
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5
|
||||
>5 : 5
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
>x : 3 | 4 | 5
|
||||
}
|
||||
catch (e) {
|
||||
>e : any
|
||||
|
||||
x; // 0 | 1 | 2 | 3 | 4 | 5
|
||||
>x : 0 | 1 | 2 | 3 | 4 | 5
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -259,3 +259,73 @@ function t1() {
|
||||
})();
|
||||
x; // Reachable
|
||||
}
|
||||
|
||||
// Repro from #39043
|
||||
|
||||
type State = { tag: "one" } | { tag: "two" } | { tag: "three" };
|
||||
|
||||
function notallowed(arg: number) {
|
||||
let state: State = { tag: "one" };
|
||||
try {
|
||||
state = { tag: "two" };
|
||||
try {
|
||||
state = { tag: "three" };
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
catch (err) {
|
||||
state.tag;
|
||||
if (state.tag !== "one" && state.tag !== "two") {
|
||||
console.log(state.tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function f20() {
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0;
|
||||
try {
|
||||
x = 1;
|
||||
try {
|
||||
x = 2;
|
||||
try {
|
||||
x = 3;
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
}
|
||||
x; // 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 6;
|
||||
}
|
||||
x; // 3 | 4 | 5 | 6
|
||||
}
|
||||
|
||||
function f21() {
|
||||
let x: 0 | 1 | 2 | 3 | 4 | 5 = 0;
|
||||
try {
|
||||
x = 1;
|
||||
try {
|
||||
x = 2;
|
||||
try {
|
||||
x = 3;
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 4;
|
||||
}
|
||||
x; // 3 | 4
|
||||
}
|
||||
finally {
|
||||
if (!!true) x = 5;
|
||||
}
|
||||
x; // 3 | 4 | 5
|
||||
}
|
||||
catch (e) {
|
||||
x; // 0 | 1 | 2 | 3 | 4 | 5
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user