Skip to content

Commit 08567f7

Browse files
committed
[MERGE #5605 @yullin-ms] Checking label lists for labels
Merge pull request #5605 from pr/yullin/continue_break_after_label Fixes OS: 18576812 In defer parsing, when continue or break to label is in the same statement as label; check current label lists for labels.
2 parents bffb885 + 9b66595 commit 08567f7

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

lib/Parser/Parse.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10509,25 +10509,32 @@ ParseNodePtr Parser::ParseStatement()
1050910509
else
1051010510
{
1051110511
this->GetScanner()->Scan();
10512-
for (pstmt = m_pstmtCur; pstmt; pstmt = pstmt->pstmtOuter)
10512+
// Check if label is found within the current label id list.
10513+
auto checkLabelList = [&](LabelId* list, StmtNest* checkStmtOp)
1051310514
{
10514-
LabelId* pLabelId;
10515-
for (pLabelId = pstmt->pLabelId; pLabelId; pLabelId = pLabelId->next)
10515+
for (LabelId* pLabelId = list; pLabelId; pLabelId = pLabelId->next)
1051610516
{
10517-
1051810517
if (pid == pLabelId->pid)
1051910518
{
1052010519
// Found the label. Make sure we can use it. We can
1052110520
// break out of any statement, but we can only
1052210521
// continue loops.
1052310522
if (fnop == fnopContinue &&
10524-
!(ParseNode::Grfnop(pstmt->op) & fnop))
10523+
!(ParseNode::Grfnop(checkStmtOp->op) & fnop))
1052510524
{
1052610525
Error(ERRbadContinue);
1052710526
}
10528-
goto LNeedTerminator;
10527+
return true;
1052910528
}
1053010529
}
10530+
return false;
10531+
};
10532+
10533+
if (checkLabelList(pLabelIdList, m_pstmtCur)) goto LNeedTerminator;
10534+
10535+
for (pstmt = m_pstmtCur; pstmt; pstmt = pstmt->pstmtOuter)
10536+
{
10537+
if (checkLabelList(pstmt->pLabelId, pstmt)) goto LNeedTerminator;
1053110538
}
1053210539
}
1053310540
Error(ERRnoLabel);

test/Basics/Labels.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,19 @@ testNoSyntaxErrorWithDanglingStaticAfterLabel=
338338
testRuntimeErrorWithDanglingStaticAfterLabel=
339339
`L: static
340340
x = 0`
341+
342+
testSyntaxErrorWithContinueAfterLabel=
343+
`function fn() {
344+
L:
345+
continue L;
346+
}`
347+
348+
testNoLabelNotFoundWithBreakAfterLabel=
349+
`function fn() {
350+
L:
351+
break L;
352+
}`
353+
341354

342355
function testModuleScript(source, message, shouldFail = false) {
343356
let testfunc = () => testRunner.LoadModule(source, 'samethread', shouldFail);
@@ -467,6 +480,8 @@ var tests = [
467480
assert.throws(() => eval(testRuntimeErrorWithDanglingAwaitAfterLabel), ReferenceError, "Expected reference error from stranded await being used after label", "'await' is not defined")
468481
assert.throws(() => eval(testRuntimeErrorWithDanglingStaticAfterLabel), ReferenceError, "Expected reference error from stranded static being used after label", "'static' is not defined")
469482
assert.doesNotThrow(() => eval(testNoSyntaxErrorWithDanglingStaticAfterLabel), "Expected no issue parsing since static is viewed as an identifier")
483+
assert.throws(() => eval(testSyntaxErrorWithContinueAfterLabel), SyntaxError, "Expected syntax error from having continue outside of loop", "Can't have 'continue' outside of loop")
484+
assert.doesNotThrow(() => eval(testNoLabelNotFoundWithBreakAfterLabel), "Expected no issue from finding label")
470485
}
471486
}
472487
];

0 commit comments

Comments
 (0)