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