Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1015)

Unified Diff: src/parsing/preparser.cc

Issue 1871923003: Add parsing for ambient declarations (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@types-devel
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/parsing/preparser.cc
diff --git a/src/parsing/preparser.cc b/src/parsing/preparser.cc
index 526e45e31dc0266bcbc22d7f4e8548eefc172043..d73a2fc383c3d5d5c06e5676c547fa036474f2fd 100644
--- a/src/parsing/preparser.cc
+++ b/src/parsing/preparser.cc
@@ -140,9 +140,9 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
PreParserExpression PreParserTraits::ParseClassLiteral(
PreParserIdentifier name, Scanner::Location class_name_location,
- bool name_is_strict_reserved, int pos, bool* ok) {
- return pre_parser_->ParseClassLiteral(name, class_name_location,
- name_is_strict_reserved, pos, ok);
+ bool name_is_strict_reserved, int pos, bool ambient, bool* ok) {
+ return pre_parser_->ParseClassLiteral(
+ name, class_name_location, name_is_strict_reserved, pos, ambient, ok);
}
@@ -160,7 +160,8 @@ PreParserExpression PreParserTraits::ParseClassLiteral(
// it is used) are generally omitted.
-PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
+PreParser::Statement PreParser::ParseStatementListItem(bool top_level,
+ bool* ok) {
// ECMA 262 6th Edition
// StatementListItem[Yield, Return] :
// Statement[?Yield, ?Return]
@@ -178,24 +179,34 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
// LexicalDeclaration[In, Yield] :
// LetOrConst BindingList[?In, ?Yield] ;
+ // Allow ambient variable, function, and class declarations.
+ bool ambient =
+ scope_->typed() && CheckContextualKeyword(CStrVector("declare"));
+ if (ambient && !top_level) {
+ *ok = false;
+ ReportMessage(MessageTemplate::kIllegalDeclare);
+ return Statement::Default();
+ }
switch (peek()) {
case Token::FUNCTION:
- return ParseFunctionDeclaration(ok);
+ return ParseFunctionDeclaration(ambient, ok);
case Token::CLASS:
- return ParseClassDeclaration(ok);
+ return ParseClassDeclaration(ambient, ok);
case Token::CONST:
if (allow_const()) {
- return ParseVariableStatement(kStatementListItem, ok);
+ return ParseVariableStatement(kStatementListItem, ambient, ok);
}
break;
+ case Token::VAR:
+ return ParseVariableStatement(kStatementListItem, ambient, ok);
case Token::LET:
if (IsNextLetKeyword()) {
- return ParseVariableStatement(kStatementListItem, ok);
+ return ParseVariableStatement(kStatementListItem, ambient, ok);
}
break;
case Token::IDENTIFIER:
case Token::FUTURE_STRICT_RESERVED_WORD: {
- if (!scope_->typed()) break;
+ if (!scope_->typed() || ambient) break;
int pos = peek_position();
if (CheckContextualKeyword(CStrVector("type"))) {
return ParseTypeAliasDeclaration(pos, ok);
@@ -204,15 +215,20 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
}
break;
}
- // TODO(nikolaos): ambient
default:
break;
}
+ if (ambient) {
+ *ok = false;
+ ReportMessageAt(scanner()->peek_location(),
+ MessageTemplate::kBadAmbientDeclaration);
+ return Statement::Default();
+ }
return ParseStatement(kAllowLabelledFunctionStatement, ok);
}
-void PreParser::ParseStatementList(int end_token, bool* ok,
+void PreParser::ParseStatementList(int end_token, bool top_level, bool* ok,
Scanner::BookmarkScope* bookmark) {
// SourceElements ::
// (Statement)* <end_token>
@@ -229,7 +245,7 @@ void PreParser::ParseStatementList(int end_token, bool* ok,
}
bool starts_with_identifier = peek() == Token::IDENTIFIER;
Scanner::Location token_loc = scanner()->peek_location();
- Statement statement = ParseStatementListItem(ok);
+ Statement statement = ParseStatementListItem(top_level, ok);
if (!*ok) return;
if (directive_prologue) {
@@ -308,7 +324,7 @@ PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) {
(legacy && allow_harmony_restrictive_declarations())) {
return ParseSubStatement(kDisallowLabelledFunctionStatement, ok);
} else {
- return ParseFunctionDeclaration(CHECK_OK);
+ return ParseFunctionDeclaration(false, CHECK_OK);
}
}
@@ -397,7 +413,7 @@ PreParser::Statement PreParser::ParseSubStatement(
return ParseDebuggerStatement(ok);
case Token::VAR:
- return ParseVariableStatement(kStatement, ok);
+ return ParseVariableStatement(kStatement, false, ok);
default:
return ParseExpressionOrLabelledStatement(allow_function, ok);
@@ -405,7 +421,8 @@ PreParser::Statement PreParser::ParseSubStatement(
}
-PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
+PreParser::Statement PreParser::ParseFunctionDeclaration(bool ambient,
+ bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
// GeneratorDeclaration ::
@@ -417,18 +434,20 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
+ typesystem::TypeFlags type_flags =
+ ambient ? typesystem::kAmbient : typesystem::kAllowSignature;
ParseFunctionLiteral(name, scanner()->location(),
is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
is_generator ? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction,
pos, FunctionLiteral::kDeclaration, language_mode(),
- typesystem::kAllowSignature, CHECK_OK);
+ type_flags, CHECK_OK);
return Statement::FunctionDeclaration();
}
-PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
+PreParser::Statement PreParser::ParseClassDeclaration(bool ambient, bool* ok) {
Expect(Token::CLASS, CHECK_OK);
if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
ReportMessage(MessageTemplate::kSloppyLexical);
@@ -441,7 +460,7 @@ PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
Identifier name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
- CHECK_OK);
+ ambient, CHECK_OK);
return Statement::Default();
}
@@ -453,7 +472,7 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
Expect(Token::LBRACE, CHECK_OK);
Statement final = Statement::Default();
while (peek() != Token::RBRACE) {
- final = ParseStatementListItem(CHECK_OK);
+ final = ParseStatementListItem(false, CHECK_OK);
}
Expect(Token::RBRACE, ok);
return final;
@@ -461,13 +480,13 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
PreParser::Statement PreParser::ParseVariableStatement(
- VariableDeclarationContext var_context,
- bool* ok) {
+ VariableDeclarationContext var_context, bool ambient, bool* ok) {
// VariableStatement ::
// VariableDeclarations ';'
- Statement result = ParseVariableDeclarations(
- var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK);
+ Statement result =
+ ParseVariableDeclarations(var_context, nullptr, nullptr, nullptr, nullptr,
+ nullptr, ambient, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return result;
}
@@ -481,7 +500,7 @@ PreParser::Statement PreParser::ParseVariableStatement(
PreParser::Statement PreParser::ParseVariableDeclarations(
VariableDeclarationContext var_context, int* num_decl, bool* is_lexical,
bool* is_binding_pattern, Scanner::Location* first_initializer_loc,
- Scanner::Location* bindings_loc, bool* ok) {
+ Scanner::Location* bindings_loc, bool ambient, bool* ok) {
// VariableDeclarations ::
// ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
//
@@ -554,6 +573,12 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
ParseValidType(CHECK_OK);
}
+ // Skip initializers, for ambient declarations.
rossberg 2016/04/20 15:16:35 Nit: maybe don't say "skip initializers", but "no
nickie 2016/04/21 13:57:10 Done.
+ if (ambient) {
+ nvars++;
+ continue;
+ }
+
Scanner::Location variable_loc = scanner()->location();
nvars++;
if (Check(Token::ASSIGN)) {
@@ -625,7 +650,7 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
// ES#sec-labelled-function-declarations Labelled Function Declarations
if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
if (allow_function == kAllowLabelledFunctionStatement) {
- return ParseFunctionDeclaration(ok);
+ return ParseFunctionDeclaration(false, ok);
} else {
return ParseScopedStatement(true, ok);
}
@@ -779,7 +804,7 @@ PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
while (token != Token::CASE &&
token != Token::DEFAULT &&
token != Token::RBRACE) {
- statement = ParseStatementListItem(CHECK_OK);
+ statement = ParseStatementListItem(false, CHECK_OK);
token = peek();
}
}
@@ -834,7 +859,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
Scanner::Location bindings_loc = Scanner::Location::invalid();
ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical,
&is_binding_pattern, &first_initializer_loc,
- &bindings_loc, CHECK_OK);
+ &bindings_loc, false, CHECK_OK);
if (CheckInOrOf(&mode, ok)) {
if (!*ok) return Statement::Default();
if (decl_count != 1) {
@@ -1055,15 +1080,16 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
parenthesized_function_ = false;
// Parse optional type annotation.
- if (scope_->typed() &&
- !(type_flags & typesystem::kDisallowTypeAnnotation) &&
+ if (scope_->typed() && !(type_flags & typesystem::kDisallowTypeAnnotation) &&
Check(Token::COLON)) { // Braces required here.
ParseValidType(CHECK_OK);
}
- // Allow for a function signature (i.e., a literal without body).
- if (peek() != Token::LBRACE && scope_->typed() &&
- (type_flags & typesystem::kAllowSignature)) {
+ // Allow or even enforce a function signature (i.e., literal without body),
+ // In that case, return a nullptr instead of a function literal.
+ if ((type_flags & typesystem::kDisallowBody) ||
+ (peek() != Token::LBRACE && scope_->typed() &&
+ (type_flags & typesystem::kAllowSignature))) {
ExpectSemicolon(CHECK_OK);
return this->EmptyExpression();
}
@@ -1072,7 +1098,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
if (is_lazily_parsed) {
ParseLazyFunctionLiteralBody(CHECK_OK);
} else {
- ParseStatementList(Token::RBRACE, CHECK_OK);
+ ParseStatementList(Token::RBRACE, false, CHECK_OK);
}
Expect(Token::RBRACE, CHECK_OK);
@@ -1100,7 +1126,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
Scanner::BookmarkScope* bookmark) {
int body_start = position();
- ParseStatementList(Token::RBRACE, ok, bookmark);
+ ParseStatementList(Token::RBRACE, false, ok, bookmark);
if (!*ok) return;
if (bookmark && bookmark->HasBeenReset()) return;
@@ -1116,7 +1142,7 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
PreParserExpression PreParser::ParseClassLiteral(
PreParserIdentifier name, Scanner::Location class_name_location,
- bool name_is_strict_reserved, int pos, bool* ok) {
+ bool name_is_strict_reserved, int pos, bool ambient, bool* ok) {
// All parts of a ClassDeclaration and ClassExpression are strict code.
if (name_is_strict_reserved) {
ReportMessageAt(class_name_location,
@@ -1172,7 +1198,7 @@ PreParserExpression PreParser::ParseClassLiteral(
ExpressionClassifier classifier(this);
ParsePropertyDefinition(&checker, in_class, has_extends, is_static,
&is_computed_name, &has_seen_constructor,
- &classifier, &name, CHECK_OK);
+ &classifier, &name, ambient, CHECK_OK);
ValidateExpression(&classifier, CHECK_OK);
}
@@ -1212,7 +1238,7 @@ PreParserExpression PreParser::ParseDoExpression(bool* ok) {
{
BlockState block_state(&scope_, block_scope);
while (peek() != Token::RBRACE) {
- ParseStatementListItem(CHECK_OK);
+ ParseStatementListItem(false, CHECK_OK);
}
Expect(Token::RBRACE, CHECK_OK);
return PreParserExpression::Default();

Powered by Google App Engine
This is Rietveld 408576698