Skip to content

Commit e98247b

Browse files
authored
actually fix break and continue in compat mode
1 parent ba667b6 commit e98247b

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

src/compiler/jsgen.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,11 +1200,16 @@ class JSGenerator {
12001200
} else if (blockType === BlockType.CONDITIONAL || blockType === BlockType.LOOP) {
12011201
const branchVariable = this.localVariables.next();
12021202
this.source += `const ${branchVariable} = createBranchInfo(${blockType === BlockType.LOOP});\n`;
1203-
this.source += `while (${branchVariable}.branch = +(${this.generateCompatibilityLayerCall(node, false, branchVariable)})) {\n`;
1203+
this.source += `while (!${branchVariable}.escaped || (${branchVariable}.branch = +(${this.generateCompatibilityLayerCall(node, false, branchVariable)}))) {\n`;
12041204
this.source += `switch (${branchVariable}.branch) {\n`;
1205+
this.compatBranchInfo = { node, branchVar: branchVariable, escaped: false };
12051206
for (let i = 0; i < node.substacks.length; i++) {
12061207
this.source += `case ${i + 1}: {\n`;
12071208
this.descendStack(node.substacks[i], new Frame(false));
1209+
if (this.compatBranchInfo.escaped) {
1210+
this.source += `}\n`; // close break point
1211+
this.compatBranchInfo.escaped = false;
1212+
}
12081213
this.source += `break;\n`;
12091214
this.source += `}\n`; // close case
12101215
}
@@ -1213,6 +1218,7 @@ class JSGenerator {
12131218
this.source += `if (!${branchVariable}.isLoop) break;\n`;
12141219
this.yieldLoop();
12151220
this.source += '}\n'; // close while
1221+
this.compatBranchInfo = undefined;
12161222
} else {
12171223
throw new Error(`Unknown block type: ${blockType}`);
12181224
}
@@ -1306,7 +1312,13 @@ class JSGenerator {
13061312
if (inLoop) this.source += `break;\n`;
13071313
else {
13081314
// this could be an uncompiled loop block
1309-
this.source += `yield* executeInCompatibilityLayer({}, runtime.getOpcodeFunction("control_exitLoop"), false, false, "${node.id}", null);\n`;
1315+
if (this.compatBranchInfo) {
1316+
this.compatBranchInfo.escaped = true;
1317+
this.source += `${this.compatBranchInfo.branchVar}.escaped = true;\n`;
1318+
this.source += `if (false) {\n`; // stop following code in the stack
1319+
} else {
1320+
this.source += `yield* executeInCompatibilityLayer({}, runtime.getOpcodeFunction("control_exitLoop"), false, false, "${node.id}", null);\n`;
1321+
}
13101322
}
13111323
break;
13121324
}
@@ -1315,7 +1327,13 @@ class JSGenerator {
13151327
if (inLoop) this.source += `continue;\n`;
13161328
else {
13171329
// this could be an uncompiled loop block
1318-
this.source += `yield* executeInCompatibilityLayer({}, runtime.getOpcodeFunction("control_exitLoop"), false, false, "${node.id}", null);\n`;
1330+
if (this.compatBranchInfo) {
1331+
// we only need to make the loop stop stack code, not end the loop
1332+
this.compatBranchInfo.escaped = true;
1333+
this.source += `if (false) {\n`; // stop following code in the stack
1334+
} else {
1335+
this.source += `yield* executeInCompatibilityLayer({}, runtime.getOpcodeFunction("control_exitLoop"), false, false, "${node.id}", null);\n`;
1336+
}
13191337
}
13201338
break;
13211339
}

0 commit comments

Comments
 (0)