Skip to content

Commit 7691f9a

Browse files
author
Kenji Fukuda
committed
[MERGE #5568 @kfukuda2] Fixing test 262 regression for labels followed by let.
Merge pull request #5568 from kfukuda2:label262FixRS5 Initial labels change is #5482, which caused a test262 regression around labels followed by let and a new line.
2 parents dae4186 + a7dcf84 commit 7691f9a

File tree

2 files changed

+137
-11
lines changed

2 files changed

+137
-11
lines changed

lib/Parser/Parse.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9800,20 +9800,26 @@ ParseNodePtr Parser::ParseStatement()
98009800
break;
98019801

98029802
case tkID:
9803+
case tkLET:
98039804
if (m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.let)
98049805
{
9805-
if (labelledStatement)
9806-
{
9807-
Error(ERRLabelBeforeLexicalDeclaration);
9808-
}
98099806
// We see "let" at the start of a statement. This could either be a declaration or an identifier
98109807
// reference. The next token determines which.
98119808
RestorePoint parsedLet;
98129809
this->GetScanner()->Capture(&parsedLet);
98139810
ichMin = this->GetScanner()->IchMinTok();
98149811

98159812
this->GetScanner()->Scan();
9816-
if (this->NextTokenConfirmsLetDecl())
9813+
if (labelledStatement)
9814+
{
9815+
if (!this->GetScanner()->FHadNewLine() || m_token.tk == tkLBrack)
9816+
{
9817+
// In the case where a label is followed by a let, we want to fail when parsing if there is no new line after let,
9818+
// otherwise fail at runtime as let will be viewed as undefined. A left bracket after a let signifies a syntax error regardless.
9819+
Error(ERRLabelBeforeLexicalDeclaration);
9820+
}
9821+
}
9822+
else if (this->NextTokenConfirmsLetDecl())
98179823
{
98189824
pnode = ParseVariableDeclaration<buildAST>(tkLET, ichMin);
98199825
goto LNeedTerminator;
@@ -9838,7 +9844,6 @@ ParseNodePtr Parser::ParseStatement()
98389844
goto LDefaultToken;
98399845

98409846
case tkCONST:
9841-
case tkLET:
98429847
if (labelledStatement)
98439848
{
98449849
Error(ERRLabelBeforeLexicalDeclaration);

test/Basics/Labels.js

Lines changed: 126 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ testAwaitAsLabelInsideAsyncFnc =
139139
strictModeOnlyInvalidLabels = {//Maps the reserved word to the error message given when it is used as a label in strict mode
140140
"implements" : "Syntax error",
141141
"interface" : "Syntax error",
142-
"let" : "Expected identifier",
142+
"let" : "Syntax error",
143143
"package" : "Syntax error",
144144
"private" : "Syntax error",
145145
"protected" : "Syntax error",
@@ -233,14 +233,112 @@ testInvalidLabelSyntaxArrayAccess =
233233
234234
f();`
235235

236-
testInvalidLabelSyntaxFunctionCall = `function f() {
236+
testInvalidLabelSyntaxFunctionCall =
237+
`function f() {
237238
// Bad label, verify consistency in deferred parsing
238239
a():
239240
var i = 0;
240241
}
241242
242243
f();`
243-
244+
testRuntimeErrorWithDanglingLetAfterLabel =
245+
`if (true) {
246+
L: let // comment
247+
{}
248+
}`
249+
testNoSyntaxErrorWithDanglingLetAfterLabel =
250+
`if (false) {
251+
L: let // comment
252+
{}
253+
}`
254+
testRuntimeErrorWithDanglingLetAfterLabel2 =
255+
`if (true) {
256+
L: let // ASI
257+
var g = {}
258+
}`
259+
testNoSyntaxErrorWithDanglingLetAfterLabel2 =
260+
`if (false) {
261+
L: let // ASI
262+
var g = {}
263+
}`
264+
testRuntimeErrorWithDanglingLetAfterLabel3=
265+
`if (true) {
266+
L: let // ASI
267+
let a = 3
268+
}`
269+
testNoSyntaxErrorWithDanglingLetAfterLabel3=
270+
`if (false) {
271+
L: let // ASI
272+
let a = 3
273+
}`
274+
testRuntimeErrorWithDanglingLetAfterLabel4=
275+
`if (true) {
276+
L: let // ASI
277+
a = 3
278+
}`
279+
testNoSyntaxErrorWithDanglingLetAfterLabel4=
280+
`if (false) {
281+
L: let // ASI
282+
a = 3
283+
}`
284+
testNoRuntimeErrorWithDanglingVarAfterLabel=
285+
`label: var
286+
x = 0;`
287+
testSyntaxErrorWithDanglingConstAfterLabel=
288+
`label: const
289+
x = 0;`
290+
testRuntimeErrorWithDanglingYieldAfterLabel=
291+
`if (true) {
292+
L: yield // ASI
293+
console.log("b");
294+
1;
295+
}`
296+
testNoSyntaxErrorWithDanglingYieldAfterLabel=
297+
`if (false) {
298+
L: yield // ASI
299+
console.log("b");
300+
1;
301+
}`
302+
testGeneratorWithDanglingYieldAfterLabel=
303+
`function* gen(num)
304+
{
305+
L: yield // ASI
306+
++num
307+
}
308+
309+
const iterator = gen(0)
310+
if(iterator.next().value === 1)
311+
throw("Yield should not return a number");
312+
`
313+
testNoSyntaxErrorWithDanglingAwaitAfterLabel=
314+
`function fn()
315+
{
316+
for(i = 0; i < 30; i++);
317+
}
318+
if(false)
319+
{
320+
L: await
321+
fn()
322+
}`
323+
testRuntimeErrorWithDanglingAwaitAfterLabel=
324+
`function fn()
325+
{
326+
for(i = 0; i < 30; i++);
327+
}
328+
if(true)
329+
{
330+
L: await
331+
fn()
332+
}`
333+
testNoSyntaxErrorWithDanglingStaticAfterLabel=
334+
`function g(){
335+
L: static
336+
x = 0
337+
}`
338+
testRuntimeErrorWithDanglingStaticAfterLabel=
339+
`L: static
340+
x = 0`
341+
244342
function testModuleScript(source, message, shouldFail = false) {
245343
let testfunc = () => testRunner.LoadModule(source, 'samethread', shouldFail);
246344

@@ -331,8 +429,8 @@ var tests = [
331429

332430
for(let invalidLabelInStrict in strictModeOnlyInvalidLabels)
333431
{
334-
assert.throws(() =>eval(strictMode + invalidLabelInStrict + testIfLabelIsValid), SyntaxError, "Expected syntax error in strict mode for future reserved keyword '" + invalidLabelInStrict + "'", strictModeOnlyInvalidLabels[invalidLabelInStrict])
335-
assert.doesNotThrow(() =>eval(invalidLabelInStrict + testIfLabelIsValid), "Expected no syntax error for future reserved keyword '" + invalidLabelInStrict + " in non-strict mode")
432+
assert.throws(() => eval(strictMode + invalidLabelInStrict + testIfLabelIsValid), SyntaxError, "Expected syntax error in strict mode for future reserved keyword '" + invalidLabelInStrict + "'", strictModeOnlyInvalidLabels[invalidLabelInStrict])
433+
assert.doesNotThrow(() => eval(invalidLabelInStrict + testIfLabelIsValid), "Expected no syntax error for future reserved keyword '" + invalidLabelInStrict + " in non-strict mode")
336434
}
337435
}
338436
},
@@ -347,6 +445,29 @@ var tests = [
347445
assert.throws(() => eval(testInvalidLabelSyntaxArrayAccess), SyntaxError, "Expected syntax error from using malformed label", "Expected ';'")
348446
assert.throws(() => eval(testInvalidLabelSyntaxFunctionCall), SyntaxError, "Expected syntax error from using malformed label", "Expected ';'")
349447
}
448+
},
449+
{
450+
name : "Label tests, edge cases",
451+
body : function ()
452+
{
453+
assert.throws(() => eval(testRuntimeErrorWithDanglingLetAfterLabel), ReferenceError, "Expected runtime error from using let as identifier", "'let' is not defined")
454+
assert.doesNotThrow(() => eval(testNoSyntaxErrorWithDanglingLetAfterLabel), "Expected no syntax error from using let as identifier after label")
455+
assert.throws(() => eval(testRuntimeErrorWithDanglingLetAfterLabel2), ReferenceError, "Expected runtime error from using let as identifier", "'let' is not defined")
456+
assert.doesNotThrow(() => eval(testNoSyntaxErrorWithDanglingLetAfterLabel2), "Expected no syntax error from using let as identifier after label")
457+
assert.throws(() => eval(testRuntimeErrorWithDanglingLetAfterLabel3), ReferenceError, "Expected runtime error from using let as identifier", "'let' is not defined")
458+
assert.doesNotThrow(() => eval(testNoSyntaxErrorWithDanglingLetAfterLabel3), "Expected no syntax error from using let as identifier after label")
459+
assert.throws(() => eval(testRuntimeErrorWithDanglingLetAfterLabel4), ReferenceError, "Expected runtime error from using let as identifier", "'let' is not defined")
460+
assert.doesNotThrow(() => eval(testNoSyntaxErrorWithDanglingLetAfterLabel4), "Expected no syntax error from using let as identifier after label")
461+
assert.doesNotThrow(() => eval(testNoRuntimeErrorWithDanglingVarAfterLabel), "Expected no syntax error from using var after label")
462+
assert.throws(() => eval(testSyntaxErrorWithDanglingConstAfterLabel), SyntaxError, "Expected syntax error from using const after label", "Labels not allowed before lexical declaration")
463+
assert.doesNotThrow(() => eval(testNoSyntaxErrorWithDanglingYieldAfterLabel), "Expected no syntax error from using yield after label")
464+
assert.throws(() => eval(testRuntimeErrorWithDanglingYieldAfterLabel), ReferenceError, "Expected runtime error for undefined reference to yield", "'yield' is not defined")
465+
assert.doesNotThrow(() => eval(testGeneratorWithDanglingYieldAfterLabel), "Expected no error from using yield after label. Also expect the yield to not be bound to the expression.")
466+
assert.doesNotThrow(() => eval(testNoSyntaxErrorWithDanglingAwaitAfterLabel), "Expected no error from using await after label. Also expect the yield to not be bound to the expression.")
467+
assert.throws(() => eval(testRuntimeErrorWithDanglingAwaitAfterLabel), ReferenceError, "Expected reference error from stranded await being used after label", "'await' is not defined")
468+
assert.throws(() => eval(testRuntimeErrorWithDanglingStaticAfterLabel), ReferenceError, "Expected reference error from stranded static being used after label", "'static' is not defined")
469+
assert.doesNotThrow(() => eval(testNoSyntaxErrorWithDanglingStaticAfterLabel), "Expected no issue parsing since static is viewed as an identifier")
470+
}
350471
}
351472
];
352473

0 commit comments

Comments
 (0)