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

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: Minor fixes to address code review comments 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
« no previous file with comments | « src/parsing/preparser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/preparser.cc
diff --git a/src/parsing/preparser.cc b/src/parsing/preparser.cc
index 526e45e31dc0266bcbc22d7f4e8548eefc172043..7611173e2a2dd4a65a5da9ac24b13a02c295d4bb 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);
}
@@ -178,24 +178,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 && !scope_->is_toplevel_scope()) {
+ *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,10 +214,15 @@ 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);
}
@@ -308,7 +323,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 +412,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 +420,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 +433,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 +459,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();
}
@@ -450,10 +468,14 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
// Block ::
// '{' StatementList '}'
+ Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
nickie 2016/04/21 13:59:10 The changes in this method are repeated in https:/
Expect(Token::LBRACE, CHECK_OK);
Statement final = Statement::Default();
- while (peek() != Token::RBRACE) {
- final = ParseStatementListItem(CHECK_OK);
+ {
+ BlockState block_state(&scope_, block_scope);
+ while (peek() != Token::RBRACE) {
+ final = ParseStatementListItem(CHECK_OK);
+ }
}
Expect(Token::RBRACE, ok);
return final;
@@ -461,13 +483,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 +503,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 +576,12 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
ParseValidType(CHECK_OK);
}
+ // Initializers are not allowed in ambient declarations.
+ if (ambient) {
+ nvars++;
+ continue;
+ }
+
Scanner::Location variable_loc = scanner()->location();
nvars++;
if (Check(Token::ASSIGN)) {
@@ -625,7 +653,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);
}
@@ -834,7 +862,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 +1083,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();
}
@@ -1116,7 +1145,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 +1201,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);
}
« no previous file with comments | « src/parsing/preparser.h ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698