Chromium Code Reviews| 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); |
| } |