Fix break/continue when switch is nested inside loop (#11802)

* Fix break/continue when switch is nested inside loop

* merge retCheck
This commit is contained in:
Brian Ng 2020-07-07 17:38:11 -05:00 committed by GitHub
parent b1a8e72e16
commit 58cfaf20ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 60 deletions

View File

@ -844,55 +844,26 @@ class BlockScoping {
buildHas(ret: string) {
const body = this.body;
let retCheck;
const has = this.has;
const cases = [];
if (has.hasReturn) {
// typeof ret === "object"
retCheck = buildRetCheck({
RETURN: t.identifier(ret),
});
}
if (has.hasBreakContinue) {
for (const key of Object.keys(has.map)) {
cases.push(t.switchCase(t.stringLiteral(key), [has.map[key]]));
}
if (has.hasReturn) {
cases.push(t.switchCase(null, [retCheck]));
}
if (cases.length === 1) {
const single = cases[0];
body.push(
t.ifStatement(
t.binaryExpression("===", t.identifier(ret), single.test),
single.consequent[0],
t.binaryExpression("===", t.identifier(ret), t.stringLiteral(key)),
has.map[key],
),
);
} else {
if (this.loop) {
// https://github.com/babel/babel/issues/998
for (let i = 0; i < cases.length; i++) {
const caseConsequent = cases[i].consequent[0];
if (t.isBreakStatement(caseConsequent) && !caseConsequent.label) {
if (!this.loopLabel) {
this.loopLabel = this.scope.generateUidIdentifier("loop");
}
caseConsequent.label = t.cloneNode(this.loopLabel);
}
}
}
}
}
body.push(t.switchStatement(t.identifier(ret), cases));
}
} else {
if (has.hasReturn) {
body.push(retCheck);
}
// typeof ret === "object"
if (has.hasReturn) {
body.push(
buildRetCheck({
RETURN: t.identifier(ret),
}),
);
}
}
}

View File

@ -0,0 +1,15 @@
expect(() => {
for (const a of [1]) {
switch (true) {
case true: {
const b = 1;
() => b;
if (true) break;
continue;
}
case false: {
throw new Error("unreachable");
}
}
}
}).not.toThrow();

View File

@ -0,0 +1,13 @@
for (const a of [1]) {
switch (true) {
case true: {
const b = 1;
() => b;
if (true) break;
continue;
}
case false: {
throw new Error("unreachable");
}
}
}

View File

@ -0,0 +1,25 @@
for (var a of [1]) {
switch (true) {
case true:
{
var _ret = function () {
var b = 1;
(function () {
return b;
});
if (true) return "break";
return "continue";
}();
if (_ret === "break") break;
if (_ret === "continue") continue;
}
case false:
{
throw new Error("unreachable");
}
}
}

View File

@ -1,5 +1,5 @@
(function () {
var _loop2 = function (i) {
var _loop = function (i) {
fns.push(function () {
return i;
});
@ -15,18 +15,11 @@
}
};
_loop: for (var i in nums) {
var _ret = _loop2(i);
for (var i in nums) {
var _ret = _loop(i);
switch (_ret) {
case "continue":
continue;
case "break":
break _loop;
default:
if (typeof _ret === "object") return _ret.v;
}
if (_ret === "continue") continue;
if (_ret === "break") break;
if (typeof _ret === "object") return _ret.v;
}
})();

View File

@ -18,13 +18,8 @@ function foo() {
return "break";
}();
switch (_ret) {
case "break":
break;
default:
if (typeof _ret === "object") return _ret.v;
}
if (_ret === "break") break;
if (typeof _ret === "object") return _ret.v;
}
}
}