Commit e1c6fa88 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Token-range-check for callable identifier tokens

This also fixes the tokens that are identified as called identifiers.

Change-Id: I4a2179b98214f9018c8c07c0ab27f878cdae13cf
Bug: v8:6513
Reviewed-on: https://chromium-review.googlesource.com/c/1286338Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56719}
parent e19dc9f6
......@@ -3245,9 +3245,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result, bool* ok) {
case Token::LPAREN: {
int pos;
if (scanner()->current_token() == Token::IDENTIFIER ||
scanner()->current_token() == Token::SUPER ||
scanner()->current_token() == Token::ASYNC) {
if (Token::IsCallable(scanner()->current_token())) {
// For call of an identifier we want to report position of
// the identifier as position of the call in the stack trace.
pos = position();
......
......@@ -155,6 +155,8 @@ namespace internal {
T(BIGINT, nullptr, 0) \
T(STRING, nullptr, 0) \
\
/* BEGIN Callable */ \
K(SUPER, "super", 0) \
/* BEGIN AnyIdentifier */ \
/* Identifiers (not keywords or future reserved words). */ \
T(IDENTIFIER, nullptr, 0) \
......@@ -168,13 +170,13 @@ namespace internal {
T(FUTURE_STRICT_RESERVED_WORD, nullptr, 0) \
T(ESCAPED_STRICT_RESERVED_WORD, nullptr, 0) \
K(ENUM, "enum", 0) \
/* END Callable */ \
/* END AnyIdentifier */ \
K(CLASS, "class", 0) \
K(CONST, "const", 0) \
K(EXPORT, "export", 0) \
K(EXTENDS, "extends", 0) \
K(IMPORT, "import", 0) \
K(SUPER, "super", 0) \
T(PRIVATE_NAME, nullptr, 0) \
\
/* Illegal token - not able to scan. */ \
......@@ -237,6 +239,8 @@ class Token {
return false;
}
static bool IsCallable(Value token) { return IsInRange(token, SUPER, ENUM); }
static bool IsAnyIdentifier(Value token) {
return IsInRange(token, IDENTIFIER, ENUM);
}
......@@ -287,10 +291,6 @@ class Token {
static bool IsShiftOp(Value op) { return IsInRange(op, SHL, SHR); }
static bool IsTrivialExpressionToken(Value op) {
return IsInRange(op, THIS, IDENTIFIER);
}
// Returns a string corresponding to the JS token string
// (.e., "<" for the token LT) or nullptr if the token doesn't
// have a (unique) string (e.g. an IDENTIFIER).
......
......@@ -103,6 +103,31 @@ TEST(AnyIdentifierToken) {
}
}
bool TokenIsCallable(Token::Value token) {
switch (token) {
case Token::SUPER:
case Token::IDENTIFIER:
case Token::ASYNC:
case Token::AWAIT:
case Token::YIELD:
case Token::LET:
case Token::STATIC:
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::ESCAPED_STRICT_RESERVED_WORD:
case Token::ENUM:
return true;
default:
return false;
}
}
TEST(CallableToken) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsCallable(token), Token::IsCallable(token));
}
}
bool TokenIsIdentifier(Token::Value token, LanguageMode language_mode,
bool is_generator, bool disallow_await) {
switch (token) {
......@@ -386,31 +411,6 @@ TEST(IsShiftOp) {
}
}
bool TokenIsTrivialExpressionToken(Token::Value token) {
switch (token) {
case Token::SMI:
case Token::NUMBER:
case Token::BIGINT:
case Token::NULL_LITERAL:
case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL:
case Token::STRING:
case Token::IDENTIFIER:
case Token::THIS:
return true;
default:
return false;
}
}
TEST(IsTrivialExpressionToken) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsTrivialExpressionToken(token),
Token::IsTrivialExpressionToken(token));
}
}
TEST(ScanKeywords) {
struct KeywordToken {
const char* keyword;
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function f(async) {
async()
}
f()
*%(basename)s:6: TypeError: async is not a function
async()
^
TypeError: async is not a function
at f (*%(basename)s:6:3)
at *%(basename)s:8:1
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function f(await) {
await()
}
f()
*%(basename)s:6: TypeError: await is not a function
await()
^
TypeError: await is not a function
at f (*%(basename)s:6:3)
at *%(basename)s:8:1
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function f(let) {
let()
}
f()
*%(basename)s:6: TypeError: let is not a function
let()
^
TypeError: let is not a function
at f (*%(basename)s:6:3)
at *%(basename)s:8:1
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function f(static) {
static()
}
f()
*%(basename)s:6: TypeError: static is not a function
static()
^
TypeError: static is not a function
at f (*%(basename)s:6:3)
at *%(basename)s:8:1
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function f(yield) {
yield()
}
f()
*%(basename)s:6: TypeError: yield is not a function
yield()
^
TypeError: yield is not a function
at f (*%(basename)s:6:3)
at *%(basename)s:8:1
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment