| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
| 6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/bailout-reason.h" | |
| 11 #include "src/expression-classifier.h" | 10 #include "src/expression-classifier.h" |
| 12 #include "src/func-name-inferrer.h" | 11 #include "src/func-name-inferrer.h" |
| 13 #include "src/hashmap.h" | |
| 14 #include "src/messages.h" | 12 #include "src/messages.h" |
| 13 #include "src/parser-base.h" |
| 15 #include "src/scanner.h" | 14 #include "src/scanner.h" |
| 16 #include "src/scopes.h" | 15 #include "src/scopes.h" |
| 17 #include "src/token.h" | 16 #include "src/token.h" |
| 18 | 17 |
| 19 namespace v8 { | 18 namespace v8 { |
| 20 namespace internal { | 19 namespace internal { |
| 21 | 20 |
| 22 | |
| 23 enum FunctionNameValidity { | |
| 24 kFunctionNameIsStrictReserved, | |
| 25 kSkipFunctionNameCheck, | |
| 26 kFunctionNameValidityUnknown | |
| 27 }; | |
| 28 | |
| 29 | |
| 30 // Common base class shared between parser and pre-parser. Traits encapsulate | |
| 31 // the differences between Parser and PreParser: | |
| 32 | |
| 33 // - Return types: For example, Parser functions return Expression* and | |
| 34 // PreParser functions return PreParserExpression. | |
| 35 | |
| 36 // - Creating parse tree nodes: Parser generates an AST during the recursive | |
| 37 // descent. PreParser doesn't create a tree. Instead, it passes around minimal | |
| 38 // data objects (PreParserExpression, PreParserIdentifier etc.) which contain | |
| 39 // just enough data for the upper layer functions. PreParserFactory is | |
| 40 // responsible for creating these dummy objects. It provides a similar kind of | |
| 41 // interface as AstNodeFactory, so ParserBase doesn't need to care which one is | |
| 42 // used. | |
| 43 | |
| 44 // - Miscellaneous other tasks interleaved with the recursive descent. For | |
| 45 // example, Parser keeps track of which function literals should be marked as | |
| 46 // pretenured, and PreParser doesn't care. | |
| 47 | |
| 48 // The traits are expected to contain the following typedefs: | |
| 49 // struct Traits { | |
| 50 // // In particular... | |
| 51 // struct Type { | |
| 52 // // Used by FunctionState and BlockState. | |
| 53 // typedef Scope; | |
| 54 // typedef GeneratorVariable; | |
| 55 // // Return types for traversing functions. | |
| 56 // typedef Identifier; | |
| 57 // typedef Expression; | |
| 58 // typedef FunctionLiteral; | |
| 59 // typedef ClassLiteral; | |
| 60 // typedef ObjectLiteralProperty; | |
| 61 // typedef Literal; | |
| 62 // typedef ExpressionList; | |
| 63 // typedef PropertyList; | |
| 64 // typedef FormalParameter; | |
| 65 // // For constructing objects returned by the traversing functions. | |
| 66 // typedef Factory; | |
| 67 // }; | |
| 68 // // ... | |
| 69 // }; | |
| 70 | |
| 71 template <typename Traits> | |
| 72 class ParserBase : public Traits { | |
| 73 public: | |
| 74 // Shorten type names defined by Traits. | |
| 75 typedef typename Traits::Type::Expression ExpressionT; | |
| 76 typedef typename Traits::Type::Identifier IdentifierT; | |
| 77 typedef typename Traits::Type::FormalParameter FormalParameterT; | |
| 78 typedef typename Traits::Type::FunctionLiteral FunctionLiteralT; | |
| 79 typedef typename Traits::Type::Literal LiteralT; | |
| 80 typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT; | |
| 81 typedef typename Traits::Type::FormalParameterParsingState | |
| 82 FormalParameterParsingStateT; | |
| 83 | |
| 84 ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit, | |
| 85 v8::Extension* extension, AstValueFactory* ast_value_factory, | |
| 86 ParserRecorder* log, typename Traits::Type::Parser this_object) | |
| 87 : Traits(this_object), | |
| 88 parenthesized_function_(false), | |
| 89 scope_(NULL), | |
| 90 function_state_(NULL), | |
| 91 extension_(extension), | |
| 92 fni_(NULL), | |
| 93 ast_value_factory_(ast_value_factory), | |
| 94 log_(log), | |
| 95 mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. | |
| 96 stack_limit_(stack_limit), | |
| 97 zone_(zone), | |
| 98 scanner_(scanner), | |
| 99 stack_overflow_(false), | |
| 100 allow_lazy_(false), | |
| 101 allow_natives_(false), | |
| 102 allow_harmony_arrow_functions_(false), | |
| 103 allow_harmony_sloppy_(false), | |
| 104 allow_harmony_computed_property_names_(false), | |
| 105 allow_harmony_rest_params_(false), | |
| 106 allow_harmony_spreadcalls_(false), | |
| 107 allow_harmony_destructuring_(false), | |
| 108 allow_harmony_spread_arrays_(false), | |
| 109 allow_harmony_new_target_(false), | |
| 110 allow_strong_mode_(false), | |
| 111 allow_legacy_const_(true) {} | |
| 112 | |
| 113 #define ALLOW_ACCESSORS(name) \ | |
| 114 bool allow_##name() const { return allow_##name##_; } \ | |
| 115 void set_allow_##name(bool allow) { allow_##name##_ = allow; } | |
| 116 | |
| 117 ALLOW_ACCESSORS(lazy); | |
| 118 ALLOW_ACCESSORS(natives); | |
| 119 ALLOW_ACCESSORS(harmony_arrow_functions); | |
| 120 ALLOW_ACCESSORS(harmony_sloppy); | |
| 121 ALLOW_ACCESSORS(harmony_computed_property_names); | |
| 122 ALLOW_ACCESSORS(harmony_rest_params); | |
| 123 ALLOW_ACCESSORS(harmony_spreadcalls); | |
| 124 ALLOW_ACCESSORS(harmony_destructuring); | |
| 125 ALLOW_ACCESSORS(harmony_spread_arrays); | |
| 126 ALLOW_ACCESSORS(harmony_new_target); | |
| 127 ALLOW_ACCESSORS(strong_mode); | |
| 128 ALLOW_ACCESSORS(legacy_const); | |
| 129 #undef ALLOW_ACCESSORS | |
| 130 | |
| 131 bool allow_harmony_modules() const { return scanner()->HarmonyModules(); } | |
| 132 bool allow_harmony_unicode() const { return scanner()->HarmonyUnicode(); } | |
| 133 | |
| 134 void set_allow_harmony_modules(bool a) { scanner()->SetHarmonyModules(a); } | |
| 135 void set_allow_harmony_unicode(bool a) { scanner()->SetHarmonyUnicode(a); } | |
| 136 | |
| 137 protected: | |
| 138 enum AllowRestrictedIdentifiers { | |
| 139 kAllowRestrictedIdentifiers, | |
| 140 kDontAllowRestrictedIdentifiers | |
| 141 }; | |
| 142 | |
| 143 enum Mode { | |
| 144 PARSE_LAZILY, | |
| 145 PARSE_EAGERLY | |
| 146 }; | |
| 147 | |
| 148 enum VariableDeclarationContext { | |
| 149 kStatementListItem, | |
| 150 kStatement, | |
| 151 kForStatement | |
| 152 }; | |
| 153 | |
| 154 class Checkpoint; | |
| 155 class ObjectLiteralCheckerBase; | |
| 156 | |
| 157 // --------------------------------------------------------------------------- | |
| 158 // FunctionState and BlockState together implement the parser's scope stack. | |
| 159 // The parser's current scope is in scope_. BlockState and FunctionState | |
| 160 // constructors push on the scope stack and the destructors pop. They are also | |
| 161 // used to hold the parser's per-function and per-block state. | |
| 162 class BlockState BASE_EMBEDDED { | |
| 163 public: | |
| 164 BlockState(Scope** scope_stack, Scope* scope) | |
| 165 : scope_stack_(scope_stack), outer_scope_(*scope_stack) { | |
| 166 *scope_stack_ = scope; | |
| 167 } | |
| 168 ~BlockState() { *scope_stack_ = outer_scope_; } | |
| 169 | |
| 170 private: | |
| 171 Scope** scope_stack_; | |
| 172 Scope* outer_scope_; | |
| 173 }; | |
| 174 | |
| 175 class FunctionState BASE_EMBEDDED { | |
| 176 public: | |
| 177 FunctionState(FunctionState** function_state_stack, Scope** scope_stack, | |
| 178 Scope* scope, FunctionKind kind, | |
| 179 typename Traits::Type::Factory* factory); | |
| 180 ~FunctionState(); | |
| 181 | |
| 182 int NextMaterializedLiteralIndex() { | |
| 183 return next_materialized_literal_index_++; | |
| 184 } | |
| 185 int materialized_literal_count() { | |
| 186 return next_materialized_literal_index_; | |
| 187 } | |
| 188 | |
| 189 void SkipMaterializedLiterals(int count) { | |
| 190 next_materialized_literal_index_ += count; | |
| 191 } | |
| 192 | |
| 193 void AddProperty() { expected_property_count_++; } | |
| 194 int expected_property_count() { return expected_property_count_; } | |
| 195 | |
| 196 Scanner::Location this_location() const { return this_location_; } | |
| 197 Scanner::Location super_location() const { return super_location_; } | |
| 198 Scanner::Location return_location() const { return return_location_; } | |
| 199 void set_this_location(Scanner::Location location) { | |
| 200 this_location_ = location; | |
| 201 } | |
| 202 void set_super_location(Scanner::Location location) { | |
| 203 super_location_ = location; | |
| 204 } | |
| 205 void set_return_location(Scanner::Location location) { | |
| 206 return_location_ = location; | |
| 207 } | |
| 208 | |
| 209 bool is_generator() const { return IsGeneratorFunction(kind_); } | |
| 210 | |
| 211 FunctionKind kind() const { return kind_; } | |
| 212 FunctionState* outer() const { return outer_function_state_; } | |
| 213 | |
| 214 void set_generator_object_variable( | |
| 215 typename Traits::Type::GeneratorVariable* variable) { | |
| 216 DCHECK(variable != NULL); | |
| 217 DCHECK(is_generator()); | |
| 218 generator_object_variable_ = variable; | |
| 219 } | |
| 220 typename Traits::Type::GeneratorVariable* generator_object_variable() | |
| 221 const { | |
| 222 return generator_object_variable_; | |
| 223 } | |
| 224 | |
| 225 typename Traits::Type::Factory* factory() { return factory_; } | |
| 226 | |
| 227 private: | |
| 228 // Used to assign an index to each literal that needs materialization in | |
| 229 // the function. Includes regexp literals, and boilerplate for object and | |
| 230 // array literals. | |
| 231 int next_materialized_literal_index_; | |
| 232 | |
| 233 // Properties count estimation. | |
| 234 int expected_property_count_; | |
| 235 | |
| 236 // Location of most recent use of 'this' (invalid if none). | |
| 237 Scanner::Location this_location_; | |
| 238 | |
| 239 // Location of most recent 'return' statement (invalid if none). | |
| 240 Scanner::Location return_location_; | |
| 241 | |
| 242 // Location of call to the "super" constructor (invalid if none). | |
| 243 Scanner::Location super_location_; | |
| 244 | |
| 245 FunctionKind kind_; | |
| 246 // For generators, this variable may hold the generator object. It variable | |
| 247 // is used by yield expressions and return statements. It is not necessary | |
| 248 // for generator functions to have this variable set. | |
| 249 Variable* generator_object_variable_; | |
| 250 | |
| 251 FunctionState** function_state_stack_; | |
| 252 FunctionState* outer_function_state_; | |
| 253 Scope** scope_stack_; | |
| 254 Scope* outer_scope_; | |
| 255 typename Traits::Type::Factory* factory_; | |
| 256 | |
| 257 friend class ParserTraits; | |
| 258 friend class Checkpoint; | |
| 259 }; | |
| 260 | |
| 261 // Annoyingly, arrow functions first parse as comma expressions, then when we | |
| 262 // see the => we have to go back and reinterpret the arguments as being formal | |
| 263 // parameters. To do so we need to reset some of the parser state back to | |
| 264 // what it was before the arguments were first seen. | |
| 265 class Checkpoint BASE_EMBEDDED { | |
| 266 public: | |
| 267 explicit Checkpoint(ParserBase* parser) { | |
| 268 function_state_ = parser->function_state_; | |
| 269 next_materialized_literal_index_ = | |
| 270 function_state_->next_materialized_literal_index_; | |
| 271 expected_property_count_ = function_state_->expected_property_count_; | |
| 272 } | |
| 273 | |
| 274 void Restore(int* materialized_literal_index_delta) { | |
| 275 *materialized_literal_index_delta = | |
| 276 function_state_->next_materialized_literal_index_ - | |
| 277 next_materialized_literal_index_; | |
| 278 function_state_->next_materialized_literal_index_ = | |
| 279 next_materialized_literal_index_; | |
| 280 function_state_->expected_property_count_ = expected_property_count_; | |
| 281 } | |
| 282 | |
| 283 private: | |
| 284 FunctionState* function_state_; | |
| 285 int next_materialized_literal_index_; | |
| 286 int expected_property_count_; | |
| 287 }; | |
| 288 | |
| 289 class ParsingModeScope BASE_EMBEDDED { | |
| 290 public: | |
| 291 ParsingModeScope(ParserBase* parser, Mode mode) | |
| 292 : parser_(parser), | |
| 293 old_mode_(parser->mode()) { | |
| 294 parser_->mode_ = mode; | |
| 295 } | |
| 296 ~ParsingModeScope() { | |
| 297 parser_->mode_ = old_mode_; | |
| 298 } | |
| 299 | |
| 300 private: | |
| 301 ParserBase* parser_; | |
| 302 Mode old_mode_; | |
| 303 }; | |
| 304 | |
| 305 Scope* NewScope(Scope* parent, ScopeType scope_type) { | |
| 306 // Must always pass the function kind for FUNCTION_SCOPE and ARROW_SCOPE. | |
| 307 DCHECK(scope_type != FUNCTION_SCOPE); | |
| 308 DCHECK(scope_type != ARROW_SCOPE); | |
| 309 return NewScope(parent, scope_type, kNormalFunction); | |
| 310 } | |
| 311 | |
| 312 Scope* NewScope(Scope* parent, ScopeType scope_type, FunctionKind kind) { | |
| 313 DCHECK(ast_value_factory()); | |
| 314 DCHECK(scope_type != MODULE_SCOPE || allow_harmony_modules()); | |
| 315 DCHECK(!IsArrowFunction(kind) || scope_type == ARROW_SCOPE); | |
| 316 Scope* result = new (zone()) | |
| 317 Scope(zone(), parent, scope_type, ast_value_factory(), kind); | |
| 318 result->Initialize(); | |
| 319 return result; | |
| 320 } | |
| 321 | |
| 322 Scanner* scanner() const { return scanner_; } | |
| 323 AstValueFactory* ast_value_factory() const { return ast_value_factory_; } | |
| 324 int position() { return scanner_->location().beg_pos; } | |
| 325 int peek_position() { return scanner_->peek_location().beg_pos; } | |
| 326 bool stack_overflow() const { return stack_overflow_; } | |
| 327 void set_stack_overflow() { stack_overflow_ = true; } | |
| 328 Mode mode() const { return mode_; } | |
| 329 Zone* zone() const { return zone_; } | |
| 330 | |
| 331 INLINE(Token::Value peek()) { | |
| 332 if (stack_overflow_) return Token::ILLEGAL; | |
| 333 return scanner()->peek(); | |
| 334 } | |
| 335 | |
| 336 INLINE(Token::Value Next()) { | |
| 337 if (stack_overflow_) return Token::ILLEGAL; | |
| 338 { | |
| 339 if (GetCurrentStackPosition() < stack_limit_) { | |
| 340 // Any further calls to Next or peek will return the illegal token. | |
| 341 // The current call must return the next token, which might already | |
| 342 // have been peek'ed. | |
| 343 stack_overflow_ = true; | |
| 344 } | |
| 345 } | |
| 346 return scanner()->Next(); | |
| 347 } | |
| 348 | |
| 349 void Consume(Token::Value token) { | |
| 350 Token::Value next = Next(); | |
| 351 USE(next); | |
| 352 USE(token); | |
| 353 DCHECK(next == token); | |
| 354 } | |
| 355 | |
| 356 bool Check(Token::Value token) { | |
| 357 Token::Value next = peek(); | |
| 358 if (next == token) { | |
| 359 Consume(next); | |
| 360 return true; | |
| 361 } | |
| 362 return false; | |
| 363 } | |
| 364 | |
| 365 void Expect(Token::Value token, bool* ok) { | |
| 366 Token::Value next = Next(); | |
| 367 if (next != token) { | |
| 368 ReportUnexpectedToken(next); | |
| 369 *ok = false; | |
| 370 } | |
| 371 } | |
| 372 | |
| 373 void ExpectSemicolon(bool* ok) { | |
| 374 // Check for automatic semicolon insertion according to | |
| 375 // the rules given in ECMA-262, section 7.9, page 21. | |
| 376 Token::Value tok = peek(); | |
| 377 if (tok == Token::SEMICOLON) { | |
| 378 Next(); | |
| 379 return; | |
| 380 } | |
| 381 if (scanner()->HasAnyLineTerminatorBeforeNext() || | |
| 382 tok == Token::RBRACE || | |
| 383 tok == Token::EOS) { | |
| 384 return; | |
| 385 } | |
| 386 Expect(Token::SEMICOLON, ok); | |
| 387 } | |
| 388 | |
| 389 bool peek_any_identifier() { | |
| 390 Token::Value next = peek(); | |
| 391 return next == Token::IDENTIFIER || next == Token::FUTURE_RESERVED_WORD || | |
| 392 next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || | |
| 393 next == Token::STATIC || next == Token::YIELD; | |
| 394 } | |
| 395 | |
| 396 bool CheckContextualKeyword(Vector<const char> keyword) { | |
| 397 if (PeekContextualKeyword(keyword)) { | |
| 398 Consume(Token::IDENTIFIER); | |
| 399 return true; | |
| 400 } | |
| 401 return false; | |
| 402 } | |
| 403 | |
| 404 bool PeekContextualKeyword(Vector<const char> keyword) { | |
| 405 return peek() == Token::IDENTIFIER && | |
| 406 scanner()->is_next_contextual_keyword(keyword); | |
| 407 } | |
| 408 | |
| 409 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { | |
| 410 Expect(Token::IDENTIFIER, ok); | |
| 411 if (!*ok) return; | |
| 412 if (!scanner()->is_literal_contextual_keyword(keyword)) { | |
| 413 ReportUnexpectedToken(scanner()->current_token()); | |
| 414 *ok = false; | |
| 415 } | |
| 416 } | |
| 417 | |
| 418 bool CheckInOrOf( | |
| 419 bool accept_OF, ForEachStatement::VisitMode* visit_mode, bool* ok) { | |
| 420 if (Check(Token::IN)) { | |
| 421 if (is_strong(language_mode())) { | |
| 422 ReportMessageAt(scanner()->location(), MessageTemplate::kStrongForIn); | |
| 423 *ok = false; | |
| 424 } else { | |
| 425 *visit_mode = ForEachStatement::ENUMERATE; | |
| 426 } | |
| 427 return true; | |
| 428 } else if (accept_OF && CheckContextualKeyword(CStrVector("of"))) { | |
| 429 *visit_mode = ForEachStatement::ITERATE; | |
| 430 return true; | |
| 431 } | |
| 432 return false; | |
| 433 } | |
| 434 | |
| 435 // Checks whether an octal literal was last seen between beg_pos and end_pos. | |
| 436 // If so, reports an error. Only called for strict mode and template strings. | |
| 437 void CheckOctalLiteral(int beg_pos, int end_pos, | |
| 438 MessageTemplate::Template message, bool* ok) { | |
| 439 Scanner::Location octal = scanner()->octal_position(); | |
| 440 if (octal.IsValid() && beg_pos <= octal.beg_pos && | |
| 441 octal.end_pos <= end_pos) { | |
| 442 ReportMessageAt(octal, message); | |
| 443 scanner()->clear_octal_position(); | |
| 444 *ok = false; | |
| 445 } | |
| 446 } | |
| 447 | |
| 448 inline void CheckStrictOctalLiteral(int beg_pos, int end_pos, bool* ok) { | |
| 449 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kStrictOctalLiteral, | |
| 450 ok); | |
| 451 } | |
| 452 | |
| 453 inline void CheckTemplateOctalLiteral(int beg_pos, int end_pos, bool* ok) { | |
| 454 CheckOctalLiteral(beg_pos, end_pos, MessageTemplate::kTemplateOctalLiteral, | |
| 455 ok); | |
| 456 } | |
| 457 | |
| 458 // Checking the name of a function literal. This has to be done after parsing | |
| 459 // the function, since the function can declare itself strict. | |
| 460 void CheckFunctionName(LanguageMode language_mode, IdentifierT function_name, | |
| 461 FunctionNameValidity function_name_validity, | |
| 462 const Scanner::Location& function_name_loc, bool* ok) { | |
| 463 if (function_name_validity == kSkipFunctionNameCheck) return; | |
| 464 // The function name needs to be checked in strict mode. | |
| 465 if (is_sloppy(language_mode)) return; | |
| 466 | |
| 467 if (this->IsEvalOrArguments(function_name)) { | |
| 468 Traits::ReportMessageAt(function_name_loc, | |
| 469 MessageTemplate::kStrictEvalArguments); | |
| 470 *ok = false; | |
| 471 return; | |
| 472 } | |
| 473 if (function_name_validity == kFunctionNameIsStrictReserved) { | |
| 474 Traits::ReportMessageAt(function_name_loc, | |
| 475 MessageTemplate::kUnexpectedStrictReserved); | |
| 476 *ok = false; | |
| 477 return; | |
| 478 } | |
| 479 if (is_strong(language_mode) && this->IsUndefined(function_name)) { | |
| 480 Traits::ReportMessageAt(function_name_loc, | |
| 481 MessageTemplate::kStrongUndefined); | |
| 482 *ok = false; | |
| 483 return; | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 // Determine precedence of given token. | |
| 488 static int Precedence(Token::Value token, bool accept_IN) { | |
| 489 if (token == Token::IN && !accept_IN) | |
| 490 return 0; // 0 precedence will terminate binary expression parsing | |
| 491 return Token::Precedence(token); | |
| 492 } | |
| 493 | |
| 494 typename Traits::Type::Factory* factory() { | |
| 495 return function_state_->factory(); | |
| 496 } | |
| 497 | |
| 498 LanguageMode language_mode() { return scope_->language_mode(); } | |
| 499 bool is_generator() const { return function_state_->is_generator(); } | |
| 500 | |
| 501 bool allow_const() { | |
| 502 return is_strict(language_mode()) || allow_harmony_sloppy() || | |
| 503 allow_legacy_const(); | |
| 504 } | |
| 505 | |
| 506 bool allow_let() { | |
| 507 return is_strict(language_mode()) || allow_harmony_sloppy(); | |
| 508 } | |
| 509 | |
| 510 // Report syntax errors. | |
| 511 void ReportMessage(MessageTemplate::Template message, const char* arg = NULL, | |
| 512 ParseErrorType error_type = kSyntaxError) { | |
| 513 Scanner::Location source_location = scanner()->location(); | |
| 514 Traits::ReportMessageAt(source_location, message, arg, error_type); | |
| 515 } | |
| 516 | |
| 517 void ReportMessageAt(Scanner::Location location, | |
| 518 MessageTemplate::Template message, | |
| 519 ParseErrorType error_type = kSyntaxError) { | |
| 520 Traits::ReportMessageAt(location, message, reinterpret_cast<const char*>(0), | |
| 521 error_type); | |
| 522 } | |
| 523 | |
| 524 void GetUnexpectedTokenMessage( | |
| 525 Token::Value token, MessageTemplate::Template* message, const char** arg, | |
| 526 MessageTemplate::Template default_ = MessageTemplate::kUnexpectedToken); | |
| 527 | |
| 528 void ReportUnexpectedToken(Token::Value token); | |
| 529 void ReportUnexpectedTokenAt( | |
| 530 Scanner::Location location, Token::Value token, | |
| 531 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken); | |
| 532 | |
| 533 | |
| 534 void ReportClassifierError(const ExpressionClassifier::Error& error) { | |
| 535 Traits::ReportMessageAt(error.location, error.message, error.arg, | |
| 536 kSyntaxError); | |
| 537 } | |
| 538 | |
| 539 void ValidateExpression(const ExpressionClassifier* classifier, bool* ok) { | |
| 540 if (!classifier->is_valid_expression()) { | |
| 541 ReportClassifierError(classifier->expression_error()); | |
| 542 *ok = false; | |
| 543 } | |
| 544 } | |
| 545 | |
| 546 void ValidateBindingPattern(const ExpressionClassifier* classifier, | |
| 547 bool* ok) { | |
| 548 if (!classifier->is_valid_binding_pattern()) { | |
| 549 ReportClassifierError(classifier->binding_pattern_error()); | |
| 550 *ok = false; | |
| 551 } | |
| 552 } | |
| 553 | |
| 554 void ValidateAssignmentPattern(const ExpressionClassifier* classifier, | |
| 555 bool* ok) { | |
| 556 if (!classifier->is_valid_assignment_pattern()) { | |
| 557 ReportClassifierError(classifier->assignment_pattern_error()); | |
| 558 *ok = false; | |
| 559 } | |
| 560 } | |
| 561 | |
| 562 void ValidateFormalParameters(const ExpressionClassifier* classifier, | |
| 563 LanguageMode language_mode, | |
| 564 bool allow_duplicates, bool* ok) { | |
| 565 if (!allow_duplicates && | |
| 566 !classifier->is_valid_formal_parameter_list_without_duplicates()) { | |
| 567 ReportClassifierError(classifier->duplicate_formal_parameter_error()); | |
| 568 *ok = false; | |
| 569 } else if (is_strict(language_mode) && | |
| 570 !classifier->is_valid_strict_mode_formal_parameters()) { | |
| 571 ReportClassifierError(classifier->strict_mode_formal_parameter_error()); | |
| 572 *ok = false; | |
| 573 } else if (is_strong(language_mode) && | |
| 574 !classifier->is_valid_strong_mode_formal_parameters()) { | |
| 575 ReportClassifierError(classifier->strong_mode_formal_parameter_error()); | |
| 576 *ok = false; | |
| 577 } | |
| 578 } | |
| 579 | |
| 580 void ValidateArrowFormalParameters(const ExpressionClassifier* classifier, | |
| 581 ExpressionT expr, | |
| 582 bool parenthesized_formals, bool* ok) { | |
| 583 if (classifier->is_valid_binding_pattern()) { | |
| 584 // A simple arrow formal parameter: IDENTIFIER => BODY. | |
| 585 if (!this->IsIdentifier(expr)) { | |
| 586 Traits::ReportMessageAt(scanner()->location(), | |
| 587 MessageTemplate::kUnexpectedToken, | |
| 588 Token::String(scanner()->current_token())); | |
| 589 *ok = false; | |
| 590 } | |
| 591 } else if (!classifier->is_valid_arrow_formal_parameters()) { | |
| 592 // If after parsing the expr, we see an error but the expression is | |
| 593 // neither a valid binding pattern nor a valid parenthesized formal | |
| 594 // parameter list, show the "arrow formal parameters" error if the formals | |
| 595 // started with a parenthesis, and the binding pattern error otherwise. | |
| 596 const ExpressionClassifier::Error& error = | |
| 597 parenthesized_formals ? classifier->arrow_formal_parameters_error() | |
| 598 : classifier->binding_pattern_error(); | |
| 599 ReportClassifierError(error); | |
| 600 *ok = false; | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 void ExpressionUnexpectedToken(ExpressionClassifier* classifier) { | |
| 605 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | |
| 606 const char* arg; | |
| 607 GetUnexpectedTokenMessage(peek(), &message, &arg); | |
| 608 classifier->RecordExpressionError(scanner()->peek_location(), message, arg); | |
| 609 } | |
| 610 | |
| 611 void BindingPatternUnexpectedToken(ExpressionClassifier* classifier) { | |
| 612 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | |
| 613 const char* arg; | |
| 614 GetUnexpectedTokenMessage(peek(), &message, &arg); | |
| 615 classifier->RecordBindingPatternError(scanner()->peek_location(), message, | |
| 616 arg); | |
| 617 } | |
| 618 | |
| 619 void ArrowFormalParametersUnexpectedToken(ExpressionClassifier* classifier) { | |
| 620 MessageTemplate::Template message = MessageTemplate::kUnexpectedToken; | |
| 621 const char* arg; | |
| 622 GetUnexpectedTokenMessage(peek(), &message, &arg); | |
| 623 classifier->RecordArrowFormalParametersError(scanner()->peek_location(), | |
| 624 message, arg); | |
| 625 } | |
| 626 | |
| 627 // Recursive descent functions: | |
| 628 | |
| 629 // Parses an identifier that is valid for the current scope, in particular it | |
| 630 // fails on strict mode future reserved keywords in a strict scope. If | |
| 631 // allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or | |
| 632 // "arguments" as identifier even in strict mode (this is needed in cases like | |
| 633 // "var foo = eval;"). | |
| 634 IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); | |
| 635 IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | |
| 636 bool* ok); | |
| 637 // Parses an identifier or a strict mode future reserved word, and indicate | |
| 638 // whether it is strict mode future reserved. | |
| 639 IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | |
| 640 bool* ok); | |
| 641 IdentifierT ParseIdentifierName(bool* ok); | |
| 642 // Parses an identifier and determines whether or not it is 'get' or 'set'. | |
| 643 IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set, | |
| 644 bool* ok); | |
| 645 | |
| 646 | |
| 647 ExpressionT ParseRegExpLiteral(bool seen_equal, | |
| 648 ExpressionClassifier* classifier, bool* ok); | |
| 649 | |
| 650 ExpressionT ParsePrimaryExpression(ExpressionClassifier* classifier, | |
| 651 bool* ok); | |
| 652 ExpressionT ParseExpression(bool accept_IN, bool* ok); | |
| 653 ExpressionT ParseExpression(bool accept_IN, ExpressionClassifier* classifier, | |
| 654 bool* ok); | |
| 655 ExpressionT ParseArrayLiteral(ExpressionClassifier* classifier, bool* ok); | |
| 656 ExpressionT ParsePropertyName(IdentifierT* name, bool* is_get, bool* is_set, | |
| 657 bool* is_static, bool* is_computed_name, | |
| 658 ExpressionClassifier* classifier, bool* ok); | |
| 659 ExpressionT ParseObjectLiteral(ExpressionClassifier* classifier, bool* ok); | |
| 660 ObjectLiteralPropertyT ParsePropertyDefinition( | |
| 661 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | |
| 662 bool is_static, bool* is_computed_name, bool* has_seen_constructor, | |
| 663 ExpressionClassifier* classifier, bool* ok); | |
| 664 typename Traits::Type::ExpressionList ParseArguments( | |
| 665 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, | |
| 666 bool* ok); | |
| 667 ExpressionT ParseAssignmentExpression(bool accept_IN, | |
| 668 ExpressionClassifier* classifier, | |
| 669 bool* ok); | |
| 670 ExpressionT ParseYieldExpression(ExpressionClassifier* classifier, bool* ok); | |
| 671 ExpressionT ParseConditionalExpression(bool accept_IN, | |
| 672 ExpressionClassifier* classifier, | |
| 673 bool* ok); | |
| 674 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, | |
| 675 ExpressionClassifier* classifier, bool* ok); | |
| 676 ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok); | |
| 677 ExpressionT ParsePostfixExpression(ExpressionClassifier* classifier, | |
| 678 bool* ok); | |
| 679 ExpressionT ParseLeftHandSideExpression(ExpressionClassifier* classifier, | |
| 680 bool* ok); | |
| 681 ExpressionT ParseMemberWithNewPrefixesExpression( | |
| 682 ExpressionClassifier* classifier, bool* ok); | |
| 683 ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok); | |
| 684 ExpressionT ParseMemberExpressionContinuation( | |
| 685 ExpressionT expression, ExpressionClassifier* classifier, bool* ok); | |
| 686 ExpressionT ParseArrowFunctionLiteral( | |
| 687 const FormalParameterParsingStateT& parsing_state, | |
| 688 const ExpressionClassifier& classifier, bool* ok); | |
| 689 ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, | |
| 690 ExpressionClassifier* classifier, bool* ok); | |
| 691 void AddTemplateExpression(ExpressionT); | |
| 692 ExpressionT ParseSuperExpression(bool is_new, | |
| 693 ExpressionClassifier* classifier, bool* ok); | |
| 694 ExpressionT ParseNewTargetExpression(bool* ok); | |
| 695 ExpressionT ParseStrongInitializationExpression( | |
| 696 ExpressionClassifier* classifier, bool* ok); | |
| 697 ExpressionT ParseStrongSuperCallExpression(ExpressionClassifier* classifier, | |
| 698 bool* ok); | |
| 699 | |
| 700 void ParseFormalParameter(bool is_rest, | |
| 701 FormalParameterParsingStateT* parsing_result, | |
| 702 ExpressionClassifier* classifier, bool* ok); | |
| 703 int ParseFormalParameterList(FormalParameterParsingStateT* parsing_state, | |
| 704 ExpressionClassifier* classifier, bool* ok); | |
| 705 void CheckArityRestrictions( | |
| 706 int param_count, FunctionLiteral::ArityRestriction arity_restriction, | |
| 707 bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok); | |
| 708 | |
| 709 // Checks if the expression is a valid reference expression (e.g., on the | |
| 710 // left-hand side of assignments). Although ruled out by ECMA as early errors, | |
| 711 // we allow calls for web compatibility and rewrite them to a runtime throw. | |
| 712 ExpressionT CheckAndRewriteReferenceExpression( | |
| 713 ExpressionT expression, Scanner::Location location, | |
| 714 MessageTemplate::Template message, bool* ok); | |
| 715 | |
| 716 // Used to validate property names in object literals and class literals | |
| 717 enum PropertyKind { | |
| 718 kAccessorProperty, | |
| 719 kValueProperty, | |
| 720 kMethodProperty | |
| 721 }; | |
| 722 | |
| 723 class ObjectLiteralCheckerBase { | |
| 724 public: | |
| 725 explicit ObjectLiteralCheckerBase(ParserBase* parser) : parser_(parser) {} | |
| 726 | |
| 727 virtual void CheckProperty(Token::Value property, PropertyKind type, | |
| 728 bool is_static, bool is_generator, bool* ok) = 0; | |
| 729 | |
| 730 virtual ~ObjectLiteralCheckerBase() {} | |
| 731 | |
| 732 protected: | |
| 733 ParserBase* parser() const { return parser_; } | |
| 734 Scanner* scanner() const { return parser_->scanner(); } | |
| 735 | |
| 736 private: | |
| 737 ParserBase* parser_; | |
| 738 }; | |
| 739 | |
| 740 // Validation per ES6 object literals. | |
| 741 class ObjectLiteralChecker : public ObjectLiteralCheckerBase { | |
| 742 public: | |
| 743 explicit ObjectLiteralChecker(ParserBase* parser) | |
| 744 : ObjectLiteralCheckerBase(parser), has_seen_proto_(false) {} | |
| 745 | |
| 746 void CheckProperty(Token::Value property, PropertyKind type, bool is_static, | |
| 747 bool is_generator, bool* ok) override; | |
| 748 | |
| 749 private: | |
| 750 bool IsProto() { return this->scanner()->LiteralMatches("__proto__", 9); } | |
| 751 | |
| 752 bool has_seen_proto_; | |
| 753 }; | |
| 754 | |
| 755 // Validation per ES6 class literals. | |
| 756 class ClassLiteralChecker : public ObjectLiteralCheckerBase { | |
| 757 public: | |
| 758 explicit ClassLiteralChecker(ParserBase* parser) | |
| 759 : ObjectLiteralCheckerBase(parser), has_seen_constructor_(false) {} | |
| 760 | |
| 761 void CheckProperty(Token::Value property, PropertyKind type, bool is_static, | |
| 762 bool is_generator, bool* ok) override; | |
| 763 | |
| 764 private: | |
| 765 bool IsConstructor() { | |
| 766 return this->scanner()->LiteralMatches("constructor", 11); | |
| 767 } | |
| 768 bool IsPrototype() { | |
| 769 return this->scanner()->LiteralMatches("prototype", 9); | |
| 770 } | |
| 771 | |
| 772 bool has_seen_constructor_; | |
| 773 }; | |
| 774 | |
| 775 // If true, the next (and immediately following) function literal is | |
| 776 // preceded by a parenthesis. | |
| 777 // Heuristically that means that the function will be called immediately, | |
| 778 // so never lazily compile it. | |
| 779 bool parenthesized_function_; | |
| 780 | |
| 781 Scope* scope_; // Scope stack. | |
| 782 FunctionState* function_state_; // Function state stack. | |
| 783 v8::Extension* extension_; | |
| 784 FuncNameInferrer* fni_; | |
| 785 AstValueFactory* ast_value_factory_; // Not owned. | |
| 786 ParserRecorder* log_; | |
| 787 Mode mode_; | |
| 788 uintptr_t stack_limit_; | |
| 789 | |
| 790 private: | |
| 791 Zone* zone_; | |
| 792 | |
| 793 Scanner* scanner_; | |
| 794 bool stack_overflow_; | |
| 795 | |
| 796 bool allow_lazy_; | |
| 797 bool allow_natives_; | |
| 798 bool allow_harmony_arrow_functions_; | |
| 799 bool allow_harmony_sloppy_; | |
| 800 bool allow_harmony_computed_property_names_; | |
| 801 bool allow_harmony_rest_params_; | |
| 802 bool allow_harmony_spreadcalls_; | |
| 803 bool allow_harmony_destructuring_; | |
| 804 bool allow_harmony_spread_arrays_; | |
| 805 bool allow_harmony_new_target_; | |
| 806 bool allow_strong_mode_; | |
| 807 bool allow_legacy_const_; | |
| 808 }; | |
| 809 | |
| 810 | |
| 811 class PreParserIdentifier { | 21 class PreParserIdentifier { |
| 812 public: | 22 public: |
| 813 PreParserIdentifier() : type_(kUnknownIdentifier) {} | 23 PreParserIdentifier() : type_(kUnknownIdentifier) {} |
| 814 static PreParserIdentifier Default() { | 24 static PreParserIdentifier Default() { |
| 815 return PreParserIdentifier(kUnknownIdentifier); | 25 return PreParserIdentifier(kUnknownIdentifier); |
| 816 } | 26 } |
| 817 static PreParserIdentifier Eval() { | 27 static PreParserIdentifier Eval() { |
| 818 return PreParserIdentifier(kEvalIdentifier); | 28 return PreParserIdentifier(kEvalIdentifier); |
| 819 } | 29 } |
| 820 static PreParserIdentifier Arguments() { | 30 static PreParserIdentifier Arguments() { |
| (...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1835 } | 1045 } |
| 1836 | 1046 |
| 1837 | 1047 |
| 1838 PreParserStatementList PreParserTraits::ParseEagerFunctionBody( | 1048 PreParserStatementList PreParserTraits::ParseEagerFunctionBody( |
| 1839 PreParserIdentifier function_name, int pos, | 1049 PreParserIdentifier function_name, int pos, |
| 1840 const PreParserFormalParameterParsingState& formal_parameters, | 1050 const PreParserFormalParameterParsingState& formal_parameters, |
| 1841 Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok) { | 1051 Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok) { |
| 1842 return pre_parser_->ParseEagerFunctionBody( | 1052 return pre_parser_->ParseEagerFunctionBody( |
| 1843 function_name, pos, formal_parameters, fvar, fvar_init_op, kind, ok); | 1053 function_name, pos, formal_parameters, fvar, fvar_init_op, kind, ok); |
| 1844 } | 1054 } |
| 1845 | |
| 1846 | |
| 1847 template <class Traits> | |
| 1848 ParserBase<Traits>::FunctionState::FunctionState( | |
| 1849 FunctionState** function_state_stack, Scope** scope_stack, Scope* scope, | |
| 1850 FunctionKind kind, typename Traits::Type::Factory* factory) | |
| 1851 : next_materialized_literal_index_(0), | |
| 1852 expected_property_count_(0), | |
| 1853 this_location_(Scanner::Location::invalid()), | |
| 1854 return_location_(Scanner::Location::invalid()), | |
| 1855 super_location_(Scanner::Location::invalid()), | |
| 1856 kind_(kind), | |
| 1857 generator_object_variable_(NULL), | |
| 1858 function_state_stack_(function_state_stack), | |
| 1859 outer_function_state_(*function_state_stack), | |
| 1860 scope_stack_(scope_stack), | |
| 1861 outer_scope_(*scope_stack), | |
| 1862 factory_(factory) { | |
| 1863 *scope_stack_ = scope; | |
| 1864 *function_state_stack = this; | |
| 1865 } | |
| 1866 | |
| 1867 | |
| 1868 template <class Traits> | |
| 1869 ParserBase<Traits>::FunctionState::~FunctionState() { | |
| 1870 *scope_stack_ = outer_scope_; | |
| 1871 *function_state_stack_ = outer_function_state_; | |
| 1872 } | |
| 1873 | |
| 1874 | |
| 1875 template <class Traits> | |
| 1876 void ParserBase<Traits>::GetUnexpectedTokenMessage( | |
| 1877 Token::Value token, MessageTemplate::Template* message, const char** arg, | |
| 1878 MessageTemplate::Template default_) { | |
| 1879 // Four of the tokens are treated specially | |
| 1880 switch (token) { | |
| 1881 case Token::EOS: | |
| 1882 *message = MessageTemplate::kUnexpectedEOS; | |
| 1883 *arg = nullptr; | |
| 1884 break; | |
| 1885 case Token::SMI: | |
| 1886 case Token::NUMBER: | |
| 1887 *message = MessageTemplate::kUnexpectedTokenNumber; | |
| 1888 *arg = nullptr; | |
| 1889 break; | |
| 1890 case Token::STRING: | |
| 1891 *message = MessageTemplate::kUnexpectedTokenString; | |
| 1892 *arg = nullptr; | |
| 1893 break; | |
| 1894 case Token::IDENTIFIER: | |
| 1895 *message = MessageTemplate::kUnexpectedTokenIdentifier; | |
| 1896 *arg = nullptr; | |
| 1897 break; | |
| 1898 case Token::FUTURE_RESERVED_WORD: | |
| 1899 *message = MessageTemplate::kUnexpectedReserved; | |
| 1900 *arg = nullptr; | |
| 1901 break; | |
| 1902 case Token::LET: | |
| 1903 case Token::STATIC: | |
| 1904 case Token::YIELD: | |
| 1905 case Token::FUTURE_STRICT_RESERVED_WORD: | |
| 1906 *message = is_strict(language_mode()) | |
| 1907 ? MessageTemplate::kUnexpectedStrictReserved | |
| 1908 : MessageTemplate::kUnexpectedTokenIdentifier; | |
| 1909 *arg = nullptr; | |
| 1910 break; | |
| 1911 case Token::TEMPLATE_SPAN: | |
| 1912 case Token::TEMPLATE_TAIL: | |
| 1913 *message = MessageTemplate::kUnexpectedTemplateString; | |
| 1914 *arg = nullptr; | |
| 1915 break; | |
| 1916 default: | |
| 1917 const char* name = Token::String(token); | |
| 1918 DCHECK(name != NULL); | |
| 1919 *arg = name; | |
| 1920 break; | |
| 1921 } | |
| 1922 } | |
| 1923 | |
| 1924 | |
| 1925 template <class Traits> | |
| 1926 void ParserBase<Traits>::ReportUnexpectedToken(Token::Value token) { | |
| 1927 return ReportUnexpectedTokenAt(scanner_->location(), token); | |
| 1928 } | |
| 1929 | |
| 1930 | |
| 1931 template <class Traits> | |
| 1932 void ParserBase<Traits>::ReportUnexpectedTokenAt( | |
| 1933 Scanner::Location source_location, Token::Value token, | |
| 1934 MessageTemplate::Template message) { | |
| 1935 const char* arg; | |
| 1936 GetUnexpectedTokenMessage(token, &message, &arg); | |
| 1937 Traits::ReportMessageAt(source_location, message, arg); | |
| 1938 } | |
| 1939 | |
| 1940 | |
| 1941 template <class Traits> | |
| 1942 typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( | |
| 1943 AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { | |
| 1944 ExpressionClassifier classifier; | |
| 1945 auto result = ParseAndClassifyIdentifier(&classifier, ok); | |
| 1946 if (!*ok) return Traits::EmptyIdentifier(); | |
| 1947 | |
| 1948 if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { | |
| 1949 ValidateAssignmentPattern(&classifier, ok); | |
| 1950 if (!*ok) return Traits::EmptyIdentifier(); | |
| 1951 ValidateBindingPattern(&classifier, ok); | |
| 1952 if (!*ok) return Traits::EmptyIdentifier(); | |
| 1953 } else { | |
| 1954 ValidateExpression(&classifier, ok); | |
| 1955 if (!*ok) return Traits::EmptyIdentifier(); | |
| 1956 } | |
| 1957 | |
| 1958 return result; | |
| 1959 } | |
| 1960 | |
| 1961 | |
| 1962 template <class Traits> | |
| 1963 typename ParserBase<Traits>::IdentifierT | |
| 1964 ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier, | |
| 1965 bool* ok) { | |
| 1966 Token::Value next = Next(); | |
| 1967 if (next == Token::IDENTIFIER) { | |
| 1968 IdentifierT name = this->GetSymbol(scanner()); | |
| 1969 // When this function is used to read a formal parameter, we don't always | |
| 1970 // know whether the function is going to be strict or sloppy. Indeed for | |
| 1971 // arrow functions we don't always know that the identifier we are reading | |
| 1972 // is actually a formal parameter. Therefore besides the errors that we | |
| 1973 // must detect because we know we're in strict mode, we also record any | |
| 1974 // error that we might make in the future once we know the language mode. | |
| 1975 if (this->IsEval(name)) { | |
| 1976 classifier->RecordStrictModeFormalParameterError( | |
| 1977 scanner()->location(), MessageTemplate::kStrictEvalArguments); | |
| 1978 if (is_strict(language_mode())) { | |
| 1979 classifier->RecordBindingPatternError( | |
| 1980 scanner()->location(), MessageTemplate::kStrictEvalArguments); | |
| 1981 } | |
| 1982 } | |
| 1983 if (this->IsArguments(name)) { | |
| 1984 scope_->RecordArgumentsUsage(); | |
| 1985 classifier->RecordStrictModeFormalParameterError( | |
| 1986 scanner()->location(), MessageTemplate::kStrictEvalArguments); | |
| 1987 if (is_strict(language_mode())) { | |
| 1988 classifier->RecordBindingPatternError( | |
| 1989 scanner()->location(), MessageTemplate::kStrictEvalArguments); | |
| 1990 } | |
| 1991 if (is_strong(language_mode())) { | |
| 1992 classifier->RecordExpressionError(scanner()->location(), | |
| 1993 MessageTemplate::kStrongArguments); | |
| 1994 } | |
| 1995 } | |
| 1996 if (this->IsUndefined(name)) { | |
| 1997 classifier->RecordStrongModeFormalParameterError( | |
| 1998 scanner()->location(), MessageTemplate::kStrongUndefined); | |
| 1999 if (is_strong(language_mode())) { | |
| 2000 // TODO(dslomov): allow 'undefined' in nested patterns. | |
| 2001 classifier->RecordBindingPatternError( | |
| 2002 scanner()->location(), MessageTemplate::kStrongUndefined); | |
| 2003 classifier->RecordAssignmentPatternError( | |
| 2004 scanner()->location(), MessageTemplate::kStrongUndefined); | |
| 2005 } | |
| 2006 } | |
| 2007 | |
| 2008 if (classifier->duplicate_finder() != nullptr && | |
| 2009 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { | |
| 2010 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | |
| 2011 } | |
| 2012 return name; | |
| 2013 } else if (is_sloppy(language_mode()) && | |
| 2014 (next == Token::FUTURE_STRICT_RESERVED_WORD || | |
| 2015 next == Token::LET || next == Token::STATIC || | |
| 2016 (next == Token::YIELD && !is_generator()))) { | |
| 2017 classifier->RecordStrictModeFormalParameterError( | |
| 2018 scanner()->location(), MessageTemplate::kUnexpectedStrictReserved); | |
| 2019 return this->GetSymbol(scanner()); | |
| 2020 } else { | |
| 2021 this->ReportUnexpectedToken(next); | |
| 2022 *ok = false; | |
| 2023 return Traits::EmptyIdentifier(); | |
| 2024 } | |
| 2025 } | |
| 2026 | |
| 2027 | |
| 2028 template <class Traits> | |
| 2029 typename ParserBase<Traits>::IdentifierT ParserBase< | |
| 2030 Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, | |
| 2031 bool* ok) { | |
| 2032 Token::Value next = Next(); | |
| 2033 if (next == Token::IDENTIFIER) { | |
| 2034 *is_strict_reserved = false; | |
| 2035 } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET || | |
| 2036 next == Token::STATIC || | |
| 2037 (next == Token::YIELD && !this->is_generator())) { | |
| 2038 *is_strict_reserved = true; | |
| 2039 } else { | |
| 2040 ReportUnexpectedToken(next); | |
| 2041 *ok = false; | |
| 2042 return Traits::EmptyIdentifier(); | |
| 2043 } | |
| 2044 | |
| 2045 IdentifierT name = this->GetSymbol(scanner()); | |
| 2046 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); | |
| 2047 return name; | |
| 2048 } | |
| 2049 | |
| 2050 | |
| 2051 template <class Traits> | |
| 2052 typename ParserBase<Traits>::IdentifierT | |
| 2053 ParserBase<Traits>::ParseIdentifierName(bool* ok) { | |
| 2054 Token::Value next = Next(); | |
| 2055 if (next != Token::IDENTIFIER && next != Token::FUTURE_RESERVED_WORD && | |
| 2056 next != Token::LET && next != Token::STATIC && next != Token::YIELD && | |
| 2057 next != Token::FUTURE_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) { | |
| 2058 this->ReportUnexpectedToken(next); | |
| 2059 *ok = false; | |
| 2060 return Traits::EmptyIdentifier(); | |
| 2061 } | |
| 2062 | |
| 2063 IdentifierT name = this->GetSymbol(scanner()); | |
| 2064 if (this->IsArguments(name)) scope_->RecordArgumentsUsage(); | |
| 2065 return name; | |
| 2066 } | |
| 2067 | |
| 2068 | |
| 2069 template <class Traits> | |
| 2070 typename ParserBase<Traits>::IdentifierT | |
| 2071 ParserBase<Traits>::ParseIdentifierNameOrGetOrSet(bool* is_get, | |
| 2072 bool* is_set, | |
| 2073 bool* ok) { | |
| 2074 IdentifierT result = ParseIdentifierName(ok); | |
| 2075 if (!*ok) return Traits::EmptyIdentifier(); | |
| 2076 scanner()->IsGetOrSet(is_get, is_set); | |
| 2077 return result; | |
| 2078 } | |
| 2079 | |
| 2080 | |
| 2081 template <class Traits> | |
| 2082 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral( | |
| 2083 bool seen_equal, ExpressionClassifier* classifier, bool* ok) { | |
| 2084 int pos = peek_position(); | |
| 2085 if (!scanner()->ScanRegExpPattern(seen_equal)) { | |
| 2086 Next(); | |
| 2087 ReportMessage(MessageTemplate::kUnterminatedRegExp); | |
| 2088 *ok = false; | |
| 2089 return Traits::EmptyExpression(); | |
| 2090 } | |
| 2091 | |
| 2092 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
| 2093 | |
| 2094 IdentifierT js_pattern = this->GetNextSymbol(scanner()); | |
| 2095 if (!scanner()->ScanRegExpFlags()) { | |
| 2096 Next(); | |
| 2097 ReportMessage(MessageTemplate::kMalformedRegExpFlags); | |
| 2098 *ok = false; | |
| 2099 return Traits::EmptyExpression(); | |
| 2100 } | |
| 2101 IdentifierT js_flags = this->GetNextSymbol(scanner()); | |
| 2102 Next(); | |
| 2103 return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, | |
| 2104 is_strong(language_mode()), pos); | |
| 2105 } | |
| 2106 | |
| 2107 | |
| 2108 #define CHECK_OK ok); \ | |
| 2109 if (!*ok) return this->EmptyExpression(); \ | |
| 2110 ((void)0 | |
| 2111 #define DUMMY ) // to make indentation work | |
| 2112 #undef DUMMY | |
| 2113 | |
| 2114 // Used in functions where the return type is not ExpressionT. | |
| 2115 #define CHECK_OK_CUSTOM(x) ok); \ | |
| 2116 if (!*ok) return this->x(); \ | |
| 2117 ((void)0 | |
| 2118 #define DUMMY ) // to make indentation work | |
| 2119 #undef DUMMY | |
| 2120 | |
| 2121 | |
| 2122 template <class Traits> | |
| 2123 typename ParserBase<Traits>::ExpressionT | |
| 2124 ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier, | |
| 2125 bool* ok) { | |
| 2126 // PrimaryExpression :: | |
| 2127 // 'this' | |
| 2128 // 'null' | |
| 2129 // 'true' | |
| 2130 // 'false' | |
| 2131 // Identifier | |
| 2132 // Number | |
| 2133 // String | |
| 2134 // ArrayLiteral | |
| 2135 // ObjectLiteral | |
| 2136 // RegExpLiteral | |
| 2137 // ClassLiteral | |
| 2138 // '(' Expression ')' | |
| 2139 // TemplateLiteral | |
| 2140 | |
| 2141 int beg_pos = scanner()->peek_location().beg_pos; | |
| 2142 int end_pos = scanner()->peek_location().end_pos; | |
| 2143 ExpressionT result = this->EmptyExpression(); | |
| 2144 Token::Value token = peek(); | |
| 2145 switch (token) { | |
| 2146 case Token::THIS: { | |
| 2147 BindingPatternUnexpectedToken(classifier); | |
| 2148 Consume(Token::THIS); | |
| 2149 if (FLAG_strong_this && is_strong(language_mode())) { | |
| 2150 // Constructors' usages of 'this' in strong mode are parsed separately. | |
| 2151 // TODO(rossberg): this does not work with arrow functions yet. | |
| 2152 if (i::IsConstructor(function_state_->kind())) { | |
| 2153 ReportMessage(MessageTemplate::kStrongConstructorThis); | |
| 2154 *ok = false; | |
| 2155 break; | |
| 2156 } | |
| 2157 } | |
| 2158 result = this->ThisExpression(scope_, factory(), beg_pos); | |
| 2159 break; | |
| 2160 } | |
| 2161 | |
| 2162 case Token::NULL_LITERAL: | |
| 2163 case Token::TRUE_LITERAL: | |
| 2164 case Token::FALSE_LITERAL: | |
| 2165 BindingPatternUnexpectedToken(classifier); | |
| 2166 Next(); | |
| 2167 result = | |
| 2168 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); | |
| 2169 break; | |
| 2170 case Token::SMI: | |
| 2171 case Token::NUMBER: | |
| 2172 classifier->RecordBindingPatternError( | |
| 2173 scanner()->location(), MessageTemplate::kUnexpectedTokenNumber); | |
| 2174 Next(); | |
| 2175 result = | |
| 2176 this->ExpressionFromLiteral(token, beg_pos, scanner(), factory()); | |
| 2177 break; | |
| 2178 | |
| 2179 case Token::IDENTIFIER: | |
| 2180 case Token::LET: | |
| 2181 case Token::STATIC: | |
| 2182 case Token::YIELD: | |
| 2183 case Token::FUTURE_STRICT_RESERVED_WORD: { | |
| 2184 // Using eval or arguments in this context is OK even in strict mode. | |
| 2185 IdentifierT name = ParseAndClassifyIdentifier(classifier, CHECK_OK); | |
| 2186 result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, | |
| 2187 factory()); | |
| 2188 break; | |
| 2189 } | |
| 2190 | |
| 2191 case Token::STRING: { | |
| 2192 classifier->RecordBindingPatternError( | |
| 2193 scanner()->location(), MessageTemplate::kUnexpectedTokenString); | |
| 2194 Consume(Token::STRING); | |
| 2195 result = this->ExpressionFromString(beg_pos, scanner(), factory()); | |
| 2196 break; | |
| 2197 } | |
| 2198 | |
| 2199 case Token::ASSIGN_DIV: | |
| 2200 result = this->ParseRegExpLiteral(true, classifier, CHECK_OK); | |
| 2201 break; | |
| 2202 | |
| 2203 case Token::DIV: | |
| 2204 result = this->ParseRegExpLiteral(false, classifier, CHECK_OK); | |
| 2205 break; | |
| 2206 | |
| 2207 case Token::LBRACK: | |
| 2208 if (!allow_harmony_destructuring()) { | |
| 2209 BindingPatternUnexpectedToken(classifier); | |
| 2210 } | |
| 2211 result = this->ParseArrayLiteral(classifier, CHECK_OK); | |
| 2212 break; | |
| 2213 | |
| 2214 case Token::LBRACE: | |
| 2215 if (!allow_harmony_destructuring()) { | |
| 2216 BindingPatternUnexpectedToken(classifier); | |
| 2217 } | |
| 2218 result = this->ParseObjectLiteral(classifier, CHECK_OK); | |
| 2219 break; | |
| 2220 | |
| 2221 case Token::LPAREN: | |
| 2222 // Arrow function formal parameters are either a single identifier or a | |
| 2223 // list of BindingPattern productions enclosed in parentheses. | |
| 2224 // Parentheses are not valid on the LHS of a BindingPattern, so we use the | |
| 2225 // is_valid_binding_pattern() check to detect multiple levels of | |
| 2226 // parenthesization. | |
| 2227 if (!classifier->is_valid_binding_pattern()) { | |
| 2228 ArrowFormalParametersUnexpectedToken(classifier); | |
| 2229 } | |
| 2230 BindingPatternUnexpectedToken(classifier); | |
| 2231 Consume(Token::LPAREN); | |
| 2232 if (allow_harmony_arrow_functions() && Check(Token::RPAREN)) { | |
| 2233 // As a primary expression, the only thing that can follow "()" is "=>". | |
| 2234 classifier->RecordBindingPatternError(scanner()->location(), | |
| 2235 MessageTemplate::kUnexpectedToken, | |
| 2236 Token::String(Token::RPAREN)); | |
| 2237 // Give a good error to the user who might have typed e.g. "return();". | |
| 2238 if (peek() != Token::ARROW) { | |
| 2239 ReportUnexpectedTokenAt(scanner_->peek_location(), peek(), | |
| 2240 MessageTemplate::kMissingArrow); | |
| 2241 *ok = false; | |
| 2242 return this->EmptyExpression(); | |
| 2243 } | |
| 2244 Scope* scope = | |
| 2245 this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); | |
| 2246 FormalParameterParsingStateT parsing_state(scope); | |
| 2247 scope->set_start_position(beg_pos); | |
| 2248 ExpressionClassifier args_classifier; | |
| 2249 result = this->ParseArrowFunctionLiteral(parsing_state, args_classifier, | |
| 2250 CHECK_OK); | |
| 2251 } else if (allow_harmony_arrow_functions() && | |
| 2252 allow_harmony_rest_params() && Check(Token::ELLIPSIS)) { | |
| 2253 // (...x) => y | |
| 2254 Scope* scope = | |
| 2255 this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); | |
| 2256 FormalParameterParsingStateT parsing_state(scope); | |
| 2257 scope->set_start_position(beg_pos); | |
| 2258 ExpressionClassifier args_classifier; | |
| 2259 const bool is_rest = true; | |
| 2260 this->ParseFormalParameter(is_rest, &parsing_state, &args_classifier, | |
| 2261 CHECK_OK); | |
| 2262 if (peek() == Token::COMMA) { | |
| 2263 ReportMessageAt(scanner()->peek_location(), | |
| 2264 MessageTemplate::kParamAfterRest); | |
| 2265 *ok = false; | |
| 2266 return this->EmptyExpression(); | |
| 2267 } | |
| 2268 Expect(Token::RPAREN, CHECK_OK); | |
| 2269 result = this->ParseArrowFunctionLiteral(parsing_state, args_classifier, | |
| 2270 CHECK_OK); | |
| 2271 } else { | |
| 2272 // Heuristically try to detect immediately called functions before | |
| 2273 // seeing the call parentheses. | |
| 2274 parenthesized_function_ = (peek() == Token::FUNCTION); | |
| 2275 result = this->ParseExpression(true, classifier, CHECK_OK); | |
| 2276 Expect(Token::RPAREN, CHECK_OK); | |
| 2277 } | |
| 2278 break; | |
| 2279 | |
| 2280 case Token::CLASS: { | |
| 2281 BindingPatternUnexpectedToken(classifier); | |
| 2282 Consume(Token::CLASS); | |
| 2283 if (!allow_harmony_sloppy() && is_sloppy(language_mode())) { | |
| 2284 ReportMessage(MessageTemplate::kSloppyLexical); | |
| 2285 *ok = false; | |
| 2286 break; | |
| 2287 } | |
| 2288 int class_token_position = position(); | |
| 2289 IdentifierT name = this->EmptyIdentifier(); | |
| 2290 bool is_strict_reserved_name = false; | |
| 2291 Scanner::Location class_name_location = Scanner::Location::invalid(); | |
| 2292 if (peek_any_identifier()) { | |
| 2293 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, | |
| 2294 CHECK_OK); | |
| 2295 class_name_location = scanner()->location(); | |
| 2296 } | |
| 2297 result = this->ParseClassLiteral(name, class_name_location, | |
| 2298 is_strict_reserved_name, | |
| 2299 class_token_position, CHECK_OK); | |
| 2300 break; | |
| 2301 } | |
| 2302 | |
| 2303 case Token::TEMPLATE_SPAN: | |
| 2304 case Token::TEMPLATE_TAIL: | |
| 2305 result = this->ParseTemplateLiteral(Traits::NoTemplateTag(), beg_pos, | |
| 2306 classifier, CHECK_OK); | |
| 2307 break; | |
| 2308 | |
| 2309 case Token::MOD: | |
| 2310 if (allow_natives() || extension_ != NULL) { | |
| 2311 result = this->ParseV8Intrinsic(CHECK_OK); | |
| 2312 break; | |
| 2313 } | |
| 2314 // If we're not allowing special syntax we fall-through to the | |
| 2315 // default case. | |
| 2316 | |
| 2317 default: { | |
| 2318 Next(); | |
| 2319 ReportUnexpectedToken(token); | |
| 2320 *ok = false; | |
| 2321 } | |
| 2322 } | |
| 2323 | |
| 2324 return result; | |
| 2325 } | |
| 2326 | |
| 2327 | |
| 2328 template <class Traits> | |
| 2329 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( | |
| 2330 bool accept_IN, bool* ok) { | |
| 2331 ExpressionClassifier classifier; | |
| 2332 ExpressionT result = ParseExpression(accept_IN, &classifier, CHECK_OK); | |
| 2333 ValidateExpression(&classifier, CHECK_OK); | |
| 2334 return result; | |
| 2335 } | |
| 2336 | |
| 2337 | |
| 2338 // Precedence = 1 | |
| 2339 template <class Traits> | |
| 2340 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseExpression( | |
| 2341 bool accept_IN, ExpressionClassifier* classifier, bool* ok) { | |
| 2342 // Expression :: | |
| 2343 // AssignmentExpression | |
| 2344 // Expression ',' AssignmentExpression | |
| 2345 | |
| 2346 ExpressionClassifier binding_classifier; | |
| 2347 ExpressionT result = | |
| 2348 this->ParseAssignmentExpression(accept_IN, &binding_classifier, CHECK_OK); | |
| 2349 classifier->Accumulate(binding_classifier, | |
| 2350 ExpressionClassifier::AllProductions); | |
| 2351 bool seen_rest = false; | |
| 2352 while (peek() == Token::COMMA) { | |
| 2353 if (seen_rest) { | |
| 2354 // At this point the production can't possibly be valid, but we don't know | |
| 2355 // which error to signal. | |
| 2356 classifier->RecordArrowFormalParametersError( | |
| 2357 scanner()->peek_location(), MessageTemplate::kParamAfterRest); | |
| 2358 } | |
| 2359 Consume(Token::COMMA); | |
| 2360 bool is_rest = false; | |
| 2361 if (allow_harmony_rest_params() && peek() == Token::ELLIPSIS) { | |
| 2362 // 'x, y, ...z' in CoverParenthesizedExpressionAndArrowParameterList only | |
| 2363 // as the formal parameters of'(x, y, ...z) => foo', and is not itself a | |
| 2364 // valid expression or binding pattern. | |
| 2365 ExpressionUnexpectedToken(classifier); | |
| 2366 BindingPatternUnexpectedToken(classifier); | |
| 2367 Consume(Token::ELLIPSIS); | |
| 2368 seen_rest = is_rest = true; | |
| 2369 } | |
| 2370 int pos = position(); | |
| 2371 ExpressionT right = this->ParseAssignmentExpression( | |
| 2372 accept_IN, &binding_classifier, CHECK_OK); | |
| 2373 if (is_rest) right = factory()->NewSpread(right, pos); | |
| 2374 classifier->Accumulate(binding_classifier, | |
| 2375 ExpressionClassifier::AllProductions); | |
| 2376 result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos); | |
| 2377 } | |
| 2378 return result; | |
| 2379 } | |
| 2380 | |
| 2381 | |
| 2382 template <class Traits> | |
| 2383 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral( | |
| 2384 ExpressionClassifier* classifier, bool* ok) { | |
| 2385 // ArrayLiteral :: | |
| 2386 // '[' Expression? (',' Expression?)* ']' | |
| 2387 | |
| 2388 int pos = peek_position(); | |
| 2389 typename Traits::Type::ExpressionList values = | |
| 2390 this->NewExpressionList(4, zone_); | |
| 2391 Expect(Token::LBRACK, CHECK_OK); | |
| 2392 while (peek() != Token::RBRACK) { | |
| 2393 bool seen_spread = false; | |
| 2394 ExpressionT elem = this->EmptyExpression(); | |
| 2395 if (peek() == Token::COMMA) { | |
| 2396 if (is_strong(language_mode())) { | |
| 2397 ReportMessageAt(scanner()->peek_location(), | |
| 2398 MessageTemplate::kStrongEllision); | |
| 2399 *ok = false; | |
| 2400 return this->EmptyExpression(); | |
| 2401 } | |
| 2402 elem = this->GetLiteralTheHole(peek_position(), factory()); | |
| 2403 } else if (peek() == Token::ELLIPSIS) { | |
| 2404 if (!allow_harmony_spread_arrays()) { | |
| 2405 ExpressionUnexpectedToken(classifier); | |
| 2406 } | |
| 2407 int start_pos = peek_position(); | |
| 2408 Consume(Token::ELLIPSIS); | |
| 2409 ExpressionT argument = | |
| 2410 this->ParseAssignmentExpression(true, classifier, CHECK_OK); | |
| 2411 elem = factory()->NewSpread(argument, start_pos); | |
| 2412 seen_spread = true; | |
| 2413 } else { | |
| 2414 elem = this->ParseAssignmentExpression(true, classifier, CHECK_OK); | |
| 2415 } | |
| 2416 values->Add(elem, zone_); | |
| 2417 if (peek() != Token::RBRACK) { | |
| 2418 if (seen_spread) { | |
| 2419 BindingPatternUnexpectedToken(classifier); | |
| 2420 } | |
| 2421 Expect(Token::COMMA, CHECK_OK); | |
| 2422 } | |
| 2423 } | |
| 2424 Expect(Token::RBRACK, CHECK_OK); | |
| 2425 | |
| 2426 // Update the scope information before the pre-parsing bailout. | |
| 2427 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
| 2428 | |
| 2429 return factory()->NewArrayLiteral(values, literal_index, | |
| 2430 is_strong(language_mode()), pos); | |
| 2431 } | |
| 2432 | |
| 2433 | |
| 2434 template <class Traits> | |
| 2435 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParsePropertyName( | |
| 2436 IdentifierT* name, bool* is_get, bool* is_set, bool* is_static, | |
| 2437 bool* is_computed_name, ExpressionClassifier* classifier, bool* ok) { | |
| 2438 Token::Value token = peek(); | |
| 2439 int pos = peek_position(); | |
| 2440 | |
| 2441 // For non computed property names we normalize the name a bit: | |
| 2442 // | |
| 2443 // "12" -> 12 | |
| 2444 // 12.3 -> "12.3" | |
| 2445 // 12.30 -> "12.3" | |
| 2446 // identifier -> "identifier" | |
| 2447 // | |
| 2448 // This is important because we use the property name as a key in a hash | |
| 2449 // table when we compute constant properties. | |
| 2450 switch (token) { | |
| 2451 case Token::STRING: | |
| 2452 Consume(Token::STRING); | |
| 2453 *name = this->GetSymbol(scanner()); | |
| 2454 break; | |
| 2455 | |
| 2456 case Token::SMI: | |
| 2457 Consume(Token::SMI); | |
| 2458 *name = this->GetNumberAsSymbol(scanner()); | |
| 2459 break; | |
| 2460 | |
| 2461 case Token::NUMBER: | |
| 2462 Consume(Token::NUMBER); | |
| 2463 *name = this->GetNumberAsSymbol(scanner()); | |
| 2464 break; | |
| 2465 | |
| 2466 case Token::LBRACK: | |
| 2467 if (allow_harmony_computed_property_names_) { | |
| 2468 *is_computed_name = true; | |
| 2469 Consume(Token::LBRACK); | |
| 2470 ExpressionClassifier computed_name_classifier; | |
| 2471 ExpressionT expression = ParseAssignmentExpression( | |
| 2472 true, &computed_name_classifier, CHECK_OK); | |
| 2473 classifier->AccumulateReclassifyingAsPattern(computed_name_classifier); | |
| 2474 Expect(Token::RBRACK, CHECK_OK); | |
| 2475 return expression; | |
| 2476 } | |
| 2477 | |
| 2478 // Fall through. | |
| 2479 case Token::STATIC: | |
| 2480 *is_static = true; | |
| 2481 | |
| 2482 // Fall through. | |
| 2483 default: | |
| 2484 *name = ParseIdentifierNameOrGetOrSet(is_get, is_set, CHECK_OK); | |
| 2485 break; | |
| 2486 } | |
| 2487 | |
| 2488 uint32_t index; | |
| 2489 return this->IsArrayIndex(*name, &index) | |
| 2490 ? factory()->NewNumberLiteral(index, pos) | |
| 2491 : factory()->NewStringLiteral(*name, pos); | |
| 2492 } | |
| 2493 | |
| 2494 | |
| 2495 template <class Traits> | |
| 2496 typename ParserBase<Traits>::ObjectLiteralPropertyT | |
| 2497 ParserBase<Traits>::ParsePropertyDefinition( | |
| 2498 ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends, | |
| 2499 bool is_static, bool* is_computed_name, bool* has_seen_constructor, | |
| 2500 ExpressionClassifier* classifier, bool* ok) { | |
| 2501 DCHECK(!in_class || is_static || has_seen_constructor != nullptr); | |
| 2502 ExpressionT value = this->EmptyExpression(); | |
| 2503 IdentifierT name = this->EmptyIdentifier(); | |
| 2504 bool is_get = false; | |
| 2505 bool is_set = false; | |
| 2506 bool name_is_static = false; | |
| 2507 bool is_generator = Check(Token::MUL); | |
| 2508 | |
| 2509 Token::Value name_token = peek(); | |
| 2510 int next_beg_pos = scanner()->peek_location().beg_pos; | |
| 2511 int next_end_pos = scanner()->peek_location().end_pos; | |
| 2512 ExpressionT name_expression = ParsePropertyName( | |
| 2513 &name, &is_get, &is_set, &name_is_static, is_computed_name, classifier, | |
| 2514 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2515 | |
| 2516 if (fni_ != nullptr && !*is_computed_name) { | |
| 2517 this->PushLiteralName(fni_, name); | |
| 2518 } | |
| 2519 | |
| 2520 if (!in_class && !is_generator && peek() == Token::COLON) { | |
| 2521 // PropertyDefinition : PropertyName ':' AssignmentExpression | |
| 2522 if (!*is_computed_name) { | |
| 2523 checker->CheckProperty(name_token, kValueProperty, is_static, | |
| 2524 is_generator, | |
| 2525 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2526 } | |
| 2527 Consume(Token::COLON); | |
| 2528 value = this->ParseAssignmentExpression( | |
| 2529 true, classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2530 | |
| 2531 } else if (is_generator || peek() == Token::LPAREN) { | |
| 2532 // Concise Method | |
| 2533 if (!*is_computed_name) { | |
| 2534 checker->CheckProperty(name_token, kMethodProperty, is_static, | |
| 2535 is_generator, | |
| 2536 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2537 } | |
| 2538 | |
| 2539 FunctionKind kind = is_generator ? FunctionKind::kConciseGeneratorMethod | |
| 2540 : FunctionKind::kConciseMethod; | |
| 2541 | |
| 2542 if (in_class && !is_static && this->IsConstructor(name)) { | |
| 2543 *has_seen_constructor = true; | |
| 2544 kind = has_extends ? FunctionKind::kSubclassConstructor | |
| 2545 : FunctionKind::kBaseConstructor; | |
| 2546 } | |
| 2547 | |
| 2548 if (!in_class) kind = WithObjectLiteralBit(kind); | |
| 2549 | |
| 2550 value = this->ParseFunctionLiteral( | |
| 2551 name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
| 2552 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | |
| 2553 FunctionLiteral::NORMAL_ARITY, | |
| 2554 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2555 | |
| 2556 return factory()->NewObjectLiteralProperty(name_expression, value, | |
| 2557 ObjectLiteralProperty::COMPUTED, | |
| 2558 is_static, *is_computed_name); | |
| 2559 | |
| 2560 } else if (in_class && name_is_static && !is_static) { | |
| 2561 // static MethodDefinition | |
| 2562 return ParsePropertyDefinition(checker, true, has_extends, true, | |
| 2563 is_computed_name, nullptr, classifier, ok); | |
| 2564 } else if (is_get || is_set) { | |
| 2565 // Accessor | |
| 2566 name = this->EmptyIdentifier(); | |
| 2567 bool dont_care = false; | |
| 2568 name_token = peek(); | |
| 2569 | |
| 2570 name_expression = ParsePropertyName( | |
| 2571 &name, &dont_care, &dont_care, &dont_care, is_computed_name, classifier, | |
| 2572 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2573 | |
| 2574 if (!*is_computed_name) { | |
| 2575 checker->CheckProperty(name_token, kAccessorProperty, is_static, | |
| 2576 is_generator, | |
| 2577 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2578 } | |
| 2579 | |
| 2580 FunctionKind kind = FunctionKind::kAccessorFunction; | |
| 2581 if (!in_class) kind = WithObjectLiteralBit(kind); | |
| 2582 typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral( | |
| 2583 name, scanner()->location(), kSkipFunctionNameCheck, kind, | |
| 2584 RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, | |
| 2585 is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY, | |
| 2586 CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2587 | |
| 2588 // Make sure the name expression is a string since we need a Name for | |
| 2589 // Runtime_DefineAccessorPropertyUnchecked and since we can determine this | |
| 2590 // statically we can skip the extra runtime check. | |
| 2591 if (!*is_computed_name) { | |
| 2592 name_expression = | |
| 2593 factory()->NewStringLiteral(name, name_expression->position()); | |
| 2594 } | |
| 2595 | |
| 2596 return factory()->NewObjectLiteralProperty( | |
| 2597 name_expression, value, | |
| 2598 is_get ? ObjectLiteralProperty::GETTER : ObjectLiteralProperty::SETTER, | |
| 2599 is_static, *is_computed_name); | |
| 2600 | |
| 2601 } else if (!in_class && Token::IsIdentifier(name_token, language_mode(), | |
| 2602 this->is_generator())) { | |
| 2603 DCHECK(!*is_computed_name); | |
| 2604 DCHECK(!is_static); | |
| 2605 | |
| 2606 if (classifier->duplicate_finder() != nullptr && | |
| 2607 scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) { | |
| 2608 classifier->RecordDuplicateFormalParameterError(scanner()->location()); | |
| 2609 } | |
| 2610 | |
| 2611 ExpressionT lhs = this->ExpressionFromIdentifier( | |
| 2612 name, next_beg_pos, next_end_pos, scope_, factory()); | |
| 2613 if (peek() == Token::ASSIGN) { | |
| 2614 this->ExpressionUnexpectedToken(classifier); | |
| 2615 Consume(Token::ASSIGN); | |
| 2616 ExpressionClassifier rhs_classifier; | |
| 2617 ExpressionT rhs = this->ParseAssignmentExpression( | |
| 2618 true, &rhs_classifier, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); | |
| 2619 classifier->AccumulateReclassifyingAsPattern(rhs_classifier); | |
| 2620 value = factory()->NewAssignment(Token::ASSIGN, lhs, rhs, | |
| 2621 RelocInfo::kNoPosition); | |
| 2622 } else { | |
| 2623 value = lhs; | |
| 2624 } | |
| 2625 return factory()->NewObjectLiteralProperty( | |
| 2626 name_expression, value, ObjectLiteralProperty::COMPUTED, false, false); | |
| 2627 | |
| 2628 } else { | |
| 2629 Token::Value next = Next(); | |
| 2630 ReportUnexpectedToken(next); | |
| 2631 *ok = false; | |
| 2632 return this->EmptyObjectLiteralProperty(); | |
| 2633 } | |
| 2634 | |
| 2635 return factory()->NewObjectLiteralProperty(name_expression, value, is_static, | |
| 2636 *is_computed_name); | |
| 2637 } | |
| 2638 | |
| 2639 | |
| 2640 template <class Traits> | |
| 2641 typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral( | |
| 2642 ExpressionClassifier* classifier, bool* ok) { | |
| 2643 // ObjectLiteral :: | |
| 2644 // '{' (PropertyDefinition (',' PropertyDefinition)* ','? )? '}' | |
| 2645 | |
| 2646 int pos = peek_position(); | |
| 2647 typename Traits::Type::PropertyList properties = | |
| 2648 this->NewPropertyList(4, zone_); | |
| 2649 int number_of_boilerplate_properties = 0; | |
| 2650 bool has_function = false; | |
| 2651 bool has_computed_names = false; | |
| 2652 ObjectLiteralChecker checker(this); | |
| 2653 | |
| 2654 Expect(Token::LBRACE, CHECK_OK); | |
| 2655 | |
| 2656 while (peek() != Token::RBRACE) { | |
| 2657 if (fni_ != nullptr) fni_->Enter(); | |
| 2658 | |
| 2659 const bool in_class = false; | |
| 2660 const bool is_static = false; | |
| 2661 const bool has_extends = false; | |
| 2662 bool is_computed_name = false; | |
| 2663 ObjectLiteralPropertyT property = this->ParsePropertyDefinition( | |
| 2664 &checker, in_class, has_extends, is_static, &is_computed_name, NULL, | |
| 2665 classifier, CHECK_OK); | |
| 2666 | |
| 2667 if (is_computed_name) { | |
| 2668 has_computed_names = true; | |
| 2669 } | |
| 2670 | |
| 2671 // Mark top-level object literals that contain function literals and | |
| 2672 // pretenure the literal so it can be added as a constant function | |
| 2673 // property. (Parser only.) | |
| 2674 this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, property, | |
| 2675 &has_function); | |
| 2676 | |
| 2677 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | |
| 2678 if (!has_computed_names && this->IsBoilerplateProperty(property)) { | |
| 2679 number_of_boilerplate_properties++; | |
| 2680 } | |
| 2681 properties->Add(property, zone()); | |
| 2682 | |
| 2683 if (peek() != Token::RBRACE) { | |
| 2684 // Need {} because of the CHECK_OK macro. | |
| 2685 Expect(Token::COMMA, CHECK_OK); | |
| 2686 } | |
| 2687 | |
| 2688 if (fni_ != nullptr) { | |
| 2689 fni_->Infer(); | |
| 2690 fni_->Leave(); | |
| 2691 } | |
| 2692 } | |
| 2693 Expect(Token::RBRACE, CHECK_OK); | |
| 2694 | |
| 2695 // Computation of literal_index must happen before pre parse bailout. | |
| 2696 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
| 2697 | |
| 2698 return factory()->NewObjectLiteral(properties, | |
| 2699 literal_index, | |
| 2700 number_of_boilerplate_properties, | |
| 2701 has_function, | |
| 2702 is_strong(language_mode()), | |
| 2703 pos); | |
| 2704 } | |
| 2705 | |
| 2706 | |
| 2707 template <class Traits> | |
| 2708 typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments( | |
| 2709 Scanner::Location* first_spread_arg_loc, ExpressionClassifier* classifier, | |
| 2710 bool* ok) { | |
| 2711 // Arguments :: | |
| 2712 // '(' (AssignmentExpression)*[','] ')' | |
| 2713 | |
| 2714 Scanner::Location spread_arg = Scanner::Location::invalid(); | |
| 2715 typename Traits::Type::ExpressionList result = | |
| 2716 this->NewExpressionList(4, zone_); | |
| 2717 Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList)); | |
| 2718 bool done = (peek() == Token::RPAREN); | |
| 2719 bool was_unspread = false; | |
| 2720 int unspread_sequences_count = 0; | |
| 2721 while (!done) { | |
| 2722 bool is_spread = allow_harmony_spreadcalls() && (peek() == Token::ELLIPSIS); | |
| 2723 int start_pos = peek_position(); | |
| 2724 if (is_spread) Consume(Token::ELLIPSIS); | |
| 2725 | |
| 2726 ExpressionT argument = this->ParseAssignmentExpression( | |
| 2727 true, classifier, CHECK_OK_CUSTOM(NullExpressionList)); | |
| 2728 if (is_spread) { | |
| 2729 if (!spread_arg.IsValid()) { | |
| 2730 spread_arg.beg_pos = start_pos; | |
| 2731 spread_arg.end_pos = peek_position(); | |
| 2732 } | |
| 2733 argument = factory()->NewSpread(argument, start_pos); | |
| 2734 } | |
| 2735 result->Add(argument, zone_); | |
| 2736 | |
| 2737 // unspread_sequences_count is the number of sequences of parameters which | |
| 2738 // are not prefixed with a spread '...' operator. | |
| 2739 if (is_spread) { | |
| 2740 was_unspread = false; | |
| 2741 } else if (!was_unspread) { | |
| 2742 was_unspread = true; | |
| 2743 unspread_sequences_count++; | |
| 2744 } | |
| 2745 | |
| 2746 if (result->length() > Code::kMaxArguments) { | |
| 2747 ReportMessage(MessageTemplate::kTooManyArguments); | |
| 2748 *ok = false; | |
| 2749 return this->NullExpressionList(); | |
| 2750 } | |
| 2751 done = (peek() != Token::COMMA); | |
| 2752 if (!done) { | |
| 2753 Next(); | |
| 2754 } | |
| 2755 } | |
| 2756 Scanner::Location location = scanner_->location(); | |
| 2757 if (Token::RPAREN != Next()) { | |
| 2758 ReportMessageAt(location, MessageTemplate::kUnterminatedArgList); | |
| 2759 *ok = false; | |
| 2760 return this->NullExpressionList(); | |
| 2761 } | |
| 2762 *first_spread_arg_loc = spread_arg; | |
| 2763 | |
| 2764 if (spread_arg.IsValid()) { | |
| 2765 // Unspread parameter sequences are translated into array literals in the | |
| 2766 // parser. Ensure that the number of materialized literals matches between | |
| 2767 // the parser and preparser | |
| 2768 Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count); | |
| 2769 } | |
| 2770 | |
| 2771 return result; | |
| 2772 } | |
| 2773 | |
| 2774 // Precedence = 2 | |
| 2775 template <class Traits> | |
| 2776 typename ParserBase<Traits>::ExpressionT | |
| 2777 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, | |
| 2778 ExpressionClassifier* classifier, | |
| 2779 bool* ok) { | |
| 2780 // AssignmentExpression :: | |
| 2781 // ConditionalExpression | |
| 2782 // ArrowFunction | |
| 2783 // YieldExpression | |
| 2784 // LeftHandSideExpression AssignmentOperator AssignmentExpression | |
| 2785 | |
| 2786 Scanner::Location lhs_location = scanner()->peek_location(); | |
| 2787 | |
| 2788 if (peek() == Token::YIELD && is_generator()) { | |
| 2789 return this->ParseYieldExpression(classifier, ok); | |
| 2790 } | |
| 2791 | |
| 2792 if (fni_ != NULL) fni_->Enter(); | |
| 2793 ParserBase<Traits>::Checkpoint checkpoint(this); | |
| 2794 ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder()); | |
| 2795 bool parenthesized_formals = peek() == Token::LPAREN; | |
| 2796 if (!parenthesized_formals) { | |
| 2797 ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier); | |
| 2798 } | |
| 2799 ExpressionT expression = this->ParseConditionalExpression( | |
| 2800 accept_IN, &arrow_formals_classifier, CHECK_OK); | |
| 2801 | |
| 2802 if (allow_harmony_arrow_functions() && peek() == Token::ARROW) { | |
| 2803 BindingPatternUnexpectedToken(classifier); | |
| 2804 ValidateArrowFormalParameters(&arrow_formals_classifier, expression, | |
| 2805 parenthesized_formals, CHECK_OK); | |
| 2806 Scanner::Location loc(lhs_location.beg_pos, scanner()->location().end_pos); | |
| 2807 Scope* scope = | |
| 2808 this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction); | |
| 2809 FormalParameterParsingStateT parsing_state(scope); | |
| 2810 checkpoint.Restore(&parsing_state.materialized_literals_count); | |
| 2811 | |
| 2812 scope->set_start_position(lhs_location.beg_pos); | |
| 2813 Scanner::Location duplicate_loc = Scanner::Location::invalid(); | |
| 2814 this->ParseArrowFunctionFormalParameters(&parsing_state, expression, loc, | |
| 2815 &duplicate_loc, CHECK_OK); | |
| 2816 if (duplicate_loc.IsValid()) { | |
| 2817 arrow_formals_classifier.RecordDuplicateFormalParameterError( | |
| 2818 duplicate_loc); | |
| 2819 } | |
| 2820 expression = this->ParseArrowFunctionLiteral( | |
| 2821 parsing_state, arrow_formals_classifier, CHECK_OK); | |
| 2822 return expression; | |
| 2823 } | |
| 2824 | |
| 2825 // "expression" was not itself an arrow function parameter list, but it might | |
| 2826 // form part of one. Propagate speculative formal parameter error locations. | |
| 2827 classifier->Accumulate(arrow_formals_classifier, | |
| 2828 ExpressionClassifier::StandardProductions | | |
| 2829 ExpressionClassifier::FormalParametersProductions); | |
| 2830 | |
| 2831 if (!Token::IsAssignmentOp(peek())) { | |
| 2832 if (fni_ != NULL) fni_->Leave(); | |
| 2833 // Parsed conditional expression only (no assignment). | |
| 2834 return expression; | |
| 2835 } | |
| 2836 | |
| 2837 if (!allow_harmony_destructuring()) { | |
| 2838 BindingPatternUnexpectedToken(classifier); | |
| 2839 } | |
| 2840 | |
| 2841 expression = this->CheckAndRewriteReferenceExpression( | |
| 2842 expression, lhs_location, MessageTemplate::kInvalidLhsInAssignment, | |
| 2843 CHECK_OK); | |
| 2844 expression = this->MarkExpressionAsAssigned(expression); | |
| 2845 | |
| 2846 Token::Value op = Next(); // Get assignment operator. | |
| 2847 if (op != Token::ASSIGN) { | |
| 2848 classifier->RecordBindingPatternError(scanner()->location(), | |
| 2849 MessageTemplate::kUnexpectedToken, | |
| 2850 Token::String(op)); | |
| 2851 } | |
| 2852 int pos = position(); | |
| 2853 | |
| 2854 ExpressionClassifier rhs_classifier; | |
| 2855 ExpressionT right = | |
| 2856 this->ParseAssignmentExpression(accept_IN, &rhs_classifier, CHECK_OK); | |
| 2857 classifier->AccumulateReclassifyingAsPattern(rhs_classifier); | |
| 2858 | |
| 2859 // TODO(1231235): We try to estimate the set of properties set by | |
| 2860 // constructors. We define a new property whenever there is an | |
| 2861 // assignment to a property of 'this'. We should probably only add | |
| 2862 // properties if we haven't seen them before. Otherwise we'll | |
| 2863 // probably overestimate the number of properties. | |
| 2864 if (op == Token::ASSIGN && this->IsThisProperty(expression)) { | |
| 2865 function_state_->AddProperty(); | |
| 2866 } | |
| 2867 | |
| 2868 this->CheckAssigningFunctionLiteralToProperty(expression, right); | |
| 2869 | |
| 2870 if (fni_ != NULL) { | |
| 2871 // Check if the right hand side is a call to avoid inferring a | |
| 2872 // name if we're dealing with "a = function(){...}();"-like | |
| 2873 // expression. | |
| 2874 if ((op == Token::INIT_VAR | |
| 2875 || op == Token::INIT_CONST_LEGACY | |
| 2876 || op == Token::ASSIGN) | |
| 2877 && (!right->IsCall() && !right->IsCallNew())) { | |
| 2878 fni_->Infer(); | |
| 2879 } else { | |
| 2880 fni_->RemoveLastFunction(); | |
| 2881 } | |
| 2882 fni_->Leave(); | |
| 2883 } | |
| 2884 | |
| 2885 return factory()->NewAssignment(op, expression, right, pos); | |
| 2886 } | |
| 2887 | |
| 2888 template <class Traits> | |
| 2889 typename ParserBase<Traits>::ExpressionT | |
| 2890 ParserBase<Traits>::ParseYieldExpression(ExpressionClassifier* classifier, | |
| 2891 bool* ok) { | |
| 2892 // YieldExpression :: | |
| 2893 // 'yield' ([no line terminator] '*'? AssignmentExpression)? | |
| 2894 int pos = peek_position(); | |
| 2895 Expect(Token::YIELD, CHECK_OK); | |
| 2896 ExpressionT generator_object = | |
| 2897 factory()->NewVariableProxy(function_state_->generator_object_variable()); | |
| 2898 ExpressionT expression = Traits::EmptyExpression(); | |
| 2899 Yield::Kind kind = Yield::kSuspend; | |
| 2900 if (!scanner()->HasAnyLineTerminatorBeforeNext()) { | |
| 2901 if (Check(Token::MUL)) kind = Yield::kDelegating; | |
| 2902 switch (peek()) { | |
| 2903 case Token::EOS: | |
| 2904 case Token::SEMICOLON: | |
| 2905 case Token::RBRACE: | |
| 2906 case Token::RBRACK: | |
| 2907 case Token::RPAREN: | |
| 2908 case Token::COLON: | |
| 2909 case Token::COMMA: | |
| 2910 // The above set of tokens is the complete set of tokens that can appear | |
| 2911 // after an AssignmentExpression, and none of them can start an | |
| 2912 // AssignmentExpression. This allows us to avoid looking for an RHS for | |
| 2913 // a Yield::kSuspend operation, given only one look-ahead token. | |
| 2914 if (kind == Yield::kSuspend) | |
| 2915 break; | |
| 2916 DCHECK_EQ(Yield::kDelegating, kind); | |
| 2917 // Delegating yields require an RHS; fall through. | |
| 2918 default: | |
| 2919 expression = ParseAssignmentExpression(false, classifier, CHECK_OK); | |
| 2920 break; | |
| 2921 } | |
| 2922 } | |
| 2923 if (kind == Yield::kDelegating) { | |
| 2924 // var iterator = subject[Symbol.iterator](); | |
| 2925 expression = this->GetIterator(expression, factory()); | |
| 2926 } | |
| 2927 typename Traits::Type::YieldExpression yield = | |
| 2928 factory()->NewYield(generator_object, expression, kind, pos); | |
| 2929 return yield; | |
| 2930 } | |
| 2931 | |
| 2932 | |
| 2933 // Precedence = 3 | |
| 2934 template <class Traits> | |
| 2935 typename ParserBase<Traits>::ExpressionT | |
| 2936 ParserBase<Traits>::ParseConditionalExpression(bool accept_IN, | |
| 2937 ExpressionClassifier* classifier, | |
| 2938 bool* ok) { | |
| 2939 // ConditionalExpression :: | |
| 2940 // LogicalOrExpression | |
| 2941 // LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression | |
| 2942 | |
| 2943 int pos = peek_position(); | |
| 2944 // We start using the binary expression parser for prec >= 4 only! | |
| 2945 ExpressionT expression = | |
| 2946 this->ParseBinaryExpression(4, accept_IN, classifier, CHECK_OK); | |
| 2947 if (peek() != Token::CONDITIONAL) return expression; | |
| 2948 BindingPatternUnexpectedToken(classifier); | |
| 2949 Consume(Token::CONDITIONAL); | |
| 2950 // In parsing the first assignment expression in conditional | |
| 2951 // expressions we always accept the 'in' keyword; see ECMA-262, | |
| 2952 // section 11.12, page 58. | |
| 2953 ExpressionT left = ParseAssignmentExpression(true, classifier, CHECK_OK); | |
| 2954 Expect(Token::COLON, CHECK_OK); | |
| 2955 ExpressionT right = | |
| 2956 ParseAssignmentExpression(accept_IN, classifier, CHECK_OK); | |
| 2957 return factory()->NewConditional(expression, left, right, pos); | |
| 2958 } | |
| 2959 | |
| 2960 | |
| 2961 // Precedence >= 4 | |
| 2962 template <class Traits> | |
| 2963 typename ParserBase<Traits>::ExpressionT | |
| 2964 ParserBase<Traits>::ParseBinaryExpression(int prec, bool accept_IN, | |
| 2965 ExpressionClassifier* classifier, | |
| 2966 bool* ok) { | |
| 2967 DCHECK(prec >= 4); | |
| 2968 ExpressionT x = this->ParseUnaryExpression(classifier, CHECK_OK); | |
| 2969 for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) { | |
| 2970 // prec1 >= 4 | |
| 2971 while (Precedence(peek(), accept_IN) == prec1) { | |
| 2972 BindingPatternUnexpectedToken(classifier); | |
| 2973 Token::Value op = Next(); | |
| 2974 Scanner::Location op_location = scanner()->location(); | |
| 2975 int pos = position(); | |
| 2976 ExpressionT y = | |
| 2977 ParseBinaryExpression(prec1 + 1, accept_IN, classifier, CHECK_OK); | |
| 2978 | |
| 2979 if (this->ShortcutNumericLiteralBinaryExpression(&x, y, op, pos, | |
| 2980 factory())) { | |
| 2981 continue; | |
| 2982 } | |
| 2983 | |
| 2984 // For now we distinguish between comparisons and other binary | |
| 2985 // operations. (We could combine the two and get rid of this | |
| 2986 // code and AST node eventually.) | |
| 2987 if (Token::IsCompareOp(op)) { | |
| 2988 // We have a comparison. | |
| 2989 Token::Value cmp = op; | |
| 2990 switch (op) { | |
| 2991 case Token::NE: cmp = Token::EQ; break; | |
| 2992 case Token::NE_STRICT: cmp = Token::EQ_STRICT; break; | |
| 2993 default: break; | |
| 2994 } | |
| 2995 if (cmp == Token::EQ && is_strong(language_mode())) { | |
| 2996 ReportMessageAt(op_location, MessageTemplate::kStrongEqual); | |
| 2997 *ok = false; | |
| 2998 return this->EmptyExpression(); | |
| 2999 } | |
| 3000 x = factory()->NewCompareOperation(cmp, x, y, pos); | |
| 3001 if (cmp != op) { | |
| 3002 // The comparison was negated - add a NOT. | |
| 3003 x = factory()->NewUnaryOperation(Token::NOT, x, pos); | |
| 3004 } | |
| 3005 | |
| 3006 } else { | |
| 3007 // We have a "normal" binary operation. | |
| 3008 x = factory()->NewBinaryOperation(op, x, y, pos); | |
| 3009 } | |
| 3010 } | |
| 3011 } | |
| 3012 return x; | |
| 3013 } | |
| 3014 | |
| 3015 | |
| 3016 template <class Traits> | |
| 3017 typename ParserBase<Traits>::ExpressionT | |
| 3018 ParserBase<Traits>::ParseUnaryExpression(ExpressionClassifier* classifier, | |
| 3019 bool* ok) { | |
| 3020 // UnaryExpression :: | |
| 3021 // PostfixExpression | |
| 3022 // 'delete' UnaryExpression | |
| 3023 // 'void' UnaryExpression | |
| 3024 // 'typeof' UnaryExpression | |
| 3025 // '++' UnaryExpression | |
| 3026 // '--' UnaryExpression | |
| 3027 // '+' UnaryExpression | |
| 3028 // '-' UnaryExpression | |
| 3029 // '~' UnaryExpression | |
| 3030 // '!' UnaryExpression | |
| 3031 | |
| 3032 Token::Value op = peek(); | |
| 3033 if (Token::IsUnaryOp(op)) { | |
| 3034 BindingPatternUnexpectedToken(classifier); | |
| 3035 | |
| 3036 op = Next(); | |
| 3037 int pos = position(); | |
| 3038 ExpressionT expression = ParseUnaryExpression(classifier, CHECK_OK); | |
| 3039 | |
| 3040 if (op == Token::DELETE && is_strict(language_mode())) { | |
| 3041 if (is_strong(language_mode())) { | |
| 3042 ReportMessage(MessageTemplate::kStrongDelete); | |
| 3043 *ok = false; | |
| 3044 return this->EmptyExpression(); | |
| 3045 } else if (this->IsIdentifier(expression)) { | |
| 3046 // "delete identifier" is a syntax error in strict mode. | |
| 3047 ReportMessage(MessageTemplate::kStrictDelete); | |
| 3048 *ok = false; | |
| 3049 return this->EmptyExpression(); | |
| 3050 } | |
| 3051 } | |
| 3052 | |
| 3053 // Allow Traits do rewrite the expression. | |
| 3054 return this->BuildUnaryExpression(expression, op, pos, factory()); | |
| 3055 } else if (Token::IsCountOp(op)) { | |
| 3056 BindingPatternUnexpectedToken(classifier); | |
| 3057 op = Next(); | |
| 3058 Scanner::Location lhs_location = scanner()->peek_location(); | |
| 3059 ExpressionT expression = this->ParseUnaryExpression(classifier, CHECK_OK); | |
| 3060 expression = this->CheckAndRewriteReferenceExpression( | |
| 3061 expression, lhs_location, MessageTemplate::kInvalidLhsInPrefixOp, | |
| 3062 CHECK_OK); | |
| 3063 this->MarkExpressionAsAssigned(expression); | |
| 3064 | |
| 3065 return factory()->NewCountOperation(op, | |
| 3066 true /* prefix */, | |
| 3067 expression, | |
| 3068 position()); | |
| 3069 | |
| 3070 } else { | |
| 3071 return this->ParsePostfixExpression(classifier, ok); | |
| 3072 } | |
| 3073 } | |
| 3074 | |
| 3075 | |
| 3076 template <class Traits> | |
| 3077 typename ParserBase<Traits>::ExpressionT | |
| 3078 ParserBase<Traits>::ParsePostfixExpression(ExpressionClassifier* classifier, | |
| 3079 bool* ok) { | |
| 3080 // PostfixExpression :: | |
| 3081 // LeftHandSideExpression ('++' | '--')? | |
| 3082 | |
| 3083 Scanner::Location lhs_location = scanner()->peek_location(); | |
| 3084 ExpressionT expression = | |
| 3085 this->ParseLeftHandSideExpression(classifier, CHECK_OK); | |
| 3086 if (!scanner()->HasAnyLineTerminatorBeforeNext() && | |
| 3087 Token::IsCountOp(peek())) { | |
| 3088 BindingPatternUnexpectedToken(classifier); | |
| 3089 | |
| 3090 expression = this->CheckAndRewriteReferenceExpression( | |
| 3091 expression, lhs_location, MessageTemplate::kInvalidLhsInPostfixOp, | |
| 3092 CHECK_OK); | |
| 3093 expression = this->MarkExpressionAsAssigned(expression); | |
| 3094 | |
| 3095 Token::Value next = Next(); | |
| 3096 expression = | |
| 3097 factory()->NewCountOperation(next, | |
| 3098 false /* postfix */, | |
| 3099 expression, | |
| 3100 position()); | |
| 3101 } | |
| 3102 return expression; | |
| 3103 } | |
| 3104 | |
| 3105 | |
| 3106 template <class Traits> | |
| 3107 typename ParserBase<Traits>::ExpressionT | |
| 3108 ParserBase<Traits>::ParseLeftHandSideExpression( | |
| 3109 ExpressionClassifier* classifier, bool* ok) { | |
| 3110 // LeftHandSideExpression :: | |
| 3111 // (NewExpression | MemberExpression) ... | |
| 3112 | |
| 3113 ExpressionT result = | |
| 3114 this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK); | |
| 3115 | |
| 3116 while (true) { | |
| 3117 switch (peek()) { | |
| 3118 case Token::LBRACK: { | |
| 3119 BindingPatternUnexpectedToken(classifier); | |
| 3120 Consume(Token::LBRACK); | |
| 3121 int pos = position(); | |
| 3122 ExpressionT index = ParseExpression(true, classifier, CHECK_OK); | |
| 3123 result = factory()->NewProperty(result, index, pos); | |
| 3124 Expect(Token::RBRACK, CHECK_OK); | |
| 3125 break; | |
| 3126 } | |
| 3127 | |
| 3128 case Token::LPAREN: { | |
| 3129 BindingPatternUnexpectedToken(classifier); | |
| 3130 | |
| 3131 if (is_strong(language_mode()) && this->IsIdentifier(result) && | |
| 3132 this->IsEval(this->AsIdentifier(result))) { | |
| 3133 ReportMessage(MessageTemplate::kStrongDirectEval); | |
| 3134 *ok = false; | |
| 3135 return this->EmptyExpression(); | |
| 3136 } | |
| 3137 int pos; | |
| 3138 if (scanner()->current_token() == Token::IDENTIFIER) { | |
| 3139 // For call of an identifier we want to report position of | |
| 3140 // the identifier as position of the call in the stack trace. | |
| 3141 pos = position(); | |
| 3142 } else { | |
| 3143 // For other kinds of calls we record position of the parenthesis as | |
| 3144 // position of the call. Note that this is extremely important for | |
| 3145 // expressions of the form function(){...}() for which call position | |
| 3146 // should not point to the closing brace otherwise it will intersect | |
| 3147 // with positions recorded for function literal and confuse debugger. | |
| 3148 pos = peek_position(); | |
| 3149 // Also the trailing parenthesis are a hint that the function will | |
| 3150 // be called immediately. If we happen to have parsed a preceding | |
| 3151 // function literal eagerly, we can also compile it eagerly. | |
| 3152 if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { | |
| 3153 result->AsFunctionLiteral()->set_should_eager_compile(); | |
| 3154 } | |
| 3155 } | |
| 3156 Scanner::Location spread_pos; | |
| 3157 typename Traits::Type::ExpressionList args = | |
| 3158 ParseArguments(&spread_pos, classifier, CHECK_OK); | |
| 3159 | |
| 3160 // Keep track of eval() calls since they disable all local variable | |
| 3161 // optimizations. | |
| 3162 // The calls that need special treatment are the | |
| 3163 // direct eval calls. These calls are all of the form eval(...), with | |
| 3164 // no explicit receiver. | |
| 3165 // These calls are marked as potentially direct eval calls. Whether | |
| 3166 // they are actually direct calls to eval is determined at run time. | |
| 3167 this->CheckPossibleEvalCall(result, scope_); | |
| 3168 | |
| 3169 if (spread_pos.IsValid()) { | |
| 3170 args = Traits::PrepareSpreadArguments(args); | |
| 3171 result = Traits::SpreadCall(result, args, pos); | |
| 3172 } else { | |
| 3173 result = factory()->NewCall(result, args, pos); | |
| 3174 } | |
| 3175 if (fni_ != NULL) fni_->RemoveLastFunction(); | |
| 3176 break; | |
| 3177 } | |
| 3178 | |
| 3179 case Token::PERIOD: { | |
| 3180 BindingPatternUnexpectedToken(classifier); | |
| 3181 Consume(Token::PERIOD); | |
| 3182 int pos = position(); | |
| 3183 IdentifierT name = ParseIdentifierName(CHECK_OK); | |
| 3184 result = factory()->NewProperty( | |
| 3185 result, factory()->NewStringLiteral(name, pos), pos); | |
| 3186 if (fni_ != NULL) this->PushLiteralName(fni_, name); | |
| 3187 break; | |
| 3188 } | |
| 3189 | |
| 3190 case Token::TEMPLATE_SPAN: | |
| 3191 case Token::TEMPLATE_TAIL: { | |
| 3192 BindingPatternUnexpectedToken(classifier); | |
| 3193 result = ParseTemplateLiteral(result, position(), classifier, CHECK_OK); | |
| 3194 break; | |
| 3195 } | |
| 3196 | |
| 3197 default: | |
| 3198 return result; | |
| 3199 } | |
| 3200 } | |
| 3201 } | |
| 3202 | |
| 3203 | |
| 3204 template <class Traits> | |
| 3205 typename ParserBase<Traits>::ExpressionT | |
| 3206 ParserBase<Traits>::ParseMemberWithNewPrefixesExpression( | |
| 3207 ExpressionClassifier* classifier, bool* ok) { | |
| 3208 // NewExpression :: | |
| 3209 // ('new')+ MemberExpression | |
| 3210 // | |
| 3211 // NewTarget :: | |
| 3212 // 'new' '.' 'target' | |
| 3213 | |
| 3214 // The grammar for new expressions is pretty warped. We can have several 'new' | |
| 3215 // keywords following each other, and then a MemberExpression. When we see '(' | |
| 3216 // after the MemberExpression, it's associated with the rightmost unassociated | |
| 3217 // 'new' to create a NewExpression with arguments. However, a NewExpression | |
| 3218 // can also occur without arguments. | |
| 3219 | |
| 3220 // Examples of new expression: | |
| 3221 // new foo.bar().baz means (new (foo.bar)()).baz | |
| 3222 // new foo()() means (new foo())() | |
| 3223 // new new foo()() means (new (new foo())()) | |
| 3224 // new new foo means new (new foo) | |
| 3225 // new new foo() means new (new foo()) | |
| 3226 // new new foo().bar().baz means (new (new foo()).bar()).baz | |
| 3227 | |
| 3228 if (peek() == Token::NEW) { | |
| 3229 BindingPatternUnexpectedToken(classifier); | |
| 3230 Consume(Token::NEW); | |
| 3231 int new_pos = position(); | |
| 3232 ExpressionT result = this->EmptyExpression(); | |
| 3233 if (peek() == Token::SUPER) { | |
| 3234 const bool is_new = true; | |
| 3235 result = ParseSuperExpression(is_new, classifier, CHECK_OK); | |
| 3236 } else if (allow_harmony_new_target() && peek() == Token::PERIOD) { | |
| 3237 return ParseNewTargetExpression(CHECK_OK); | |
| 3238 } else { | |
| 3239 result = this->ParseMemberWithNewPrefixesExpression(classifier, CHECK_OK); | |
| 3240 } | |
| 3241 if (peek() == Token::LPAREN) { | |
| 3242 // NewExpression with arguments. | |
| 3243 Scanner::Location spread_pos; | |
| 3244 typename Traits::Type::ExpressionList args = | |
| 3245 this->ParseArguments(&spread_pos, classifier, CHECK_OK); | |
| 3246 | |
| 3247 if (spread_pos.IsValid()) { | |
| 3248 args = Traits::PrepareSpreadArguments(args); | |
| 3249 result = Traits::SpreadCallNew(result, args, new_pos); | |
| 3250 } else { | |
| 3251 result = factory()->NewCallNew(result, args, new_pos); | |
| 3252 } | |
| 3253 // The expression can still continue with . or [ after the arguments. | |
| 3254 result = | |
| 3255 this->ParseMemberExpressionContinuation(result, classifier, CHECK_OK); | |
| 3256 return result; | |
| 3257 } | |
| 3258 // NewExpression without arguments. | |
| 3259 return factory()->NewCallNew(result, this->NewExpressionList(0, zone_), | |
| 3260 new_pos); | |
| 3261 } | |
| 3262 // No 'new' or 'super' keyword. | |
| 3263 return this->ParseMemberExpression(classifier, ok); | |
| 3264 } | |
| 3265 | |
| 3266 | |
| 3267 template <class Traits> | |
| 3268 typename ParserBase<Traits>::ExpressionT | |
| 3269 ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier, | |
| 3270 bool* ok) { | |
| 3271 // MemberExpression :: | |
| 3272 // (PrimaryExpression | FunctionLiteral | ClassLiteral) | |
| 3273 // ('[' Expression ']' | '.' Identifier | Arguments | TemplateLiteral)* | |
| 3274 | |
| 3275 // The '[' Expression ']' and '.' Identifier parts are parsed by | |
| 3276 // ParseMemberExpressionContinuation, and the Arguments part is parsed by the | |
| 3277 // caller. | |
| 3278 | |
| 3279 // Parse the initial primary or function expression. | |
| 3280 ExpressionT result = this->EmptyExpression(); | |
| 3281 if (peek() == Token::FUNCTION) { | |
| 3282 BindingPatternUnexpectedToken(classifier); | |
| 3283 | |
| 3284 Consume(Token::FUNCTION); | |
| 3285 int function_token_position = position(); | |
| 3286 bool is_generator = Check(Token::MUL); | |
| 3287 IdentifierT name = this->EmptyIdentifier(); | |
| 3288 bool is_strict_reserved_name = false; | |
| 3289 Scanner::Location function_name_location = Scanner::Location::invalid(); | |
| 3290 FunctionLiteral::FunctionType function_type = | |
| 3291 FunctionLiteral::ANONYMOUS_EXPRESSION; | |
| 3292 if (peek_any_identifier()) { | |
| 3293 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, | |
| 3294 CHECK_OK); | |
| 3295 function_name_location = scanner()->location(); | |
| 3296 function_type = FunctionLiteral::NAMED_EXPRESSION; | |
| 3297 } | |
| 3298 result = this->ParseFunctionLiteral( | |
| 3299 name, function_name_location, | |
| 3300 is_strict_reserved_name ? kFunctionNameIsStrictReserved | |
| 3301 : kFunctionNameValidityUnknown, | |
| 3302 is_generator ? FunctionKind::kGeneratorFunction | |
| 3303 : FunctionKind::kNormalFunction, | |
| 3304 function_token_position, function_type, FunctionLiteral::NORMAL_ARITY, | |
| 3305 CHECK_OK); | |
| 3306 } else if (peek() == Token::SUPER) { | |
| 3307 const bool is_new = false; | |
| 3308 result = ParseSuperExpression(is_new, classifier, CHECK_OK); | |
| 3309 } else { | |
| 3310 result = ParsePrimaryExpression(classifier, CHECK_OK); | |
| 3311 } | |
| 3312 | |
| 3313 result = ParseMemberExpressionContinuation(result, classifier, CHECK_OK); | |
| 3314 return result; | |
| 3315 } | |
| 3316 | |
| 3317 | |
| 3318 template <class Traits> | |
| 3319 typename ParserBase<Traits>::ExpressionT | |
| 3320 ParserBase<Traits>::ParseStrongInitializationExpression( | |
| 3321 ExpressionClassifier* classifier, bool* ok) { | |
| 3322 // InitializationExpression :: (strong mode) | |
| 3323 // 'this' '.' IdentifierName '=' AssignmentExpression | |
| 3324 // 'this' '[' Expression ']' '=' AssignmentExpression | |
| 3325 | |
| 3326 if (fni_ != NULL) fni_->Enter(); | |
| 3327 | |
| 3328 Consume(Token::THIS); | |
| 3329 int pos = position(); | |
| 3330 function_state_->set_this_location(scanner()->location()); | |
| 3331 ExpressionT this_expr = this->ThisExpression(scope_, factory(), pos); | |
| 3332 | |
| 3333 ExpressionT left = this->EmptyExpression(); | |
| 3334 switch (peek()) { | |
| 3335 case Token::LBRACK: { | |
| 3336 Consume(Token::LBRACK); | |
| 3337 int pos = position(); | |
| 3338 ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK); | |
| 3339 left = factory()->NewProperty(this_expr, index, pos); | |
| 3340 if (fni_ != NULL) { | |
| 3341 this->PushPropertyName(fni_, index); | |
| 3342 } | |
| 3343 Expect(Token::RBRACK, CHECK_OK); | |
| 3344 break; | |
| 3345 } | |
| 3346 case Token::PERIOD: { | |
| 3347 Consume(Token::PERIOD); | |
| 3348 int pos = position(); | |
| 3349 IdentifierT name = ParseIdentifierName(CHECK_OK); | |
| 3350 left = factory()->NewProperty( | |
| 3351 this_expr, factory()->NewStringLiteral(name, pos), pos); | |
| 3352 if (fni_ != NULL) { | |
| 3353 this->PushLiteralName(fni_, name); | |
| 3354 } | |
| 3355 break; | |
| 3356 } | |
| 3357 default: | |
| 3358 ReportMessage(MessageTemplate::kStrongConstructorThis); | |
| 3359 *ok = false; | |
| 3360 return this->EmptyExpression(); | |
| 3361 } | |
| 3362 | |
| 3363 if (peek() != Token::ASSIGN) { | |
| 3364 ReportMessageAt(function_state_->this_location(), | |
| 3365 MessageTemplate::kStrongConstructorThis); | |
| 3366 *ok = false; | |
| 3367 return this->EmptyExpression(); | |
| 3368 } | |
| 3369 Consume(Token::ASSIGN); | |
| 3370 left = this->MarkExpressionAsAssigned(left); | |
| 3371 | |
| 3372 ExpressionT right = | |
| 3373 this->ParseAssignmentExpression(true, classifier, CHECK_OK); | |
| 3374 this->CheckAssigningFunctionLiteralToProperty(left, right); | |
| 3375 function_state_->AddProperty(); | |
| 3376 if (fni_ != NULL) { | |
| 3377 // Check if the right hand side is a call to avoid inferring a | |
| 3378 // name if we're dealing with "this.a = function(){...}();"-like | |
| 3379 // expression. | |
| 3380 if (!right->IsCall() && !right->IsCallNew()) { | |
| 3381 fni_->Infer(); | |
| 3382 } else { | |
| 3383 fni_->RemoveLastFunction(); | |
| 3384 } | |
| 3385 fni_->Leave(); | |
| 3386 } | |
| 3387 | |
| 3388 if (function_state_->return_location().IsValid()) { | |
| 3389 ReportMessageAt(function_state_->return_location(), | |
| 3390 MessageTemplate::kStrongConstructorReturnMisplaced); | |
| 3391 *ok = false; | |
| 3392 return this->EmptyExpression(); | |
| 3393 } | |
| 3394 | |
| 3395 return factory()->NewAssignment(Token::ASSIGN, left, right, pos); | |
| 3396 } | |
| 3397 | |
| 3398 | |
| 3399 template <class Traits> | |
| 3400 typename ParserBase<Traits>::ExpressionT | |
| 3401 ParserBase<Traits>::ParseStrongSuperCallExpression( | |
| 3402 ExpressionClassifier* classifier, bool* ok) { | |
| 3403 // SuperCallExpression :: (strong mode) | |
| 3404 // 'super' '(' ExpressionList ')' | |
| 3405 BindingPatternUnexpectedToken(classifier); | |
| 3406 | |
| 3407 Consume(Token::SUPER); | |
| 3408 int pos = position(); | |
| 3409 Scanner::Location super_loc = scanner()->location(); | |
| 3410 ExpressionT expr = this->SuperCallReference(scope_, factory(), pos); | |
| 3411 | |
| 3412 if (peek() != Token::LPAREN) { | |
| 3413 ReportMessage(MessageTemplate::kStrongConstructorSuper); | |
| 3414 *ok = false; | |
| 3415 return this->EmptyExpression(); | |
| 3416 } | |
| 3417 | |
| 3418 Scanner::Location spread_pos; | |
| 3419 typename Traits::Type::ExpressionList args = | |
| 3420 ParseArguments(&spread_pos, classifier, CHECK_OK); | |
| 3421 | |
| 3422 // TODO(rossberg): This doesn't work with arrow functions yet. | |
| 3423 if (!IsSubclassConstructor(function_state_->kind())) { | |
| 3424 ReportMessage(MessageTemplate::kUnexpectedSuper); | |
| 3425 *ok = false; | |
| 3426 return this->EmptyExpression(); | |
| 3427 } else if (function_state_->super_location().IsValid()) { | |
| 3428 ReportMessageAt(scanner()->location(), | |
| 3429 MessageTemplate::kStrongSuperCallDuplicate); | |
| 3430 *ok = false; | |
| 3431 return this->EmptyExpression(); | |
| 3432 } else if (function_state_->this_location().IsValid()) { | |
| 3433 ReportMessageAt(scanner()->location(), | |
| 3434 MessageTemplate::kStrongSuperCallMisplaced); | |
| 3435 *ok = false; | |
| 3436 return this->EmptyExpression(); | |
| 3437 } else if (function_state_->return_location().IsValid()) { | |
| 3438 ReportMessageAt(function_state_->return_location(), | |
| 3439 MessageTemplate::kStrongConstructorReturnMisplaced); | |
| 3440 *ok = false; | |
| 3441 return this->EmptyExpression(); | |
| 3442 } | |
| 3443 | |
| 3444 function_state_->set_super_location(super_loc); | |
| 3445 if (spread_pos.IsValid()) { | |
| 3446 args = Traits::PrepareSpreadArguments(args); | |
| 3447 return Traits::SpreadCall(expr, args, pos); | |
| 3448 } else { | |
| 3449 return factory()->NewCall(expr, args, pos); | |
| 3450 } | |
| 3451 } | |
| 3452 | |
| 3453 | |
| 3454 template <class Traits> | |
| 3455 typename ParserBase<Traits>::ExpressionT | |
| 3456 ParserBase<Traits>::ParseSuperExpression(bool is_new, | |
| 3457 ExpressionClassifier* classifier, | |
| 3458 bool* ok) { | |
| 3459 int pos = position(); | |
| 3460 Expect(Token::SUPER, CHECK_OK); | |
| 3461 | |
| 3462 Scope* scope = scope_->DeclarationScope(); | |
| 3463 while (scope->is_eval_scope() || scope->is_arrow_scope()) { | |
| 3464 scope = scope->outer_scope(); | |
| 3465 DCHECK_NOT_NULL(scope); | |
| 3466 scope = scope->DeclarationScope(); | |
| 3467 } | |
| 3468 | |
| 3469 FunctionKind kind = scope->function_kind(); | |
| 3470 if (IsConciseMethod(kind) || IsAccessorFunction(kind) || | |
| 3471 i::IsConstructor(kind)) { | |
| 3472 if (peek() == Token::PERIOD || peek() == Token::LBRACK) { | |
| 3473 scope->RecordSuperPropertyUsage(); | |
| 3474 return this->SuperPropertyReference(scope_, factory(), pos); | |
| 3475 } | |
| 3476 // new super() is never allowed. | |
| 3477 // super() is only allowed in derived constructor | |
| 3478 if (!is_new && peek() == Token::LPAREN && IsSubclassConstructor(kind)) { | |
| 3479 if (is_strong(language_mode())) { | |
| 3480 // Super calls in strong mode are parsed separately. | |
| 3481 ReportMessageAt(scanner()->location(), | |
| 3482 MessageTemplate::kStrongConstructorSuper); | |
| 3483 *ok = false; | |
| 3484 return this->EmptyExpression(); | |
| 3485 } | |
| 3486 // TODO(rossberg): This might not be the correct FunctionState for the | |
| 3487 // method here. | |
| 3488 function_state_->set_super_location(scanner()->location()); | |
| 3489 return this->SuperCallReference(scope_, factory(), pos); | |
| 3490 } | |
| 3491 } | |
| 3492 | |
| 3493 ReportMessageAt(scanner()->location(), MessageTemplate::kUnexpectedSuper); | |
| 3494 *ok = false; | |
| 3495 return this->EmptyExpression(); | |
| 3496 } | |
| 3497 | |
| 3498 | |
| 3499 template <class Traits> | |
| 3500 typename ParserBase<Traits>::ExpressionT | |
| 3501 ParserBase<Traits>::ParseNewTargetExpression(bool* ok) { | |
| 3502 int pos = position(); | |
| 3503 Consume(Token::PERIOD); | |
| 3504 ExpectContextualKeyword(CStrVector("target"), CHECK_OK); | |
| 3505 | |
| 3506 Scope* scope = scope_->DeclarationScope(); | |
| 3507 while (scope->is_eval_scope() || scope->is_arrow_scope()) { | |
| 3508 scope = scope->outer_scope(); | |
| 3509 DCHECK_NOT_NULL(scope); | |
| 3510 scope = scope->DeclarationScope(); | |
| 3511 } | |
| 3512 | |
| 3513 if (!scope->is_function_scope()) { | |
| 3514 ReportMessageAt(scanner()->location(), | |
| 3515 MessageTemplate::kUnexpectedNewTarget); | |
| 3516 *ok = false; | |
| 3517 return this->EmptyExpression(); | |
| 3518 } | |
| 3519 | |
| 3520 return this->NewTargetExpression(scope_, factory(), pos); | |
| 3521 } | |
| 3522 | |
| 3523 | |
| 3524 template <class Traits> | |
| 3525 typename ParserBase<Traits>::ExpressionT | |
| 3526 ParserBase<Traits>::ParseMemberExpressionContinuation( | |
| 3527 ExpressionT expression, ExpressionClassifier* classifier, bool* ok) { | |
| 3528 // Parses this part of MemberExpression: | |
| 3529 // ('[' Expression ']' | '.' Identifier | TemplateLiteral)* | |
| 3530 while (true) { | |
| 3531 switch (peek()) { | |
| 3532 case Token::LBRACK: { | |
| 3533 BindingPatternUnexpectedToken(classifier); | |
| 3534 | |
| 3535 Consume(Token::LBRACK); | |
| 3536 int pos = position(); | |
| 3537 ExpressionT index = this->ParseExpression(true, classifier, CHECK_OK); | |
| 3538 expression = factory()->NewProperty(expression, index, pos); | |
| 3539 if (fni_ != NULL) { | |
| 3540 this->PushPropertyName(fni_, index); | |
| 3541 } | |
| 3542 Expect(Token::RBRACK, CHECK_OK); | |
| 3543 break; | |
| 3544 } | |
| 3545 case Token::PERIOD: { | |
| 3546 BindingPatternUnexpectedToken(classifier); | |
| 3547 | |
| 3548 Consume(Token::PERIOD); | |
| 3549 int pos = position(); | |
| 3550 IdentifierT name = ParseIdentifierName(CHECK_OK); | |
| 3551 expression = factory()->NewProperty( | |
| 3552 expression, factory()->NewStringLiteral(name, pos), pos); | |
| 3553 if (fni_ != NULL) { | |
| 3554 this->PushLiteralName(fni_, name); | |
| 3555 } | |
| 3556 break; | |
| 3557 } | |
| 3558 case Token::TEMPLATE_SPAN: | |
| 3559 case Token::TEMPLATE_TAIL: { | |
| 3560 BindingPatternUnexpectedToken(classifier); | |
| 3561 int pos; | |
| 3562 if (scanner()->current_token() == Token::IDENTIFIER) { | |
| 3563 pos = position(); | |
| 3564 } else { | |
| 3565 pos = peek_position(); | |
| 3566 if (expression->IsFunctionLiteral() && mode() == PARSE_EAGERLY) { | |
| 3567 // If the tag function looks like an IIFE, set_parenthesized() to | |
| 3568 // force eager compilation. | |
| 3569 expression->AsFunctionLiteral()->set_should_eager_compile(); | |
| 3570 } | |
| 3571 } | |
| 3572 expression = | |
| 3573 ParseTemplateLiteral(expression, pos, classifier, CHECK_OK); | |
| 3574 break; | |
| 3575 } | |
| 3576 default: | |
| 3577 return expression; | |
| 3578 } | |
| 3579 } | |
| 3580 DCHECK(false); | |
| 3581 return this->EmptyExpression(); | |
| 3582 } | |
| 3583 | |
| 3584 | |
| 3585 template <class Traits> | |
| 3586 void ParserBase<Traits>::ParseFormalParameter( | |
| 3587 bool is_rest, FormalParameterParsingStateT* parsing_state, | |
| 3588 ExpressionClassifier* classifier, bool* ok) { | |
| 3589 // FormalParameter[Yield,GeneratorParameter] : | |
| 3590 // BindingElement[?Yield, ?GeneratorParameter] | |
| 3591 | |
| 3592 Token::Value next = peek(); | |
| 3593 ExpressionT pattern = ParsePrimaryExpression(classifier, ok); | |
| 3594 if (!*ok) return; | |
| 3595 | |
| 3596 ValidateBindingPattern(classifier, ok); | |
| 3597 if (!*ok) return; | |
| 3598 | |
| 3599 if (!allow_harmony_destructuring() && !Traits::IsIdentifier(pattern)) { | |
| 3600 ReportUnexpectedToken(next); | |
| 3601 *ok = false; | |
| 3602 return; | |
| 3603 } | |
| 3604 | |
| 3605 if (parsing_state->is_simple_parameter_list) { | |
| 3606 parsing_state->is_simple_parameter_list = | |
| 3607 !is_rest && Traits::IsIdentifier(pattern); | |
| 3608 } | |
| 3609 parsing_state->has_rest = is_rest; | |
| 3610 if (is_rest && !Traits::IsIdentifier(pattern)) { | |
| 3611 ReportUnexpectedToken(next); | |
| 3612 *ok = false; | |
| 3613 return; | |
| 3614 } | |
| 3615 Traits::DeclareFormalParameter(parsing_state, pattern, classifier, is_rest); | |
| 3616 } | |
| 3617 | |
| 3618 | |
| 3619 template <class Traits> | |
| 3620 int ParserBase<Traits>::ParseFormalParameterList( | |
| 3621 FormalParameterParsingStateT* parsing_state, | |
| 3622 ExpressionClassifier* classifier, bool* ok) { | |
| 3623 // FormalParameters[Yield,GeneratorParameter] : | |
| 3624 // [empty] | |
| 3625 // FormalParameterList[?Yield, ?GeneratorParameter] | |
| 3626 // | |
| 3627 // FormalParameterList[Yield,GeneratorParameter] : | |
| 3628 // FunctionRestParameter[?Yield] | |
| 3629 // FormalsList[?Yield, ?GeneratorParameter] | |
| 3630 // FormalsList[?Yield, ?GeneratorParameter] , FunctionRestParameter[?Yield] | |
| 3631 // | |
| 3632 // FormalsList[Yield,GeneratorParameter] : | |
| 3633 // FormalParameter[?Yield, ?GeneratorParameter] | |
| 3634 // FormalsList[?Yield, ?GeneratorParameter] , | |
| 3635 // FormalParameter[?Yield,?GeneratorParameter] | |
| 3636 | |
| 3637 int parameter_count = 0; | |
| 3638 | |
| 3639 if (peek() != Token::RPAREN) { | |
| 3640 do { | |
| 3641 if (++parameter_count > Code::kMaxArguments) { | |
| 3642 ReportMessage(MessageTemplate::kTooManyParameters); | |
| 3643 *ok = false; | |
| 3644 return -1; | |
| 3645 } | |
| 3646 bool is_rest = allow_harmony_rest_params() && Check(Token::ELLIPSIS); | |
| 3647 ParseFormalParameter(is_rest, parsing_state, classifier, ok); | |
| 3648 if (!*ok) return -1; | |
| 3649 } while (!parsing_state->has_rest && Check(Token::COMMA)); | |
| 3650 | |
| 3651 if (parsing_state->has_rest && peek() == Token::COMMA) { | |
| 3652 ReportMessageAt(scanner()->peek_location(), | |
| 3653 MessageTemplate::kParamAfterRest); | |
| 3654 *ok = false; | |
| 3655 return -1; | |
| 3656 } | |
| 3657 } | |
| 3658 | |
| 3659 return parameter_count; | |
| 3660 } | |
| 3661 | |
| 3662 | |
| 3663 template <class Traits> | |
| 3664 void ParserBase<Traits>::CheckArityRestrictions( | |
| 3665 int param_count, FunctionLiteral::ArityRestriction arity_restriction, | |
| 3666 bool has_rest, int formals_start_pos, int formals_end_pos, bool* ok) { | |
| 3667 switch (arity_restriction) { | |
| 3668 case FunctionLiteral::GETTER_ARITY: | |
| 3669 if (param_count != 0) { | |
| 3670 ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), | |
| 3671 MessageTemplate::kBadGetterArity); | |
| 3672 *ok = false; | |
| 3673 } | |
| 3674 break; | |
| 3675 case FunctionLiteral::SETTER_ARITY: | |
| 3676 if (param_count != 1) { | |
| 3677 ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), | |
| 3678 MessageTemplate::kBadSetterArity); | |
| 3679 *ok = false; | |
| 3680 } | |
| 3681 if (has_rest) { | |
| 3682 ReportMessageAt(Scanner::Location(formals_start_pos, formals_end_pos), | |
| 3683 MessageTemplate::kBadSetterRestParameter); | |
| 3684 *ok = false; | |
| 3685 } | |
| 3686 break; | |
| 3687 default: | |
| 3688 break; | |
| 3689 } | |
| 3690 } | |
| 3691 | |
| 3692 | |
| 3693 template <class Traits> | |
| 3694 typename ParserBase<Traits>::ExpressionT | |
| 3695 ParserBase<Traits>::ParseArrowFunctionLiteral( | |
| 3696 const FormalParameterParsingStateT& formal_parameters, | |
| 3697 const ExpressionClassifier& formals_classifier, bool* ok) { | |
| 3698 if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { | |
| 3699 // ASI inserts `;` after arrow parameters if a line terminator is found. | |
| 3700 // `=> ...` is never a valid expression, so report as syntax error. | |
| 3701 // If next token is not `=>`, it's a syntax error anyways. | |
| 3702 ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW); | |
| 3703 *ok = false; | |
| 3704 return this->EmptyExpression(); | |
| 3705 } | |
| 3706 | |
| 3707 typename Traits::Type::StatementList body; | |
| 3708 int num_parameters = formal_parameters.scope->num_parameters(); | |
| 3709 int materialized_literal_count = -1; | |
| 3710 int expected_property_count = -1; | |
| 3711 Scanner::Location super_loc; | |
| 3712 | |
| 3713 { | |
| 3714 typename Traits::Type::Factory function_factory(ast_value_factory()); | |
| 3715 FunctionState function_state(&function_state_, &scope_, | |
| 3716 formal_parameters.scope, kArrowFunction, | |
| 3717 &function_factory); | |
| 3718 | |
| 3719 function_state.SkipMaterializedLiterals( | |
| 3720 formal_parameters.materialized_literals_count); | |
| 3721 | |
| 3722 this->ReindexLiterals(formal_parameters); | |
| 3723 | |
| 3724 Expect(Token::ARROW, CHECK_OK); | |
| 3725 | |
| 3726 if (peek() == Token::LBRACE) { | |
| 3727 // Multiple statement body | |
| 3728 Consume(Token::LBRACE); | |
| 3729 bool is_lazily_parsed = | |
| 3730 (mode() == PARSE_LAZILY && scope_->AllowsLazyCompilation()); | |
| 3731 if (is_lazily_parsed) { | |
| 3732 body = this->NewStatementList(0, zone()); | |
| 3733 this->SkipLazyFunctionBody(&materialized_literal_count, | |
| 3734 &expected_property_count, CHECK_OK); | |
| 3735 } else { | |
| 3736 body = this->ParseEagerFunctionBody( | |
| 3737 this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters, | |
| 3738 NULL, Token::INIT_VAR, kArrowFunction, CHECK_OK); | |
| 3739 materialized_literal_count = | |
| 3740 function_state.materialized_literal_count(); | |
| 3741 expected_property_count = function_state.expected_property_count(); | |
| 3742 } | |
| 3743 } else { | |
| 3744 // Single-expression body | |
| 3745 int pos = position(); | |
| 3746 parenthesized_function_ = false; | |
| 3747 ExpressionClassifier classifier; | |
| 3748 ExpressionT expression = | |
| 3749 ParseAssignmentExpression(true, &classifier, CHECK_OK); | |
| 3750 ValidateExpression(&classifier, CHECK_OK); | |
| 3751 body = this->NewStatementList(1, zone()); | |
| 3752 this->AddParameterInitializationBlock(formal_parameters, body, CHECK_OK); | |
| 3753 body->Add(factory()->NewReturnStatement(expression, pos), zone()); | |
| 3754 materialized_literal_count = function_state.materialized_literal_count(); | |
| 3755 expected_property_count = function_state.expected_property_count(); | |
| 3756 } | |
| 3757 super_loc = function_state.super_location(); | |
| 3758 | |
| 3759 formal_parameters.scope->set_end_position(scanner()->location().end_pos); | |
| 3760 | |
| 3761 // Arrow function formal parameters are parsed as StrictFormalParameterList, | |
| 3762 // which is not the same as "parameters of a strict function"; it only means | |
| 3763 // that duplicates are not allowed. Of course, the arrow function may | |
| 3764 // itself be strict as well. | |
| 3765 const bool allow_duplicate_parameters = false; | |
| 3766 this->ValidateFormalParameters(&formals_classifier, language_mode(), | |
| 3767 allow_duplicate_parameters, CHECK_OK); | |
| 3768 | |
| 3769 // Validate strict mode. | |
| 3770 if (is_strict(language_mode())) { | |
| 3771 CheckStrictOctalLiteral(formal_parameters.scope->start_position(), | |
| 3772 scanner()->location().end_pos, CHECK_OK); | |
| 3773 } | |
| 3774 if (is_strict(language_mode()) || allow_harmony_sloppy()) { | |
| 3775 this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); | |
| 3776 } | |
| 3777 } | |
| 3778 | |
| 3779 FunctionLiteralT function_literal = factory()->NewFunctionLiteral( | |
| 3780 this->EmptyIdentifierString(), ast_value_factory(), | |
| 3781 formal_parameters.scope, body, materialized_literal_count, | |
| 3782 expected_property_count, num_parameters, | |
| 3783 FunctionLiteral::kNoDuplicateParameters, | |
| 3784 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction, | |
| 3785 FunctionLiteral::kShouldLazyCompile, FunctionKind::kArrowFunction, | |
| 3786 formal_parameters.scope->start_position()); | |
| 3787 | |
| 3788 function_literal->set_function_token_position( | |
| 3789 formal_parameters.scope->start_position()); | |
| 3790 if (super_loc.IsValid()) function_state_->set_super_location(super_loc); | |
| 3791 | |
| 3792 if (fni_ != NULL) this->InferFunctionName(fni_, function_literal); | |
| 3793 | |
| 3794 return function_literal; | |
| 3795 } | |
| 3796 | |
| 3797 | |
| 3798 template <typename Traits> | |
| 3799 typename ParserBase<Traits>::ExpressionT | |
| 3800 ParserBase<Traits>::ParseTemplateLiteral(ExpressionT tag, int start, | |
| 3801 ExpressionClassifier* classifier, | |
| 3802 bool* ok) { | |
| 3803 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal | |
| 3804 // text followed by a substitution expression), finalized by a single | |
| 3805 // TEMPLATE_TAIL. | |
| 3806 // | |
| 3807 // In terms of draft language, TEMPLATE_SPAN may be either the TemplateHead or | |
| 3808 // TemplateMiddle productions, while TEMPLATE_TAIL is either TemplateTail, or | |
| 3809 // NoSubstitutionTemplate. | |
| 3810 // | |
| 3811 // When parsing a TemplateLiteral, we must have scanned either an initial | |
| 3812 // TEMPLATE_SPAN, or a TEMPLATE_TAIL. | |
| 3813 CHECK(peek() == Token::TEMPLATE_SPAN || peek() == Token::TEMPLATE_TAIL); | |
| 3814 | |
| 3815 // If we reach a TEMPLATE_TAIL first, we are parsing a NoSubstitutionTemplate. | |
| 3816 // In this case we may simply consume the token and build a template with a | |
| 3817 // single TEMPLATE_SPAN and no expressions. | |
| 3818 if (peek() == Token::TEMPLATE_TAIL) { | |
| 3819 Consume(Token::TEMPLATE_TAIL); | |
| 3820 int pos = position(); | |
| 3821 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); | |
| 3822 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos); | |
| 3823 Traits::AddTemplateSpan(&ts, true); | |
| 3824 return Traits::CloseTemplateLiteral(&ts, start, tag); | |
| 3825 } | |
| 3826 | |
| 3827 Consume(Token::TEMPLATE_SPAN); | |
| 3828 int pos = position(); | |
| 3829 typename Traits::TemplateLiteralState ts = Traits::OpenTemplateLiteral(pos); | |
| 3830 Traits::AddTemplateSpan(&ts, false); | |
| 3831 Token::Value next; | |
| 3832 | |
| 3833 // If we open with a TEMPLATE_SPAN, we must scan the subsequent expression, | |
| 3834 // and repeat if the following token is a TEMPLATE_SPAN as well (in this | |
| 3835 // case, representing a TemplateMiddle). | |
| 3836 | |
| 3837 do { | |
| 3838 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); | |
| 3839 next = peek(); | |
| 3840 if (next == Token::EOS) { | |
| 3841 ReportMessageAt(Scanner::Location(start, peek_position()), | |
| 3842 MessageTemplate::kUnterminatedTemplate); | |
| 3843 *ok = false; | |
| 3844 return Traits::EmptyExpression(); | |
| 3845 } else if (next == Token::ILLEGAL) { | |
| 3846 Traits::ReportMessageAt( | |
| 3847 Scanner::Location(position() + 1, peek_position()), | |
| 3848 MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError); | |
| 3849 *ok = false; | |
| 3850 return Traits::EmptyExpression(); | |
| 3851 } | |
| 3852 | |
| 3853 int expr_pos = peek_position(); | |
| 3854 ExpressionT expression = this->ParseExpression(true, classifier, CHECK_OK); | |
| 3855 Traits::AddTemplateExpression(&ts, expression); | |
| 3856 | |
| 3857 if (peek() != Token::RBRACE) { | |
| 3858 ReportMessageAt(Scanner::Location(expr_pos, peek_position()), | |
| 3859 MessageTemplate::kUnterminatedTemplateExpr); | |
| 3860 *ok = false; | |
| 3861 return Traits::EmptyExpression(); | |
| 3862 } | |
| 3863 | |
| 3864 // If we didn't die parsing that expression, our next token should be a | |
| 3865 // TEMPLATE_SPAN or TEMPLATE_TAIL. | |
| 3866 next = scanner()->ScanTemplateContinuation(); | |
| 3867 Next(); | |
| 3868 pos = position(); | |
| 3869 | |
| 3870 if (next == Token::EOS) { | |
| 3871 ReportMessageAt(Scanner::Location(start, pos), | |
| 3872 MessageTemplate::kUnterminatedTemplate); | |
| 3873 *ok = false; | |
| 3874 return Traits::EmptyExpression(); | |
| 3875 } else if (next == Token::ILLEGAL) { | |
| 3876 Traits::ReportMessageAt( | |
| 3877 Scanner::Location(position() + 1, peek_position()), | |
| 3878 MessageTemplate::kUnexpectedToken, "ILLEGAL", kSyntaxError); | |
| 3879 *ok = false; | |
| 3880 return Traits::EmptyExpression(); | |
| 3881 } | |
| 3882 | |
| 3883 Traits::AddTemplateSpan(&ts, next == Token::TEMPLATE_TAIL); | |
| 3884 } while (next == Token::TEMPLATE_SPAN); | |
| 3885 | |
| 3886 DCHECK_EQ(next, Token::TEMPLATE_TAIL); | |
| 3887 CheckTemplateOctalLiteral(pos, peek_position(), CHECK_OK); | |
| 3888 // Once we've reached a TEMPLATE_TAIL, we can close the TemplateLiteral. | |
| 3889 return Traits::CloseTemplateLiteral(&ts, start, tag); | |
| 3890 } | |
| 3891 | |
| 3892 | |
| 3893 template <typename Traits> | |
| 3894 typename ParserBase<Traits>::ExpressionT | |
| 3895 ParserBase<Traits>::CheckAndRewriteReferenceExpression( | |
| 3896 ExpressionT expression, Scanner::Location location, | |
| 3897 MessageTemplate::Template message, bool* ok) { | |
| 3898 if (this->IsIdentifier(expression)) { | |
| 3899 if (is_strict(language_mode()) && | |
| 3900 this->IsEvalOrArguments(this->AsIdentifier(expression))) { | |
| 3901 this->ReportMessageAt(location, MessageTemplate::kStrictEvalArguments, | |
| 3902 kSyntaxError); | |
| 3903 *ok = false; | |
| 3904 return this->EmptyExpression(); | |
| 3905 } | |
| 3906 if (is_strong(language_mode()) && | |
| 3907 this->IsUndefined(this->AsIdentifier(expression))) { | |
| 3908 this->ReportMessageAt(location, MessageTemplate::kStrongUndefined, | |
| 3909 kSyntaxError); | |
| 3910 *ok = false; | |
| 3911 return this->EmptyExpression(); | |
| 3912 } | |
| 3913 } | |
| 3914 if (expression->IsValidReferenceExpression()) { | |
| 3915 return expression; | |
| 3916 } else if (expression->IsCall()) { | |
| 3917 // If it is a call, make it a runtime error for legacy web compatibility. | |
| 3918 // Rewrite `expr' to `expr[throw ReferenceError]'. | |
| 3919 int pos = location.beg_pos; | |
| 3920 ExpressionT error = this->NewThrowReferenceError(message, pos); | |
| 3921 return factory()->NewProperty(expression, error, pos); | |
| 3922 } else { | |
| 3923 this->ReportMessageAt(location, message, kReferenceError); | |
| 3924 *ok = false; | |
| 3925 return this->EmptyExpression(); | |
| 3926 } | |
| 3927 } | |
| 3928 | |
| 3929 | |
| 3930 #undef CHECK_OK | |
| 3931 #undef CHECK_OK_CUSTOM | |
| 3932 | |
| 3933 | |
| 3934 template <typename Traits> | |
| 3935 void ParserBase<Traits>::ObjectLiteralChecker::CheckProperty( | |
| 3936 Token::Value property, PropertyKind type, bool is_static, bool is_generator, | |
| 3937 bool* ok) { | |
| 3938 DCHECK(!is_static); | |
| 3939 DCHECK(!is_generator || type == kMethodProperty); | |
| 3940 | |
| 3941 if (property == Token::SMI || property == Token::NUMBER) return; | |
| 3942 | |
| 3943 if (type == kValueProperty && IsProto()) { | |
| 3944 if (has_seen_proto_) { | |
| 3945 this->parser()->ReportMessage(MessageTemplate::kDuplicateProto); | |
| 3946 *ok = false; | |
| 3947 return; | |
| 3948 } | |
| 3949 has_seen_proto_ = true; | |
| 3950 return; | |
| 3951 } | |
| 3952 } | |
| 3953 | |
| 3954 | |
| 3955 template <typename Traits> | |
| 3956 void ParserBase<Traits>::ClassLiteralChecker::CheckProperty( | |
| 3957 Token::Value property, PropertyKind type, bool is_static, bool is_generator, | |
| 3958 bool* ok) { | |
| 3959 DCHECK(type == kMethodProperty || type == kAccessorProperty); | |
| 3960 | |
| 3961 if (property == Token::SMI || property == Token::NUMBER) return; | |
| 3962 | |
| 3963 if (is_static) { | |
| 3964 if (IsPrototype()) { | |
| 3965 this->parser()->ReportMessage(MessageTemplate::kStaticPrototype); | |
| 3966 *ok = false; | |
| 3967 return; | |
| 3968 } | |
| 3969 } else if (IsConstructor()) { | |
| 3970 if (is_generator || type == kAccessorProperty) { | |
| 3971 MessageTemplate::Template msg = | |
| 3972 is_generator ? MessageTemplate::kConstructorIsGenerator | |
| 3973 : MessageTemplate::kConstructorIsAccessor; | |
| 3974 this->parser()->ReportMessage(msg); | |
| 3975 *ok = false; | |
| 3976 return; | |
| 3977 } | |
| 3978 if (has_seen_constructor_) { | |
| 3979 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); | |
| 3980 *ok = false; | |
| 3981 return; | |
| 3982 } | |
| 3983 has_seen_constructor_ = true; | |
| 3984 return; | |
| 3985 } | |
| 3986 } | |
| 3987 } } // v8::internal | 1055 } } // v8::internal |
| 3988 | 1056 |
| 3989 #endif // V8_PREPARSER_H | 1057 #endif // V8_PREPARSER_H |
| OLD | NEW |