1317153 - Error for incorrect usage of await keyword is not helpful.
parent
943a0d43ee
commit
184697b9c4
|
@ -2631,39 +2631,62 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WARNING: Do not call this function directly.
|
* WARNING: Do not call this function directly.
|
||||||
* Call either MatchOrInsertSemicolonAfterExpression or
|
* Call either matchOrInsertSemicolonAfterExpression or
|
||||||
* MatchOrInsertSemicolonAfterNonExpression instead, depending on context.
|
* matchOrInsertSemicolonAfterNonExpression instead, depending on context.
|
||||||
*/
|
*/
|
||||||
static bool
|
template <typename ParseHandler>
|
||||||
MatchOrInsertSemicolonHelper(TokenStream& ts, TokenStream::Modifier modifier)
|
bool
|
||||||
|
Parser<ParseHandler>::matchOrInsertSemicolonHelper(TokenStream::Modifier modifier)
|
||||||
{
|
{
|
||||||
TokenKind tt = TOK_EOF;
|
TokenKind tt = TOK_EOF;
|
||||||
if (!ts.peekTokenSameLine(&tt, modifier))
|
if (!tokenStream.peekTokenSameLine(&tt, modifier))
|
||||||
return false;
|
return false;
|
||||||
if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
|
if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
|
||||||
|
/*
|
||||||
|
* When current token is `await` and it's outside of async function,
|
||||||
|
* it's possibly intended to be an await expression.
|
||||||
|
*
|
||||||
|
* await f();
|
||||||
|
* ^
|
||||||
|
* |
|
||||||
|
* tried to insert semicolon here
|
||||||
|
*
|
||||||
|
* Detect this situation and throw an understandable error. Otherwise
|
||||||
|
* we'd throw a confusing "missing ; before statement" error.
|
||||||
|
*/
|
||||||
|
if (!pc->isAsync() &&
|
||||||
|
tokenStream.currentToken().type == TOK_NAME &&
|
||||||
|
tokenStream.currentName() == context->names().await)
|
||||||
|
{
|
||||||
|
error(JSMSG_AWAIT_OUTSIDE_ASYNC);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Advance the scanner for proper error location reporting. */
|
/* Advance the scanner for proper error location reporting. */
|
||||||
ts.consumeKnownToken(tt, modifier);
|
tokenStream.consumeKnownToken(tt, modifier);
|
||||||
ts.reportError(JSMSG_SEMI_BEFORE_STMNT);
|
error(JSMSG_SEMI_BEFORE_STMNT);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool matched;
|
bool matched;
|
||||||
if (!ts.matchToken(&matched, TOK_SEMI, modifier))
|
if (!tokenStream.matchToken(&matched, TOK_SEMI, modifier))
|
||||||
return false;
|
return false;
|
||||||
if (!matched && modifier == TokenStream::None)
|
if (!matched && modifier == TokenStream::None)
|
||||||
ts.addModifierException(TokenStream::OperandIsNone);
|
tokenStream.addModifierException(TokenStream::OperandIsNone);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
template <typename ParseHandler>
|
||||||
MatchOrInsertSemicolonAfterExpression(TokenStream& ts)
|
bool
|
||||||
|
Parser<ParseHandler>::matchOrInsertSemicolonAfterExpression()
|
||||||
{
|
{
|
||||||
return MatchOrInsertSemicolonHelper(ts, TokenStream::None);
|
return matchOrInsertSemicolonHelper(TokenStream::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
template <typename ParseHandler>
|
||||||
MatchOrInsertSemicolonAfterNonExpression(TokenStream& ts)
|
bool
|
||||||
|
Parser<ParseHandler>::matchOrInsertSemicolonAfterNonExpression()
|
||||||
{
|
{
|
||||||
return MatchOrInsertSemicolonHelper(ts, TokenStream::Operand);
|
return matchOrInsertSemicolonHelper(TokenStream::Operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ParseHandler>
|
template <typename ParseHandler>
|
||||||
|
@ -3020,7 +3043,7 @@ Parser<FullParseHandler>::skipLazyInnerFunction(ParseNode* pn, uint32_t preludeS
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (kind == Statement && fun->isExprBody()) {
|
if (kind == Statement && fun->isExprBody()) {
|
||||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterExpression())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3503,7 +3526,7 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
|
||||||
if (tokenStream.hadError())
|
if (tokenStream.hadError())
|
||||||
return false;
|
return false;
|
||||||
funbox->bufEnd = pos().end;
|
funbox->bufEnd = pos().end;
|
||||||
if (kind == Statement && !MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (kind == Statement && !matchOrInsertSemicolonAfterExpression())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4639,7 +4662,7 @@ Parser<ParseHandler>::lexicalDeclaration(YieldHandling yieldHandling, bool isCon
|
||||||
* See 8.1.1.1.6 and the note in 13.2.1.
|
* See 8.1.1.1.6 and the note in 13.2.1.
|
||||||
*/
|
*/
|
||||||
Node decl = declarationList(yieldHandling, isConst ? PNK_CONST : PNK_LET);
|
Node decl = declarationList(yieldHandling, isConst ? PNK_CONST : PNK_LET);
|
||||||
if (!decl || !MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (!decl || !matchOrInsertSemicolonAfterExpression())
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
return decl;
|
return decl;
|
||||||
|
@ -4880,7 +4903,7 @@ Parser<FullParseHandler>::importDeclaration()
|
||||||
if (!moduleSpec)
|
if (!moduleSpec)
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterNonExpression())
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
ParseNode* node =
|
ParseNode* node =
|
||||||
|
@ -5023,7 +5046,7 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||||
// export { x } // ExportDeclaration, terminated by ASI
|
// export { x } // ExportDeclaration, terminated by ASI
|
||||||
// fro\u006D // ExpressionStatement, the name "from"
|
// fro\u006D // ExpressionStatement, the name "from"
|
||||||
//
|
//
|
||||||
// In that case let MatchOrInsertSemicolonAfterNonExpression sort out
|
// In that case let matchOrInsertSemicolonAfterNonExpression sort out
|
||||||
// ASI or any necessary error.
|
// ASI or any necessary error.
|
||||||
TokenKind tt;
|
TokenKind tt;
|
||||||
if (!tokenStream.getToken(&tt, TokenStream::Operand))
|
if (!tokenStream.getToken(&tt, TokenStream::Operand))
|
||||||
|
@ -5039,7 +5062,7 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||||
if (!moduleSpec)
|
if (!moduleSpec)
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterNonExpression())
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
ParseNode* node = handler.newExportFromDeclaration(begin, kid, moduleSpec);
|
ParseNode* node = handler.newExportFromDeclaration(begin, kid, moduleSpec);
|
||||||
|
@ -5051,7 +5074,7 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||||
|
|
||||||
tokenStream.ungetToken();
|
tokenStream.ungetToken();
|
||||||
|
|
||||||
if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterNonExpression())
|
||||||
return null();
|
return null();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5085,7 +5108,7 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||||
if (!moduleSpec)
|
if (!moduleSpec)
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterNonExpression())
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
ParseNode* node = handler.newExportFromDeclaration(begin, kid, moduleSpec);
|
ParseNode* node = handler.newExportFromDeclaration(begin, kid, moduleSpec);
|
||||||
|
@ -5121,7 +5144,7 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||||
kid = declarationList(YieldIsName, PNK_VAR);
|
kid = declarationList(YieldIsName, PNK_VAR);
|
||||||
if (!kid)
|
if (!kid)
|
||||||
return null();
|
return null();
|
||||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterExpression())
|
||||||
return null();
|
return null();
|
||||||
if (!checkExportedNamesForDeclaration(kid))
|
if (!checkExportedNamesForDeclaration(kid))
|
||||||
return null();
|
return null();
|
||||||
|
@ -5174,7 +5197,7 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||||
kid = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited);
|
kid = assignExpr(InAllowed, YieldIsKeyword, TripledotProhibited);
|
||||||
if (!kid)
|
if (!kid)
|
||||||
return null();
|
return null();
|
||||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterExpression())
|
||||||
return null();
|
return null();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5239,7 +5262,7 @@ Parser<ParseHandler>::expressionStatement(YieldHandling yieldHandling, InvokedPr
|
||||||
/* possibleError = */ nullptr, invoked);
|
/* possibleError = */ nullptr, invoked);
|
||||||
if (!pnexpr)
|
if (!pnexpr)
|
||||||
return null();
|
return null();
|
||||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterExpression())
|
||||||
return null();
|
return null();
|
||||||
return handler.newExprStatement(pnexpr, pos().end);
|
return handler.newExprStatement(pnexpr, pos().end);
|
||||||
}
|
}
|
||||||
|
@ -5870,7 +5893,7 @@ Parser<ParseHandler>::continueStatement(YieldHandling yieldHandling)
|
||||||
return null();
|
return null();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterNonExpression())
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
return handler.newContinueStatement(label, TokenPos(begin, pos().end));
|
return handler.newContinueStatement(label, TokenPos(begin, pos().end));
|
||||||
|
@ -5910,7 +5933,7 @@ Parser<ParseHandler>::breakStatement(YieldHandling yieldHandling)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterNonExpression())
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
return handler.newBreakStatement(label, TokenPos(begin, pos().end));
|
return handler.newBreakStatement(label, TokenPos(begin, pos().end));
|
||||||
|
@ -5950,10 +5973,10 @@ Parser<ParseHandler>::returnStatement(YieldHandling yieldHandling)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exprNode) {
|
if (exprNode) {
|
||||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterExpression())
|
||||||
return null();
|
return null();
|
||||||
} else {
|
} else {
|
||||||
if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterNonExpression())
|
||||||
return null();
|
return null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6250,7 +6273,7 @@ Parser<ParseHandler>::throwStatement(YieldHandling yieldHandling)
|
||||||
if (!throwExpr)
|
if (!throwExpr)
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterExpression())
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
return handler.newThrowStatement(throwExpr, TokenPos(begin, pos().end));
|
return handler.newThrowStatement(throwExpr, TokenPos(begin, pos().end));
|
||||||
|
@ -6477,7 +6500,7 @@ Parser<ParseHandler>::debuggerStatement()
|
||||||
{
|
{
|
||||||
TokenPos p;
|
TokenPos p;
|
||||||
p.begin = pos().begin;
|
p.begin = pos().begin;
|
||||||
if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterNonExpression())
|
||||||
return null();
|
return null();
|
||||||
p.end = pos().end;
|
p.end = pos().end;
|
||||||
|
|
||||||
|
@ -6784,7 +6807,7 @@ Parser<ParseHandler>::variableStatement(YieldHandling yieldHandling)
|
||||||
Node vars = declarationList(yieldHandling, PNK_VAR);
|
Node vars = declarationList(yieldHandling, PNK_VAR);
|
||||||
if (!vars)
|
if (!vars)
|
||||||
return null();
|
return null();
|
||||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
if (!matchOrInsertSemicolonAfterExpression())
|
||||||
return null();
|
return null();
|
||||||
return vars;
|
return vars;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1354,6 +1354,10 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
||||||
bool finishFunction();
|
bool finishFunction();
|
||||||
bool leaveInnerFunction(ParseContext* outerpc);
|
bool leaveInnerFunction(ParseContext* outerpc);
|
||||||
|
|
||||||
|
bool matchOrInsertSemicolonHelper(TokenStream::Modifier modifier);
|
||||||
|
bool matchOrInsertSemicolonAfterExpression();
|
||||||
|
bool matchOrInsertSemicolonAfterNonExpression();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum FunctionCallBehavior {
|
enum FunctionCallBehavior {
|
||||||
PermitAssignmentToFunctionCalls,
|
PermitAssignmentToFunctionCalls,
|
||||||
|
|
|
@ -186,6 +186,7 @@ MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'as'
|
||||||
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
|
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
|
||||||
MSG_DEF(JSMSG_ASYNC_GENERATOR, 0, JSEXN_SYNTAXERR, "generator function or method can't be async")
|
MSG_DEF(JSMSG_ASYNC_GENERATOR, 0, JSEXN_SYNTAXERR, "generator function or method can't be async")
|
||||||
MSG_DEF(JSMSG_AWAIT_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "await can't be used in default expression")
|
MSG_DEF(JSMSG_AWAIT_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "await can't be used in default expression")
|
||||||
|
MSG_DEF(JSMSG_AWAIT_OUTSIDE_ASYNC, 0, JSEXN_SYNTAXERR, "await is only valid in async functions")
|
||||||
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
|
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
|
||||||
MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
|
MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
|
||||||
MSG_DEF(JSMSG_BAD_CONST_DECL, 0, JSEXN_SYNTAXERR, "missing = in const declaration")
|
MSG_DEF(JSMSG_BAD_CONST_DECL, 0, JSEXN_SYNTAXERR, "missing = in const declaration")
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
var BUGNUMBER = 1317153;
|
||||||
|
var summary = "await outside of async function should provide better error";
|
||||||
|
|
||||||
|
print(BUGNUMBER + ": " + summary);
|
||||||
|
|
||||||
|
let caught = false;
|
||||||
|
try {
|
||||||
|
eval("await 10");
|
||||||
|
} catch(e) {
|
||||||
|
assertEq(e.message, "await is only valid in async functions");
|
||||||
|
caught = true;
|
||||||
|
}
|
||||||
|
assertEq(caught, true);
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(true, true);
|
Loading…
Reference in New Issue