v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
preparser.cc
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <cmath>
29 
30 #include "../include/v8stdint.h"
31 
32 #include "allocation.h"
33 #include "checks.h"
34 #include "conversions.h"
35 #include "conversions-inl.h"
36 #include "globals.h"
37 #include "hashmap.h"
38 #include "list.h"
39 #include "preparse-data-format.h"
40 #include "preparse-data.h"
41 #include "preparser.h"
42 #include "unicode.h"
43 #include "utils.h"
44 
45 #if V8_LIBC_MSVCRT && (_MSC_VER < 1800)
46 namespace std {
47 
48 // Usually defined in math.h, but not in MSVC until VS2013+.
49 // Abstracted to work
50 int isfinite(double value);
51 
52 } // namespace std
53 #endif
54 
55 namespace v8 {
56 namespace internal {
57 
58 
60  bool* ok) {
61  if (expression.IsIdentifier() &&
62  expression.AsIdentifier().IsEvalOrArguments()) {
63  pre_parser_->ReportMessage("strict_eval_arguments",
65  *ok = false;
66  }
67 }
68 
69 
71  const char* message,
73  bool is_reference_error) {
74  ReportMessageAt(location.beg_pos,
75  location.end_pos,
76  message,
77  args.length() > 0 ? args[0] : NULL,
78  is_reference_error);
79 }
80 
81 
83  const char* type,
84  const char* name_opt,
85  bool is_reference_error) {
86  pre_parser_->log_
87  ->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
88 }
89 
90 
92  int end_pos,
93  const char* type,
94  const char* name_opt,
95  bool is_reference_error) {
96  pre_parser_->log_->LogMessage(start_pos, end_pos, type, name_opt);
97 }
98 
99 
101  pre_parser_->LogSymbol();
102  if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
104  } else if (scanner->current_token() ==
105  Token::FUTURE_STRICT_RESERVED_WORD) {
107  } else if (scanner->current_token() == Token::YIELD) {
109  }
110  if (scanner->UnescapedLiteralMatches("eval", 4)) {
111  return PreParserIdentifier::Eval();
112  }
113  if (scanner->UnescapedLiteralMatches("arguments", 9)) {
115  }
117 }
118 
119 
121  int pos, Scanner* scanner, PreParserFactory* factory) {
122  pre_parser_->LogSymbol();
123  if (scanner->UnescapedLiteralMatches("use strict", 10)) {
125  }
127 }
128 
129 
131  return pre_parser_->ParseV8Intrinsic(ok);
132 }
133 
134 
137  Scanner::Location function_name_location,
138  bool name_is_strict_reserved,
139  bool is_generator,
140  int function_token_position,
141  FunctionLiteral::FunctionType type,
142  bool* ok) {
143  return pre_parser_->ParseFunctionLiteral(
144  name, function_name_location, name_is_strict_reserved, is_generator,
145  function_token_position, type, ok);
146 }
147 
148 
150  StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
151  log_ = log;
152  // Lazy functions always have trivial outer scopes (no with/catch scopes).
153  PreParserScope top_scope(scope_, GLOBAL_SCOPE);
154  FunctionState top_state(&function_state_, &scope_, &top_scope);
155  scope_->SetStrictMode(strict_mode);
156  PreParserScope function_scope(scope_, FUNCTION_SCOPE);
157  FunctionState function_state(&function_state_, &scope_, &function_scope);
158  function_state.set_is_generator(is_generator);
159  ASSERT_EQ(Token::LBRACE, scanner()->current_token());
160  bool ok = true;
161  int start_position = peek_position();
162  ParseLazyFunctionLiteralBody(&ok);
164  if (!ok) {
165  ReportUnexpectedToken(scanner()->current_token());
166  } else {
167  ASSERT_EQ(Token::RBRACE, scanner()->peek());
168  if (scope_->strict_mode() == STRICT) {
169  int end_pos = scanner()->location().end_pos;
170  CheckOctalLiteral(start_position, end_pos, &ok);
171  }
172  }
173  return kPreParseSuccess;
174 }
175 
176 
177 // Preparsing checks a JavaScript program and emits preparse-data that helps
178 // a later parsing to be faster.
179 // See preparser-data.h for the data.
180 
181 // The PreParser checks that the syntax follows the grammar for JavaScript,
182 // and collects some information about the program along the way.
183 // The grammar check is only performed in order to understand the program
184 // sufficiently to deduce some information about it, that can be used
185 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
186 // rather it is to speed up properly written and correct programs.
187 // That means that contextual checks (like a label being declared where
188 // it is used) are generally omitted.
189 
190 
191 #define CHECK_OK ok); \
192  if (!*ok) return kUnknownSourceElements; \
193  ((void)0
194 #define DUMMY ) // to make indentation work
195 #undef DUMMY
196 
197 
198 PreParser::Statement PreParser::ParseSourceElement(bool* ok) {
199  // (Ecma 262 5th Edition, clause 14):
200  // SourceElement:
201  // Statement
202  // FunctionDeclaration
203  //
204  // In harmony mode we allow additionally the following productions
205  // SourceElement:
206  // LetDeclaration
207  // ConstDeclaration
208  // GeneratorDeclaration
209 
210  switch (peek()) {
211  case Token::FUNCTION:
212  return ParseFunctionDeclaration(ok);
213  case Token::LET:
214  case Token::CONST:
215  return ParseVariableStatement(kSourceElement, ok);
216  default:
217  return ParseStatement(ok);
218  }
219 }
220 
221 
222 PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
223  bool* ok) {
224  // SourceElements ::
225  // (Statement)* <end_token>
226 
227  bool directive_prologue = true;
228  while (peek() != end_token) {
229  if (directive_prologue && peek() != Token::STRING) {
230  directive_prologue = false;
231  }
232  Statement statement = ParseSourceElement(CHECK_OK);
233  if (directive_prologue) {
234  if (statement.IsUseStrictLiteral()) {
235  scope_->SetStrictMode(STRICT);
236  } else if (!statement.IsStringLiteral()) {
237  directive_prologue = false;
238  }
239  }
240  }
241  return kUnknownSourceElements;
242 }
243 
244 
245 #undef CHECK_OK
246 #define CHECK_OK ok); \
247  if (!*ok) return Statement::Default(); \
248  ((void)0
249 #define DUMMY ) // to make indentation work
250 #undef DUMMY
251 
252 
253 PreParser::Statement PreParser::ParseStatement(bool* ok) {
254  // Statement ::
255  // Block
256  // VariableStatement
257  // EmptyStatement
258  // ExpressionStatement
259  // IfStatement
260  // IterationStatement
261  // ContinueStatement
262  // BreakStatement
263  // ReturnStatement
264  // WithStatement
265  // LabelledStatement
266  // SwitchStatement
267  // ThrowStatement
268  // TryStatement
269  // DebuggerStatement
270 
271  // Note: Since labels can only be used by 'break' and 'continue'
272  // statements, which themselves are only valid within blocks,
273  // iterations or 'switch' statements (i.e., BreakableStatements),
274  // labels can be simply ignored in all other cases; except for
275  // trivial labeled break statements 'label: break label' which is
276  // parsed into an empty statement.
277 
278  // Keep the source position of the statement
279  switch (peek()) {
280  case Token::LBRACE:
281  return ParseBlock(ok);
282 
283  case Token::CONST:
284  case Token::LET:
285  case Token::VAR:
286  return ParseVariableStatement(kStatement, ok);
287 
288  case Token::SEMICOLON:
289  Next();
290  return Statement::Default();
291 
292  case Token::IF:
293  return ParseIfStatement(ok);
294 
295  case Token::DO:
296  return ParseDoWhileStatement(ok);
297 
298  case Token::WHILE:
299  return ParseWhileStatement(ok);
300 
301  case Token::FOR:
302  return ParseForStatement(ok);
303 
304  case Token::CONTINUE:
305  return ParseContinueStatement(ok);
306 
307  case Token::BREAK:
308  return ParseBreakStatement(ok);
309 
310  case Token::RETURN:
311  return ParseReturnStatement(ok);
312 
313  case Token::WITH:
314  return ParseWithStatement(ok);
315 
316  case Token::SWITCH:
317  return ParseSwitchStatement(ok);
318 
319  case Token::THROW:
320  return ParseThrowStatement(ok);
321 
322  case Token::TRY:
323  return ParseTryStatement(ok);
324 
325  case Token::FUNCTION: {
326  Scanner::Location start_location = scanner()->peek_location();
327  Statement statement = ParseFunctionDeclaration(CHECK_OK);
328  Scanner::Location end_location = scanner()->location();
329  if (strict_mode() == STRICT) {
330  PreParserTraits::ReportMessageAt(start_location.beg_pos,
331  end_location.end_pos,
332  "strict_function",
333  NULL);
334  *ok = false;
335  return Statement::Default();
336  } else {
337  return statement;
338  }
339  }
340 
341  case Token::DEBUGGER:
342  return ParseDebuggerStatement(ok);
343 
344  default:
345  return ParseExpressionOrLabelledStatement(ok);
346  }
347 }
348 
349 
350 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
351  // FunctionDeclaration ::
352  // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
353  // GeneratorDeclaration ::
354  // 'function' '*' Identifier '(' FormalParameterListopt ')'
355  // '{' FunctionBody '}'
356  Expect(Token::FUNCTION, CHECK_OK);
357  int pos = position();
359  bool is_strict_reserved = false;
361  &is_strict_reserved, CHECK_OK);
362  ParseFunctionLiteral(name,
363  scanner()->location(),
364  is_strict_reserved,
365  is_generator,
366  pos,
367  FunctionLiteral::DECLARATION,
368  CHECK_OK);
369  return Statement::FunctionDeclaration();
370 }
371 
372 
373 PreParser::Statement PreParser::ParseBlock(bool* ok) {
374  // Block ::
375  // '{' Statement* '}'
376 
377  // Note that a Block does not introduce a new execution scope!
378  // (ECMA-262, 3rd, 12.2)
379  //
380  Expect(Token::LBRACE, CHECK_OK);
381  while (peek() != Token::RBRACE) {
382  if (allow_harmony_scoping() && strict_mode() == STRICT) {
383  ParseSourceElement(CHECK_OK);
384  } else {
385  ParseStatement(CHECK_OK);
386  }
387  }
388  Expect(Token::RBRACE, ok);
389  return Statement::Default();
390 }
391 
392 
393 PreParser::Statement PreParser::ParseVariableStatement(
394  VariableDeclarationContext var_context,
395  bool* ok) {
396  // VariableStatement ::
397  // VariableDeclarations ';'
398 
399  Statement result = ParseVariableDeclarations(var_context,
400  NULL,
401  NULL,
402  CHECK_OK);
404  return result;
405 }
406 
407 
408 // If the variable declaration declares exactly one non-const
409 // variable, then *var is set to that variable. In all other cases,
410 // *var is untouched; in particular, it is the caller's responsibility
411 // to initialize it properly. This mechanism is also used for the parsing
412 // of 'for-in' loops.
413 PreParser::Statement PreParser::ParseVariableDeclarations(
414  VariableDeclarationContext var_context,
415  VariableDeclarationProperties* decl_props,
416  int* num_decl,
417  bool* ok) {
418  // VariableDeclarations ::
419  // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
420  //
421  // The ES6 Draft Rev3 specifies the following grammar for const declarations
422  //
423  // ConstDeclaration ::
424  // const ConstBinding (',' ConstBinding)* ';'
425  // ConstBinding ::
426  // Identifier '=' AssignmentExpression
427  //
428  // TODO(ES6):
429  // ConstBinding ::
430  // BindingPattern '=' AssignmentExpression
431  bool require_initializer = false;
432  if (peek() == Token::VAR) {
434  } else if (peek() == Token::CONST) {
435  // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
436  //
437  // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
438  //
439  // * It is a Syntax Error if the code that matches this production is not
440  // contained in extended code.
441  //
442  // However disallowing const in sloppy mode will break compatibility with
443  // existing pages. Therefore we keep allowing const with the old
444  // non-harmony semantics in sloppy mode.
446  if (strict_mode() == STRICT) {
447  if (allow_harmony_scoping()) {
448  if (var_context != kSourceElement && var_context != kForStatement) {
449  ReportMessageAt(scanner()->peek_location(), "unprotected_const");
450  *ok = false;
451  return Statement::Default();
452  }
453  require_initializer = true;
454  } else {
455  Scanner::Location location = scanner()->peek_location();
456  ReportMessageAt(location, "strict_const");
457  *ok = false;
458  return Statement::Default();
459  }
460  }
461  } else if (peek() == Token::LET) {
462  // ES6 Draft Rev4 section 12.2.1:
463  //
464  // LetDeclaration : let LetBindingList ;
465  //
466  // * It is a Syntax Error if the code that matches this production is not
467  // contained in extended code.
468  //
469  // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
470  if (!allow_harmony_scoping() || strict_mode() == SLOPPY) {
471  ReportMessageAt(scanner()->peek_location(), "illegal_let");
472  *ok = false;
473  return Statement::Default();
474  }
476  if (var_context != kSourceElement &&
477  var_context != kForStatement) {
478  ReportMessageAt(scanner()->peek_location(), "unprotected_let");
479  *ok = false;
480  return Statement::Default();
481  }
482  } else {
483  *ok = false;
484  return Statement::Default();
485  }
486 
487  // The scope of a var/const declared variable anywhere inside a function
488  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
489  // of a let declared variable is the scope of the immediately enclosing
490  // block.
491  int nvars = 0; // the number of variables declared
492  do {
493  // Parse variable name.
494  if (nvars > 0) Consume(Token::COMMA);
496  nvars++;
497  if (peek() == Token::ASSIGN || require_initializer) {
498  Expect(Token::ASSIGN, CHECK_OK);
499  ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
500  if (decl_props != NULL) *decl_props = kHasInitializers;
501  }
502  } while (peek() == Token::COMMA);
503 
504  if (num_decl != NULL) *num_decl = nvars;
505  return Statement::Default();
506 }
507 
508 
509 PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
510  // ExpressionStatement | LabelledStatement ::
511  // Expression ';'
512  // Identifier ':' Statement
513 
514  bool starts_with_identifier = peek_any_identifier();
515  Expression expr = ParseExpression(true, CHECK_OK);
516  // Even if the expression starts with an identifier, it is not necessarily an
517  // identifier. For example, "foo + bar" starts with an identifier but is not
518  // an identifier.
519  if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
520  // Expression is a single identifier, and not, e.g., a parenthesized
521  // identifier.
522  ASSERT(!expr.AsIdentifier().IsFutureReserved());
523  ASSERT(strict_mode() == SLOPPY ||
524  (!expr.AsIdentifier().IsFutureStrictReserved() &&
525  !expr.AsIdentifier().IsYield()));
526  Consume(Token::COLON);
527  return ParseStatement(ok);
528  // Preparsing is disabled for extensions (because the extension details
529  // aren't passed to lazily compiled functions), so we don't
530  // accept "native function" in the preparser.
531  }
532  // Parsed expression statement.
534  return Statement::ExpressionStatement(expr);
535 }
536 
537 
538 PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
539  // IfStatement ::
540  // 'if' '(' Expression ')' Statement ('else' Statement)?
541 
542  Expect(Token::IF, CHECK_OK);
543  Expect(Token::LPAREN, CHECK_OK);
544  ParseExpression(true, CHECK_OK);
545  Expect(Token::RPAREN, CHECK_OK);
546  ParseStatement(CHECK_OK);
547  if (peek() == Token::ELSE) {
548  Next();
549  ParseStatement(CHECK_OK);
550  }
551  return Statement::Default();
552 }
553 
554 
555 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
556  // ContinueStatement ::
557  // 'continue' [no line terminator] Identifier? ';'
558 
559  Expect(Token::CONTINUE, CHECK_OK);
560  Token::Value tok = peek();
561  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
562  tok != Token::SEMICOLON &&
563  tok != Token::RBRACE &&
564  tok != Token::EOS) {
565  // ECMA allows "eval" or "arguments" as labels even in strict mode.
567  }
569  return Statement::Default();
570 }
571 
572 
573 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
574  // BreakStatement ::
575  // 'break' [no line terminator] Identifier? ';'
576 
578  Token::Value tok = peek();
579  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
580  tok != Token::SEMICOLON &&
581  tok != Token::RBRACE &&
582  tok != Token::EOS) {
583  // ECMA allows "eval" or "arguments" as labels even in strict mode.
585  }
587  return Statement::Default();
588 }
589 
590 
591 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
592  // ReturnStatement ::
593  // 'return' [no line terminator] Expression? ';'
594 
595  // Consume the return token. It is necessary to do the before
596  // reporting any errors on it, because of the way errors are
597  // reported (underlining).
598  Expect(Token::RETURN, CHECK_OK);
599 
600  // An ECMAScript program is considered syntactically incorrect if it
601  // contains a return statement that is not within the body of a
602  // function. See ECMA-262, section 12.9, page 67.
603  // This is not handled during preparsing.
604 
605  Token::Value tok = peek();
606  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
607  tok != Token::SEMICOLON &&
608  tok != Token::RBRACE &&
609  tok != Token::EOS) {
610  ParseExpression(true, CHECK_OK);
611  }
613  return Statement::Default();
614 }
615 
616 
617 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
618  // WithStatement ::
619  // 'with' '(' Expression ')' Statement
620  Expect(Token::WITH, CHECK_OK);
621  if (strict_mode() == STRICT) {
622  ReportMessageAt(scanner()->location(), "strict_mode_with");
623  *ok = false;
624  return Statement::Default();
625  }
626  Expect(Token::LPAREN, CHECK_OK);
627  ParseExpression(true, CHECK_OK);
628  Expect(Token::RPAREN, CHECK_OK);
629 
630  PreParserScope with_scope(scope_, WITH_SCOPE);
631  BlockState block_state(&scope_, &with_scope);
632  ParseStatement(CHECK_OK);
633  return Statement::Default();
634 }
635 
636 
637 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
638  // SwitchStatement ::
639  // 'switch' '(' Expression ')' '{' CaseClause* '}'
640 
641  Expect(Token::SWITCH, CHECK_OK);
642  Expect(Token::LPAREN, CHECK_OK);
643  ParseExpression(true, CHECK_OK);
644  Expect(Token::RPAREN, CHECK_OK);
645 
646  Expect(Token::LBRACE, CHECK_OK);
647  Token::Value token = peek();
648  while (token != Token::RBRACE) {
649  if (token == Token::CASE) {
651  ParseExpression(true, CHECK_OK);
652  } else {
654  }
655  Expect(Token::COLON, CHECK_OK);
656  token = peek();
657  while (token != Token::CASE &&
658  token != Token::DEFAULT &&
659  token != Token::RBRACE) {
660  ParseStatement(CHECK_OK);
661  token = peek();
662  }
663  }
664  Expect(Token::RBRACE, ok);
665  return Statement::Default();
666 }
667 
668 
669 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
670  // DoStatement ::
671  // 'do' Statement 'while' '(' Expression ')' ';'
672 
673  Expect(Token::DO, CHECK_OK);
674  ParseStatement(CHECK_OK);
675  Expect(Token::WHILE, CHECK_OK);
676  Expect(Token::LPAREN, CHECK_OK);
677  ParseExpression(true, CHECK_OK);
678  Expect(Token::RPAREN, ok);
679  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
680  return Statement::Default();
681 }
682 
683 
684 PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
685  // WhileStatement ::
686  // 'while' '(' Expression ')' Statement
687 
688  Expect(Token::WHILE, CHECK_OK);
689  Expect(Token::LPAREN, CHECK_OK);
690  ParseExpression(true, CHECK_OK);
691  Expect(Token::RPAREN, CHECK_OK);
692  ParseStatement(ok);
693  return Statement::Default();
694 }
695 
696 
697 bool PreParser::CheckInOrOf(bool accept_OF) {
698  if (Check(Token::IN) ||
699  (allow_for_of() && accept_OF &&
701  return true;
702  }
703  return false;
704 }
705 
706 
707 PreParser::Statement PreParser::ParseForStatement(bool* ok) {
708  // ForStatement ::
709  // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
710 
711  Expect(Token::FOR, CHECK_OK);
712  Expect(Token::LPAREN, CHECK_OK);
713  if (peek() != Token::SEMICOLON) {
714  if (peek() == Token::VAR || peek() == Token::CONST ||
715  peek() == Token::LET) {
716  bool is_let = peek() == Token::LET;
717  int decl_count;
718  VariableDeclarationProperties decl_props = kHasNoInitializers;
719  ParseVariableDeclarations(
720  kForStatement, &decl_props, &decl_count, CHECK_OK);
721  bool has_initializers = decl_props == kHasInitializers;
722  bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
723  bool accept_OF = !has_initializers;
724  if (accept_IN && CheckInOrOf(accept_OF)) {
725  ParseExpression(true, CHECK_OK);
726  Expect(Token::RPAREN, CHECK_OK);
727 
728  ParseStatement(CHECK_OK);
729  return Statement::Default();
730  }
731  } else {
732  Expression lhs = ParseExpression(false, CHECK_OK);
733  if (CheckInOrOf(lhs.IsIdentifier())) {
734  ParseExpression(true, CHECK_OK);
735  Expect(Token::RPAREN, CHECK_OK);
736 
737  ParseStatement(CHECK_OK);
738  return Statement::Default();
739  }
740  }
741  }
742 
743  // Parsed initializer at this point.
744  Expect(Token::SEMICOLON, CHECK_OK);
745 
746  if (peek() != Token::SEMICOLON) {
747  ParseExpression(true, CHECK_OK);
748  }
749  Expect(Token::SEMICOLON, CHECK_OK);
750 
751  if (peek() != Token::RPAREN) {
752  ParseExpression(true, CHECK_OK);
753  }
754  Expect(Token::RPAREN, CHECK_OK);
755 
756  ParseStatement(ok);
757  return Statement::Default();
758 }
759 
760 
761 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
762  // ThrowStatement ::
763  // 'throw' [no line terminator] Expression ';'
764 
765  Expect(Token::THROW, CHECK_OK);
766  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
767  ReportMessageAt(scanner()->location(), "newline_after_throw");
768  *ok = false;
769  return Statement::Default();
770  }
771  ParseExpression(true, CHECK_OK);
772  ExpectSemicolon(ok);
773  return Statement::Default();
774 }
775 
776 
777 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
778  // TryStatement ::
779  // 'try' Block Catch
780  // 'try' Block Finally
781  // 'try' Block Catch Finally
782  //
783  // Catch ::
784  // 'catch' '(' Identifier ')' Block
785  //
786  // Finally ::
787  // 'finally' Block
788 
789  Expect(Token::TRY, CHECK_OK);
790 
791  ParseBlock(CHECK_OK);
792 
793  Token::Value tok = peek();
794  if (tok != Token::CATCH && tok != Token::FINALLY) {
795  ReportMessageAt(scanner()->location(), "no_catch_or_finally");
796  *ok = false;
797  return Statement::Default();
798  }
799  if (tok == Token::CATCH) {
800  Consume(Token::CATCH);
801  Expect(Token::LPAREN, CHECK_OK);
803  Expect(Token::RPAREN, CHECK_OK);
804  {
805  PreParserScope with_scope(scope_, WITH_SCOPE);
806  BlockState block_state(&scope_, &with_scope);
807  ParseBlock(CHECK_OK);
808  }
809  tok = peek();
810  }
811  if (tok == Token::FINALLY) {
812  Consume(Token::FINALLY);
813  ParseBlock(CHECK_OK);
814  }
815  return Statement::Default();
816 }
817 
818 
819 PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
820  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
821  // contexts this is used as a statement which invokes the debugger as if a
822  // break point is present.
823  // DebuggerStatement ::
824  // 'debugger' ';'
825 
826  Expect(Token::DEBUGGER, CHECK_OK);
827  ExpectSemicolon(ok);
828  return Statement::Default();
829 }
830 
831 
832 #undef CHECK_OK
833 #define CHECK_OK ok); \
834  if (!*ok) return Expression::Default(); \
835  ((void)0
836 #define DUMMY ) // to make indentation work
837 #undef DUMMY
838 
839 
840 PreParser::Expression PreParser::ParseFunctionLiteral(
841  Identifier function_name,
842  Scanner::Location function_name_location,
843  bool name_is_strict_reserved,
844  bool is_generator,
845  int function_token_pos,
846  FunctionLiteral::FunctionType function_type,
847  bool* ok) {
848  // Function ::
849  // '(' FormalParameterList? ')' '{' FunctionBody '}'
850 
851  // Parse function body.
852  ScopeType outer_scope_type = scope_->type();
853  PreParserScope function_scope(scope_, FUNCTION_SCOPE);
854  FunctionState function_state(&function_state_, &scope_, &function_scope);
855  function_state.set_is_generator(is_generator);
856  // FormalParameterList ::
857  // '(' (Identifier)*[','] ')'
858  Expect(Token::LPAREN, CHECK_OK);
859  int start_position = position();
860  bool done = (peek() == Token::RPAREN);
861  DuplicateFinder duplicate_finder(scanner()->unicode_cache());
862  // We don't yet know if the function will be strict, so we cannot yet produce
863  // errors for parameter names or duplicates. However, we remember the
864  // locations of these errors if they occur and produce the errors later.
865  Scanner::Location eval_args_error_loc = Scanner::Location::invalid();
866  Scanner::Location dupe_error_loc = Scanner::Location::invalid();
867  Scanner::Location reserved_error_loc = Scanner::Location::invalid();
868  while (!done) {
869  bool is_strict_reserved = false;
870  Identifier param_name =
871  ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
872  if (!eval_args_error_loc.IsValid() && param_name.IsEvalOrArguments()) {
873  eval_args_error_loc = scanner()->location();
874  }
875  if (!reserved_error_loc.IsValid() && is_strict_reserved) {
876  reserved_error_loc = scanner()->location();
877  }
878 
879  int prev_value = scanner()->FindSymbol(&duplicate_finder, 1);
880 
881  if (!dupe_error_loc.IsValid() && prev_value != 0) {
882  dupe_error_loc = scanner()->location();
883  }
884 
885  done = (peek() == Token::RPAREN);
886  if (!done) {
888  }
889  }
890  Expect(Token::RPAREN, CHECK_OK);
891 
892  // See Parser::ParseFunctionLiteral for more information about lazy parsing
893  // and lazy compilation.
894  bool is_lazily_parsed = (outer_scope_type == GLOBAL_SCOPE && allow_lazy() &&
896  parenthesized_function_ = false;
897 
898  Expect(Token::LBRACE, CHECK_OK);
899  if (is_lazily_parsed) {
900  ParseLazyFunctionLiteralBody(CHECK_OK);
901  } else {
902  ParseSourceElements(Token::RBRACE, ok);
903  }
904  Expect(Token::RBRACE, CHECK_OK);
905 
906  // Validate strict mode. We can do this only after parsing the function,
907  // since the function can declare itself strict.
908  if (strict_mode() == STRICT) {
909  if (function_name.IsEvalOrArguments()) {
910  ReportMessageAt(function_name_location, "strict_eval_arguments");
911  *ok = false;
912  return Expression::Default();
913  }
914  if (name_is_strict_reserved) {
915  ReportMessageAt(function_name_location, "unexpected_strict_reserved");
916  *ok = false;
917  return Expression::Default();
918  }
919  if (eval_args_error_loc.IsValid()) {
920  ReportMessageAt(eval_args_error_loc, "strict_eval_arguments");
921  *ok = false;
922  return Expression::Default();
923  }
924  if (dupe_error_loc.IsValid()) {
925  ReportMessageAt(dupe_error_loc, "strict_param_dupe");
926  *ok = false;
927  return Expression::Default();
928  }
929  if (reserved_error_loc.IsValid()) {
930  ReportMessageAt(reserved_error_loc, "unexpected_strict_reserved");
931  *ok = false;
932  return Expression::Default();
933  }
934 
935  int end_position = scanner()->location().end_pos;
936  CheckOctalLiteral(start_position, end_position, CHECK_OK);
937  }
938 
939  return Expression::Default();
940 }
941 
942 
943 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
944  int body_start = position();
945  bool is_logging = log_->ShouldLogSymbols();
946  if (is_logging) log_->PauseRecording();
947  ParseSourceElements(Token::RBRACE, ok);
948  if (is_logging) log_->ResumeRecording();
949  if (!*ok) return;
950 
951  // Position right after terminal '}'.
952  ASSERT_EQ(Token::RBRACE, scanner()->peek());
953  int body_end = scanner()->peek_location().end_pos;
954  log_->LogFunction(body_start, body_end,
955  function_state_->materialized_literal_count(),
956  function_state_->expected_property_count(),
957  strict_mode());
958 }
959 
960 
961 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
962  // CallRuntime ::
963  // '%' Identifier Arguments
964  Expect(Token::MOD, CHECK_OK);
965  if (!allow_natives_syntax()) {
966  *ok = false;
967  return Expression::Default();
968  }
969  // Allow "eval" or "arguments" for backward compatibility.
971  ParseArguments(ok);
972 
973  return Expression::Default();
974 }
975 
976 #undef CHECK_OK
977 
978 
979 void PreParser::LogSymbol() {
980  if (log_->ShouldLogSymbols()) {
982  }
983 }
984 
985 
986 } } // v8::internal
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
static PreParserExpression Default()
Definition: preparser.h:563
PreParserExpression ParseV8Intrinsic(bool *ok)
Definition: preparser.cc:130
static PreParserIdentifier Arguments()
Definition: preparser.h:518
ExpressionT ParseExpression(bool accept_IN, bool *ok)
static PreParserIdentifier Yield()
Definition: preparser.h:527
PreParserIdentifier AsIdentifier()
Definition: preparser.h:595
void CheckOctalLiteral(int beg_pos, int end_pos, bool *ok)
Definition: preparser.h:349
int FindSymbol(DuplicateFinder *finder, int value)
Definition: scanner.cc:1155
PreParserExpression ExpressionFromString(int pos, Scanner *scanner, PreParserFactory *factory=NULL)
Definition: preparser.cc:120
static PreParserIdentifier Eval()
Definition: preparser.h:515
PreParserIdentifier GetSymbol(Scanner *scanner)
Definition: preparser.cc:100
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
Definition: flags.cc:665
void CheckStrictModeLValue(PreParserExpression expression, bool *ok)
Definition: preparser.cc:59
PreParserIdentifier Identifier
Definition: preparser.h:1005
void ReportUnexpectedToken(Token::Value token)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT enable GDBJIT interface for all code objects dump only objects containing this substring stress the GC compactor to flush out pretty print source code print source AST function name where to insert a breakpoint print scopes for builtins trace contexts operations print stuff during garbage collection report code statistics after GC report handles after GC trace cache state transitions print interface inference details prints when objects are turned into dictionaries report heap spill statistics along with trace isolate state changes trace regexp bytecode execution Minimal Log all events to the log file Log API events to the log file Log heap samples on garbage collection for the hp2ps tool log positions Log suspect operations Used with turns on browser compatible mode for profiling v8 log
Definition: flags.cc:806
#define ASSERT(condition)
Definition: checks.h:329
ExpressionT ParseAssignmentExpression(bool accept_IN, bool *ok)
int isfinite(double x)
PreParserTraits::Type::Scope * scope_
Definition: preparser.h:488
bool UnescapedLiteralMatches(const char *data, int length)
Definition: scanner.h:407
IdentifierT ParseIdentifierOrStrictReservedWord(bool *is_strict_reserved, bool *ok)
static PreParserExpression UseStrictStringLiteral()
Definition: preparser.h:576
#define IN
void ReportMessageAt(Scanner::Location location, const char *message, bool is_reference_error=false)
Definition: preparser.h:380
static PreParserExpression StringLiteral()
Definition: preparser.h:572
static PreParserIdentifier FutureStrictReserved()
Definition: preparser.h:524
void ReportMessage(const char *message, Vector< const char * > args, bool is_reference_error=false)
Definition: preparser.h:374
int length() const
Definition: utils.h:420
#define CHECK_OK
Definition: preparser.cc:833
bool CheckContextualKeyword(Vector< const char > keyword)
Definition: preparser.h:329
PreParserExpression ParseFunctionLiteral(PreParserIdentifier name, Scanner::Location function_name_location, bool name_is_strict_reserved, bool is_generator, int function_token_position, FunctionLiteral::FunctionType type, bool *ok)
Definition: preparser.cc:135
#define COMMA
Definition: flags.h:101
PreParserExpression Expression
Definition: preparser.h:1006
virtual void LogFunction(int start, int end, int literals, int properties, StrictMode strict_mode)=0
static PreParserIdentifier Default()
Definition: preparser.h:512
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
static Location invalid()
Definition: scanner.h:356
#define CASE(name)
Location location() const
Definition: scanner.h:375
PreParseResult PreParseLazyFunction(StrictMode strict_mode, bool is_generator, ParserRecorder *log)
Definition: preparser.cc:149
virtual void ResumeRecording()
Definition: preparse-data.h:71
void LogSymbol(ParserRecorder *log, int position)
Definition: scanner.cc:1163
void ReportMessageAt(Scanner::Location location, const char *message, Vector< const char * > args, bool is_reference_error=false)
Definition: preparser.cc:70
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
Token::Value current_token()
Definition: scanner.h:372
static PreParserIdentifier FutureReserved()
Definition: preparser.h:521
PreParserTraits::Type::ExpressionList ParseArguments(bool *ok)
void Expect(Token::Value token, bool *ok)
Definition: preparser.h:297
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
virtual void LogMessage(int start, int end, const char *message, const char *argument_opt)=0
IdentifierT ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool *ok)
Location peek_location() const
Definition: scanner.h:382
ParserRecorder * log_
Definition: preparser.h:492