Classes: static should still be treated as a strict reserved word
When --harmony-classes is enabled we did not treat static as a strict reserved word. BUG=v8:3642 LOG=Y R=rossberg@chromium.org Review URL: https://codereview.chromium.org/652743009 Cr-Commit-Position: refs/heads/master@{#25087} git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25087 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e525e76f21
commit
7a63c74caf
@ -853,8 +853,7 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
|
||||
bool ParserTraits::IsFutureStrictReserved(
|
||||
const AstRawString* identifier) const {
|
||||
return identifier->IsOneByteEqualTo("yield") ||
|
||||
parser_->scanner()->IdentifierIsFutureStrictReserved(identifier);
|
||||
return parser_->scanner()->IdentifierIsFutureStrictReserved(identifier);
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,6 +50,8 @@ PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
|
||||
return PreParserIdentifier::FutureStrictReserved();
|
||||
} else if (scanner->current_token() == Token::LET) {
|
||||
return PreParserIdentifier::Let();
|
||||
} else if (scanner->current_token() == Token::STATIC) {
|
||||
return PreParserIdentifier::Static();
|
||||
} else if (scanner->current_token() == Token::YIELD) {
|
||||
return PreParserIdentifier::Yield();
|
||||
}
|
||||
@ -491,8 +493,7 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
|
||||
// identifier.
|
||||
DCHECK(!expr.AsIdentifier().IsFutureReserved());
|
||||
DCHECK(strict_mode() == SLOPPY ||
|
||||
(!expr.AsIdentifier().IsFutureStrictReserved() &&
|
||||
!expr.AsIdentifier().IsYield()));
|
||||
!IsFutureStrictReserved(expr.AsIdentifier()));
|
||||
Consume(Token::COLON);
|
||||
return ParseStatement(ok);
|
||||
// Preparsing is disabled for extensions (because the extension details
|
||||
|
@ -336,11 +336,9 @@ class ParserBase : public Traits {
|
||||
|
||||
bool peek_any_identifier() {
|
||||
Token::Value next = peek();
|
||||
return next == Token::IDENTIFIER ||
|
||||
next == Token::FUTURE_RESERVED_WORD ||
|
||||
next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
||||
next == Token::LET ||
|
||||
next == Token::YIELD;
|
||||
return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD ||
|
||||
next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
|
||||
next == Token::STATIC || next == Token::YIELD;
|
||||
}
|
||||
|
||||
bool CheckContextualKeyword(Vector<const char> keyword) {
|
||||
@ -606,6 +604,9 @@ class PreParserIdentifier {
|
||||
static PreParserIdentifier Let() {
|
||||
return PreParserIdentifier(kLetIdentifier);
|
||||
}
|
||||
static PreParserIdentifier Static() {
|
||||
return PreParserIdentifier(kStaticIdentifier);
|
||||
}
|
||||
static PreParserIdentifier Yield() {
|
||||
return PreParserIdentifier(kYieldIdentifier);
|
||||
}
|
||||
@ -619,6 +620,8 @@ class PreParserIdentifier {
|
||||
bool IsArguments(const AstValueFactory* = NULL) const {
|
||||
return type_ == kArgumentsIdentifier;
|
||||
}
|
||||
bool IsLet() const { return type_ == kLetIdentifier; }
|
||||
bool IsStatic() const { return type_ == kStaticIdentifier; }
|
||||
bool IsYield() const { return type_ == kYieldIdentifier; }
|
||||
bool IsPrototype() const { return type_ == kPrototypeIdentifier; }
|
||||
bool IsConstructor() const { return type_ == kConstructorIdentifier; }
|
||||
@ -627,14 +630,15 @@ class PreParserIdentifier {
|
||||
}
|
||||
bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; }
|
||||
bool IsFutureStrictReserved() const {
|
||||
return type_ == kFutureStrictReservedIdentifier;
|
||||
return type_ == kFutureStrictReservedIdentifier ||
|
||||
type_ == kLetIdentifier || type_ == kStaticIdentifier ||
|
||||
type_ == kYieldIdentifier;
|
||||
}
|
||||
bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; }
|
||||
V8_INLINE bool IsValidArrowParam() const {
|
||||
// A valid identifier can be an arrow function parameter
|
||||
// except for eval, arguments, yield, and reserved keywords.
|
||||
return !(IsEval() || IsArguments() || IsYield() ||
|
||||
IsFutureStrictReserved());
|
||||
return !(IsEval() || IsArguments() || IsFutureStrictReserved());
|
||||
}
|
||||
|
||||
// Allow identifier->name()[->length()] to work. The preparser
|
||||
@ -651,6 +655,7 @@ class PreParserIdentifier {
|
||||
kFutureReservedIdentifier,
|
||||
kFutureStrictReservedIdentifier,
|
||||
kLetIdentifier,
|
||||
kStaticIdentifier,
|
||||
kYieldIdentifier,
|
||||
kEvalIdentifier,
|
||||
kArgumentsIdentifier,
|
||||
@ -1172,7 +1177,7 @@ class PreParserTraits {
|
||||
}
|
||||
|
||||
static bool IsFutureStrictReserved(PreParserIdentifier identifier) {
|
||||
return identifier.IsYield() || identifier.IsFutureStrictReserved();
|
||||
return identifier.IsFutureStrictReserved();
|
||||
}
|
||||
|
||||
static bool IsBoilerplateProperty(PreParserExpression property) {
|
||||
@ -1593,6 +1598,7 @@ void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) {
|
||||
case Token::FUTURE_RESERVED_WORD:
|
||||
return ReportMessageAt(source_location, "unexpected_reserved");
|
||||
case Token::LET:
|
||||
case Token::STATIC:
|
||||
case Token::YIELD:
|
||||
case Token::FUTURE_STRICT_RESERVED_WORD:
|
||||
return ReportMessageAt(source_location, strict_mode() == SLOPPY
|
||||
@ -1622,8 +1628,8 @@ typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier(
|
||||
return name;
|
||||
} else if (strict_mode() == SLOPPY &&
|
||||
(next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
||||
(next == Token::LET) ||
|
||||
(next == Token::YIELD && !is_generator()))) {
|
||||
next == Token::LET || next == Token::STATIC ||
|
||||
(next == Token::YIELD && !is_generator()))) {
|
||||
return this->GetSymbol(scanner());
|
||||
} else {
|
||||
this->ReportUnexpectedToken(next);
|
||||
@ -1640,8 +1646,8 @@ typename ParserBase<Traits>::IdentifierT ParserBase<
|
||||
Token::Value next = Next();
|
||||
if (next == Token::IDENTIFIER) {
|
||||
*is_strict_reserved = false;
|
||||
} else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
||||
next == Token::LET ||
|
||||
} else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
|
||||
next == Token::STATIC ||
|
||||
(next == Token::YIELD && !this->is_generator())) {
|
||||
*is_strict_reserved = true;
|
||||
} else {
|
||||
@ -1662,7 +1668,7 @@ typename ParserBase<Traits>::IdentifierT
|
||||
ParserBase<Traits>::ParseIdentifierName(bool* ok) {
|
||||
Token::Value next = Next();
|
||||
if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD &&
|
||||
next != Token::LET && next != Token::YIELD &&
|
||||
next != Token::LET && next != Token::STATIC && next != Token::YIELD &&
|
||||
next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
|
||||
this->ReportUnexpectedToken(next);
|
||||
*ok = false;
|
||||
@ -1765,6 +1771,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
|
||||
|
||||
case Token::IDENTIFIER:
|
||||
case Token::LET:
|
||||
case Token::STATIC:
|
||||
case Token::YIELD:
|
||||
case Token::FUTURE_STRICT_RESERVED_WORD: {
|
||||
// Using eval or arguments in this context is OK even in strict mode.
|
||||
|
@ -1006,11 +1006,15 @@ static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
|
||||
bool Scanner::IdentifierIsFutureStrictReserved(
|
||||
const AstRawString* string) const {
|
||||
// Keywords are always 1-byte strings.
|
||||
return string->is_one_byte() &&
|
||||
Token::FUTURE_STRICT_RESERVED_WORD ==
|
||||
KeywordOrIdentifierToken(string->raw_data(), string->length(),
|
||||
harmony_scoping_, harmony_modules_,
|
||||
harmony_classes_);
|
||||
if (!string->is_one_byte()) return false;
|
||||
if (string->IsOneByteEqualTo("let") || string->IsOneByteEqualTo("static") ||
|
||||
string->IsOneByteEqualTo("yield")) {
|
||||
return true;
|
||||
}
|
||||
return Token::FUTURE_STRICT_RESERVED_WORD ==
|
||||
KeywordOrIdentifierToken(string->raw_data(), string->length(),
|
||||
harmony_scoping_, harmony_modules_,
|
||||
harmony_classes_);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1814,6 +1814,33 @@ TEST(NoErrorsEvalAndArgumentsStrict) {
|
||||
}
|
||||
|
||||
|
||||
#define FUTURE_STRICT_RESERVED_WORDS(V) \
|
||||
V(implements) \
|
||||
V(interface) \
|
||||
V(let) \
|
||||
V(package) \
|
||||
V(private) \
|
||||
V(protected) \
|
||||
V(public) \
|
||||
V(static) \
|
||||
V(yield)
|
||||
|
||||
|
||||
#define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
|
||||
"var " #NAME ";", \
|
||||
"var foo, " #NAME ";", \
|
||||
"try { } catch (" #NAME ") { }", \
|
||||
"function " #NAME "() { }", \
|
||||
"(function " #NAME "() { })", \
|
||||
"function foo(" #NAME ") { }", \
|
||||
"function foo(bar, " #NAME ") { }", \
|
||||
#NAME " = 1;", \
|
||||
#NAME " += 1;", \
|
||||
"var foo = " #NAME " = 1;", \
|
||||
"++" #NAME ";", \
|
||||
#NAME " ++;",
|
||||
|
||||
|
||||
TEST(ErrorsFutureStrictReservedWords) {
|
||||
// Tests that both preparsing and parsing produce the right kind of errors for
|
||||
// using future strict reserved words as identifiers. Without the strict mode,
|
||||
@ -1826,24 +1853,19 @@ TEST(ErrorsFutureStrictReservedWords) {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
const char* statement_data[] = {
|
||||
"var interface;",
|
||||
"var foo, interface;",
|
||||
"try { } catch (interface) { }",
|
||||
"function interface() { }",
|
||||
"function foo(interface) { }",
|
||||
"function foo(bar, interface) { }",
|
||||
"interface = 1;",
|
||||
"var foo = interface = 1;",
|
||||
"++interface;",
|
||||
"interface++;",
|
||||
"var yield = 13;",
|
||||
const char* statement_data[] {
|
||||
FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ParserFlag always_flags[] = {kAllowArrowFunctions};
|
||||
RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
|
||||
arraysize(always_flags));
|
||||
|
||||
static const ParserFlag classes_flags[] = {
|
||||
kAllowArrowFunctions, kAllowClasses, kAllowHarmonyScoping};
|
||||
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
|
||||
classes_flags, arraysize(classes_flags));
|
||||
}
|
||||
|
||||
|
||||
@ -1856,23 +1878,18 @@ TEST(NoErrorsFutureStrictReservedWords) {
|
||||
};
|
||||
|
||||
const char* statement_data[] = {
|
||||
"var interface;",
|
||||
"var foo, interface;",
|
||||
"try { } catch (interface) { }",
|
||||
"function interface() { }",
|
||||
"function foo(interface) { }",
|
||||
"function foo(bar, interface) { }",
|
||||
"interface = 1;",
|
||||
"var foo = interface = 1;",
|
||||
"++interface;",
|
||||
"interface++;",
|
||||
"var yield = 13;",
|
||||
FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ParserFlag always_flags[] = {kAllowArrowFunctions};
|
||||
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
|
||||
static const ParserFlag classes_flags[] = {
|
||||
kAllowArrowFunctions, kAllowClasses, kAllowHarmonyScoping};
|
||||
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
|
||||
classes_flags, arraysize(classes_flags));
|
||||
}
|
||||
|
||||
|
||||
@ -2252,12 +2269,13 @@ TEST(ErrorsIllegalWordsAsLabelsStrict) {
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
|
||||
const char* statement_data[] = {
|
||||
"super: while(true) { break super; }",
|
||||
"interface: while(true) { break interface; }",
|
||||
"yield: while(true) { break yield; }",
|
||||
FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
|
||||
NULL
|
||||
};
|
||||
#undef LABELLED_WHILE
|
||||
|
||||
RunParserSyncTest(context_data, statement_data, kError);
|
||||
}
|
||||
@ -2288,6 +2306,27 @@ TEST(NoErrorsIllegalWordsAsLabels) {
|
||||
}
|
||||
|
||||
|
||||
TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
|
||||
const char* context_data[][2] = {
|
||||
{ "", ""},
|
||||
{ "function test_func() {", "}" },
|
||||
{ "() => {", "}" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
|
||||
const char* statement_data[] {
|
||||
FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
|
||||
NULL
|
||||
};
|
||||
#undef LABELLED_WHILE
|
||||
|
||||
static const ParserFlag always_flags[] = {kAllowArrowFunctions};
|
||||
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
}
|
||||
|
||||
|
||||
TEST(ErrorsParenthesizedLabels) {
|
||||
// Parenthesized identifiers shouldn't be recognized as labels.
|
||||
const char* context_data[][2] = {
|
||||
|
Loading…
Reference in New Issue
Block a user