Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1 | // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include <cmath> |
| 6 | |
| 7 | #include "src/allocation.h" |
| 8 | #include "src/base/logging.h" |
| 9 | #include "src/conversions-inl.h" |
| 10 | #include "src/conversions.h" |
| 11 | #include "src/globals.h" |
| 12 | #include "src/hashmap.h" |
| 13 | #include "src/list.h" |
| 14 | #include "src/parsing/parser-base.h" |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 15 | #include "src/parsing/preparse-data-format.h" |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 16 | #include "src/parsing/preparse-data.h" |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 17 | #include "src/parsing/preparser.h" |
| 18 | #include "src/unicode.h" |
| 19 | #include "src/utils.h" |
| 20 | |
| 21 | namespace v8 { |
| 22 | namespace internal { |
| 23 | |
| 24 | void PreParserTraits::ReportMessageAt(Scanner::Location location, |
| 25 | MessageTemplate::Template message, |
| 26 | const char* arg, |
| 27 | ParseErrorType error_type) { |
| 28 | ReportMessageAt(location.beg_pos, location.end_pos, message, arg, error_type); |
| 29 | } |
| 30 | |
| 31 | |
| 32 | void PreParserTraits::ReportMessageAt(int start_pos, int end_pos, |
| 33 | MessageTemplate::Template message, |
| 34 | const char* arg, |
| 35 | ParseErrorType error_type) { |
| 36 | pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg, error_type); |
| 37 | } |
| 38 | |
| 39 | |
| 40 | PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) { |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 41 | if (scanner->current_token() == Token::ENUM) { |
| 42 | return PreParserIdentifier::Enum(); |
| 43 | } else if (scanner->current_token() == Token::AWAIT) { |
| 44 | return PreParserIdentifier::Await(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 45 | } else if (scanner->current_token() == |
| 46 | Token::FUTURE_STRICT_RESERVED_WORD) { |
| 47 | return PreParserIdentifier::FutureStrictReserved(); |
| 48 | } else if (scanner->current_token() == Token::LET) { |
| 49 | return PreParserIdentifier::Let(); |
| 50 | } else if (scanner->current_token() == Token::STATIC) { |
| 51 | return PreParserIdentifier::Static(); |
| 52 | } else if (scanner->current_token() == Token::YIELD) { |
| 53 | return PreParserIdentifier::Yield(); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 54 | } else if (scanner->current_token() == Token::ASYNC) { |
| 55 | return PreParserIdentifier::Async(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 56 | } |
| 57 | if (scanner->UnescapedLiteralMatches("eval", 4)) { |
| 58 | return PreParserIdentifier::Eval(); |
| 59 | } |
| 60 | if (scanner->UnescapedLiteralMatches("arguments", 9)) { |
| 61 | return PreParserIdentifier::Arguments(); |
| 62 | } |
| 63 | if (scanner->UnescapedLiteralMatches("undefined", 9)) { |
| 64 | return PreParserIdentifier::Undefined(); |
| 65 | } |
| 66 | if (scanner->LiteralMatches("prototype", 9)) { |
| 67 | return PreParserIdentifier::Prototype(); |
| 68 | } |
| 69 | if (scanner->LiteralMatches("constructor", 11)) { |
| 70 | return PreParserIdentifier::Constructor(); |
| 71 | } |
| 72 | return PreParserIdentifier::Default(); |
| 73 | } |
| 74 | |
| 75 | |
| 76 | PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) { |
| 77 | return PreParserIdentifier::Default(); |
| 78 | } |
| 79 | |
| 80 | |
| 81 | PreParserExpression PreParserTraits::ExpressionFromString( |
| 82 | int pos, Scanner* scanner, PreParserFactory* factory) { |
| 83 | if (scanner->UnescapedLiteralMatches("use strict", 10)) { |
| 84 | return PreParserExpression::UseStrictStringLiteral(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 85 | } |
| 86 | return PreParserExpression::StringLiteral(); |
| 87 | } |
| 88 | |
| 89 | |
| 90 | PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) { |
| 91 | return pre_parser_->ParseV8Intrinsic(ok); |
| 92 | } |
| 93 | |
| 94 | |
| 95 | PreParserExpression PreParserTraits::ParseFunctionLiteral( |
| 96 | PreParserIdentifier name, Scanner::Location function_name_location, |
| 97 | FunctionNameValidity function_name_validity, FunctionKind kind, |
| 98 | int function_token_position, FunctionLiteral::FunctionType type, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 99 | LanguageMode language_mode, bool* ok) { |
| 100 | return pre_parser_->ParseFunctionLiteral( |
| 101 | name, function_name_location, function_name_validity, kind, |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 102 | function_token_position, type, language_mode, ok); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 103 | } |
| 104 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 105 | PreParser::PreParseResult PreParser::PreParseLazyFunction( |
| 106 | LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters, |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 107 | bool parsing_module, ParserRecorder* log, Scanner::BookmarkScope* bookmark, |
| 108 | int* use_counts) { |
| 109 | parsing_module_ = parsing_module; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 110 | log_ = log; |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 111 | use_counts_ = use_counts; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 112 | // Lazy functions always have trivial outer scopes (no with/catch scopes). |
| 113 | Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE); |
| 114 | PreParserFactory top_factory(NULL); |
| 115 | FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction, |
| 116 | &top_factory); |
| 117 | scope_->SetLanguageMode(language_mode); |
| 118 | Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind); |
| 119 | if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters(); |
| 120 | PreParserFactory function_factory(NULL); |
| 121 | FunctionState function_state(&function_state_, &scope_, function_scope, kind, |
| 122 | &function_factory); |
| 123 | DCHECK_EQ(Token::LBRACE, scanner()->current_token()); |
| 124 | bool ok = true; |
| 125 | int start_position = peek_position(); |
| 126 | ParseLazyFunctionLiteralBody(&ok, bookmark); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 127 | use_counts_ = nullptr; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 128 | if (bookmark && bookmark->HasBeenReset()) { |
| 129 | // Do nothing, as we've just aborted scanning this function. |
| 130 | } else if (stack_overflow()) { |
| 131 | return kPreParseStackOverflow; |
| 132 | } else if (!ok) { |
| 133 | ReportUnexpectedToken(scanner()->current_token()); |
| 134 | } else { |
| 135 | DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
| 136 | if (is_strict(scope_->language_mode())) { |
| 137 | int end_pos = scanner()->location().end_pos; |
| 138 | CheckStrictOctalLiteral(start_position, end_pos, &ok); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 139 | CheckDecimalLiteralWithLeadingZero(use_counts, start_position, end_pos); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 140 | if (!ok) return kPreParseSuccess; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 141 | } |
| 142 | } |
| 143 | return kPreParseSuccess; |
| 144 | } |
| 145 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 146 | PreParserExpression PreParserTraits::ParseClassLiteral( |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 147 | Type::ExpressionClassifier* classifier, PreParserIdentifier name, |
| 148 | Scanner::Location class_name_location, bool name_is_strict_reserved, |
| 149 | int pos, bool* ok) { |
| 150 | return pre_parser_->ParseClassLiteral(classifier, name, class_name_location, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 151 | name_is_strict_reserved, pos, ok); |
| 152 | } |
| 153 | |
| 154 | |
| 155 | // Preparsing checks a JavaScript program and emits preparse-data that helps |
| 156 | // a later parsing to be faster. |
| 157 | // See preparser-data.h for the data. |
| 158 | |
| 159 | // The PreParser checks that the syntax follows the grammar for JavaScript, |
| 160 | // and collects some information about the program along the way. |
| 161 | // The grammar check is only performed in order to understand the program |
| 162 | // sufficiently to deduce some information about it, that can be used |
| 163 | // to speed up later parsing. Finding errors is not the goal of pre-parsing, |
| 164 | // rather it is to speed up properly written and correct programs. |
| 165 | // That means that contextual checks (like a label being declared where |
| 166 | // it is used) are generally omitted. |
| 167 | |
| 168 | |
| 169 | PreParser::Statement PreParser::ParseStatementListItem(bool* ok) { |
| 170 | // ECMA 262 6th Edition |
| 171 | // StatementListItem[Yield, Return] : |
| 172 | // Statement[?Yield, ?Return] |
| 173 | // Declaration[?Yield] |
| 174 | // |
| 175 | // Declaration[Yield] : |
| 176 | // HoistableDeclaration[?Yield] |
| 177 | // ClassDeclaration[?Yield] |
| 178 | // LexicalDeclaration[In, ?Yield] |
| 179 | // |
| 180 | // HoistableDeclaration[Yield, Default] : |
| 181 | // FunctionDeclaration[?Yield, ?Default] |
| 182 | // GeneratorDeclaration[?Yield, ?Default] |
| 183 | // |
| 184 | // LexicalDeclaration[In, Yield] : |
| 185 | // LetOrConst BindingList[?In, ?Yield] ; |
| 186 | |
| 187 | switch (peek()) { |
| 188 | case Token::FUNCTION: |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 189 | return ParseHoistableDeclaration(ok); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 190 | case Token::CLASS: |
| 191 | return ParseClassDeclaration(ok); |
| 192 | case Token::CONST: |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 193 | return ParseVariableStatement(kStatementListItem, ok); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 194 | case Token::LET: |
| 195 | if (IsNextLetKeyword()) { |
| 196 | return ParseVariableStatement(kStatementListItem, ok); |
| 197 | } |
| 198 | break; |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 199 | case Token::ASYNC: |
| 200 | if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && |
| 201 | !scanner()->HasAnyLineTerminatorAfterNext()) { |
| 202 | Consume(Token::ASYNC); |
| 203 | return ParseAsyncFunctionDeclaration(ok); |
| 204 | } |
| 205 | /* falls through */ |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 206 | default: |
| 207 | break; |
| 208 | } |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 209 | return ParseStatement(kAllowLabelledFunctionStatement, ok); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 210 | } |
| 211 | |
| 212 | |
| 213 | void PreParser::ParseStatementList(int end_token, bool* ok, |
| 214 | Scanner::BookmarkScope* bookmark) { |
| 215 | // SourceElements :: |
| 216 | // (Statement)* <end_token> |
| 217 | |
| 218 | // Bookkeeping for trial parse if bookmark is set: |
| 219 | DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet()); |
| 220 | bool maybe_reset = bookmark != nullptr; |
| 221 | int count_statements = 0; |
| 222 | |
| 223 | bool directive_prologue = true; |
| 224 | while (peek() != end_token) { |
| 225 | if (directive_prologue && peek() != Token::STRING) { |
| 226 | directive_prologue = false; |
| 227 | } |
| 228 | bool starts_with_identifier = peek() == Token::IDENTIFIER; |
| 229 | Scanner::Location token_loc = scanner()->peek_location(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 230 | Statement statement = ParseStatementListItem(ok); |
| 231 | if (!*ok) return; |
| 232 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 233 | if (directive_prologue) { |
| 234 | bool use_strict_found = statement.IsUseStrictLiteral(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 235 | |
| 236 | if (use_strict_found) { |
| 237 | scope_->SetLanguageMode( |
| 238 | static_cast<LanguageMode>(scope_->language_mode() | STRICT)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 239 | } else if (!statement.IsStringLiteral()) { |
| 240 | directive_prologue = false; |
| 241 | } |
| 242 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 243 | if (use_strict_found && !scope_->HasSimpleParameters()) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 244 | // TC39 deemed "use strict" directives to be an error when occurring |
| 245 | // in the body of a function with non-simple parameter list, on |
| 246 | // 29/7/2015. https://goo.gl/ueA7Ln |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 247 | PreParserTraits::ReportMessageAt( |
| 248 | token_loc, MessageTemplate::kIllegalLanguageModeDirective, |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 249 | "use strict"); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 250 | *ok = false; |
| 251 | return; |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | // If we're allowed to reset to a bookmark, we will do so when we see a long |
| 256 | // and trivial function. |
| 257 | // Our current definition of 'long and trivial' is: |
| 258 | // - over 200 statements |
| 259 | // - all starting with an identifier (i.e., no if, for, while, etc.) |
| 260 | if (maybe_reset && (!starts_with_identifier || |
| 261 | ++count_statements > kLazyParseTrialLimit)) { |
| 262 | if (count_statements > kLazyParseTrialLimit) { |
| 263 | bookmark->Reset(); |
| 264 | return; |
| 265 | } |
| 266 | maybe_reset = false; |
| 267 | } |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | |
| 272 | #define CHECK_OK ok); \ |
| 273 | if (!*ok) return Statement::Default(); \ |
| 274 | ((void)0 |
| 275 | #define DUMMY ) // to make indentation work |
| 276 | #undef DUMMY |
| 277 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 278 | PreParser::Statement PreParser::ParseStatement( |
| 279 | AllowLabelledFunctionStatement allow_function, bool* ok) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 280 | // Statement :: |
| 281 | // EmptyStatement |
| 282 | // ... |
| 283 | |
| 284 | if (peek() == Token::SEMICOLON) { |
| 285 | Next(); |
| 286 | return Statement::Default(); |
| 287 | } |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 288 | return ParseSubStatement(allow_function, ok); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 289 | } |
| 290 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 291 | PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) { |
| 292 | if (is_strict(language_mode()) || peek() != Token::FUNCTION || |
| 293 | (legacy && allow_harmony_restrictive_declarations())) { |
| 294 | return ParseSubStatement(kDisallowLabelledFunctionStatement, ok); |
| 295 | } else { |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 296 | Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); |
| 297 | BlockState block_state(&scope_, body_scope); |
| 298 | return ParseFunctionDeclaration(ok); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 299 | } |
| 300 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 301 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 302 | PreParser::Statement PreParser::ParseSubStatement( |
| 303 | AllowLabelledFunctionStatement allow_function, bool* ok) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 304 | // Statement :: |
| 305 | // Block |
| 306 | // VariableStatement |
| 307 | // EmptyStatement |
| 308 | // ExpressionStatement |
| 309 | // IfStatement |
| 310 | // IterationStatement |
| 311 | // ContinueStatement |
| 312 | // BreakStatement |
| 313 | // ReturnStatement |
| 314 | // WithStatement |
| 315 | // LabelledStatement |
| 316 | // SwitchStatement |
| 317 | // ThrowStatement |
| 318 | // TryStatement |
| 319 | // DebuggerStatement |
| 320 | |
| 321 | // Note: Since labels can only be used by 'break' and 'continue' |
| 322 | // statements, which themselves are only valid within blocks, |
| 323 | // iterations or 'switch' statements (i.e., BreakableStatements), |
| 324 | // labels can be simply ignored in all other cases; except for |
| 325 | // trivial labeled break statements 'label: break label' which is |
| 326 | // parsed into an empty statement. |
| 327 | |
| 328 | // Keep the source position of the statement |
| 329 | switch (peek()) { |
| 330 | case Token::LBRACE: |
| 331 | return ParseBlock(ok); |
| 332 | |
| 333 | case Token::SEMICOLON: |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 334 | Next(); |
| 335 | return Statement::Default(); |
| 336 | |
| 337 | case Token::IF: |
| 338 | return ParseIfStatement(ok); |
| 339 | |
| 340 | case Token::DO: |
| 341 | return ParseDoWhileStatement(ok); |
| 342 | |
| 343 | case Token::WHILE: |
| 344 | return ParseWhileStatement(ok); |
| 345 | |
| 346 | case Token::FOR: |
| 347 | return ParseForStatement(ok); |
| 348 | |
| 349 | case Token::CONTINUE: |
| 350 | return ParseContinueStatement(ok); |
| 351 | |
| 352 | case Token::BREAK: |
| 353 | return ParseBreakStatement(ok); |
| 354 | |
| 355 | case Token::RETURN: |
| 356 | return ParseReturnStatement(ok); |
| 357 | |
| 358 | case Token::WITH: |
| 359 | return ParseWithStatement(ok); |
| 360 | |
| 361 | case Token::SWITCH: |
| 362 | return ParseSwitchStatement(ok); |
| 363 | |
| 364 | case Token::THROW: |
| 365 | return ParseThrowStatement(ok); |
| 366 | |
| 367 | case Token::TRY: |
| 368 | return ParseTryStatement(ok); |
| 369 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 370 | case Token::FUNCTION: |
| 371 | // FunctionDeclaration only allowed as a StatementListItem, not in |
| 372 | // an arbitrary Statement position. Exceptions such as |
| 373 | // ES#sec-functiondeclarations-in-ifstatement-statement-clauses |
| 374 | // are handled by calling ParseScopedStatement rather than |
| 375 | // ParseSubStatement directly. |
| 376 | ReportMessageAt(scanner()->peek_location(), |
| 377 | is_strict(language_mode()) |
| 378 | ? MessageTemplate::kStrictFunction |
| 379 | : MessageTemplate::kSloppyFunction); |
| 380 | *ok = false; |
| 381 | return Statement::Default(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 382 | |
| 383 | case Token::DEBUGGER: |
| 384 | return ParseDebuggerStatement(ok); |
| 385 | |
| 386 | case Token::VAR: |
| 387 | return ParseVariableStatement(kStatement, ok); |
| 388 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 389 | default: |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 390 | return ParseExpressionOrLabelledStatement(allow_function, ok); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 391 | } |
| 392 | } |
| 393 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 394 | PreParser::Statement PreParser::ParseHoistableDeclaration( |
| 395 | int pos, ParseFunctionFlags flags, bool* ok) { |
| 396 | const bool is_generator = flags & ParseFunctionFlags::kIsGenerator; |
| 397 | const bool is_async = flags & ParseFunctionFlags::kIsAsync; |
| 398 | DCHECK(!is_generator || !is_async); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 399 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 400 | bool is_strict_reserved = false; |
| 401 | Identifier name = ParseIdentifierOrStrictReservedWord( |
| 402 | &is_strict_reserved, CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 403 | |
| 404 | if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) { |
| 405 | ReportMessageAt(scanner()->location(), |
| 406 | MessageTemplate::kAwaitBindingIdentifier); |
| 407 | *ok = false; |
| 408 | return Statement::Default(); |
| 409 | } |
| 410 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 411 | ParseFunctionLiteral(name, scanner()->location(), |
| 412 | is_strict_reserved ? kFunctionNameIsStrictReserved |
| 413 | : kFunctionNameValidityUnknown, |
| 414 | is_generator ? FunctionKind::kGeneratorFunction |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 415 | : is_async ? FunctionKind::kAsyncFunction |
| 416 | : FunctionKind::kNormalFunction, |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 417 | pos, FunctionLiteral::kDeclaration, language_mode(), |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 418 | CHECK_OK); |
| 419 | return Statement::FunctionDeclaration(); |
| 420 | } |
| 421 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 422 | PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(bool* ok) { |
| 423 | // AsyncFunctionDeclaration :: |
| 424 | // async [no LineTerminator here] function BindingIdentifier[Await] |
| 425 | // ( FormalParameters[Await] ) { AsyncFunctionBody } |
| 426 | DCHECK_EQ(scanner()->current_token(), Token::ASYNC); |
| 427 | int pos = position(); |
| 428 | Expect(Token::FUNCTION, CHECK_OK); |
| 429 | ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; |
| 430 | return ParseHoistableDeclaration(pos, flags, ok); |
| 431 | } |
| 432 | |
| 433 | PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) { |
| 434 | // FunctionDeclaration :: |
| 435 | // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
| 436 | // GeneratorDeclaration :: |
| 437 | // 'function' '*' Identifier '(' FormalParameterListopt ')' |
| 438 | // '{' FunctionBody '}' |
| 439 | |
| 440 | Expect(Token::FUNCTION, CHECK_OK); |
| 441 | int pos = position(); |
| 442 | ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; |
| 443 | if (Check(Token::MUL)) { |
| 444 | flags |= ParseFunctionFlags::kIsGenerator; |
| 445 | } |
| 446 | return ParseHoistableDeclaration(pos, flags, ok); |
| 447 | } |
| 448 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 449 | |
| 450 | PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { |
| 451 | Expect(Token::CLASS, CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 452 | |
| 453 | int pos = position(); |
| 454 | bool is_strict_reserved = false; |
| 455 | Identifier name = |
| 456 | ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 457 | ParseClassLiteral(nullptr, name, scanner()->location(), is_strict_reserved, |
| 458 | pos, CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 459 | return Statement::Default(); |
| 460 | } |
| 461 | |
| 462 | |
| 463 | PreParser::Statement PreParser::ParseBlock(bool* ok) { |
| 464 | // Block :: |
| 465 | // '{' StatementList '}' |
| 466 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 467 | Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 468 | Expect(Token::LBRACE, CHECK_OK); |
| 469 | Statement final = Statement::Default(); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 470 | { |
| 471 | BlockState block_state(&scope_, block_scope); |
| 472 | while (peek() != Token::RBRACE) { |
| 473 | final = ParseStatementListItem(CHECK_OK); |
| 474 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 475 | } |
| 476 | Expect(Token::RBRACE, ok); |
| 477 | return final; |
| 478 | } |
| 479 | |
| 480 | |
| 481 | PreParser::Statement PreParser::ParseVariableStatement( |
| 482 | VariableDeclarationContext var_context, |
| 483 | bool* ok) { |
| 484 | // VariableStatement :: |
| 485 | // VariableDeclarations ';' |
| 486 | |
| 487 | Statement result = ParseVariableDeclarations( |
| 488 | var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK); |
| 489 | ExpectSemicolon(CHECK_OK); |
| 490 | return result; |
| 491 | } |
| 492 | |
| 493 | |
| 494 | // If the variable declaration declares exactly one non-const |
| 495 | // variable, then *var is set to that variable. In all other cases, |
| 496 | // *var is untouched; in particular, it is the caller's responsibility |
| 497 | // to initialize it properly. This mechanism is also used for the parsing |
| 498 | // of 'for-in' loops. |
| 499 | PreParser::Statement PreParser::ParseVariableDeclarations( |
| 500 | VariableDeclarationContext var_context, int* num_decl, bool* is_lexical, |
| 501 | bool* is_binding_pattern, Scanner::Location* first_initializer_loc, |
| 502 | Scanner::Location* bindings_loc, bool* ok) { |
| 503 | // VariableDeclarations :: |
| 504 | // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
| 505 | // |
| 506 | // The ES6 Draft Rev3 specifies the following grammar for const declarations |
| 507 | // |
| 508 | // ConstDeclaration :: |
| 509 | // const ConstBinding (',' ConstBinding)* ';' |
| 510 | // ConstBinding :: |
| 511 | // Identifier '=' AssignmentExpression |
| 512 | // |
| 513 | // TODO(ES6): |
| 514 | // ConstBinding :: |
| 515 | // BindingPattern '=' AssignmentExpression |
| 516 | bool require_initializer = false; |
| 517 | bool lexical = false; |
| 518 | bool is_pattern = false; |
| 519 | if (peek() == Token::VAR) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 520 | Consume(Token::VAR); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 521 | } else if (peek() == Token::CONST) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 522 | // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: |
| 523 | // |
| 524 | // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' |
| 525 | // |
| 526 | // * It is a Syntax Error if the code that matches this production is not |
| 527 | // contained in extended code. |
| 528 | // |
| 529 | // However disallowing const in sloppy mode will break compatibility with |
| 530 | // existing pages. Therefore we keep allowing const with the old |
| 531 | // non-harmony semantics in sloppy mode. |
| 532 | Consume(Token::CONST); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 533 | DCHECK(var_context != kStatement); |
| 534 | require_initializer = true; |
| 535 | lexical = true; |
| 536 | } else if (peek() == Token::LET) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 537 | Consume(Token::LET); |
| 538 | DCHECK(var_context != kStatement); |
| 539 | lexical = true; |
| 540 | } else { |
| 541 | *ok = false; |
| 542 | return Statement::Default(); |
| 543 | } |
| 544 | |
| 545 | // The scope of a var/const declared variable anywhere inside a function |
| 546 | // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope |
| 547 | // of a let declared variable is the scope of the immediately enclosing |
| 548 | // block. |
| 549 | int nvars = 0; // the number of variables declared |
| 550 | int bindings_start = peek_position(); |
| 551 | do { |
| 552 | // Parse binding pattern. |
| 553 | if (nvars > 0) Consume(Token::COMMA); |
| 554 | int decl_pos = peek_position(); |
| 555 | PreParserExpression pattern = PreParserExpression::Default(); |
| 556 | { |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 557 | ExpressionClassifier pattern_classifier(this); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 558 | pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
| 559 | |
| 560 | ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
| 561 | if (lexical) { |
| 562 | ValidateLetPattern(&pattern_classifier, CHECK_OK); |
| 563 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 564 | } |
| 565 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 566 | is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 567 | |
| 568 | Scanner::Location variable_loc = scanner()->location(); |
| 569 | nvars++; |
| 570 | if (Check(Token::ASSIGN)) { |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 571 | ExpressionClassifier classifier(this); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 572 | ParseAssignmentExpression(var_context != kForStatement, &classifier, |
| 573 | CHECK_OK); |
| 574 | ValidateExpression(&classifier, CHECK_OK); |
| 575 | |
| 576 | variable_loc.end_pos = scanner()->location().end_pos; |
| 577 | if (first_initializer_loc && !first_initializer_loc->IsValid()) { |
| 578 | *first_initializer_loc = variable_loc; |
| 579 | } |
| 580 | } else if ((require_initializer || is_pattern) && |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 581 | (var_context != kForStatement || !PeekInOrOf())) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 582 | PreParserTraits::ReportMessageAt( |
| 583 | Scanner::Location(decl_pos, scanner()->location().end_pos), |
| 584 | MessageTemplate::kDeclarationMissingInitializer, |
| 585 | is_pattern ? "destructuring" : "const"); |
| 586 | *ok = false; |
| 587 | return Statement::Default(); |
| 588 | } |
| 589 | } while (peek() == Token::COMMA); |
| 590 | |
| 591 | if (bindings_loc) { |
| 592 | *bindings_loc = |
| 593 | Scanner::Location(bindings_start, scanner()->location().end_pos); |
| 594 | } |
| 595 | |
| 596 | if (num_decl != nullptr) *num_decl = nvars; |
| 597 | if (is_lexical != nullptr) *is_lexical = lexical; |
| 598 | if (is_binding_pattern != nullptr) *is_binding_pattern = is_pattern; |
| 599 | return Statement::Default(); |
| 600 | } |
| 601 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 602 | PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
| 603 | Consume(Token::FUNCTION); |
| 604 | int pos = position(); |
| 605 | ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; |
| 606 | if (Check(Token::MUL)) { |
| 607 | flags |= ParseFunctionFlags::kIsGenerator; |
| 608 | if (allow_harmony_restrictive_declarations()) { |
| 609 | PreParserTraits::ReportMessageAt( |
| 610 | scanner()->location(), MessageTemplate::kGeneratorInLegacyContext); |
| 611 | *ok = false; |
| 612 | return Statement::Default(); |
| 613 | } |
| 614 | } |
| 615 | return ParseHoistableDeclaration(pos, flags, ok); |
| 616 | } |
| 617 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 618 | PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( |
| 619 | AllowLabelledFunctionStatement allow_function, bool* ok) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 620 | // ExpressionStatement | LabelledStatement :: |
| 621 | // Expression ';' |
| 622 | // Identifier ':' Statement |
| 623 | |
| 624 | switch (peek()) { |
| 625 | case Token::FUNCTION: |
| 626 | case Token::LBRACE: |
| 627 | UNREACHABLE(); // Always handled by the callers. |
| 628 | case Token::CLASS: |
| 629 | ReportUnexpectedToken(Next()); |
| 630 | *ok = false; |
| 631 | return Statement::Default(); |
| 632 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 633 | default: |
| 634 | break; |
| 635 | } |
| 636 | |
| 637 | bool starts_with_identifier = peek_any_identifier(); |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 638 | ExpressionClassifier classifier(this); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 639 | Expression expr = ParseExpression(true, &classifier, CHECK_OK); |
| 640 | ValidateExpression(&classifier, CHECK_OK); |
| 641 | |
| 642 | // Even if the expression starts with an identifier, it is not necessarily an |
| 643 | // identifier. For example, "foo + bar" starts with an identifier but is not |
| 644 | // an identifier. |
| 645 | if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { |
| 646 | // Expression is a single identifier, and not, e.g., a parenthesized |
| 647 | // identifier. |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 648 | DCHECK(!expr.AsIdentifier().IsEnum()); |
| 649 | DCHECK(!parsing_module_ || !expr.AsIdentifier().IsAwait()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 650 | DCHECK(is_sloppy(language_mode()) || |
| 651 | !IsFutureStrictReserved(expr.AsIdentifier())); |
| 652 | Consume(Token::COLON); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 653 | // ES#sec-labelled-function-declarations Labelled Function Declarations |
| 654 | if (peek() == Token::FUNCTION && is_sloppy(language_mode())) { |
| 655 | if (allow_function == kAllowLabelledFunctionStatement) { |
| 656 | return ParseFunctionDeclaration(ok); |
| 657 | } else { |
| 658 | return ParseScopedStatement(true, ok); |
| 659 | } |
| 660 | } |
| 661 | Statement statement = |
| 662 | ParseStatement(kDisallowLabelledFunctionStatement, ok); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 663 | return statement.IsJumpStatement() ? Statement::Default() : statement; |
| 664 | // Preparsing is disabled for extensions (because the extension details |
| 665 | // aren't passed to lazily compiled functions), so we don't |
| 666 | // accept "native function" in the preparser. |
| 667 | } |
| 668 | // Parsed expression statement. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 669 | ExpectSemicolon(CHECK_OK); |
| 670 | return Statement::ExpressionStatement(expr); |
| 671 | } |
| 672 | |
| 673 | |
| 674 | PreParser::Statement PreParser::ParseIfStatement(bool* ok) { |
| 675 | // IfStatement :: |
| 676 | // 'if' '(' Expression ')' Statement ('else' Statement)? |
| 677 | |
| 678 | Expect(Token::IF, CHECK_OK); |
| 679 | Expect(Token::LPAREN, CHECK_OK); |
| 680 | ParseExpression(true, CHECK_OK); |
| 681 | Expect(Token::RPAREN, CHECK_OK); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 682 | Statement stat = ParseScopedStatement(false, CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 683 | if (peek() == Token::ELSE) { |
| 684 | Next(); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 685 | Statement else_stat = ParseScopedStatement(false, CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 686 | stat = (stat.IsJumpStatement() && else_stat.IsJumpStatement()) ? |
| 687 | Statement::Jump() : Statement::Default(); |
| 688 | } else { |
| 689 | stat = Statement::Default(); |
| 690 | } |
| 691 | return stat; |
| 692 | } |
| 693 | |
| 694 | |
| 695 | PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { |
| 696 | // ContinueStatement :: |
| 697 | // 'continue' [no line terminator] Identifier? ';' |
| 698 | |
| 699 | Expect(Token::CONTINUE, CHECK_OK); |
| 700 | Token::Value tok = peek(); |
| 701 | if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 702 | tok != Token::SEMICOLON && |
| 703 | tok != Token::RBRACE && |
| 704 | tok != Token::EOS) { |
| 705 | // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 706 | ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 707 | } |
| 708 | ExpectSemicolon(CHECK_OK); |
| 709 | return Statement::Jump(); |
| 710 | } |
| 711 | |
| 712 | |
| 713 | PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { |
| 714 | // BreakStatement :: |
| 715 | // 'break' [no line terminator] Identifier? ';' |
| 716 | |
| 717 | Expect(Token::BREAK, CHECK_OK); |
| 718 | Token::Value tok = peek(); |
| 719 | if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 720 | tok != Token::SEMICOLON && |
| 721 | tok != Token::RBRACE && |
| 722 | tok != Token::EOS) { |
| 723 | // ECMA allows "eval" or "arguments" as labels even in strict mode. |
| 724 | ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 725 | } |
| 726 | ExpectSemicolon(CHECK_OK); |
| 727 | return Statement::Jump(); |
| 728 | } |
| 729 | |
| 730 | |
| 731 | PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { |
| 732 | // ReturnStatement :: |
| 733 | // 'return' [no line terminator] Expression? ';' |
| 734 | |
| 735 | // Consume the return token. It is necessary to do before |
| 736 | // reporting any errors on it, because of the way errors are |
| 737 | // reported (underlining). |
| 738 | Expect(Token::RETURN, CHECK_OK); |
| 739 | function_state_->set_return_location(scanner()->location()); |
| 740 | |
| 741 | // An ECMAScript program is considered syntactically incorrect if it |
| 742 | // contains a return statement that is not within the body of a |
| 743 | // function. See ECMA-262, section 12.9, page 67. |
| 744 | // This is not handled during preparsing. |
| 745 | |
| 746 | Token::Value tok = peek(); |
| 747 | if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
| 748 | tok != Token::SEMICOLON && |
| 749 | tok != Token::RBRACE && |
| 750 | tok != Token::EOS) { |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 751 | // Because of the return code rewriting that happens in case of a subclass |
| 752 | // constructor we don't want to accept tail calls, therefore we don't set |
| 753 | // ReturnExprScope to kInsideValidReturnStatement here. |
| 754 | ReturnExprContext return_expr_context = |
| 755 | IsSubclassConstructor(function_state_->kind()) |
| 756 | ? function_state_->return_expr_context() |
| 757 | : ReturnExprContext::kInsideValidReturnStatement; |
| 758 | |
| 759 | ReturnExprScope maybe_allow_tail_calls(function_state_, |
| 760 | return_expr_context); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 761 | ParseExpression(true, CHECK_OK); |
| 762 | } |
| 763 | ExpectSemicolon(CHECK_OK); |
| 764 | return Statement::Jump(); |
| 765 | } |
| 766 | |
| 767 | |
| 768 | PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
| 769 | // WithStatement :: |
| 770 | // 'with' '(' Expression ')' Statement |
| 771 | Expect(Token::WITH, CHECK_OK); |
| 772 | if (is_strict(language_mode())) { |
| 773 | ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith); |
| 774 | *ok = false; |
| 775 | return Statement::Default(); |
| 776 | } |
| 777 | Expect(Token::LPAREN, CHECK_OK); |
| 778 | ParseExpression(true, CHECK_OK); |
| 779 | Expect(Token::RPAREN, CHECK_OK); |
| 780 | |
| 781 | Scope* with_scope = NewScope(scope_, WITH_SCOPE); |
| 782 | BlockState block_state(&scope_, with_scope); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 783 | ParseScopedStatement(true, CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 784 | return Statement::Default(); |
| 785 | } |
| 786 | |
| 787 | |
| 788 | PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { |
| 789 | // SwitchStatement :: |
| 790 | // 'switch' '(' Expression ')' '{' CaseClause* '}' |
| 791 | |
| 792 | Expect(Token::SWITCH, CHECK_OK); |
| 793 | Expect(Token::LPAREN, CHECK_OK); |
| 794 | ParseExpression(true, CHECK_OK); |
| 795 | Expect(Token::RPAREN, CHECK_OK); |
| 796 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 797 | Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE); |
| 798 | { |
| 799 | BlockState cases_block_state(&scope_, cases_scope); |
| 800 | Expect(Token::LBRACE, CHECK_OK); |
| 801 | Token::Value token = peek(); |
| 802 | while (token != Token::RBRACE) { |
| 803 | if (token == Token::CASE) { |
| 804 | Expect(Token::CASE, CHECK_OK); |
| 805 | ParseExpression(true, CHECK_OK); |
| 806 | } else { |
| 807 | Expect(Token::DEFAULT, CHECK_OK); |
| 808 | } |
| 809 | Expect(Token::COLON, CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 810 | token = peek(); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 811 | Statement statement = Statement::Jump(); |
| 812 | while (token != Token::CASE && |
| 813 | token != Token::DEFAULT && |
| 814 | token != Token::RBRACE) { |
| 815 | statement = ParseStatementListItem(CHECK_OK); |
| 816 | token = peek(); |
| 817 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 818 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 819 | } |
| 820 | Expect(Token::RBRACE, ok); |
| 821 | return Statement::Default(); |
| 822 | } |
| 823 | |
| 824 | |
| 825 | PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { |
| 826 | // DoStatement :: |
| 827 | // 'do' Statement 'while' '(' Expression ')' ';' |
| 828 | |
| 829 | Expect(Token::DO, CHECK_OK); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 830 | ParseScopedStatement(true, CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 831 | Expect(Token::WHILE, CHECK_OK); |
| 832 | Expect(Token::LPAREN, CHECK_OK); |
| 833 | ParseExpression(true, CHECK_OK); |
| 834 | Expect(Token::RPAREN, ok); |
| 835 | if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON); |
| 836 | return Statement::Default(); |
| 837 | } |
| 838 | |
| 839 | |
| 840 | PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { |
| 841 | // WhileStatement :: |
| 842 | // 'while' '(' Expression ')' Statement |
| 843 | |
| 844 | Expect(Token::WHILE, CHECK_OK); |
| 845 | Expect(Token::LPAREN, CHECK_OK); |
| 846 | ParseExpression(true, CHECK_OK); |
| 847 | Expect(Token::RPAREN, CHECK_OK); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 848 | ParseScopedStatement(true, ok); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 849 | return Statement::Default(); |
| 850 | } |
| 851 | |
| 852 | |
| 853 | PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
| 854 | // ForStatement :: |
| 855 | // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 856 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 857 | // Create an in-between scope for let-bound iteration variables. |
| 858 | Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
| 859 | bool has_lexical = false; |
| 860 | |
| 861 | BlockState block_state(&scope_, for_scope); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 862 | Expect(Token::FOR, CHECK_OK); |
| 863 | Expect(Token::LPAREN, CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 864 | if (peek() != Token::SEMICOLON) { |
| 865 | ForEachStatement::VisitMode mode; |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 866 | if (peek() == Token::VAR || peek() == Token::CONST || |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 867 | (peek() == Token::LET && IsNextLetKeyword())) { |
| 868 | int decl_count; |
| 869 | bool is_lexical; |
| 870 | bool is_binding_pattern; |
| 871 | Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
| 872 | Scanner::Location bindings_loc = Scanner::Location::invalid(); |
| 873 | ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, |
| 874 | &is_binding_pattern, &first_initializer_loc, |
| 875 | &bindings_loc, CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 876 | if (is_lexical) has_lexical = true; |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 877 | if (CheckInOrOf(&mode, ok)) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 878 | if (!*ok) return Statement::Default(); |
| 879 | if (decl_count != 1) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 880 | PreParserTraits::ReportMessageAt( |
| 881 | bindings_loc, MessageTemplate::kForInOfLoopMultiBindings, |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 882 | ForEachStatement::VisitModeString(mode)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 883 | *ok = false; |
| 884 | return Statement::Default(); |
| 885 | } |
| 886 | if (first_initializer_loc.IsValid() && |
| 887 | (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 888 | is_lexical || is_binding_pattern || allow_harmony_for_in())) { |
| 889 | // Only increment the use count if we would have let this through |
| 890 | // without the flag. |
| 891 | if (use_counts_ != nullptr && allow_harmony_for_in()) { |
| 892 | ++use_counts_[v8::Isolate::kForInInitializer]; |
| 893 | } |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 894 | PreParserTraits::ReportMessageAt( |
| 895 | first_initializer_loc, MessageTemplate::kForInOfLoopInitializer, |
| 896 | ForEachStatement::VisitModeString(mode)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 897 | *ok = false; |
| 898 | return Statement::Default(); |
| 899 | } |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 900 | |
| 901 | if (mode == ForEachStatement::ITERATE) { |
| 902 | ExpressionClassifier classifier(this); |
| 903 | ParseAssignmentExpression(true, &classifier, CHECK_OK); |
| 904 | RewriteNonPattern(&classifier, CHECK_OK); |
| 905 | } else { |
| 906 | ParseExpression(true, CHECK_OK); |
| 907 | } |
| 908 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 909 | Expect(Token::RPAREN, CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 910 | { |
| 911 | ReturnExprScope no_tail_calls(function_state_, |
| 912 | ReturnExprContext::kInsideForInOfBody); |
| 913 | ParseScopedStatement(true, CHECK_OK); |
| 914 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 915 | return Statement::Default(); |
| 916 | } |
| 917 | } else { |
| 918 | int lhs_beg_pos = peek_position(); |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 919 | ExpressionClassifier classifier(this); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 920 | Expression lhs = ParseExpression(false, &classifier, CHECK_OK); |
| 921 | int lhs_end_pos = scanner()->location().end_pos; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 922 | bool is_for_each = CheckInOrOf(&mode, ok); |
| 923 | if (!*ok) return Statement::Default(); |
| 924 | bool is_destructuring = is_for_each && |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 925 | (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()); |
| 926 | |
| 927 | if (is_destructuring) { |
| 928 | ValidateAssignmentPattern(&classifier, CHECK_OK); |
| 929 | } else { |
| 930 | ValidateExpression(&classifier, CHECK_OK); |
| 931 | } |
| 932 | |
| 933 | if (is_for_each) { |
| 934 | if (!is_destructuring) { |
| 935 | lhs = CheckAndRewriteReferenceExpression( |
| 936 | lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor, |
| 937 | kSyntaxError, CHECK_OK); |
| 938 | } |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 939 | |
| 940 | if (mode == ForEachStatement::ITERATE) { |
| 941 | ExpressionClassifier classifier(this); |
| 942 | ParseAssignmentExpression(true, &classifier, CHECK_OK); |
| 943 | RewriteNonPattern(&classifier, CHECK_OK); |
| 944 | } else { |
| 945 | ParseExpression(true, CHECK_OK); |
| 946 | } |
| 947 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 948 | Expect(Token::RPAREN, CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 949 | Scope* body_scope = NewScope(scope_, BLOCK_SCOPE); |
| 950 | { |
| 951 | BlockState block_state(&scope_, body_scope); |
| 952 | ParseScopedStatement(true, CHECK_OK); |
| 953 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 954 | return Statement::Default(); |
| 955 | } |
| 956 | } |
| 957 | } |
| 958 | |
| 959 | // Parsed initializer at this point. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 960 | Expect(Token::SEMICOLON, CHECK_OK); |
| 961 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 962 | // If there are let bindings, then condition and the next statement of the |
| 963 | // for loop must be parsed in a new scope. |
| 964 | Scope* inner_scope = scope_; |
| 965 | if (has_lexical) inner_scope = NewScope(for_scope, BLOCK_SCOPE); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 966 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 967 | { |
| 968 | BlockState block_state(&scope_, inner_scope); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 969 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 970 | if (peek() != Token::SEMICOLON) { |
| 971 | ParseExpression(true, CHECK_OK); |
| 972 | } |
| 973 | Expect(Token::SEMICOLON, CHECK_OK); |
| 974 | |
| 975 | if (peek() != Token::RPAREN) { |
| 976 | ParseExpression(true, CHECK_OK); |
| 977 | } |
| 978 | Expect(Token::RPAREN, CHECK_OK); |
| 979 | |
| 980 | ParseScopedStatement(true, ok); |
| 981 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 982 | return Statement::Default(); |
| 983 | } |
| 984 | |
| 985 | |
| 986 | PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { |
| 987 | // ThrowStatement :: |
| 988 | // 'throw' [no line terminator] Expression ';' |
| 989 | |
| 990 | Expect(Token::THROW, CHECK_OK); |
| 991 | if (scanner()->HasAnyLineTerminatorBeforeNext()) { |
| 992 | ReportMessageAt(scanner()->location(), MessageTemplate::kNewlineAfterThrow); |
| 993 | *ok = false; |
| 994 | return Statement::Default(); |
| 995 | } |
| 996 | ParseExpression(true, CHECK_OK); |
| 997 | ExpectSemicolon(ok); |
| 998 | return Statement::Jump(); |
| 999 | } |
| 1000 | |
| 1001 | |
| 1002 | PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
| 1003 | // TryStatement :: |
| 1004 | // 'try' Block Catch |
| 1005 | // 'try' Block Finally |
| 1006 | // 'try' Block Catch Finally |
| 1007 | // |
| 1008 | // Catch :: |
| 1009 | // 'catch' '(' Identifier ')' Block |
| 1010 | // |
| 1011 | // Finally :: |
| 1012 | // 'finally' Block |
| 1013 | |
| 1014 | Expect(Token::TRY, CHECK_OK); |
| 1015 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1016 | { |
| 1017 | ReturnExprScope no_tail_calls(function_state_, |
| 1018 | ReturnExprContext::kInsideTryBlock); |
| 1019 | ParseBlock(CHECK_OK); |
| 1020 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1021 | |
| 1022 | Token::Value tok = peek(); |
| 1023 | if (tok != Token::CATCH && tok != Token::FINALLY) { |
| 1024 | ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally); |
| 1025 | *ok = false; |
| 1026 | return Statement::Default(); |
| 1027 | } |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1028 | TailCallExpressionList tail_call_expressions_in_catch_block(zone()); |
| 1029 | bool catch_block_exists = false; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1030 | if (tok == Token::CATCH) { |
| 1031 | Consume(Token::CATCH); |
| 1032 | Expect(Token::LPAREN, CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1033 | Scope* catch_scope = NewScope(scope_, CATCH_SCOPE); |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1034 | ExpressionClassifier pattern_classifier(this); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1035 | ParsePrimaryExpression(&pattern_classifier, CHECK_OK); |
| 1036 | ValidateBindingPattern(&pattern_classifier, CHECK_OK); |
| 1037 | Expect(Token::RPAREN, CHECK_OK); |
| 1038 | { |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1039 | CollectExpressionsInTailPositionToListScope |
| 1040 | collect_tail_call_expressions_scope( |
| 1041 | function_state_, &tail_call_expressions_in_catch_block); |
| 1042 | BlockState block_state(&scope_, catch_scope); |
| 1043 | Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
| 1044 | { |
| 1045 | BlockState block_state(&scope_, block_scope); |
| 1046 | ParseBlock(CHECK_OK); |
| 1047 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1048 | } |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1049 | catch_block_exists = true; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1050 | tok = peek(); |
| 1051 | } |
| 1052 | if (tok == Token::FINALLY) { |
| 1053 | Consume(Token::FINALLY); |
| 1054 | ParseBlock(CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1055 | if (FLAG_harmony_explicit_tailcalls && catch_block_exists && |
| 1056 | tail_call_expressions_in_catch_block.has_explicit_tail_calls()) { |
| 1057 | // TODO(ishell): update chapter number. |
| 1058 | // ES8 XX.YY.ZZ |
| 1059 | ReportMessageAt(tail_call_expressions_in_catch_block.location(), |
| 1060 | MessageTemplate::kUnexpectedTailCallInCatchBlock); |
| 1061 | *ok = false; |
| 1062 | return Statement::Default(); |
| 1063 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1064 | } |
| 1065 | return Statement::Default(); |
| 1066 | } |
| 1067 | |
| 1068 | |
| 1069 | PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { |
| 1070 | // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser |
| 1071 | // contexts this is used as a statement which invokes the debugger as if a |
| 1072 | // break point is present. |
| 1073 | // DebuggerStatement :: |
| 1074 | // 'debugger' ';' |
| 1075 | |
| 1076 | Expect(Token::DEBUGGER, CHECK_OK); |
| 1077 | ExpectSemicolon(ok); |
| 1078 | return Statement::Default(); |
| 1079 | } |
| 1080 | |
| 1081 | |
| 1082 | #undef CHECK_OK |
| 1083 | #define CHECK_OK ok); \ |
| 1084 | if (!*ok) return Expression::Default(); \ |
| 1085 | ((void)0 |
| 1086 | #define DUMMY ) // to make indentation work |
| 1087 | #undef DUMMY |
| 1088 | |
| 1089 | |
| 1090 | PreParser::Expression PreParser::ParseFunctionLiteral( |
| 1091 | Identifier function_name, Scanner::Location function_name_location, |
| 1092 | FunctionNameValidity function_name_validity, FunctionKind kind, |
| 1093 | int function_token_pos, FunctionLiteral::FunctionType function_type, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1094 | LanguageMode language_mode, bool* ok) { |
| 1095 | // Function :: |
| 1096 | // '(' FormalParameterList? ')' '{' FunctionBody '}' |
| 1097 | |
| 1098 | // Parse function body. |
| 1099 | bool outer_is_script_scope = scope_->is_script_scope(); |
| 1100 | Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind); |
| 1101 | function_scope->SetLanguageMode(language_mode); |
| 1102 | PreParserFactory factory(NULL); |
| 1103 | FunctionState function_state(&function_state_, &scope_, function_scope, kind, |
| 1104 | &factory); |
| 1105 | DuplicateFinder duplicate_finder(scanner()->unicode_cache()); |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1106 | ExpressionClassifier formals_classifier(this, &duplicate_finder); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1107 | |
| 1108 | Expect(Token::LPAREN, CHECK_OK); |
| 1109 | int start_position = scanner()->location().beg_pos; |
| 1110 | function_scope->set_start_position(start_position); |
| 1111 | PreParserFormalParameters formals(function_scope); |
| 1112 | ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK); |
| 1113 | Expect(Token::RPAREN, CHECK_OK); |
| 1114 | int formals_end_position = scanner()->location().end_pos; |
| 1115 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1116 | CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1117 | formals_end_position, CHECK_OK); |
| 1118 | |
| 1119 | // See Parser::ParseFunctionLiteral for more information about lazy parsing |
| 1120 | // and lazy compilation. |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1121 | bool is_lazily_parsed = (outer_is_script_scope && allow_lazy() && |
| 1122 | !function_state_->this_function_is_parenthesized()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1123 | |
| 1124 | Expect(Token::LBRACE, CHECK_OK); |
| 1125 | if (is_lazily_parsed) { |
| 1126 | ParseLazyFunctionLiteralBody(CHECK_OK); |
| 1127 | } else { |
| 1128 | ParseStatementList(Token::RBRACE, CHECK_OK); |
| 1129 | } |
| 1130 | Expect(Token::RBRACE, CHECK_OK); |
| 1131 | |
| 1132 | // Parsing the body may change the language mode in our scope. |
| 1133 | language_mode = function_scope->language_mode(); |
| 1134 | |
| 1135 | // Validate name and parameter names. We can do this only after parsing the |
| 1136 | // function, since the function can declare itself strict. |
| 1137 | CheckFunctionName(language_mode, function_name, function_name_validity, |
| 1138 | function_name_location, CHECK_OK); |
| 1139 | const bool allow_duplicate_parameters = |
| 1140 | is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); |
| 1141 | ValidateFormalParameters(&formals_classifier, language_mode, |
| 1142 | allow_duplicate_parameters, CHECK_OK); |
| 1143 | |
| 1144 | if (is_strict(language_mode)) { |
| 1145 | int end_position = scanner()->location().end_pos; |
| 1146 | CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1147 | CheckDecimalLiteralWithLeadingZero(use_counts_, start_position, |
| 1148 | end_position); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1149 | } |
| 1150 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1151 | return Expression::Default(); |
| 1152 | } |
| 1153 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1154 | PreParser::Expression PreParser::ParseAsyncFunctionExpression(bool* ok) { |
| 1155 | // AsyncFunctionDeclaration :: |
| 1156 | // async [no LineTerminator here] function ( FormalParameters[Await] ) |
| 1157 | // { AsyncFunctionBody } |
| 1158 | // |
| 1159 | // async [no LineTerminator here] function BindingIdentifier[Await] |
| 1160 | // ( FormalParameters[Await] ) { AsyncFunctionBody } |
| 1161 | int pos = position(); |
| 1162 | Expect(Token::FUNCTION, CHECK_OK); |
| 1163 | bool is_strict_reserved = false; |
| 1164 | Identifier name; |
| 1165 | FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression; |
| 1166 | |
| 1167 | if (peek_any_identifier()) { |
| 1168 | type = FunctionLiteral::kNamedExpression; |
| 1169 | name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
| 1170 | if (this->IsAwait(name)) { |
| 1171 | ReportMessageAt(scanner()->location(), |
| 1172 | MessageTemplate::kAwaitBindingIdentifier); |
| 1173 | *ok = false; |
| 1174 | return Expression::Default(); |
| 1175 | } |
| 1176 | } |
| 1177 | |
| 1178 | ParseFunctionLiteral(name, scanner()->location(), |
| 1179 | is_strict_reserved ? kFunctionNameIsStrictReserved |
| 1180 | : kFunctionNameValidityUnknown, |
| 1181 | FunctionKind::kAsyncFunction, pos, type, language_mode(), |
| 1182 | CHECK_OK); |
| 1183 | return Expression::Default(); |
| 1184 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1185 | |
| 1186 | void PreParser::ParseLazyFunctionLiteralBody(bool* ok, |
| 1187 | Scanner::BookmarkScope* bookmark) { |
| 1188 | int body_start = position(); |
| 1189 | ParseStatementList(Token::RBRACE, ok, bookmark); |
| 1190 | if (!*ok) return; |
| 1191 | if (bookmark && bookmark->HasBeenReset()) return; |
| 1192 | |
| 1193 | // Position right after terminal '}'. |
| 1194 | DCHECK_EQ(Token::RBRACE, scanner()->peek()); |
| 1195 | int body_end = scanner()->peek_location().end_pos; |
| 1196 | log_->LogFunction(body_start, body_end, |
| 1197 | function_state_->materialized_literal_count(), |
| 1198 | function_state_->expected_property_count(), language_mode(), |
| 1199 | scope_->uses_super_property(), scope_->calls_eval()); |
| 1200 | } |
| 1201 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1202 | PreParserExpression PreParser::ParseClassLiteral( |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 1203 | ExpressionClassifier* classifier, PreParserIdentifier name, |
| 1204 | Scanner::Location class_name_location, bool name_is_strict_reserved, |
| 1205 | int pos, bool* ok) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1206 | // All parts of a ClassDeclaration and ClassExpression are strict code. |
| 1207 | if (name_is_strict_reserved) { |
| 1208 | ReportMessageAt(class_name_location, |
| 1209 | MessageTemplate::kUnexpectedStrictReserved); |
| 1210 | *ok = false; |
| 1211 | return EmptyExpression(); |
| 1212 | } |
| 1213 | if (IsEvalOrArguments(name)) { |
| 1214 | ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); |
| 1215 | *ok = false; |
| 1216 | return EmptyExpression(); |
| 1217 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1218 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 1219 | LanguageMode class_language_mode = language_mode(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1220 | Scope* scope = NewScope(scope_, BLOCK_SCOPE); |
| 1221 | BlockState block_state(&scope_, scope); |
| 1222 | scope_->SetLanguageMode( |
| 1223 | static_cast<LanguageMode>(class_language_mode | STRICT)); |
| 1224 | // TODO(marja): Make PreParser use scope names too. |
| 1225 | // scope_->SetScopeName(name); |
| 1226 | |
| 1227 | bool has_extends = Check(Token::EXTENDS); |
| 1228 | if (has_extends) { |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 1229 | ExpressionClassifier extends_classifier(this); |
| 1230 | ParseLeftHandSideExpression(&extends_classifier, CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1231 | CheckNoTailCallExpressions(&extends_classifier, CHECK_OK); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 1232 | ValidateExpression(&extends_classifier, CHECK_OK); |
| 1233 | if (classifier != nullptr) { |
| 1234 | classifier->Accumulate(&extends_classifier, |
| 1235 | ExpressionClassifier::ExpressionProductions); |
| 1236 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1237 | } |
| 1238 | |
| 1239 | ClassLiteralChecker checker(this); |
| 1240 | bool has_seen_constructor = false; |
| 1241 | |
| 1242 | Expect(Token::LBRACE, CHECK_OK); |
| 1243 | while (peek() != Token::RBRACE) { |
| 1244 | if (Check(Token::SEMICOLON)) continue; |
| 1245 | const bool in_class = true; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1246 | bool is_computed_name = false; // Classes do not care about computed |
| 1247 | // property names here. |
| 1248 | Identifier name; |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 1249 | ExpressionClassifier property_classifier(this); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1250 | ParsePropertyDefinition(&checker, in_class, has_extends, MethodKind::Normal, |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1251 | &is_computed_name, &has_seen_constructor, |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 1252 | &property_classifier, &name, CHECK_OK); |
| 1253 | ValidateExpression(&property_classifier, CHECK_OK); |
| 1254 | if (classifier != nullptr) { |
| 1255 | classifier->Accumulate(&property_classifier, |
| 1256 | ExpressionClassifier::ExpressionProductions); |
| 1257 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1258 | } |
| 1259 | |
| 1260 | Expect(Token::RBRACE, CHECK_OK); |
| 1261 | |
| 1262 | return Expression::Default(); |
| 1263 | } |
| 1264 | |
| 1265 | |
| 1266 | PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { |
| 1267 | // CallRuntime :: |
| 1268 | // '%' Identifier Arguments |
| 1269 | Expect(Token::MOD, CHECK_OK); |
| 1270 | if (!allow_natives()) { |
| 1271 | *ok = false; |
| 1272 | return Expression::Default(); |
| 1273 | } |
| 1274 | // Allow "eval" or "arguments" for backward compatibility. |
| 1275 | ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| 1276 | Scanner::Location spread_pos; |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1277 | ExpressionClassifier classifier(this); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1278 | ParseArguments(&spread_pos, &classifier, ok); |
| 1279 | ValidateExpression(&classifier, CHECK_OK); |
| 1280 | |
| 1281 | DCHECK(!spread_pos.IsValid()); |
| 1282 | |
| 1283 | return Expression::Default(); |
| 1284 | } |
| 1285 | |
| 1286 | |
| 1287 | PreParserExpression PreParser::ParseDoExpression(bool* ok) { |
| 1288 | // AssignmentExpression :: |
| 1289 | // do '{' StatementList '}' |
| 1290 | Expect(Token::DO, CHECK_OK); |
| 1291 | Expect(Token::LBRACE, CHECK_OK); |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1292 | while (peek() != Token::RBRACE) { |
| 1293 | ParseStatementListItem(CHECK_OK); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1294 | } |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 1295 | Expect(Token::RBRACE, CHECK_OK); |
| 1296 | return PreParserExpression::Default(); |
| 1297 | } |
| 1298 | |
| 1299 | void PreParserTraits::ParseAsyncArrowSingleExpressionBody( |
| 1300 | PreParserStatementList body, bool accept_IN, |
| 1301 | Type::ExpressionClassifier* classifier, int pos, bool* ok) { |
| 1302 | Scope* scope = pre_parser_->scope_; |
| 1303 | scope->ForceContextAllocation(); |
| 1304 | |
| 1305 | PreParserExpression return_value = |
| 1306 | pre_parser_->ParseAssignmentExpression(accept_IN, classifier, ok); |
| 1307 | if (!*ok) return; |
| 1308 | |
| 1309 | body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1310 | } |
| 1311 | |
| 1312 | #undef CHECK_OK |
| 1313 | |
| 1314 | |
| 1315 | } // namespace internal |
| 1316 | } // namespace v8 |