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