mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 01:08:39 +09:00
1317379 - Disallow generator functions and async functions as direct children of if/else.
This commit is contained in:
parent
8589f6e316
commit
dd359c6105
3 changed files with 87 additions and 21 deletions
|
|
@ -5248,33 +5248,74 @@ Parser<ParseHandler>::consequentOrAlternative(YieldHandling yieldHandling)
|
|||
if (!tokenStream.peekToken(&next, TokenStream::Operand))
|
||||
return null();
|
||||
|
||||
if (next == TOK_FUNCTION) {
|
||||
// Annex B.3.4 says that unbraced function declarations under if/else
|
||||
// in non-strict code act as if they were braced. That is,
|
||||
// |if (x) function f() {}| is parsed as |if (x) { function f() {} }|.
|
||||
if (!pc->sc()->strict()) {
|
||||
tokenStream.consumeKnownToken(next, TokenStream::Operand);
|
||||
// Annex B.3.4 says that unbraced FunctionDeclarations under if/else in
|
||||
// non-strict code act as if they were braced: |if (x) function f() {}|
|
||||
// parses as |if (x) { function f() {} }|.
|
||||
//
|
||||
// Careful! FunctionDeclaration doesn't include generators or async
|
||||
// functions.
|
||||
if (next == TOK_NAME &&
|
||||
!tokenStream.nextNameContainsEscape() &&
|
||||
tokenStream.nextName() == context->names().async)
|
||||
{
|
||||
tokenStream.consumeKnownToken(next, TokenStream::Operand);
|
||||
|
||||
ParseContext::Statement stmt(pc, StatementKind::Block);
|
||||
ParseContext::Scope scope(this);
|
||||
if (!scope.init(pc))
|
||||
return null();
|
||||
// Peek only on the same line: ExpressionStatement's lookahead
|
||||
// restriction is phrased as
|
||||
//
|
||||
// [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]
|
||||
//
|
||||
// meaning that code like this is valid:
|
||||
//
|
||||
// if (true)
|
||||
// async // ASI opportunity
|
||||
// function clownshoes() {}
|
||||
TokenKind maybeFunction;
|
||||
if (!tokenStream.peekTokenSameLine(&maybeFunction))
|
||||
return null();
|
||||
|
||||
TokenPos funcPos = pos();
|
||||
Node fun = functionStmt(pos().begin, yieldHandling, NameRequired);
|
||||
if (!fun)
|
||||
return null();
|
||||
|
||||
Node block = handler.newStatementList(funcPos);
|
||||
if (!block)
|
||||
return null();
|
||||
|
||||
handler.addStatementToList(block, fun);
|
||||
return finishLexicalScope(scope, block);
|
||||
if (maybeFunction == TOK_FUNCTION) {
|
||||
error(JSMSG_FORBIDDEN_AS_STATEMENT, "async function declarations");
|
||||
return null();
|
||||
}
|
||||
|
||||
// Function declarations are a syntax error in strict mode code.
|
||||
// Parser::statement reports that error.
|
||||
// Otherwise this |async| begins an ExpressionStatement.
|
||||
tokenStream.ungetToken();
|
||||
} else if (next == TOK_FUNCTION) {
|
||||
tokenStream.consumeKnownToken(next, TokenStream::Operand);
|
||||
|
||||
// Parser::statement would handle this, but as this function handles
|
||||
// every other error case, it seems best to handle this.
|
||||
if (pc->sc()->strict()) {
|
||||
error(JSMSG_FORBIDDEN_AS_STATEMENT, "function declarations");
|
||||
return null();
|
||||
}
|
||||
|
||||
TokenKind maybeStar;
|
||||
if (!tokenStream.peekToken(&maybeStar))
|
||||
return null();
|
||||
|
||||
if (maybeStar == TOK_MUL) {
|
||||
error(JSMSG_FORBIDDEN_AS_STATEMENT, "generator declarations");
|
||||
return null();
|
||||
}
|
||||
|
||||
ParseContext::Statement stmt(pc, StatementKind::Block);
|
||||
ParseContext::Scope scope(this);
|
||||
if (!scope.init(pc))
|
||||
return null();
|
||||
|
||||
TokenPos funcPos = pos();
|
||||
Node fun = functionStmt(pos().begin, yieldHandling, NameRequired);
|
||||
if (!fun)
|
||||
return null();
|
||||
|
||||
Node block = handler.newStatementList(funcPos);
|
||||
if (!block)
|
||||
return null();
|
||||
|
||||
handler.addStatementToList(block, fun);
|
||||
return finishLexicalScope(scope, block);
|
||||
}
|
||||
|
||||
return statement(yieldHandling);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
assertThrowsInstanceOf(() => eval("if (1) async function foo() {}"),
|
||||
SyntaxError);
|
||||
assertThrowsInstanceOf(() => eval("'use strict'; if (1) async function foo() {}"),
|
||||
SyntaxError);
|
||||
|
||||
var async = 42;
|
||||
assertEq(eval("if (1) async \n function foo() {}"), 42);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
11
js/src/tests/ecma_6/Generators/forbidden-as-consequent.js
Normal file
11
js/src/tests/ecma_6/Generators/forbidden-as-consequent.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
assertThrowsInstanceOf(() => eval("if (1) function* foo() {}"),
|
||||
SyntaxError);
|
||||
assertThrowsInstanceOf(() => eval("'use strict'; if (1) function* foo() {}"),
|
||||
SyntaxError);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
Loading…
Add table
Add a link
Reference in a new issue