Skip to content

Commit 469795b

Browse files
Throw ERRBadAwait instead of ERRnoSemic if applicable (chakra-core#6955)
* Throw `ERRBadAwait` instead of `ERRnoSemic` if applicable
1 parent 2f15d4e commit 469795b

File tree

4 files changed

+32
-14
lines changed

4 files changed

+32
-14
lines changed

lib/Parser/Parse.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -5483,7 +5483,7 @@ ParseNodeFnc * Parser::ParseFncDeclInternal(ushort flags, LPCOLESTR pNameHint, c
54835483
{
54845484
// Class member methods have optional separators. We need to check whether we are
54855485
// getting the IchLim of the correct token.
5486-
Assert(this->GetScanner()->m_tkPrevious == tkRCurly && needScanRCurly);
5486+
Assert(this->GetScanner()->GetPrevious() == tkRCurly && needScanRCurly);
54875487

54885488
this->m_funcInArray += this->GetScanner()->IchMinTok() - /*tkRCurly*/ 1 - ichMin;
54895489
}
@@ -6529,7 +6529,7 @@ bool Parser::FastScanFormalsAndBody()
65296529
{
65306530
int opl;
65316531
OpCode nop;
6532-
tokens tkPrev = this->GetScanner()->m_tkPrevious;
6532+
tokens tkPrev = this->GetScanner()->GetPrevious();
65336533
if ((this->GetHashTbl()->TokIsBinop(tkPrev, &opl, &nop) && nop != knopNone) ||
65346534
(this->GetHashTbl()->TokIsUnop(tkPrev, &opl, &nop) &&
65356535
nop != knopNone &&
@@ -11267,6 +11267,12 @@ ParseNodePtr Parser::ParseStatement()
1126711267
default:
1126811268
if (!this->GetScanner()->FHadNewLine())
1126911269
{
11270+
Token previous = this->GetScanner()->GetPreviousToken();
11271+
if (tkID == previous.tk && wellKnownPropertyPids.await == previous.GetIdentifier(this->GetHashTbl()))
11272+
{
11273+
Error(ERRBadAwait);
11274+
}
11275+
1127011276
Error(ERRnoSemic);
1127111277
}
1127211278
else

lib/Parser/Scan.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#include "ParserPch.h"
@@ -1592,7 +1593,7 @@ tokens Scanner<EncodingPolicy>::ScanCore(bool identifyKwds)
15921593
bool seenDelimitedCommentEnd = false;
15931594

15941595
// store the last token
1595-
m_tkPrevious = m_ptoken->tk;
1596+
m_tokenPrevious = *m_ptoken;
15961597
m_iecpLimTokPrevious = IecpLimTok(); // Introduced for use by lambda parsing to find correct span of expression lambdas
15971598
m_ichLimTokPrevious = IchLimTok();
15981599
size_t savedMultiUnits = this->m_cMultiUnits;

lib/Parser/Scan.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#pragma once
@@ -705,7 +706,8 @@ class Scanner : public IScanner, public EncodingPolicy
705706
}
706707
};
707708

708-
tokens GetPrevious() { return m_tkPrevious; }
709+
tokens GetPrevious() { return m_tokenPrevious.tk; }
710+
Token GetPreviousToken() { return m_tokenPrevious; }
709711
void Capture(_Out_ RestorePoint* restorePoint);
710712
void SeekTo(const RestorePoint& restorePoint);
711713
void SeekToForcingPid(const RestorePoint& restorePoint);
@@ -756,7 +758,7 @@ class Scanner : public IScanner, public EncodingPolicy
756758
Js::ScriptContext* m_scriptContext;
757759
const Js::CharClassifier *charClassifier;
758760

759-
tokens m_tkPrevious;
761+
Token m_tokenPrevious;
760762
size_t m_iecpLimTokPrevious;
761763
charcount_t m_ichLimTokPrevious;
762764

test/es7/asyncawait-syntax.js

+18-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56

@@ -58,26 +59,26 @@ var tests = [
5859
{
5960
name: "Await in eval global scope",
6061
body: function () {
61-
assert.throws(function () { eval("var result = await call();"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
62-
assert.throws(function () { eval("await call();"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
62+
assert.throws(function () { eval("var result = await call();"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", `'await' expression not allowed in this context`);
63+
assert.throws(function () { eval("await call();"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", `'await' expression not allowed in this context`);
6364

64-
assert.throws(function () { eval("await a;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
65-
assert.throws(function () { eval("await a[0];"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
66-
assert.throws(function () { eval("await o.p;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
65+
assert.throws(function () { eval("await a;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", `'await' expression not allowed in this context`);
66+
assert.throws(function () { eval("await a[0];"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", `'await' expression not allowed in this context`);
67+
assert.throws(function () { eval("await o.p;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", `'await' expression not allowed in this context`);
6768
assert.throws(function () { eval("a[await p];"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ']'");
68-
assert.throws(function () { eval("a + await p;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
69-
assert.throws(function () { eval("await p + await q;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ';'");
69+
assert.throws(function () { eval("a + await p;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", `'await' expression not allowed in this context`);
70+
assert.throws(function () { eval("await p + await q;"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", `'await' expression not allowed in this context`);
7071
assert.throws(function () { eval("foo(await p, await q);"); }, SyntaxError, "'await' keyword is not allowed in eval global scope", "Expected ')'");
7172

7273
assert.throws(function () { eval("var lambdaParenNoArg = await () => x < y;"); }, SyntaxError, "'await' keyword is not allowed with a non-async lambda expression", "Syntax error");
73-
assert.throws(function () { eval("var lambdaArgs = await async (a, b ,c) => a + b + c;"); }, SyntaxError, "There miss parenthises", "Expected ';'");
74+
assert.throws(function () { eval("var lambdaArgs = await async (a, b ,c) => a + b + c;"); }, SyntaxError, "There miss parenthises", `'await' expression not allowed in this context`);
7475
assert.throws(function () { eval("var lambdaArgs = await (async (a, b ,c) => a + b + c);"); }, ReferenceError, "The 'await' function doesn't exists in this scope", "'await' is not defined");
7576
}
7677
},
7778
{
7879
name: "Await in a non-async function",
7980
body: function () {
80-
assert.throws(function () { eval("function method() { var x = await call(); }"); }, SyntaxError, "'await' cannot be used in a non-async function.", "Expected ';'");
81+
assert.throws(function () { eval("function method() { var x = await call(); }"); }, SyntaxError, "'await' cannot be used in a non-async function.", `'await' expression not allowed in this context`);
8182
}
8283
},
8384
{
@@ -216,6 +217,14 @@ var tests = [
216217
assert.throws(function () { eval("async function af() { (b = (c = await => {}) => {}) => {}; }"); }, SyntaxError, "await cannot appear as the formal name of an unparathensized arrow function in a nested case too", "Unexpected token '=>' after 'await'");
217218
}
218219
},
220+
{
221+
name: "Specific error message when using 'await' as a keyword outside 'async' context",
222+
body: function () {
223+
assert.throws(function () {
224+
eval(`await new Promise(() => {});`);
225+
}, SyntaxError, "await is not a keyword here", `'await' expression not allowed in this context`);
226+
}
227+
}
219228
];
220229

221230
testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });

0 commit comments

Comments
 (0)