V8 Project
parser.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #include "src/api.h"
8 #include "src/ast.h"
9 #include "src/bailout-reason.h"
11 #include "src/bootstrapper.h"
13 #include "src/codegen.h"
14 #include "src/compiler.h"
15 #include "src/messages.h"
16 #include "src/parser.h"
17 #include "src/preparser.h"
18 #include "src/runtime/runtime.h"
20 #include "src/scopeinfo.h"
21 #include "src/string-stream.h"
22 
23 namespace v8 {
24 namespace internal {
25 
27  : zone_(zone),
28  pending_empty_(false),
29  characters_(NULL),
30  terms_(),
31  alternatives_()
32 #ifdef DEBUG
33  , last_added_(ADD_NONE)
34 #endif
35  {}
36 
37 
39  pending_empty_ = false;
40  if (characters_ != NULL) {
41  RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
42  characters_ = NULL;
43  text_.Add(atom, zone());
44  LAST(ADD_ATOM);
45  }
46 }
47 
48 
51  int num_text = text_.length();
52  if (num_text == 0) {
53  return;
54  } else if (num_text == 1) {
55  terms_.Add(text_.last(), zone());
56  } else {
57  RegExpText* text = new(zone()) RegExpText(zone());
58  for (int i = 0; i < num_text; i++)
59  text_.Get(i)->AppendToText(text, zone());
60  terms_.Add(text, zone());
61  }
62  text_.Clear();
63 }
64 
65 
67  pending_empty_ = false;
68  if (characters_ == NULL) {
69  characters_ = new(zone()) ZoneList<uc16>(4, zone());
70  }
71  characters_->Add(c, zone());
72  LAST(ADD_CHAR);
73 }
74 
75 
77  pending_empty_ = true;
78 }
79 
80 
82  if (term->IsEmpty()) {
83  AddEmpty();
84  return;
85  }
86  if (term->IsTextElement()) {
88  text_.Add(term, zone());
89  } else {
90  FlushText();
91  terms_.Add(term, zone());
92  }
93  LAST(ADD_ATOM);
94 }
95 
96 
98  FlushText();
99  terms_.Add(assert, zone());
100  LAST(ADD_ASSERT);
101 }
102 
103 
105  FlushTerms();
106 }
107 
108 
110  FlushText();
111  int num_terms = terms_.length();
112  RegExpTree* alternative;
113  if (num_terms == 0) {
114  alternative = RegExpEmpty::GetInstance();
115  } else if (num_terms == 1) {
116  alternative = terms_.last();
117  } else {
118  alternative = new(zone()) RegExpAlternative(terms_.GetList(zone()));
119  }
120  alternatives_.Add(alternative, zone());
121  terms_.Clear();
122  LAST(ADD_NONE);
123 }
124 
125 
127  FlushTerms();
128  int num_alternatives = alternatives_.length();
129  if (num_alternatives == 0) {
130  return RegExpEmpty::GetInstance();
131  }
132  if (num_alternatives == 1) {
133  return alternatives_.last();
134  }
135  return new(zone()) RegExpDisjunction(alternatives_.GetList(zone()));
136 }
137 
138 
140  int min, int max, RegExpQuantifier::QuantifierType quantifier_type) {
141  if (pending_empty_) {
142  pending_empty_ = false;
143  return;
144  }
145  RegExpTree* atom;
146  if (characters_ != NULL) {
147  DCHECK(last_added_ == ADD_CHAR);
148  // Last atom was character.
150  int num_chars = char_vector.length();
151  if (num_chars > 1) {
152  Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
153  text_.Add(new(zone()) RegExpAtom(prefix), zone());
154  char_vector = char_vector.SubVector(num_chars - 1, num_chars);
155  }
156  characters_ = NULL;
157  atom = new(zone()) RegExpAtom(char_vector);
158  FlushText();
159  } else if (text_.length() > 0) {
160  DCHECK(last_added_ == ADD_ATOM);
161  atom = text_.RemoveLast();
162  FlushText();
163  } else if (terms_.length() > 0) {
164  DCHECK(last_added_ == ADD_ATOM);
165  atom = terms_.RemoveLast();
166  if (atom->max_match() == 0) {
167  // Guaranteed to only match an empty string.
168  LAST(ADD_TERM);
169  if (min == 0) {
170  return;
171  }
172  terms_.Add(atom, zone());
173  return;
174  }
175  } else {
176  // Only call immediately after adding an atom or character!
177  UNREACHABLE();
178  return;
179  }
180  terms_.Add(
181  new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone());
182  LAST(ADD_TERM);
183 }
184 
185 
186 FunctionEntry ParseData::GetFunctionEntry(int start) {
187  // The current pre-data entry must be a FunctionEntry with the given
188  // start position.
189  if ((function_index_ + FunctionEntry::kSize <= Length()) &&
190  (static_cast<int>(Data()[function_index_]) == start)) {
191  int index = function_index_;
192  function_index_ += FunctionEntry::kSize;
193  Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
194  return FunctionEntry(subvector);
195  }
196  return FunctionEntry();
197 }
198 
199 
201  int functions_size = FunctionsSize();
202  if (functions_size < 0) return 0;
203  if (functions_size % FunctionEntry::kSize != 0) return 0;
204  return functions_size / FunctionEntry::kSize;
205 }
206 
207 
209  // Check that the header data is valid and doesn't specify
210  // point to positions outside the store.
211  int data_length = Length();
212  if (data_length < PreparseDataConstants::kHeaderSize) return false;
213  if (Magic() != PreparseDataConstants::kMagicNumber) return false;
214  if (Version() != PreparseDataConstants::kCurrentVersion) return false;
215  if (HasError()) return false;
216  // Check that the space allocated for function entries is sane.
217  int functions_size = FunctionsSize();
218  if (functions_size < 0) return false;
219  if (functions_size % FunctionEntry::kSize != 0) return false;
220  // Check that the total size has room for header and function entries.
221  int minimum_size =
222  PreparseDataConstants::kHeaderSize + functions_size;
223  if (data_length < minimum_size) return false;
224  return true;
225 }
226 
227 
229  // Prepares state for use.
230  int data_length = Length();
231  if (data_length >= PreparseDataConstants::kHeaderSize) {
233  }
234 }
235 
236 
239 }
240 
241 
242 unsigned ParseData::Magic() {
244 }
245 
246 
247 unsigned ParseData::Version() {
249 }
250 
251 
253  return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
254 }
255 
256 
260  } else {
261  DCHECK(info_->cached_data() != NULL);
264  }
265  }
266 }
267 
268 
269 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) {
271  Scope* result =
272  new (zone()) Scope(parent, scope_type, ast_value_factory(), zone());
273  result->Initialize();
274  return result;
275 }
276 
277 
278 // ----------------------------------------------------------------------------
279 // Target is a support class to facilitate manipulation of the
280 // Parser's target_stack_ (the stack of potential 'break' and
281 // 'continue' statement targets). Upon construction, a new target is
282 // added; it is removed upon destruction.
283 
284 class Target BASE_EMBEDDED {
285  public:
286  Target(Target** variable, AstNode* node)
287  : variable_(variable), node_(node), previous_(*variable) {
288  *variable = this;
289  }
290 
292  *variable_ = previous_;
293  }
294 
295  Target* previous() { return previous_; }
296  AstNode* node() { return node_; }
297 
298  private:
299  Target** variable_;
301  Target* previous_;
302 };
303 
304 
305 class TargetScope BASE_EMBEDDED {
306  public:
307  explicit TargetScope(Target** variable)
308  : variable_(variable), previous_(*variable) {
309  *variable = NULL;
310  }
311 
313  *variable_ = previous_;
314  }
315 
316  private:
317  Target** variable_;
318  Target* previous_;
319 };
320 
321 
322 // ----------------------------------------------------------------------------
323 // The CHECK_OK macro is a convenient macro to enforce error
324 // handling for functions that may fail (by returning !*ok).
325 //
326 // CAUTION: This macro appends extra statements after a call,
327 // thus it must never be used where only a single statement
328 // is correct (e.g. an if statement branch w/o braces)!
329 
330 #define CHECK_OK ok); \
331  if (!*ok) return NULL; \
332  ((void)0
333 #define DUMMY ) // to make indentation work
334 #undef DUMMY
335 
336 #define CHECK_FAILED /**/); \
337  if (failed_) return NULL; \
338  ((void)0
339 #define DUMMY ) // to make indentation work
340 #undef DUMMY
341 
342 // ----------------------------------------------------------------------------
343 // Implementation of Parser
344 
346  : public ParserBase<ParserTraits>::CheckpointBase {
347  public:
349  : CheckpointBase(parser), parser_(parser) {
351  }
352 
353  void Restore() {
354  CheckpointBase::Restore();
356  }
357 
358  private:
361 };
362 
363 
364 bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
365  return identifier == parser_->ast_value_factory()->eval_string() ||
366  identifier == parser_->ast_value_factory()->arguments_string();
367 }
368 
369 
370 bool ParserTraits::IsPrototype(const AstRawString* identifier) const {
371  return identifier == parser_->ast_value_factory()->prototype_string();
372 }
373 
374 
375 bool ParserTraits::IsConstructor(const AstRawString* identifier) const {
376  return identifier == parser_->ast_value_factory()->constructor_string();
377 }
378 
379 
381  DCHECK(expression != NULL);
382  Property* property = expression->AsProperty();
383  return property != NULL &&
384  property->obj()->AsVariableProxy() != NULL &&
385  property->obj()->AsVariableProxy()->is_this();
386 }
387 
388 
390  VariableProxy* operand = expression->AsVariableProxy();
391  return operand != NULL && !operand->is_this();
392 }
393 
394 
396  Expression* expression) {
397  if (expression->IsPropertyName()) {
398  fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
399  } else {
400  fni->PushLiteralName(
401  parser_->ast_value_factory()->anonymous_function_string());
402  }
403 }
404 
405 
407  Expression* right) {
408  DCHECK(left != NULL);
409  if (left->AsProperty() != NULL &&
410  right->AsFunctionLiteral() != NULL) {
411  right->AsFunctionLiteral()->set_pretenure();
412  }
413 }
414 
415 
417  Scope* scope) {
418  VariableProxy* callee = expression->AsVariableProxy();
419  if (callee != NULL &&
420  callee->raw_name() == parser_->ast_value_factory()->eval_string()) {
421  scope->DeclarationScope()->RecordEvalCall();
422  }
423 }
424 
425 
427  VariableProxy* proxy =
428  expression != NULL ? expression->AsVariableProxy() : NULL;
429  if (proxy != NULL) proxy->set_is_assigned();
430  return expression;
431 }
432 
433 
435  Expression** x, Expression* y, Token::Value op, int pos,
437  if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
438  y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
439  double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
440  double y_val = y->AsLiteral()->raw_value()->AsNumber();
441  switch (op) {
442  case Token::ADD:
443  *x = factory->NewNumberLiteral(x_val + y_val, pos);
444  return true;
445  case Token::SUB:
446  *x = factory->NewNumberLiteral(x_val - y_val, pos);
447  return true;
448  case Token::MUL:
449  *x = factory->NewNumberLiteral(x_val * y_val, pos);
450  return true;
451  case Token::DIV:
452  *x = factory->NewNumberLiteral(x_val / y_val, pos);
453  return true;
454  case Token::BIT_OR: {
455  int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
456  *x = factory->NewNumberLiteral(value, pos);
457  return true;
458  }
459  case Token::BIT_AND: {
460  int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
461  *x = factory->NewNumberLiteral(value, pos);
462  return true;
463  }
464  case Token::BIT_XOR: {
465  int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
466  *x = factory->NewNumberLiteral(value, pos);
467  return true;
468  }
469  case Token::SHL: {
470  int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
471  *x = factory->NewNumberLiteral(value, pos);
472  return true;
473  }
474  case Token::SHR: {
475  uint32_t shift = DoubleToInt32(y_val) & 0x1f;
476  uint32_t value = DoubleToUint32(x_val) >> shift;
477  *x = factory->NewNumberLiteral(value, pos);
478  return true;
479  }
480  case Token::SAR: {
481  uint32_t shift = DoubleToInt32(y_val) & 0x1f;
482  int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
483  *x = factory->NewNumberLiteral(value, pos);
484  return true;
485  }
486  default:
487  break;
488  }
489  }
490  return false;
491 }
492 
493 
495  Expression* expression, Token::Value op, int pos,
497  DCHECK(expression != NULL);
498  if (expression->IsLiteral()) {
499  const AstValue* literal = expression->AsLiteral()->raw_value();
500  if (op == Token::NOT) {
501  // Convert the literal to a boolean condition and negate it.
502  bool condition = literal->BooleanValue();
503  return factory->NewBooleanLiteral(!condition, pos);
504  } else if (literal->IsNumber()) {
505  // Compute some expressions involving only number literals.
506  double value = literal->AsNumber();
507  switch (op) {
508  case Token::ADD:
509  return expression;
510  case Token::SUB:
511  return factory->NewNumberLiteral(-value, pos);
512  case Token::BIT_NOT:
513  return factory->NewNumberLiteral(~DoubleToInt32(value), pos);
514  default:
515  break;
516  }
517  }
518  }
519  // Desugar '+foo' => 'foo*1'
520  if (op == Token::ADD) {
521  return factory->NewBinaryOperation(
522  Token::MUL, expression, factory->NewNumberLiteral(1, pos), pos);
523  }
524  // The same idea for '-foo' => 'foo*(-1)'.
525  if (op == Token::SUB) {
526  return factory->NewBinaryOperation(
527  Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
528  }
529  // ...and one more time for '~foo' => 'foo^(~0)'.
530  if (op == Token::BIT_NOT) {
531  return factory->NewBinaryOperation(
532  Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
533  }
534  return factory->NewUnaryOperation(op, expression, pos);
535 }
536 
537 
538 Expression* ParserTraits::NewThrowReferenceError(const char* message, int pos) {
539  return NewThrowError(
540  parser_->ast_value_factory()->make_reference_error_string(), message,
541  NULL, pos);
542 }
543 
544 
546  const char* message, const AstRawString* arg, int pos) {
547  return NewThrowError(parser_->ast_value_factory()->make_syntax_error_string(),
548  message, arg, pos);
549 }
550 
551 
553  const char* message, const AstRawString* arg, int pos) {
554  return NewThrowError(parser_->ast_value_factory()->make_type_error_string(),
555  message, arg, pos);
556 }
557 
558 
560  const AstRawString* constructor, const char* message,
561  const AstRawString* arg, int pos) {
562  Zone* zone = parser_->zone();
563  int argc = arg != NULL ? 1 : 0;
564  const AstRawString* type =
567  new (zone) ZoneList<const AstRawString*>(argc, zone);
568  if (arg != NULL) {
569  array->Add(arg, zone);
570  }
571  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
572  args->Add(parser_->factory()->NewStringLiteral(type, pos), zone);
573  args->Add(parser_->factory()->NewStringListLiteral(array, pos), zone);
574  CallRuntime* call_constructor =
575  parser_->factory()->NewCallRuntime(constructor, NULL, args, pos);
576  return parser_->factory()->NewThrow(call_constructor, pos);
577 }
578 
579 
581  const char* message,
582  const char* arg,
583  bool is_reference_error) {
584  if (parser_->stack_overflow()) {
585  // Suppress the error message (syntax error or such) in the presence of a
586  // stack overflow. The isolate allows only one pending exception at at time
587  // and we want to report the stack overflow later.
588  return;
589  }
590  parser_->has_pending_error_ = true;
591  parser_->pending_error_location_ = source_location;
592  parser_->pending_error_message_ = message;
595  parser_->pending_error_is_reference_error_ = is_reference_error;
596 }
597 
598 
599 void ParserTraits::ReportMessage(const char* message,
600  const char* arg,
601  bool is_reference_error) {
602  Scanner::Location source_location = parser_->scanner()->location();
603  ReportMessageAt(source_location, message, arg, is_reference_error);
604 }
605 
606 
607 void ParserTraits::ReportMessage(const char* message,
608  const AstRawString* arg,
609  bool is_reference_error) {
610  Scanner::Location source_location = parser_->scanner()->location();
611  ReportMessageAt(source_location, message, arg, is_reference_error);
612 }
613 
614 
616  const char* message,
617  const AstRawString* arg,
618  bool is_reference_error) {
619  if (parser_->stack_overflow()) {
620  // Suppress the error message (syntax error or such) in the presence of a
621  // stack overflow. The isolate allows only one pending exception at at time
622  // and we want to report the stack overflow later.
623  return;
624  }
625  parser_->has_pending_error_ = true;
626  parser_->pending_error_location_ = source_location;
627  parser_->pending_error_message_ = message;
630  parser_->pending_error_is_reference_error_ = is_reference_error;
631 }
632 
633 
635  const AstRawString* result =
637  DCHECK(result != NULL);
638  return result;
639 }
640 
641 
643  double double_value = parser_->scanner()->DoubleValue();
644  char array[100];
645  const char* string =
646  DoubleToCString(double_value, Vector<char>(array, arraysize(array)));
647  return ast_value_factory()->GetOneByteString(string);
648 }
649 
650 
653 }
654 
655 
657  Scope* scope, AstNodeFactory<AstConstructionVisitor>* factory, int pos) {
658  return factory->NewVariableProxy(scope->receiver(), pos);
659 }
660 
662  Scope* scope, AstNodeFactory<AstConstructionVisitor>* factory, int pos) {
663  return factory->NewSuperReference(
664  ThisExpression(scope, factory, pos)->AsVariableProxy(),
665  pos);
666 }
667 
669  const AstRawString* name, Expression* extends, Expression* constructor,
670  ZoneList<ObjectLiteral::Property*>* properties, int pos,
672  return factory->NewClassLiteral(name, extends, constructor, properties, pos);
673 }
674 
676  Token::Value token, int pos,
677  Scanner* scanner,
679  switch (token) {
680  case Token::NULL_LITERAL:
681  return factory->NewNullLiteral(pos);
682  case Token::TRUE_LITERAL:
683  return factory->NewBooleanLiteral(true, pos);
684  case Token::FALSE_LITERAL:
685  return factory->NewBooleanLiteral(false, pos);
686  case Token::NUMBER: {
687  double value = scanner->DoubleValue();
688  return factory->NewNumberLiteral(value, pos);
689  }
690  default:
691  DCHECK(false);
692  }
693  return NULL;
694 }
695 
696 
698  const AstRawString* name, int pos, Scope* scope,
701  // The name may refer to a module instance object, so its type is unknown.
702 #ifdef DEBUG
703  if (FLAG_print_interface_details)
704  PrintF("# Variable %.*s ", name->length(), name->raw_data());
705 #endif
706  Interface* interface = Interface::NewUnknown(parser_->zone());
707  return scope->NewUnresolved(factory, name, interface, pos);
708 }
709 
710 
712  int pos, Scanner* scanner,
714  const AstRawString* symbol = GetSymbol(scanner);
715  if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
716  return factory->NewStringLiteral(symbol, pos);
717 }
718 
719 
722  Expression* iterator_symbol_literal =
723  factory->NewSymbolLiteral("symbolIterator", RelocInfo::kNoPosition);
724  int pos = iterable->position();
725  Expression* prop =
726  factory->NewProperty(iterable, iterator_symbol_literal, pos);
727  Zone* zone = parser_->zone();
728  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
729  return factory->NewCall(prop, args, pos);
730 }
731 
732 
734  int position, AstNodeFactory<AstConstructionVisitor>* factory) {
735  return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
736 }
737 
738 
740  return parser_->ParseV8Intrinsic(ok);
741 }
742 
743 
745  const AstRawString* name, Scanner::Location function_name_location,
746  bool name_is_strict_reserved, FunctionKind kind,
747  int function_token_position, FunctionLiteral::FunctionType type,
748  FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
750  name, function_name_location, name_is_strict_reserved, kind,
751  function_token_position, type, arity_restriction, ok);
752 }
753 
754 
756  : ParserBase<ParserTraits>(&scanner_, parse_info->stack_limit,
757  info->extension(), NULL, info->zone(),
758  info->ast_node_id_gen(), this),
759  scanner_(parse_info->unicode_cache),
760  reusable_preparser_(NULL),
761  original_scope_(NULL),
762  target_stack_(NULL),
763  cached_parse_data_(NULL),
764  info_(info),
765  has_pending_error_(false),
766  pending_error_message_(NULL),
767  pending_error_arg_(NULL),
768  pending_error_char_arg_(NULL),
769  total_preparse_skipped_(0),
770  pre_parse_timer_(NULL) {
771  DCHECK(!script().is_null() || info->source_stream() != NULL);
772  set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
773  set_allow_modules(!info->is_native() && FLAG_harmony_modules);
774  set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
775  set_allow_lazy(false); // Must be explicitly enabled.
776  set_allow_arrow_functions(FLAG_harmony_arrow_functions);
777  set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
778  set_allow_classes(FLAG_harmony_classes);
779  set_allow_harmony_object_literals(FLAG_harmony_object_literals);
780  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
781  ++feature) {
782  use_counts_[feature] = 0;
783  }
784  if (info->ast_value_factory() == NULL) {
785  // info takes ownership of AstValueFactory.
787  new AstValueFactory(zone(), parse_info->hash_seed));
788  }
789 }
790 
791 
792 FunctionLiteral* Parser::ParseProgram() {
793  // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
794  // see comment for HistogramTimerScope class.
795 
796  // It's OK to use the counters here, since this function is only called in
797  // the main thread.
798  HistogramTimerScope timer_scope(isolate()->counters()->parse(), true);
799  Handle<String> source(String::cast(script()->source()));
800  isolate()->counters()->total_parse_size()->Increment(source->length());
801  base::ElapsedTimer timer;
802  if (FLAG_trace_parse) {
803  timer.Start();
804  }
806 
807  // Initialize parser state.
808  CompleteParserRecorder recorder;
809 
811  log_ = &recorder;
814  }
815 
816  source = String::Flatten(source);
817  FunctionLiteral* result;
818 
819  Scope* top_scope = NULL;
820  Scope* eval_scope = NULL;
821  if (source->IsExternalTwoByteString()) {
822  // Notice that the stream is destroyed at the end of the branch block.
823  // The last line of the blocks can't be moved outside, even though they're
824  // identical calls.
826  Handle<ExternalTwoByteString>::cast(source), 0, source->length());
827  scanner_.Initialize(&stream);
828  result = DoParseProgram(info(), &top_scope, &eval_scope);
829  } else {
830  GenericStringUtf16CharacterStream stream(source, 0, source->length());
831  scanner_.Initialize(&stream);
832  result = DoParseProgram(info(), &top_scope, &eval_scope);
833  }
834  top_scope->set_end_position(source->length());
835  if (eval_scope != NULL) {
836  eval_scope->set_end_position(source->length());
837  }
839 
840  if (FLAG_trace_parse && result != NULL) {
841  double ms = timer.Elapsed().InMillisecondsF();
842  if (info()->is_eval()) {
843  PrintF("[parsing eval");
844  } else if (info()->script()->name()->IsString()) {
845  String* name = String::cast(info()->script()->name());
846  SmartArrayPointer<char> name_chars = name->ToCString();
847  PrintF("[parsing script: %s", name_chars.get());
848  } else {
849  PrintF("[parsing script");
850  }
851  PrintF(" - took %0.3f ms]\n", ms);
852  }
854  if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
855  log_ = NULL;
856  }
857  return result;
858 }
859 
860 
861 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
862  Scope** eval_scope) {
863  DCHECK(scope_ == NULL);
865 
866  FunctionLiteral* result = NULL;
867  {
868  *scope = NewScope(scope_, GLOBAL_SCOPE);
869  info->SetGlobalScope(*scope);
870  if (!info->context().is_null() && !info->context()->IsNativeContext()) {
871  *scope = Scope::DeserializeScopeChain(*info->context(), *scope, zone());
872  // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
873  // means the Parser cannot operate independent of the V8 heap. Tell the
874  // string table to internalize strings and values right after they're
875  // created.
877  }
878  original_scope_ = *scope;
879  if (info->is_eval()) {
880  if (!(*scope)->is_global_scope() || info->strict_mode() == STRICT) {
881  *scope = NewScope(*scope, EVAL_SCOPE);
882  }
883  } else if (info->is_global()) {
884  *scope = NewScope(*scope, GLOBAL_SCOPE);
885  }
886  (*scope)->set_start_position(0);
887  // End position will be set by the caller.
888 
889  // Compute the parsing mode.
890  Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY;
891  if (allow_natives_syntax() || extension_ != NULL ||
892  (*scope)->is_eval_scope()) {
894  }
895  ParsingModeScope parsing_mode(this, mode);
896 
897  // Enters 'scope'.
898  FunctionState function_state(&function_state_, &scope_, *scope, zone(),
900 
901  scope_->SetStrictMode(info->strict_mode());
902  ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
903  bool ok = true;
904  int beg_pos = scanner()->location().beg_pos;
905  ParseSourceElements(body, Token::EOS, info->is_eval(), true, eval_scope,
906  &ok);
907 
908  if (ok && strict_mode() == STRICT) {
909  CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
910  }
911 
912  if (ok && allow_harmony_scoping() && strict_mode() == STRICT) {
914  }
915 
917  if (body->length() != 1 ||
918  !body->at(0)->IsExpressionStatement() ||
919  !body->at(0)->AsExpressionStatement()->
920  expression()->IsFunctionLiteral()) {
921  ReportMessage("single_function_literal");
922  ok = false;
923  }
924  }
925 
926  if (ok) {
927  result = factory()->NewFunctionLiteral(
928  ast_value_factory()->empty_string(), ast_value_factory(), scope_,
929  body, function_state.materialized_literal_count(),
930  function_state.expected_property_count(),
931  function_state.handler_count(), 0,
932  FunctionLiteral::kNoDuplicateParameters,
933  FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
934  FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0);
935  result->set_ast_properties(factory()->visitor()->ast_properties());
936  result->set_dont_optimize_reason(
937  factory()->visitor()->dont_optimize_reason());
938  }
939  }
940 
941  // Make sure the target stack is empty.
943 
944  return result;
945 }
946 
947 
948 FunctionLiteral* Parser::ParseLazy() {
949  // It's OK to use the counters here, since this function is only called in
950  // the main thread.
951  HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy());
952  Handle<String> source(String::cast(script()->source()));
953  isolate()->counters()->total_parse_size()->Increment(source->length());
954  base::ElapsedTimer timer;
955  if (FLAG_trace_parse) {
956  timer.Start();
957  }
958  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
959 
960  // Initialize parser state.
961  source = String::Flatten(source);
962  FunctionLiteral* result;
963  if (source->IsExternalTwoByteString()) {
966  shared_info->start_position(),
967  shared_info->end_position());
968  result = ParseLazy(&stream);
969  } else {
970  GenericStringUtf16CharacterStream stream(source,
971  shared_info->start_position(),
972  shared_info->end_position());
973  result = ParseLazy(&stream);
974  }
975 
976  if (FLAG_trace_parse && result != NULL) {
977  double ms = timer.Elapsed().InMillisecondsF();
978  SmartArrayPointer<char> name_chars = result->debug_name()->ToCString();
979  PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
980  }
981  return result;
982 }
983 
984 
985 FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
986  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
987  scanner_.Initialize(source);
988  DCHECK(scope_ == NULL);
990 
991  Handle<String> name(String::cast(shared_info->name()));
994  const AstRawString* raw_name = ast_value_factory()->GetString(name);
995  fni_->PushEnclosingName(raw_name);
996 
997  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
998 
999  // Place holder for the result.
1000  FunctionLiteral* result = NULL;
1001 
1002  {
1003  // Parse the function literal.
1004  Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
1005  info()->SetGlobalScope(scope);
1006  if (!info()->closure().is_null()) {
1007  scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
1008  zone());
1009  }
1010  original_scope_ = scope;
1011  FunctionState function_state(&function_state_, &scope_, scope, zone(),
1013  info()->ast_node_id_gen());
1014  DCHECK(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
1015  DCHECK(info()->strict_mode() == shared_info->strict_mode());
1016  scope->SetStrictMode(shared_info->strict_mode());
1017  FunctionLiteral::FunctionType function_type = shared_info->is_expression()
1018  ? (shared_info->is_anonymous()
1019  ? FunctionLiteral::ANONYMOUS_EXPRESSION
1020  : FunctionLiteral::NAMED_EXPRESSION)
1021  : FunctionLiteral::DECLARATION;
1022  bool ok = true;
1023 
1024  if (shared_info->is_arrow()) {
1025  Expression* expression = ParseExpression(false, &ok);
1026  DCHECK(expression->IsFunctionLiteral());
1027  result = expression->AsFunctionLiteral();
1028  } else {
1029  result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
1030  false, // Strict mode name already checked.
1031  shared_info->kind(), RelocInfo::kNoPosition,
1032  function_type,
1033  FunctionLiteral::NORMAL_ARITY, &ok);
1034  }
1035  // Make sure the results agree.
1036  DCHECK(ok == (result != NULL));
1037  }
1038 
1039  // Make sure the target stack is empty.
1041 
1042  if (result != NULL) {
1043  Handle<String> inferred_name(shared_info->inferred_name());
1044  result->set_inferred_name(inferred_name);
1045  }
1046  return result;
1047 }
1048 
1049 
1051  int end_token, bool is_eval, bool is_global,
1052  Scope** eval_scope, bool* ok) {
1053  // SourceElements ::
1054  // (ModuleElement)* <end_token>
1055 
1056  // Allocate a target stack to use for this set of source
1057  // elements. This way, all scripts and functions get their own
1058  // target stack thus avoiding illegal breaks and continues across
1059  // functions.
1060  TargetScope scope(&this->target_stack_);
1061 
1062  DCHECK(processor != NULL);
1063  bool directive_prologue = true; // Parsing directive prologue.
1064 
1065  while (peek() != end_token) {
1066  if (directive_prologue && peek() != Token::STRING) {
1067  directive_prologue = false;
1068  }
1069 
1070  Scanner::Location token_loc = scanner()->peek_location();
1071  Statement* stat;
1072  if (is_global && !is_eval) {
1073  stat = ParseModuleElement(NULL, CHECK_OK);
1074  } else {
1075  stat = ParseBlockElement(NULL, CHECK_OK);
1076  }
1077  if (stat == NULL || stat->IsEmpty()) {
1078  directive_prologue = false; // End of directive prologue.
1079  continue;
1080  }
1081 
1082  if (directive_prologue) {
1083  // A shot at a directive.
1084  ExpressionStatement* e_stat;
1085  Literal* literal;
1086  // Still processing directive prologue?
1087  if ((e_stat = stat->AsExpressionStatement()) != NULL &&
1088  (literal = e_stat->expression()->AsLiteral()) != NULL &&
1089  literal->raw_value()->IsString()) {
1090  // Check "use strict" directive (ES5 14.1) and "use asm" directive. Only
1091  // one can be present.
1092  if (strict_mode() == SLOPPY &&
1093  literal->raw_value()->AsString() ==
1094  ast_value_factory()->use_strict_string() &&
1095  token_loc.end_pos - token_loc.beg_pos ==
1096  ast_value_factory()->use_strict_string()->length() + 2) {
1097  // TODO(mstarzinger): Global strict eval calls, need their own scope
1098  // as specified in ES5 10.4.2(3). The correct fix would be to always
1099  // add this scope in DoParseProgram(), but that requires adaptations
1100  // all over the code base, so we go with a quick-fix for now.
1101  // In the same manner, we have to patch the parsing mode.
1102  if (is_eval && !scope_->is_eval_scope()) {
1103  DCHECK(scope_->is_global_scope());
1104  Scope* scope = NewScope(scope_, EVAL_SCOPE);
1105  scope->set_start_position(scope_->start_position());
1106  scope->set_end_position(scope_->end_position());
1107  scope_ = scope;
1108  if (eval_scope != NULL) {
1109  // Caller will correct the positions of the ad hoc eval scope.
1110  *eval_scope = scope;
1111  }
1112  mode_ = PARSE_EAGERLY;
1113  }
1114  scope_->SetStrictMode(STRICT);
1115  // "use strict" is the only directive for now.
1116  directive_prologue = false;
1117  } else if (literal->raw_value()->AsString() ==
1118  ast_value_factory()->use_asm_string() &&
1119  token_loc.end_pos - token_loc.beg_pos ==
1120  ast_value_factory()->use_asm_string()->length() + 2) {
1121  // Store the usage count; The actual use counter on the isolate is
1122  // incremented after parsing is done.
1124  scope_->SetAsmModule();
1125  }
1126  } else {
1127  // End of the directive prologue.
1128  directive_prologue = false;
1129  }
1130  }
1131 
1132  processor->Add(stat, zone());
1133  }
1134 
1135  return 0;
1136 }
1137 
1138 
1140  bool* ok) {
1141  // (Ecma 262 5th Edition, clause 14):
1142  // SourceElement:
1143  // Statement
1144  // FunctionDeclaration
1145  //
1146  // In harmony mode we allow additionally the following productions
1147  // ModuleElement:
1148  // LetDeclaration
1149  // ConstDeclaration
1150  // ModuleDeclaration
1151  // ImportDeclaration
1152  // ExportDeclaration
1153  // GeneratorDeclaration
1154 
1155  switch (peek()) {
1156  case Token::FUNCTION:
1157  return ParseFunctionDeclaration(NULL, ok);
1158  case Token::CLASS:
1159  return ParseClassDeclaration(NULL, ok);
1160  case Token::IMPORT:
1161  return ParseImportDeclaration(ok);
1162  case Token::EXPORT:
1163  return ParseExportDeclaration(ok);
1164  case Token::CONST:
1166  case Token::LET:
1168  if (strict_mode() == STRICT) {
1170  }
1171  // Fall through.
1172  default: {
1173  Statement* stmt = ParseStatement(labels, CHECK_OK);
1174  // Handle 'module' as a context-sensitive keyword.
1175  if (FLAG_harmony_modules &&
1176  peek() == Token::IDENTIFIER &&
1177  !scanner()->HasAnyLineTerminatorBeforeNext() &&
1178  stmt != NULL) {
1179  ExpressionStatement* estmt = stmt->AsExpressionStatement();
1180  if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL &&
1181  estmt->expression()->AsVariableProxy()->raw_name() ==
1182  ast_value_factory()->module_string() &&
1183  !scanner()->literal_contains_escapes()) {
1184  return ParseModuleDeclaration(NULL, ok);
1185  }
1186  }
1187  return stmt;
1188  }
1189  }
1190 }
1191 
1192 
1194  bool* ok) {
1195  // ModuleDeclaration:
1196  // 'module' Identifier Module
1197 
1198  int pos = peek_position();
1199  const AstRawString* name =
1201 
1202 #ifdef DEBUG
1203  if (FLAG_print_interface_details)
1204  PrintF("# Module %.*s ", name->length(), name->raw_data());
1205 #endif
1206 
1207  Module* module = ParseModule(CHECK_OK);
1208  VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
1209  Declaration* declaration =
1210  factory()->NewModuleDeclaration(proxy, module, scope_, pos);
1211  Declare(declaration, true, CHECK_OK);
1212 
1213 #ifdef DEBUG
1214  if (FLAG_print_interface_details)
1215  PrintF("# Module %.*s ", name->length(), name->raw_data());
1216  if (FLAG_print_interfaces) {
1217  PrintF("module %.*s: ", name->length(), name->raw_data());
1218  module->interface()->Print();
1219  }
1220 #endif
1221 
1222  if (names) names->Add(name, zone());
1223  if (module->body() == NULL)
1224  return factory()->NewEmptyStatement(pos);
1225  else
1226  return factory()->NewModuleStatement(proxy, module->body(), pos);
1227 }
1228 
1229 
1231  // Module:
1232  // '{' ModuleElement '}'
1233  // '=' ModulePath ';'
1234  // 'at' String ';'
1235 
1236  switch (peek()) {
1237  case Token::LBRACE:
1238  return ParseModuleLiteral(ok);
1239 
1240  case Token::ASSIGN: {
1241  Expect(Token::ASSIGN, CHECK_OK);
1242  Module* result = ParseModulePath(CHECK_OK);
1244  return result;
1245  }
1246 
1247  default: {
1249  Module* result = ParseModuleUrl(CHECK_OK);
1251  return result;
1252  }
1253  }
1254 }
1255 
1256 
1258  // Module:
1259  // '{' ModuleElement '}'
1260 
1261  int pos = peek_position();
1262  // Construct block expecting 16 statements.
1263  Block* body = factory()->NewBlock(NULL, 16, false, RelocInfo::kNoPosition);
1264 #ifdef DEBUG
1265  if (FLAG_print_interface_details) PrintF("# Literal ");
1266 #endif
1267  Scope* scope = NewScope(scope_, MODULE_SCOPE);
1268 
1269  Expect(Token::LBRACE, CHECK_OK);
1270  scope->set_start_position(scanner()->location().beg_pos);
1271  scope->SetStrictMode(STRICT);
1272 
1273  {
1274  BlockState block_state(&scope_, scope);
1275  TargetCollector collector(zone());
1276  Target target(&this->target_stack_, &collector);
1277  Target target_body(&this->target_stack_, body);
1278 
1279  while (peek() != Token::RBRACE) {
1281  if (stat && !stat->IsEmpty()) {
1282  body->AddStatement(stat, zone());
1283  }
1284  }
1285  }
1286 
1287  Expect(Token::RBRACE, CHECK_OK);
1288  scope->set_end_position(scanner()->location().end_pos);
1289  body->set_scope(scope);
1290 
1291  // Check that all exports are bound.
1292  Interface* interface = scope->interface();
1293  for (Interface::Iterator it = interface->iterator();
1294  !it.done(); it.Advance()) {
1295  if (scope->LookupLocal(it.name()) == NULL) {
1296  ParserTraits::ReportMessage("module_export_undefined", it.name());
1297  *ok = false;
1298  return NULL;
1299  }
1300  }
1301 
1302  interface->MakeModule(ok);
1303  DCHECK(*ok);
1304  interface->Freeze(ok);
1305  DCHECK(*ok);
1306  return factory()->NewModuleLiteral(body, interface, pos);
1307 }
1308 
1309 
1311  // ModulePath:
1312  // Identifier
1313  // ModulePath '.' Identifier
1314 
1315  int pos = peek_position();
1316  Module* result = ParseModuleVariable(CHECK_OK);
1317  while (Check(Token::PERIOD)) {
1319 #ifdef DEBUG
1320  if (FLAG_print_interface_details)
1321  PrintF("# Path .%.*s ", name->length(), name->raw_data());
1322 #endif
1323  Module* member = factory()->NewModulePath(result, name, pos);
1324  result->interface()->Add(name, member->interface(), zone(), ok);
1325  if (!*ok) {
1326 #ifdef DEBUG
1327  if (FLAG_print_interfaces) {
1328  PrintF("PATH TYPE ERROR at '%.*s'\n", name->length(), name->raw_data());
1329  PrintF("result: ");
1330  result->interface()->Print();
1331  PrintF("member: ");
1332  member->interface()->Print();
1333  }
1334 #endif
1335  ParserTraits::ReportMessage("invalid_module_path", name);
1336  return NULL;
1337  }
1338  result = member;
1339  }
1340 
1341  return result;
1342 }
1343 
1344 
1346  // ModulePath:
1347  // Identifier
1348 
1349  int pos = peek_position();
1350  const AstRawString* name =
1352 #ifdef DEBUG
1353  if (FLAG_print_interface_details)
1354  PrintF("# Module variable %.*s ", name->length(), name->raw_data());
1355 #endif
1356  VariableProxy* proxy = scope_->NewUnresolved(
1358  scanner()->location().beg_pos);
1359 
1360  return factory()->NewModuleVariable(proxy, pos);
1361 }
1362 
1363 
1365  // Module:
1366  // String
1367 
1368  int pos = peek_position();
1370  const AstRawString* symbol = GetSymbol(scanner());
1371 
1372  // TODO(ES6): Request JS resource from environment...
1373 
1374 #ifdef DEBUG
1375  if (FLAG_print_interface_details) PrintF("# Url ");
1376 #endif
1377 
1378  // Create an empty literal as long as the feature isn't finished.
1379  USE(symbol);
1380  Scope* scope = NewScope(scope_, MODULE_SCOPE);
1381  Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
1382  body->set_scope(scope);
1383  Interface* interface = scope->interface();
1384  Module* result = factory()->NewModuleLiteral(body, interface, pos);
1385  interface->Freeze(ok);
1386  DCHECK(*ok);
1387  interface->Unify(scope->interface(), zone(), ok);
1388  DCHECK(*ok);
1389  return result;
1390 }
1391 
1392 
1394  // ModuleSpecifier:
1395  // String
1396  // ModulePath
1397 
1398  if (peek() == Token::STRING) {
1399  return ParseModuleUrl(ok);
1400  } else {
1401  return ParseModulePath(ok);
1402  }
1403 }
1404 
1405 
1407  // ImportDeclaration:
1408  // 'import' IdentifierName (',' IdentifierName)* 'from' ModuleSpecifier ';'
1409  //
1410  // TODO(ES6): implement destructuring ImportSpecifiers
1411 
1412  int pos = peek_position();
1413  Expect(Token::IMPORT, CHECK_OK);
1414  ZoneList<const AstRawString*> names(1, zone());
1415 
1417  names.Add(name, zone());
1418  while (peek() == Token::COMMA) {
1421  names.Add(name, zone());
1422  }
1423 
1427 
1428  // Generate a separate declaration for each identifier.
1429  // TODO(ES6): once we implement destructuring, make that one declaration.
1430  Block* block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
1431  for (int i = 0; i < names.length(); ++i) {
1432 #ifdef DEBUG
1433  if (FLAG_print_interface_details)
1434  PrintF("# Import %.*s ", name->length(), name->raw_data());
1435 #endif
1436  Interface* interface = Interface::NewUnknown(zone());
1437  module->interface()->Add(names[i], interface, zone(), ok);
1438  if (!*ok) {
1439 #ifdef DEBUG
1440  if (FLAG_print_interfaces) {
1441  PrintF("IMPORT TYPE ERROR at '%.*s'\n", name->length(),
1442  name->raw_data());
1443  PrintF("module: ");
1444  module->interface()->Print();
1445  }
1446 #endif
1447  ParserTraits::ReportMessage("invalid_module_path", name);
1448  return NULL;
1449  }
1450  VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
1451  Declaration* declaration =
1452  factory()->NewImportDeclaration(proxy, module, scope_, pos);
1453  Declare(declaration, true, CHECK_OK);
1454  }
1455 
1456  return block;
1457 }
1458 
1459 
1461  // ExportDeclaration:
1462  // 'export' Identifier (',' Identifier)* ';'
1463  // 'export' VariableDeclaration
1464  // 'export' FunctionDeclaration
1465  // 'export' GeneratorDeclaration
1466  // 'export' ModuleDeclaration
1467  //
1468  // TODO(ES6): implement structuring ExportSpecifiers
1469 
1470  Expect(Token::EXPORT, CHECK_OK);
1471 
1472  Statement* result = NULL;
1473  ZoneList<const AstRawString*> names(1, zone());
1474  switch (peek()) {
1475  case Token::IDENTIFIER: {
1476  int pos = position();
1477  const AstRawString* name =
1479  // Handle 'module' as a context-sensitive keyword.
1480  if (name != ast_value_factory()->module_string()) {
1481  names.Add(name, zone());
1482  while (peek() == Token::COMMA) {
1485  names.Add(name, zone());
1486  }
1488  result = factory()->NewEmptyStatement(pos);
1489  } else {
1490  result = ParseModuleDeclaration(&names, CHECK_OK);
1491  }
1492  break;
1493  }
1494 
1495  case Token::FUNCTION:
1496  result = ParseFunctionDeclaration(&names, CHECK_OK);
1497  break;
1498 
1499  case Token::CLASS:
1500  result = ParseClassDeclaration(&names, CHECK_OK);
1501  break;
1502 
1503  case Token::VAR:
1504  case Token::LET:
1505  case Token::CONST:
1506  result = ParseVariableStatement(kModuleElement, &names, CHECK_OK);
1507  break;
1508 
1509  default:
1510  *ok = false;
1511  ReportUnexpectedToken(scanner()->current_token());
1512  return NULL;
1513  }
1514 
1515  // Every export of a module may be assigned.
1516  for (int i = 0; i < names.length(); ++i) {
1517  Variable* var = scope_->Lookup(names[i]);
1518  if (var == NULL) {
1519  // TODO(sigurds) This is an export that has no definition yet,
1520  // not clear what to do in this case.
1521  continue;
1522  }
1523  if (!IsImmutableVariableMode(var->mode())) {
1524  var->set_maybe_assigned();
1525  }
1526  }
1527 
1528  // Extract declared names into export declarations and interface.
1529  Interface* interface = scope_->interface();
1530  for (int i = 0; i < names.length(); ++i) {
1531 #ifdef DEBUG
1532  if (FLAG_print_interface_details)
1533  PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data());
1534 #endif
1535  Interface* inner = Interface::NewUnknown(zone());
1536  interface->Add(names[i], inner, zone(), CHECK_OK);
1537  if (!*ok)
1538  return NULL;
1539  VariableProxy* proxy = NewUnresolved(names[i], LET, inner);
1540  USE(proxy);
1541  // TODO(rossberg): Rethink whether we actually need to store export
1542  // declarations (for compilation?).
1543  // ExportDeclaration* declaration =
1544  // factory()->NewExportDeclaration(proxy, scope_, position);
1545  // scope_->AddDeclaration(declaration);
1546  }
1547 
1548  DCHECK(result != NULL);
1549  return result;
1550 }
1551 
1552 
1554  bool* ok) {
1555  // (Ecma 262 5th Edition, clause 14):
1556  // SourceElement:
1557  // Statement
1558  // FunctionDeclaration
1559  //
1560  // In harmony mode we allow additionally the following productions
1561  // BlockElement (aka SourceElement):
1562  // LetDeclaration
1563  // ConstDeclaration
1564  // GeneratorDeclaration
1565  // ClassDeclaration
1566 
1567  switch (peek()) {
1568  case Token::FUNCTION:
1569  return ParseFunctionDeclaration(NULL, ok);
1570  case Token::CLASS:
1571  return ParseClassDeclaration(NULL, ok);
1572  case Token::CONST:
1574  case Token::LET:
1576  if (strict_mode() == STRICT) {
1578  }
1579  // Fall through.
1580  default:
1581  return ParseStatement(labels, ok);
1582  }
1583 }
1584 
1585 
1587  bool* ok) {
1588  // Statement ::
1589  // Block
1590  // VariableStatement
1591  // EmptyStatement
1592  // ExpressionStatement
1593  // IfStatement
1594  // IterationStatement
1595  // ContinueStatement
1596  // BreakStatement
1597  // ReturnStatement
1598  // WithStatement
1599  // LabelledStatement
1600  // SwitchStatement
1601  // ThrowStatement
1602  // TryStatement
1603  // DebuggerStatement
1604 
1605  // Note: Since labels can only be used by 'break' and 'continue'
1606  // statements, which themselves are only valid within blocks,
1607  // iterations or 'switch' statements (i.e., BreakableStatements),
1608  // labels can be simply ignored in all other cases; except for
1609  // trivial labeled break statements 'label: break label' which is
1610  // parsed into an empty statement.
1611  switch (peek()) {
1612  case Token::LBRACE:
1613  return ParseBlock(labels, ok);
1614 
1615  case Token::SEMICOLON:
1616  Next();
1617  return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1618 
1619  case Token::IF:
1620  return ParseIfStatement(labels, ok);
1621 
1622  case Token::DO:
1623  return ParseDoWhileStatement(labels, ok);
1624 
1625  case Token::WHILE:
1626  return ParseWhileStatement(labels, ok);
1627 
1628  case Token::FOR:
1629  return ParseForStatement(labels, ok);
1630 
1631  case Token::CONTINUE:
1632  return ParseContinueStatement(ok);
1633 
1634  case Token::BREAK:
1635  return ParseBreakStatement(labels, ok);
1636 
1637  case Token::RETURN:
1638  return ParseReturnStatement(ok);
1639 
1640  case Token::WITH:
1641  return ParseWithStatement(labels, ok);
1642 
1643  case Token::SWITCH:
1644  return ParseSwitchStatement(labels, ok);
1645 
1646  case Token::THROW:
1647  return ParseThrowStatement(ok);
1648 
1649  case Token::TRY: {
1650  // NOTE: It is somewhat complicated to have labels on
1651  // try-statements. When breaking out of a try-finally statement,
1652  // one must take great care not to treat it as a
1653  // fall-through. It is much easier just to wrap the entire
1654  // try-statement in a statement block and put the labels there
1655  Block* result =
1656  factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
1657  Target target(&this->target_stack_, result);
1658  TryStatement* statement = ParseTryStatement(CHECK_OK);
1659  if (result) result->AddStatement(statement, zone());
1660  return result;
1661  }
1662 
1663  case Token::FUNCTION: {
1664  // FunctionDeclaration is only allowed in the context of SourceElements
1665  // (Ecma 262 5th Edition, clause 14):
1666  // SourceElement:
1667  // Statement
1668  // FunctionDeclaration
1669  // Common language extension is to allow function declaration in place
1670  // of any statement. This language extension is disabled in strict mode.
1671  //
1672  // In Harmony mode, this case also handles the extension:
1673  // Statement:
1674  // GeneratorDeclaration
1675  if (strict_mode() == STRICT) {
1676  ReportMessageAt(scanner()->peek_location(), "strict_function");
1677  *ok = false;
1678  return NULL;
1679  }
1680  return ParseFunctionDeclaration(NULL, ok);
1681  }
1682 
1683  case Token::CLASS:
1684  return ParseClassDeclaration(NULL, ok);
1685 
1686  case Token::DEBUGGER:
1687  return ParseDebuggerStatement(ok);
1688 
1689  case Token::VAR:
1690  case Token::CONST:
1691  return ParseVariableStatement(kStatement, NULL, ok);
1692 
1693  case Token::LET:
1695  if (strict_mode() == STRICT) {
1696  return ParseVariableStatement(kStatement, NULL, ok);
1697  }
1698  // Fall through.
1699  default:
1700  return ParseExpressionOrLabelledStatement(labels, ok);
1701  }
1702 }
1703 
1704 
1706  VariableMode mode, Interface* interface) {
1707  // If we are inside a function, a declaration of a var/const variable is a
1708  // truly local variable, and the scope of the variable is always the function
1709  // scope.
1710  // Let/const variables in harmony mode are always added to the immediately
1711  // enclosing scope.
1713  factory(), name, interface, position());
1714 }
1715 
1716 
1717 void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
1718  VariableProxy* proxy = declaration->proxy();
1719  DCHECK(proxy->raw_name() != NULL);
1720  const AstRawString* name = proxy->raw_name();
1721  VariableMode mode = declaration->mode();
1722  Scope* declaration_scope = DeclarationScope(mode);
1723  Variable* var = NULL;
1724 
1725  // If a suitable scope exists, then we can statically declare this
1726  // variable and also set its mode. In any case, a Declaration node
1727  // will be added to the scope so that the declaration can be added
1728  // to the corresponding activation frame at runtime if necessary.
1729  // For instance declarations inside an eval scope need to be added
1730  // to the calling function context.
1731  // Similarly, strict mode eval scope does not leak variable declarations to
1732  // the caller's scope so we declare all locals, too.
1733  if (declaration_scope->is_function_scope() ||
1734  declaration_scope->is_strict_eval_scope() ||
1735  declaration_scope->is_block_scope() ||
1736  declaration_scope->is_module_scope() ||
1737  declaration_scope->is_global_scope()) {
1738  // Declare the variable in the declaration scope.
1739  // For the global scope, we have to check for collisions with earlier
1740  // (i.e., enclosing) global scopes, to maintain the illusion of a single
1741  // global scope.
1742  var = declaration_scope->is_global_scope()
1743  ? declaration_scope->Lookup(name)
1744  : declaration_scope->LookupLocal(name);
1745  if (var == NULL) {
1746  // Declare the name.
1747  var = declaration_scope->DeclareLocal(name, mode,
1748  declaration->initialization(),
1749  kNotAssigned, proxy->interface());
1750  } else if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode())
1751  || ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) &&
1752  !declaration_scope->is_global_scope())) {
1753  // The name was declared in this scope before; check for conflicting
1754  // re-declarations. We have a conflict if either of the declarations is
1755  // not a var (in the global scope, we also have to ignore legacy const for
1756  // compatibility). There is similar code in runtime.cc in the Declare
1757  // functions. The function CheckConflictingVarDeclarations checks for
1758  // var and let bindings from different scopes whereas this is a check for
1759  // conflicting declarations within the same scope. This check also covers
1760  // the special case
1761  //
1762  // function () { let x; { var x; } }
1763  //
1764  // because the var declaration is hoisted to the function scope where 'x'
1765  // is already bound.
1767  if (allow_harmony_scoping() && strict_mode() == STRICT) {
1768  // In harmony we treat re-declarations as early errors. See
1769  // ES5 16 for a definition of early errors.
1770  ParserTraits::ReportMessage("var_redeclaration", name);
1771  *ok = false;
1772  return;
1773  }
1774  Expression* expression = NewThrowTypeError(
1775  "var_redeclaration", name, declaration->position());
1776  declaration_scope->SetIllegalRedeclaration(expression);
1777  } else if (mode == VAR) {
1778  var->set_maybe_assigned();
1779  }
1780  }
1781 
1782  // We add a declaration node for every declaration. The compiler
1783  // will only generate code if necessary. In particular, declarations
1784  // for inner local variables that do not represent functions won't
1785  // result in any generated code.
1786  //
1787  // Note that we always add an unresolved proxy even if it's not
1788  // used, simply because we don't know in this method (w/o extra
1789  // parameters) if the proxy is needed or not. The proxy will be
1790  // bound during variable resolution time unless it was pre-bound
1791  // below.
1792  //
1793  // WARNING: This will lead to multiple declaration nodes for the
1794  // same variable if it is declared several times. This is not a
1795  // semantic issue as long as we keep the source order, but it may be
1796  // a performance issue since it may lead to repeated
1797  // RuntimeHidden_DeclareLookupSlot calls.
1798  declaration_scope->AddDeclaration(declaration);
1799 
1800  if (mode == CONST_LEGACY && declaration_scope->is_global_scope()) {
1801  // For global const variables we bind the proxy to a variable.
1802  DCHECK(resolve); // should be set by all callers
1804  var = new (zone())
1805  Variable(declaration_scope, name, mode, true, kind,
1806  kNeedsInitialization, kNotAssigned, proxy->interface());
1807  } else if (declaration_scope->is_eval_scope() &&
1808  declaration_scope->strict_mode() == SLOPPY) {
1809  // For variable declarations in a sloppy eval scope the proxy is bound
1810  // to a lookup variable to force a dynamic declaration using the
1811  // DeclareLookupSlot runtime function.
1813  // TODO(sigurds) figure out if kNotAssigned is OK here
1814  var = new (zone()) Variable(declaration_scope, name, mode, true, kind,
1815  declaration->initialization(), kNotAssigned,
1816  proxy->interface());
1817  var->AllocateTo(Variable::LOOKUP, -1);
1818  resolve = true;
1819  }
1820 
1821  // If requested and we have a local variable, bind the proxy to the variable
1822  // at parse-time. This is used for functions (and consts) declared inside
1823  // statements: the corresponding function (or const) variable must be in the
1824  // function scope and not a statement-local scope, e.g. as provided with a
1825  // 'with' statement:
1826  //
1827  // with (obj) {
1828  // function f() {}
1829  // }
1830  //
1831  // which is translated into:
1832  //
1833  // with (obj) {
1834  // // in this case this is not: 'var f; f = function () {};'
1835  // var f = function () {};
1836  // }
1837  //
1838  // Note that if 'f' is accessed from inside the 'with' statement, it
1839  // will be allocated in the context (because we must be able to look
1840  // it up dynamically) but it will also be accessed statically, i.e.,
1841  // with a context slot index and a context chain length for this
1842  // initialization code. Thus, inside the 'with' statement, we need
1843  // both access to the static and the dynamic context chain; the
1844  // runtime needs to provide both.
1845  if (resolve && var != NULL) {
1846  proxy->BindTo(var);
1847 
1848  if (FLAG_harmony_modules) {
1849  bool ok;
1850 #ifdef DEBUG
1851  if (FLAG_print_interface_details) {
1852  PrintF("# Declare %.*s ", var->raw_name()->length(),
1853  var->raw_name()->raw_data());
1854  }
1855 #endif
1856  proxy->interface()->Unify(var->interface(), zone(), &ok);
1857  if (!ok) {
1858 #ifdef DEBUG
1859  if (FLAG_print_interfaces) {
1860  PrintF("DECLARE TYPE ERROR\n");
1861  PrintF("proxy: ");
1862  proxy->interface()->Print();
1863  PrintF("var: ");
1864  var->interface()->Print();
1865  }
1866 #endif
1867  ParserTraits::ReportMessage("module_type_error", name);
1868  }
1869  }
1870  }
1871 }
1872 
1873 
1874 // Language extension which is only enabled for source files loaded
1875 // through the API's extension mechanism. A native function
1876 // declaration is resolved by looking up the function through a
1877 // callback provided by the extension.
1879  int pos = peek_position();
1880  Expect(Token::FUNCTION, CHECK_OK);
1881  // Allow "eval" or "arguments" for backward compatibility.
1883  Expect(Token::LPAREN, CHECK_OK);
1884  bool done = (peek() == Token::RPAREN);
1885  while (!done) {
1887  done = (peek() == Token::RPAREN);
1888  if (!done) {
1890  }
1891  }
1892  Expect(Token::RPAREN, CHECK_OK);
1893  Expect(Token::SEMICOLON, CHECK_OK);
1894 
1895  // Make sure that the function containing the native declaration
1896  // isn't lazily compiled. The extension structures are only
1897  // accessible while parsing the first time not when reparsing
1898  // because of lazy compilation.
1900 
1901  // TODO(1240846): It's weird that native function declarations are
1902  // introduced dynamically when we meet their declarations, whereas
1903  // other functions are set up when entering the surrounding scope.
1904  VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
1905  Declaration* declaration =
1906  factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
1907  Declare(declaration, true, CHECK_OK);
1908  NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
1910  return factory()->NewExpressionStatement(
1911  factory()->NewAssignment(
1912  Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition),
1913  pos);
1914 }
1915 
1916 
1918  ZoneList<const AstRawString*>* names, bool* ok) {
1919  // FunctionDeclaration ::
1920  // 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1921  // GeneratorDeclaration ::
1922  // 'function' '*' Identifier '(' FormalParameterListopt ')'
1923  // '{' FunctionBody '}'
1924  Expect(Token::FUNCTION, CHECK_OK);
1925  int pos = position();
1926  bool is_generator = Check(Token::MUL);
1927  bool is_strict_reserved = false;
1929  &is_strict_reserved, CHECK_OK);
1930  FunctionLiteral* fun =
1931  ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
1934  pos, FunctionLiteral::DECLARATION,
1935  FunctionLiteral::NORMAL_ARITY, CHECK_OK);
1936  // Even if we're not at the top-level of the global or a function
1937  // scope, we treat it as such and introduce the function with its
1938  // initial value upon entering the corresponding scope.
1939  // In ES6, a function behaves as a lexical binding, except in the
1940  // global scope, or the initial scope of eval or another function.
1941  VariableMode mode =
1943  !(scope_->is_global_scope() || scope_->is_eval_scope() ||
1944  scope_->is_function_scope()) ? LET : VAR;
1945  VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
1946  Declaration* declaration =
1947  factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
1948  Declare(declaration, true, CHECK_OK);
1949  if (names) names->Add(name, zone());
1950  return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1951 }
1952 
1953 
1955  bool* ok) {
1956  // ClassDeclaration ::
1957  // 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
1958  //
1959  // A ClassDeclaration
1960  //
1961  // class C { ... }
1962  //
1963  // has the same semantics as:
1964  //
1965  // let C = class C { ... };
1966  //
1967  // so rewrite it as such.
1968 
1969  Expect(Token::CLASS, CHECK_OK);
1970  int pos = position();
1971  bool is_strict_reserved = false;
1972  const AstRawString* name =
1973  ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
1974  Expression* value = ParseClassLiteral(name, scanner()->location(),
1975  is_strict_reserved, pos, CHECK_OK);
1976 
1977  Block* block = factory()->NewBlock(NULL, 1, true, pos);
1978  VariableMode mode = LET;
1979  VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
1980  Declaration* declaration =
1981  factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
1982  Declare(declaration, true, CHECK_OK);
1983 
1984  Token::Value init_op = Token::INIT_LET;
1985  Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos);
1986  block->AddStatement(
1987  factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
1988  zone());
1989 
1990  if (names) names->Add(name, zone());
1991  return block;
1992 }
1993 
1994 
1996  if (allow_harmony_scoping() && strict_mode() == STRICT) {
1997  return ParseScopedBlock(labels, ok);
1998  }
1999 
2000  // Block ::
2001  // '{' Statement* '}'
2002 
2003  // Note that a Block does not introduce a new execution scope!
2004  // (ECMA-262, 3rd, 12.2)
2005  //
2006  // Construct block expecting 16 statements.
2007  Block* result =
2008  factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
2009  Target target(&this->target_stack_, result);
2010  Expect(Token::LBRACE, CHECK_OK);
2011  while (peek() != Token::RBRACE) {
2013  if (stat && !stat->IsEmpty()) {
2014  result->AddStatement(stat, zone());
2015  }
2016  }
2017  Expect(Token::RBRACE, CHECK_OK);
2018  return result;
2019 }
2020 
2021 
2023  bool* ok) {
2024  // The harmony mode uses block elements instead of statements.
2025  //
2026  // Block ::
2027  // '{' BlockElement* '}'
2028 
2029  // Construct block expecting 16 statements.
2030  Block* body =
2031  factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
2032  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
2033 
2034  // Parse the statements and collect escaping labels.
2035  Expect(Token::LBRACE, CHECK_OK);
2036  block_scope->set_start_position(scanner()->location().beg_pos);
2037  { BlockState block_state(&scope_, block_scope);
2038  TargetCollector collector(zone());
2039  Target target(&this->target_stack_, &collector);
2040  Target target_body(&this->target_stack_, body);
2041 
2042  while (peek() != Token::RBRACE) {
2044  if (stat && !stat->IsEmpty()) {
2045  body->AddStatement(stat, zone());
2046  }
2047  }
2048  }
2049  Expect(Token::RBRACE, CHECK_OK);
2050  block_scope->set_end_position(scanner()->location().end_pos);
2051  block_scope = block_scope->FinalizeBlockScope();
2052  body->set_scope(block_scope);
2053  return body;
2054 }
2055 
2056 
2059  bool* ok) {
2060  // VariableStatement ::
2061  // VariableDeclarations ';'
2062 
2063  const AstRawString* ignore;
2064  Block* result =
2065  ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
2067  return result;
2068 }
2069 
2070 
2071 // If the variable declaration declares exactly one non-const
2072 // variable, then *out is set to that variable. In all other cases,
2073 // *out is untouched; in particular, it is the caller's responsibility
2074 // to initialize it properly. This mechanism is used for the parsing
2075 // of 'for-in' loops.
2077  VariableDeclarationContext var_context,
2078  VariableDeclarationProperties* decl_props,
2080  const AstRawString** out,
2081  bool* ok) {
2082  // VariableDeclarations ::
2083  // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2084  //
2085  // The ES6 Draft Rev3 specifies the following grammar for const declarations
2086  //
2087  // ConstDeclaration ::
2088  // const ConstBinding (',' ConstBinding)* ';'
2089  // ConstBinding ::
2090  // Identifier '=' AssignmentExpression
2091  //
2092  // TODO(ES6):
2093  // ConstBinding ::
2094  // BindingPattern '=' AssignmentExpression
2095 
2096  int pos = peek_position();
2097  VariableMode mode = VAR;
2098  // True if the binding needs initialization. 'let' and 'const' declared
2099  // bindings are created uninitialized by their declaration nodes and
2100  // need initialization. 'var' declared bindings are always initialized
2101  // immediately by their declaration nodes.
2102  bool needs_init = false;
2103  bool is_const = false;
2104  Token::Value init_op = Token::INIT_VAR;
2105  if (peek() == Token::VAR) {
2107  } else if (peek() == Token::CONST) {
2108  // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
2109  //
2110  // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
2111  //
2112  // * It is a Syntax Error if the code that matches this production is not
2113  // contained in extended code.
2114  //
2115  // However disallowing const in sloppy mode will break compatibility with
2116  // existing pages. Therefore we keep allowing const with the old
2117  // non-harmony semantics in sloppy mode.
2119  switch (strict_mode()) {
2120  case SLOPPY:
2121  mode = CONST_LEGACY;
2122  init_op = Token::INIT_CONST_LEGACY;
2123  break;
2124  case STRICT:
2125  if (allow_harmony_scoping()) {
2126  if (var_context == kStatement) {
2127  // In strict mode 'const' declarations are only allowed in source
2128  // element positions.
2129  ReportMessage("unprotected_const");
2130  *ok = false;
2131  return NULL;
2132  }
2133  mode = CONST;
2134  init_op = Token::INIT_CONST;
2135  } else {
2136  ReportMessage("strict_const");
2137  *ok = false;
2138  return NULL;
2139  }
2140  }
2141  is_const = true;
2142  needs_init = true;
2143  } else if (peek() == Token::LET && strict_mode() == STRICT) {
2146  if (var_context == kStatement) {
2147  // Let declarations are only allowed in source element positions.
2148  ReportMessage("unprotected_let");
2149  *ok = false;
2150  return NULL;
2151  }
2152  mode = LET;
2153  needs_init = true;
2154  init_op = Token::INIT_LET;
2155  } else {
2156  UNREACHABLE(); // by current callers
2157  }
2158 
2159  Scope* declaration_scope = DeclarationScope(mode);
2160 
2161  // The scope of a var/const declared variable anywhere inside a function
2162  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
2163  // transform a source-level var/const declaration into a (Function)
2164  // Scope declaration, and rewrite the source-level initialization into an
2165  // assignment statement. We use a block to collect multiple assignments.
2166  //
2167  // We mark the block as initializer block because we don't want the
2168  // rewriter to add a '.result' assignment to such a block (to get compliant
2169  // behavior for code such as print(eval('var x = 7')), and for cosmetic
2170  // reasons when pretty-printing. Also, unless an assignment (initialization)
2171  // is inside an initializer block, it is ignored.
2172  //
2173  // Create new block with one expected declaration.
2174  Block* block = factory()->NewBlock(NULL, 1, true, pos);
2175  int nvars = 0; // the number of variables declared
2176  const AstRawString* name = NULL;
2177  do {
2178  if (fni_ != NULL) fni_->Enter();
2179 
2180  // Parse variable name.
2181  if (nvars > 0) Consume(Token::COMMA);
2183  if (fni_ != NULL) fni_->PushVariableName(name);
2184 
2185  // Declare variable.
2186  // Note that we *always* must treat the initial value via a separate init
2187  // assignment for variables and constants because the value must be assigned
2188  // when the variable is encountered in the source. But the variable/constant
2189  // is declared (and set to 'undefined') upon entering the function within
2190  // which the variable or constant is declared. Only function variables have
2191  // an initial value in the declaration (because they are initialized upon
2192  // entering the function).
2193  //
2194  // If we have a const declaration, in an inner scope, the proxy is always
2195  // bound to the declared variable (independent of possibly surrounding with
2196  // statements).
2197  // For let/const declarations in harmony mode, we can also immediately
2198  // pre-resolve the proxy because it resides in the same scope as the
2199  // declaration.
2200  Interface* interface =
2201  is_const ? Interface::NewConst() : Interface::NewValue();
2202  VariableProxy* proxy = NewUnresolved(name, mode, interface);
2203  Declaration* declaration =
2204  factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
2205  Declare(declaration, mode != VAR, CHECK_OK);
2206  nvars++;
2207  if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
2208  ReportMessage("too_many_variables");
2209  *ok = false;
2210  return NULL;
2211  }
2212  if (names) names->Add(name, zone());
2213 
2214  // Parse initialization expression if present and/or needed. A
2215  // declaration of the form:
2216  //
2217  // var v = x;
2218  //
2219  // is syntactic sugar for:
2220  //
2221  // var v; v = x;
2222  //
2223  // In particular, we need to re-lookup 'v' (in scope_, not
2224  // declaration_scope) as it may be a different 'v' than the 'v' in the
2225  // declaration (e.g., if we are inside a 'with' statement or 'catch'
2226  // block).
2227  //
2228  // However, note that const declarations are different! A const
2229  // declaration of the form:
2230  //
2231  // const c = x;
2232  //
2233  // is *not* syntactic sugar for:
2234  //
2235  // const c; c = x;
2236  //
2237  // The "variable" c initialized to x is the same as the declared
2238  // one - there is no re-lookup (see the last parameter of the
2239  // Declare() call above).
2240 
2241  Scope* initialization_scope = is_const ? declaration_scope : scope_;
2242  Expression* value = NULL;
2243  int pos = -1;
2244  // Harmony consts have non-optional initializers.
2245  if (peek() == Token::ASSIGN || mode == CONST) {
2246  Expect(Token::ASSIGN, CHECK_OK);
2247  pos = position();
2248  value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
2249  // Don't infer if it is "a = function(){...}();"-like expression.
2250  if (fni_ != NULL &&
2251  value->AsCall() == NULL &&
2252  value->AsCallNew() == NULL) {
2253  fni_->Infer();
2254  } else {
2256  }
2257  if (decl_props != NULL) *decl_props = kHasInitializers;
2258  }
2259 
2260  // Record the end position of the initializer.
2261  if (proxy->var() != NULL) {
2262  proxy->var()->set_initializer_position(position());
2263  }
2264 
2265  // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
2266  if (value == NULL && needs_init) {
2267  value = GetLiteralUndefined(position());
2268  }
2269 
2270  // Global variable declarations must be compiled in a specific
2271  // way. When the script containing the global variable declaration
2272  // is entered, the global variable must be declared, so that if it
2273  // doesn't exist (on the global object itself, see ES5 errata) it
2274  // gets created with an initial undefined value. This is handled
2275  // by the declarations part of the function representing the
2276  // top-level global code; see Runtime::DeclareGlobalVariable. If
2277  // it already exists (in the object or in a prototype), it is
2278  // *not* touched until the variable declaration statement is
2279  // executed.
2280  //
2281  // Executing the variable declaration statement will always
2282  // guarantee to give the global object an own property.
2283  // This way, global variable declarations can shadow
2284  // properties in the prototype chain, but only after the variable
2285  // declaration statement has been executed. This is important in
2286  // browsers where the global object (window) has lots of
2287  // properties defined in prototype objects.
2288  if (initialization_scope->is_global_scope() &&
2290  // Compute the arguments for the runtime call.
2291  ZoneList<Expression*>* arguments =
2292  new(zone()) ZoneList<Expression*>(3, zone());
2293  // We have at least 1 parameter.
2294  arguments->Add(factory()->NewStringLiteral(name, pos), zone());
2295  CallRuntime* initialize;
2296 
2297  if (is_const) {
2298  arguments->Add(value, zone());
2299  value = NULL; // zap the value to avoid the unnecessary assignment
2300 
2301  // Construct the call to Runtime_InitializeConstGlobal
2302  // and add it to the initialization statement block.
2303  // Note that the function does different things depending on
2304  // the number of arguments (1 or 2).
2305  initialize = factory()->NewCallRuntime(
2306  ast_value_factory()->initialize_const_global_string(),
2307  Runtime::FunctionForId(Runtime::kInitializeConstGlobal), arguments,
2308  pos);
2309  } else {
2310  // Add strict mode.
2311  // We may want to pass singleton to avoid Literal allocations.
2312  StrictMode strict_mode = initialization_scope->strict_mode();
2313  arguments->Add(factory()->NewNumberLiteral(strict_mode, pos), zone());
2314 
2315  // Be careful not to assign a value to the global variable if
2316  // we're in a with. The initialization value should not
2317  // necessarily be stored in the global object in that case,
2318  // which is why we need to generate a separate assignment node.
2319  if (value != NULL && !inside_with()) {
2320  arguments->Add(value, zone());
2321  value = NULL; // zap the value to avoid the unnecessary assignment
2322  // Construct the call to Runtime_InitializeVarGlobal
2323  // and add it to the initialization statement block.
2324  initialize = factory()->NewCallRuntime(
2325  ast_value_factory()->initialize_var_global_string(),
2326  Runtime::FunctionForId(Runtime::kInitializeVarGlobal), arguments,
2327  pos);
2328  } else {
2329  initialize = NULL;
2330  }
2331  }
2332 
2333  if (initialize != NULL) {
2334  block->AddStatement(factory()->NewExpressionStatement(
2335  initialize, RelocInfo::kNoPosition),
2336  zone());
2337  }
2338  } else if (needs_init) {
2339  // Constant initializations always assign to the declared constant which
2340  // is always at the function scope level. This is only relevant for
2341  // dynamically looked-up variables and constants (the start context for
2342  // constant lookups is always the function context, while it is the top
2343  // context for var declared variables). Sigh...
2344  // For 'let' and 'const' declared variables in harmony mode the
2345  // initialization also always assigns to the declared variable.
2346  DCHECK(proxy != NULL);
2347  DCHECK(proxy->var() != NULL);
2348  DCHECK(value != NULL);
2349  Assignment* assignment =
2350  factory()->NewAssignment(init_op, proxy, value, pos);
2351  block->AddStatement(
2352  factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2353  zone());
2354  value = NULL;
2355  }
2356 
2357  // Add an assignment node to the initialization statement block if we still
2358  // have a pending initialization value.
2359  if (value != NULL) {
2360  DCHECK(mode == VAR);
2361  // 'var' initializations are simply assignments (with all the consequences
2362  // if they are inside a 'with' statement - they may change a 'with' object
2363  // property).
2364  VariableProxy* proxy =
2365  initialization_scope->NewUnresolved(factory(), name, interface);
2366  Assignment* assignment =
2367  factory()->NewAssignment(init_op, proxy, value, pos);
2368  block->AddStatement(
2369  factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2370  zone());
2371  }
2372 
2373  if (fni_ != NULL) fni_->Leave();
2374  } while (peek() == Token::COMMA);
2375 
2376  // If there was a single non-const declaration, return it in the output
2377  // parameter for possible use by for/in.
2378  if (nvars == 1 && !is_const) {
2379  *out = name;
2380  }
2381 
2382  return block;
2383 }
2384 
2385 
2387  const AstRawString* label) {
2388  DCHECK(label != NULL);
2389  if (labels != NULL) {
2390  for (int i = labels->length(); i-- > 0; ) {
2391  if (labels->at(i) == label) {
2392  return true;
2393  }
2394  }
2395  }
2396  return false;
2397 }
2398 
2399 
2401  ZoneList<const AstRawString*>* labels, bool* ok) {
2402  // ExpressionStatement | LabelledStatement ::
2403  // Expression ';'
2404  // Identifier ':' Statement
2405  int pos = peek_position();
2406  bool starts_with_idenfifier = peek_any_identifier();
2407  Expression* expr = ParseExpression(true, CHECK_OK);
2408  if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
2409  expr->AsVariableProxy() != NULL &&
2410  !expr->AsVariableProxy()->is_this()) {
2411  // Expression is a single identifier, and not, e.g., a parenthesized
2412  // identifier.
2413  VariableProxy* var = expr->AsVariableProxy();
2414  const AstRawString* label = var->raw_name();
2415  // TODO(1240780): We don't check for redeclaration of labels
2416  // during preparsing since keeping track of the set of active
2417  // labels requires nontrivial changes to the way scopes are
2418  // structured. However, these are probably changes we want to
2419  // make later anyway so we should go back and fix this then.
2420  if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
2421  ParserTraits::ReportMessage("label_redeclaration", label);
2422  *ok = false;
2423  return NULL;
2424  }
2425  if (labels == NULL) {
2426  labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
2427  }
2428  labels->Add(label, zone());
2429  // Remove the "ghost" variable that turned out to be a label
2430  // from the top scope. This way, we don't try to resolve it
2431  // during the scope processing.
2432  scope_->RemoveUnresolved(var);
2433  Expect(Token::COLON, CHECK_OK);
2434  return ParseStatement(labels, ok);
2435  }
2436 
2437  // If we have an extension, we allow a native function declaration.
2438  // A native function declaration starts with "native function" with
2439  // no line-terminator between the two words.
2440  if (extension_ != NULL && peek() == Token::FUNCTION &&
2441  !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL &&
2442  expr->AsVariableProxy() != NULL &&
2443  expr->AsVariableProxy()->raw_name() ==
2444  ast_value_factory()->native_string() &&
2445  !scanner()->literal_contains_escapes()) {
2446  return ParseNativeDeclaration(ok);
2447  }
2448 
2449  // Parsed expression statement, or the context-sensitive 'module' keyword.
2450  // Only expect semicolon in the former case.
2451  if (!FLAG_harmony_modules || peek() != Token::IDENTIFIER ||
2452  scanner()->HasAnyLineTerminatorBeforeNext() ||
2453  expr->AsVariableProxy() == NULL ||
2454  expr->AsVariableProxy()->raw_name() !=
2455  ast_value_factory()->module_string() ||
2456  scanner()->literal_contains_escapes()) {
2458  }
2459  return factory()->NewExpressionStatement(expr, pos);
2460 }
2461 
2462 
2464  bool* ok) {
2465  // IfStatement ::
2466  // 'if' '(' Expression ')' Statement ('else' Statement)?
2467 
2468  int pos = peek_position();
2469  Expect(Token::IF, CHECK_OK);
2470  Expect(Token::LPAREN, CHECK_OK);
2471  Expression* condition = ParseExpression(true, CHECK_OK);
2472  Expect(Token::RPAREN, CHECK_OK);
2473  Statement* then_statement = ParseStatement(labels, CHECK_OK);
2474  Statement* else_statement = NULL;
2475  if (peek() == Token::ELSE) {
2476  Next();
2477  else_statement = ParseStatement(labels, CHECK_OK);
2478  } else {
2479  else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
2480  }
2481  return factory()->NewIfStatement(
2482  condition, then_statement, else_statement, pos);
2483 }
2484 
2485 
2487  // ContinueStatement ::
2488  // 'continue' Identifier? ';'
2489 
2490  int pos = peek_position();
2491  Expect(Token::CONTINUE, CHECK_OK);
2492  const AstRawString* label = NULL;
2493  Token::Value tok = peek();
2494  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2495  tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2496  // ECMA allows "eval" or "arguments" as labels even in strict mode.
2498  }
2500  if (target == NULL) {
2501  // Illegal continue statement.
2502  const char* message = "illegal_continue";
2503  if (label != NULL) {
2504  message = "unknown_label";
2505  }
2506  ParserTraits::ReportMessage(message, label);
2507  *ok = false;
2508  return NULL;
2509  }
2511  return factory()->NewContinueStatement(target, pos);
2512 }
2513 
2514 
2516  bool* ok) {
2517  // BreakStatement ::
2518  // 'break' Identifier? ';'
2519 
2520  int pos = peek_position();
2522  const AstRawString* label = NULL;
2523  Token::Value tok = peek();
2524  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
2525  tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2526  // ECMA allows "eval" or "arguments" as labels even in strict mode.
2528  }
2529  // Parse labeled break statements that target themselves into
2530  // empty statements, e.g. 'l1: l2: l3: break l2;'
2531  if (label != NULL && ContainsLabel(labels, label)) {
2533  return factory()->NewEmptyStatement(pos);
2534  }
2535  BreakableStatement* target = NULL;
2536  target = LookupBreakTarget(label, CHECK_OK);
2537  if (target == NULL) {
2538  // Illegal break statement.
2539  const char* message = "illegal_break";
2540  if (label != NULL) {
2541  message = "unknown_label";
2542  }
2543  ParserTraits::ReportMessage(message, label);
2544  *ok = false;
2545  return NULL;
2546  }
2548  return factory()->NewBreakStatement(target, pos);
2549 }
2550 
2551 
2553  // ReturnStatement ::
2554  // 'return' Expression? ';'
2555 
2556  // Consume the return token. It is necessary to do that before
2557  // reporting any errors on it, because of the way errors are
2558  // reported (underlining).
2559  Expect(Token::RETURN, CHECK_OK);
2560  Scanner::Location loc = scanner()->location();
2561 
2562  Token::Value tok = peek();
2563  Statement* result;
2564  Expression* return_value;
2565  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
2566  tok == Token::SEMICOLON ||
2567  tok == Token::RBRACE ||
2568  tok == Token::EOS) {
2569  return_value = GetLiteralUndefined(position());
2570  } else {
2571  return_value = ParseExpression(true, CHECK_OK);
2572  }
2574  if (is_generator()) {
2575  Expression* generator = factory()->NewVariableProxy(
2576  function_state_->generator_object_variable());
2577  Expression* yield = factory()->NewYield(
2578  generator, return_value, Yield::kFinal, loc.beg_pos);
2579  result = factory()->NewExpressionStatement(yield, loc.beg_pos);
2580  } else {
2581  result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2582  }
2583 
2584  Scope* decl_scope = scope_->DeclarationScope();
2585  if (decl_scope->is_global_scope() || decl_scope->is_eval_scope()) {
2586  ReportMessageAt(loc, "illegal_return");
2587  *ok = false;
2588  return NULL;
2589  }
2590  return result;
2591 }
2592 
2593 
2595  bool* ok) {
2596  // WithStatement ::
2597  // 'with' '(' Expression ')' Statement
2598 
2599  Expect(Token::WITH, CHECK_OK);
2600  int pos = position();
2601 
2602  if (strict_mode() == STRICT) {
2603  ReportMessage("strict_mode_with");
2604  *ok = false;
2605  return NULL;
2606  }
2607 
2608  Expect(Token::LPAREN, CHECK_OK);
2609  Expression* expr = ParseExpression(true, CHECK_OK);
2610  Expect(Token::RPAREN, CHECK_OK);
2611 
2612  scope_->DeclarationScope()->RecordWithStatement();
2613  Scope* with_scope = NewScope(scope_, WITH_SCOPE);
2614  Statement* stmt;
2615  { BlockState block_state(&scope_, with_scope);
2616  with_scope->set_start_position(scanner()->peek_location().beg_pos);
2617  stmt = ParseStatement(labels, CHECK_OK);
2618  with_scope->set_end_position(scanner()->location().end_pos);
2619  }
2620  return factory()->NewWithStatement(with_scope, expr, stmt, pos);
2621 }
2622 
2623 
2624 CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2625  // CaseClause ::
2626  // 'case' Expression ':' Statement*
2627  // 'default' ':' Statement*
2628 
2629  Expression* label = NULL; // NULL expression indicates default case
2630  if (peek() == Token::CASE) {
2632  label = ParseExpression(true, CHECK_OK);
2633  } else {
2635  if (*default_seen_ptr) {
2636  ReportMessage("multiple_defaults_in_switch");
2637  *ok = false;
2638  return NULL;
2639  }
2640  *default_seen_ptr = true;
2641  }
2642  Expect(Token::COLON, CHECK_OK);
2643  int pos = position();
2644  ZoneList<Statement*>* statements =
2645  new(zone()) ZoneList<Statement*>(5, zone());
2646  while (peek() != Token::CASE &&
2647  peek() != Token::DEFAULT &&
2648  peek() != Token::RBRACE) {
2650  statements->Add(stat, zone());
2651  }
2652 
2653  return factory()->NewCaseClause(label, statements, pos);
2654 }
2655 
2656 
2658  ZoneList<const AstRawString*>* labels, bool* ok) {
2659  // SwitchStatement ::
2660  // 'switch' '(' Expression ')' '{' CaseClause* '}'
2661 
2662  SwitchStatement* statement =
2663  factory()->NewSwitchStatement(labels, peek_position());
2664  Target target(&this->target_stack_, statement);
2665 
2666  Expect(Token::SWITCH, CHECK_OK);
2667  Expect(Token::LPAREN, CHECK_OK);
2668  Expression* tag = ParseExpression(true, CHECK_OK);
2669  Expect(Token::RPAREN, CHECK_OK);
2670 
2671  bool default_seen = false;
2672  ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4, zone());
2673  Expect(Token::LBRACE, CHECK_OK);
2674  while (peek() != Token::RBRACE) {
2675  CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
2676  cases->Add(clause, zone());
2677  }
2678  Expect(Token::RBRACE, CHECK_OK);
2679 
2680  if (statement) statement->Initialize(tag, cases);
2681  return statement;
2682 }
2683 
2684 
2686  // ThrowStatement ::
2687  // 'throw' Expression ';'
2688 
2689  Expect(Token::THROW, CHECK_OK);
2690  int pos = position();
2691  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
2692  ReportMessage("newline_after_throw");
2693  *ok = false;
2694  return NULL;
2695  }
2696  Expression* exception = ParseExpression(true, CHECK_OK);
2698 
2699  return factory()->NewExpressionStatement(
2700  factory()->NewThrow(exception, pos), pos);
2701 }
2702 
2703 
2705  // TryStatement ::
2706  // 'try' Block Catch
2707  // 'try' Block Finally
2708  // 'try' Block Catch Finally
2709  //
2710  // Catch ::
2711  // 'catch' '(' Identifier ')' Block
2712  //
2713  // Finally ::
2714  // 'finally' Block
2715 
2716  Expect(Token::TRY, CHECK_OK);
2717  int pos = position();
2718 
2719  TargetCollector try_collector(zone());
2720  Block* try_block;
2721 
2722  { Target target(&this->target_stack_, &try_collector);
2723  try_block = ParseBlock(NULL, CHECK_OK);
2724  }
2725 
2726  Token::Value tok = peek();
2727  if (tok != Token::CATCH && tok != Token::FINALLY) {
2728  ReportMessage("no_catch_or_finally");
2729  *ok = false;
2730  return NULL;
2731  }
2732 
2733  // If we can break out from the catch block and there is a finally block,
2734  // then we will need to collect escaping targets from the catch
2735  // block. Since we don't know yet if there will be a finally block, we
2736  // always collect the targets.
2737  TargetCollector catch_collector(zone());
2738  Scope* catch_scope = NULL;
2739  Variable* catch_variable = NULL;
2740  Block* catch_block = NULL;
2741  const AstRawString* name = NULL;
2742  if (tok == Token::CATCH) {
2743  Consume(Token::CATCH);
2744 
2745  Expect(Token::LPAREN, CHECK_OK);
2746  catch_scope = NewScope(scope_, CATCH_SCOPE);
2747  catch_scope->set_start_position(scanner()->location().beg_pos);
2749 
2750  Expect(Token::RPAREN, CHECK_OK);
2751 
2752  Target target(&this->target_stack_, &catch_collector);
2753  VariableMode mode =
2755  catch_variable = catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
2756  BlockState block_state(&scope_, catch_scope);
2757  catch_block = ParseBlock(NULL, CHECK_OK);
2758 
2759  catch_scope->set_end_position(scanner()->location().end_pos);
2760  tok = peek();
2761  }
2762 
2763  Block* finally_block = NULL;
2764  DCHECK(tok == Token::FINALLY || catch_block != NULL);
2765  if (tok == Token::FINALLY) {
2766  Consume(Token::FINALLY);
2767  finally_block = ParseBlock(NULL, CHECK_OK);
2768  }
2769 
2770  // Simplify the AST nodes by converting:
2771  // 'try B0 catch B1 finally B2'
2772  // to:
2773  // 'try { try B0 catch B1 } finally B2'
2774 
2775  if (catch_block != NULL && finally_block != NULL) {
2776  // If we have both, create an inner try/catch.
2777  DCHECK(catch_scope != NULL && catch_variable != NULL);
2778  int index = function_state_->NextHandlerIndex();
2779  TryCatchStatement* statement = factory()->NewTryCatchStatement(
2780  index, try_block, catch_scope, catch_variable, catch_block,
2782  statement->set_escaping_targets(try_collector.targets());
2783  try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
2784  try_block->AddStatement(statement, zone());
2785  catch_block = NULL; // Clear to indicate it's been handled.
2786  }
2787 
2788  TryStatement* result = NULL;
2789  if (catch_block != NULL) {
2790  DCHECK(finally_block == NULL);
2791  DCHECK(catch_scope != NULL && catch_variable != NULL);
2792  int index = function_state_->NextHandlerIndex();
2793  result = factory()->NewTryCatchStatement(
2794  index, try_block, catch_scope, catch_variable, catch_block, pos);
2795  } else {
2796  DCHECK(finally_block != NULL);
2797  int index = function_state_->NextHandlerIndex();
2798  result = factory()->NewTryFinallyStatement(
2799  index, try_block, finally_block, pos);
2800  // Combine the jump targets of the try block and the possible catch block.
2801  try_collector.targets()->AddAll(*catch_collector.targets(), zone());
2802  }
2803 
2804  result->set_escaping_targets(try_collector.targets());
2805  return result;
2806 }
2807 
2808 
2810  ZoneList<const AstRawString*>* labels, bool* ok) {
2811  // DoStatement ::
2812  // 'do' Statement 'while' '(' Expression ')' ';'
2813 
2814  DoWhileStatement* loop =
2815  factory()->NewDoWhileStatement(labels, peek_position());
2816  Target target(&this->target_stack_, loop);
2817 
2818  Expect(Token::DO, CHECK_OK);
2820  Expect(Token::WHILE, CHECK_OK);
2821  Expect(Token::LPAREN, CHECK_OK);
2822 
2823  Expression* cond = ParseExpression(true, CHECK_OK);
2824  Expect(Token::RPAREN, CHECK_OK);
2825 
2826  // Allow do-statements to be terminated with and without
2827  // semi-colons. This allows code such as 'do;while(0)return' to
2828  // parse, which would not be the case if we had used the
2829  // ExpectSemicolon() functionality here.
2830  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2831 
2832  if (loop != NULL) loop->Initialize(cond, body);
2833  return loop;
2834 }
2835 
2836 
2838  ZoneList<const AstRawString*>* labels, bool* ok) {
2839  // WhileStatement ::
2840  // 'while' '(' Expression ')' Statement
2841 
2842  WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
2843  Target target(&this->target_stack_, loop);
2844 
2845  Expect(Token::WHILE, CHECK_OK);
2846  Expect(Token::LPAREN, CHECK_OK);
2847  Expression* cond = ParseExpression(true, CHECK_OK);
2848  Expect(Token::RPAREN, CHECK_OK);
2850 
2851  if (loop != NULL) loop->Initialize(cond, body);
2852  return loop;
2853 }
2854 
2855 
2856 bool Parser::CheckInOrOf(bool accept_OF,
2857  ForEachStatement::VisitMode* visit_mode) {
2858  if (Check(Token::IN)) {
2859  *visit_mode = ForEachStatement::ENUMERATE;
2860  return true;
2861  } else if (accept_OF && CheckContextualKeyword(CStrVector("of"))) {
2862  *visit_mode = ForEachStatement::ITERATE;
2863  return true;
2864  }
2865  return false;
2866 }
2867 
2868 
2870  Expression* each,
2871  Expression* subject,
2872  Statement* body) {
2873  ForOfStatement* for_of = stmt->AsForOfStatement();
2874 
2875  if (for_of != NULL) {
2876  Variable* iterator = scope_->DeclarationScope()->NewTemporary(
2877  ast_value_factory()->dot_iterator_string());
2878  Variable* result = scope_->DeclarationScope()->NewTemporary(
2879  ast_value_factory()->dot_result_string());
2880 
2881  Expression* assign_iterator;
2882  Expression* next_result;
2883  Expression* result_done;
2884  Expression* assign_each;
2885 
2886  // var iterator = subject[Symbol.iterator]();
2887  assign_iterator = factory()->NewAssignment(
2888  Token::ASSIGN, factory()->NewVariableProxy(iterator),
2890 
2891  // var result = iterator.next();
2892  {
2893  Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
2894  Expression* next_literal = factory()->NewStringLiteral(
2895  ast_value_factory()->next_string(), RelocInfo::kNoPosition);
2896  Expression* next_property = factory()->NewProperty(
2897  iterator_proxy, next_literal, RelocInfo::kNoPosition);
2898  ZoneList<Expression*>* next_arguments =
2899  new(zone()) ZoneList<Expression*>(0, zone());
2900  Expression* next_call = factory()->NewCall(
2901  next_property, next_arguments, RelocInfo::kNoPosition);
2902  Expression* result_proxy = factory()->NewVariableProxy(result);
2903  next_result = factory()->NewAssignment(
2904  Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition);
2905  }
2906 
2907  // result.done
2908  {
2909  Expression* done_literal = factory()->NewStringLiteral(
2910  ast_value_factory()->done_string(), RelocInfo::kNoPosition);
2911  Expression* result_proxy = factory()->NewVariableProxy(result);
2912  result_done = factory()->NewProperty(
2913  result_proxy, done_literal, RelocInfo::kNoPosition);
2914  }
2915 
2916  // each = result.value
2917  {
2918  Expression* value_literal = factory()->NewStringLiteral(
2919  ast_value_factory()->value_string(), RelocInfo::kNoPosition);
2920  Expression* result_proxy = factory()->NewVariableProxy(result);
2921  Expression* result_value = factory()->NewProperty(
2922  result_proxy, value_literal, RelocInfo::kNoPosition);
2923  assign_each = factory()->NewAssignment(
2924  Token::ASSIGN, each, result_value, RelocInfo::kNoPosition);
2925  }
2926 
2927  for_of->Initialize(each, subject, body,
2928  assign_iterator,
2929  next_result,
2930  result_done,
2931  assign_each);
2932  } else {
2933  stmt->Initialize(each, subject, body);
2934  }
2935 }
2936 
2937 
2939  Scope* inner_scope, ZoneList<const AstRawString*>* names,
2940  ForStatement* loop, Statement* init, Expression* cond, Statement* next,
2941  Statement* body, bool* ok) {
2942  // ES6 13.6.3.4 specifies that on each loop iteration the let variables are
2943  // copied into a new environment. After copying, the "next" statement of the
2944  // loop is executed to update the loop variables. The loop condition is
2945  // checked and the loop body is executed.
2946  //
2947  // We rewrite a for statement of the form
2948  //
2949  // for (let x = i; cond; next) body
2950  //
2951  // into
2952  //
2953  // {
2954  // let x = i;
2955  // temp_x = x;
2956  // flag = 1;
2957  // for (;;) {
2958  // let x = temp_x;
2959  // if (flag == 1) {
2960  // flag = 0;
2961  // } else {
2962  // next;
2963  // }
2964  // if (cond) {
2965  // <empty>
2966  // } else {
2967  // break;
2968  // }
2969  // b
2970  // temp_x = x;
2971  // }
2972  // }
2973 
2974  DCHECK(names->length() > 0);
2975  Scope* for_scope = scope_;
2976  ZoneList<Variable*> temps(names->length(), zone());
2977 
2978  Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false,
2980  outer_block->AddStatement(init, zone());
2981 
2982  const AstRawString* temp_name = ast_value_factory()->dot_for_string();
2983 
2984  // For each let variable x:
2985  // make statement: temp_x = x.
2986  for (int i = 0; i < names->length(); i++) {
2987  VariableProxy* proxy =
2988  NewUnresolved(names->at(i), LET, Interface::NewValue());
2989  Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name);
2990  VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
2991  Assignment* assignment = factory()->NewAssignment(
2992  Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
2993  Statement* assignment_statement = factory()->NewExpressionStatement(
2994  assignment, RelocInfo::kNoPosition);
2995  outer_block->AddStatement(assignment_statement, zone());
2996  temps.Add(temp, zone());
2997  }
2998 
2999  Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name);
3000  // Make statement: flag = 1.
3001  {
3002  VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3003  Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3004  Assignment* assignment = factory()->NewAssignment(
3005  Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
3006  Statement* assignment_statement = factory()->NewExpressionStatement(
3007  assignment, RelocInfo::kNoPosition);
3008  outer_block->AddStatement(assignment_statement, zone());
3009  }
3010 
3011  outer_block->AddStatement(loop, zone());
3012  outer_block->set_scope(for_scope);
3013  scope_ = inner_scope;
3014 
3015  Block* inner_block = factory()->NewBlock(NULL, 2 * names->length() + 3,
3016  false, RelocInfo::kNoPosition);
3017  int pos = scanner()->location().beg_pos;
3018  ZoneList<Variable*> inner_vars(names->length(), zone());
3019 
3020  // For each let variable x:
3021  // make statement: let x = temp_x.
3022  for (int i = 0; i < names->length(); i++) {
3023  VariableProxy* proxy =
3024  NewUnresolved(names->at(i), LET, Interface::NewValue());
3025  Declaration* declaration =
3026  factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
3027  Declare(declaration, true, CHECK_OK);
3028  inner_vars.Add(declaration->proxy()->var(), zone());
3029  VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
3030  Assignment* assignment = factory()->NewAssignment(
3031  Token::INIT_LET, proxy, temp_proxy, pos);
3032  Statement* assignment_statement = factory()->NewExpressionStatement(
3033  assignment, pos);
3034  proxy->var()->set_initializer_position(pos);
3035  inner_block->AddStatement(assignment_statement, zone());
3036  }
3037 
3038  // Make statement: if (flag == 1) { flag = 0; } else { next; }.
3039  if (next) {
3040  Expression* compare = NULL;
3041  // Make compare expresion: flag == 1.
3042  {
3043  Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
3044  VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3045  compare = factory()->NewCompareOperation(
3046  Token::EQ, flag_proxy, const1, pos);
3047  }
3048  Statement* clear_flag = NULL;
3049  // Make statement: flag = 0.
3050  {
3051  VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
3052  Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
3053  Assignment* assignment = factory()->NewAssignment(
3054  Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
3055  clear_flag = factory()->NewExpressionStatement(assignment, pos);
3056  }
3057  Statement* clear_flag_or_next = factory()->NewIfStatement(
3058  compare, clear_flag, next, RelocInfo::kNoPosition);
3059  inner_block->AddStatement(clear_flag_or_next, zone());
3060  }
3061 
3062 
3063  // Make statement: if (cond) { } else { break; }.
3064  if (cond) {
3065  Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
3067  Statement* stop = factory()->NewBreakStatement(t, RelocInfo::kNoPosition);
3068  Statement* if_not_cond_break = factory()->NewIfStatement(
3069  cond, empty, stop, cond->position());
3070  inner_block->AddStatement(if_not_cond_break, zone());
3071  }
3072 
3073  inner_block->AddStatement(body, zone());
3074 
3075  // For each let variable x:
3076  // make statement: temp_x = x;
3077  for (int i = 0; i < names->length(); i++) {
3078  VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
3079  int pos = scanner()->location().end_pos;
3080  VariableProxy* proxy = factory()->NewVariableProxy(inner_vars.at(i), pos);
3081  Assignment* assignment = factory()->NewAssignment(
3082  Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
3083  Statement* assignment_statement = factory()->NewExpressionStatement(
3084  assignment, RelocInfo::kNoPosition);
3085  inner_block->AddStatement(assignment_statement, zone());
3086  }
3087 
3088  inner_scope->set_end_position(scanner()->location().end_pos);
3089  inner_block->set_scope(inner_scope);
3090  scope_ = for_scope;
3091 
3092  loop->Initialize(NULL, NULL, NULL, inner_block);
3093  return outer_block;
3094 }
3095 
3096 
3098  bool* ok) {
3099  // ForStatement ::
3100  // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
3101 
3102  int pos = peek_position();
3103  Statement* init = NULL;
3104  ZoneList<const AstRawString*> let_bindings(1, zone());
3105 
3106  // Create an in-between scope for let-bound iteration variables.
3107  Scope* saved_scope = scope_;
3108  Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3109  scope_ = for_scope;
3110 
3111  Expect(Token::FOR, CHECK_OK);
3112  Expect(Token::LPAREN, CHECK_OK);
3113  for_scope->set_start_position(scanner()->location().beg_pos);
3114  if (peek() != Token::SEMICOLON) {
3115  if (peek() == Token::VAR || peek() == Token::CONST) {
3116  bool is_const = peek() == Token::CONST;
3117  const AstRawString* name = NULL;
3119  Block* variable_statement =
3121  CHECK_OK);
3122  bool accept_OF = decl_props == kHasNoInitializers;
3124 
3125  if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
3126  Interface* interface =
3127  is_const ? Interface::NewConst() : Interface::NewValue();
3128  ForEachStatement* loop =
3129  factory()->NewForEachStatement(mode, labels, pos);
3130  Target target(&this->target_stack_, loop);
3131 
3132  Expression* enumerable = ParseExpression(true, CHECK_OK);
3133  Expect(Token::RPAREN, CHECK_OK);
3134 
3135  VariableProxy* each =
3136  scope_->NewUnresolved(factory(), name, interface);
3137  Statement* body = ParseStatement(NULL, CHECK_OK);
3138  InitializeForEachStatement(loop, each, enumerable, body);
3139  Block* result =
3140  factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3141  result->AddStatement(variable_statement, zone());
3142  result->AddStatement(loop, zone());
3143  scope_ = saved_scope;
3144  for_scope->set_end_position(scanner()->location().end_pos);
3145  for_scope = for_scope->FinalizeBlockScope();
3146  DCHECK(for_scope == NULL);
3147  // Parsed for-in loop w/ variable/const declaration.
3148  return result;
3149  } else {
3150  init = variable_statement;
3151  }
3152  } else if (peek() == Token::LET && strict_mode() == STRICT) {
3154  const AstRawString* name = NULL;
3156  Block* variable_statement =
3157  ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
3158  &name, CHECK_OK);
3159  bool accept_IN = name != NULL && decl_props != kHasInitializers;
3160  bool accept_OF = decl_props == kHasNoInitializers;
3162 
3163  if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
3164  // Rewrite a for-in statement of the form
3165  //
3166  // for (let x in e) b
3167  //
3168  // into
3169  //
3170  // <let x' be a temporary variable>
3171  // for (x' in e) {
3172  // let x;
3173  // x = x';
3174  // b;
3175  // }
3176 
3177  // TODO(keuchel): Move the temporary variable to the block scope, after
3178  // implementing stack allocated block scoped variables.
3179  Variable* temp = scope_->DeclarationScope()->NewTemporary(
3180  ast_value_factory()->dot_for_string());
3181  VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3182  ForEachStatement* loop =
3183  factory()->NewForEachStatement(mode, labels, pos);
3184  Target target(&this->target_stack_, loop);
3185 
3186  // The expression does not see the loop variable.
3187  scope_ = saved_scope;
3188  Expression* enumerable = ParseExpression(true, CHECK_OK);
3189  scope_ = for_scope;
3190  Expect(Token::RPAREN, CHECK_OK);
3191 
3192  VariableProxy* each =
3193  scope_->NewUnresolved(factory(), name, Interface::NewValue());
3195  Block* body_block =
3196  factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3197  Assignment* assignment = factory()->NewAssignment(
3198  Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
3199  Statement* assignment_statement = factory()->NewExpressionStatement(
3200  assignment, RelocInfo::kNoPosition);
3201  body_block->AddStatement(variable_statement, zone());
3202  body_block->AddStatement(assignment_statement, zone());
3203  body_block->AddStatement(body, zone());
3204  InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
3205  scope_ = saved_scope;
3206  for_scope->set_end_position(scanner()->location().end_pos);
3207  for_scope = for_scope->FinalizeBlockScope();
3208  body_block->set_scope(for_scope);
3209  // Parsed for-in loop w/ let declaration.
3210  return loop;
3211 
3212  } else {
3213  init = variable_statement;
3214  }
3215  } else {
3216  Scanner::Location lhs_location = scanner()->peek_location();
3217  Expression* expression = ParseExpression(false, CHECK_OK);
3219  bool accept_OF = expression->AsVariableProxy();
3220 
3221  if (CheckInOrOf(accept_OF, &mode)) {
3222  expression = this->CheckAndRewriteReferenceExpression(
3223  expression, lhs_location, "invalid_lhs_in_for", CHECK_OK);
3224 
3225  ForEachStatement* loop =
3226  factory()->NewForEachStatement(mode, labels, pos);
3227  Target target(&this->target_stack_, loop);
3228 
3229  Expression* enumerable = ParseExpression(true, CHECK_OK);
3230  Expect(Token::RPAREN, CHECK_OK);
3231 
3233  InitializeForEachStatement(loop, expression, enumerable, body);
3234  scope_ = saved_scope;
3235  for_scope->set_end_position(scanner()->location().end_pos);
3236  for_scope = for_scope->FinalizeBlockScope();
3237  DCHECK(for_scope == NULL);
3238  // Parsed for-in loop.
3239  return loop;
3240 
3241  } else {
3242  init = factory()->NewExpressionStatement(
3243  expression, RelocInfo::kNoPosition);
3244  }
3245  }
3246  }
3247 
3248  // Standard 'for' loop
3249  ForStatement* loop = factory()->NewForStatement(labels, pos);
3250  Target target(&this->target_stack_, loop);
3251 
3252  // Parsed initializer at this point.
3253  Expect(Token::SEMICOLON, CHECK_OK);
3254 
3255  // If there are let bindings, then condition and the next statement of the
3256  // for loop must be parsed in a new scope.
3257  Scope* inner_scope = NULL;
3258  if (let_bindings.length() > 0) {
3259  inner_scope = NewScope(for_scope, BLOCK_SCOPE);
3260  inner_scope->set_start_position(scanner()->location().beg_pos);
3261  scope_ = inner_scope;
3262  }
3263 
3264  Expression* cond = NULL;
3265  if (peek() != Token::SEMICOLON) {
3266  cond = ParseExpression(true, CHECK_OK);
3267  }
3268  Expect(Token::SEMICOLON, CHECK_OK);
3269 
3270  Statement* next = NULL;
3271  if (peek() != Token::RPAREN) {
3272  Expression* exp = ParseExpression(true, CHECK_OK);
3273  next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition);
3274  }
3275  Expect(Token::RPAREN, CHECK_OK);
3276 
3278 
3279  Statement* result = NULL;
3280  if (let_bindings.length() > 0) {
3281  scope_ = for_scope;
3282  result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop,
3283  init, cond, next, body, CHECK_OK);
3284  scope_ = saved_scope;
3285  for_scope->set_end_position(scanner()->location().end_pos);
3286  } else {
3287  scope_ = saved_scope;
3288  for_scope->set_end_position(scanner()->location().end_pos);
3289  for_scope = for_scope->FinalizeBlockScope();
3290  if (for_scope) {
3291  // Rewrite a for statement of the form
3292  // for (const x = i; c; n) b
3293  //
3294  // into
3295  //
3296  // {
3297  // const x = i;
3298  // for (; c; n) b
3299  // }
3300  DCHECK(init != NULL);
3301  Block* block =
3302  factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3303  block->AddStatement(init, zone());
3304  block->AddStatement(loop, zone());
3305  block->set_scope(for_scope);
3306  loop->Initialize(NULL, cond, next, body);
3307  result = block;
3308  } else {
3309  loop->Initialize(init, cond, next, body);
3310  result = loop;
3311  }
3312  }
3313  return result;
3314 }
3315 
3316 
3317 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3318  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3319  // contexts this is used as a statement which invokes the debugger as i a
3320  // break point is present.
3321  // DebuggerStatement ::
3322  // 'debugger' ';'
3323 
3324  int pos = peek_position();
3325  Expect(Token::DEBUGGER, CHECK_OK);
3327  return factory()->NewDebuggerStatement(pos);
3328 }
3329 
3330 
3332  if (expression->IsLiteral()) return true;
3333  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3334  return lit != NULL && lit->is_simple();
3335 }
3336 
3337 
3339  Expression* expression) {
3340  Factory* factory = isolate->factory();
3341  DCHECK(IsCompileTimeValue(expression));
3342  Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
3343  ObjectLiteral* object_literal = expression->AsObjectLiteral();
3344  if (object_literal != NULL) {
3345  DCHECK(object_literal->is_simple());
3346  if (object_literal->fast_elements()) {
3347  result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3348  } else {
3349  result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3350  }
3351  result->set(kElementsSlot, *object_literal->constant_properties());
3352  } else {
3353  ArrayLiteral* array_literal = expression->AsArrayLiteral();
3354  DCHECK(array_literal != NULL && array_literal->is_simple());
3355  result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
3356  result->set(kElementsSlot, *array_literal->constant_elements());
3357  }
3358  return result;
3359 }
3360 
3361 
3363  Handle<FixedArray> value) {
3364  Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3365  return static_cast<LiteralType>(literal_type->value());
3366 }
3367 
3368 
3370  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3371 }
3372 
3373 
3375  Scope* scope, int* num_params,
3376  Scanner::Location* dupe_loc) {
3377  // Case for empty parameter lists:
3378  // () => ...
3379  if (expression == NULL) return true;
3380 
3381  // Too many parentheses around expression:
3382  // (( ... )) => ...
3383  if (expression->parenthesization_level() > 1) return false;
3384 
3385  // Case for a single parameter:
3386  // (foo) => ...
3387  // foo => ...
3388  if (expression->IsVariableProxy()) {
3389  if (expression->AsVariableProxy()->is_this()) return false;
3390 
3391  const AstRawString* raw_name = expression->AsVariableProxy()->raw_name();
3392  if (traits->IsEvalOrArguments(raw_name) ||
3393  traits->IsFutureStrictReserved(raw_name))
3394  return false;
3395 
3396  if (scope->IsDeclared(raw_name)) {
3397  *dupe_loc = Scanner::Location(
3398  expression->position(), expression->position() + raw_name->length());
3399  return false;
3400  }
3401 
3402  scope->DeclareParameter(raw_name, VAR);
3403  ++(*num_params);
3404  return true;
3405  }
3406 
3407  // Case for more than one parameter:
3408  // (foo, bar [, ...]) => ...
3409  if (expression->IsBinaryOperation()) {
3410  BinaryOperation* binop = expression->AsBinaryOperation();
3411  if (binop->op() != Token::COMMA || binop->left()->is_parenthesized() ||
3412  binop->right()->is_parenthesized())
3413  return false;
3414 
3415  return CheckAndDeclareArrowParameter(traits, binop->left(), scope,
3416  num_params, dupe_loc) &&
3417  CheckAndDeclareArrowParameter(traits, binop->right(), scope,
3418  num_params, dupe_loc);
3419  }
3420 
3421  // Any other kind of expression is not a valid parameter list.
3422  return false;
3423 }
3424 
3425 
3427  Expression* expression, Scope* scope, Scanner::Location* dupe_loc,
3428  bool* ok) {
3429  int num_params = 0;
3430  *ok = CheckAndDeclareArrowParameter(this, expression, scope, &num_params,
3431  dupe_loc);
3432  return num_params;
3433 }
3434 
3435 
3437  const AstRawString* function_name, Scanner::Location function_name_location,
3438  bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
3439  FunctionLiteral::FunctionType function_type,
3440  FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
3441  // Function ::
3442  // '(' FormalParameterList? ')' '{' FunctionBody '}'
3443  //
3444  // Getter ::
3445  // '(' ')' '{' FunctionBody '}'
3446  //
3447  // Setter ::
3448  // '(' PropertySetParameterList ')' '{' FunctionBody '}'
3449 
3450  int pos = function_token_pos == RelocInfo::kNoPosition
3451  ? peek_position() : function_token_pos;
3452 
3453  bool is_generator = IsGeneratorFunction(kind);
3454 
3455  // Anonymous functions were passed either the empty symbol or a null
3456  // handle as the function name. Remember if we were passed a non-empty
3457  // handle to decide whether to invoke function name inference.
3458  bool should_infer_name = function_name == NULL;
3459 
3460  // We want a non-null handle as the function name.
3461  if (should_infer_name) {
3462  function_name = ast_value_factory()->empty_string();
3463  }
3464 
3465  int num_parameters = 0;
3466  // Function declarations are function scoped in normal mode, so they are
3467  // hoisted. In harmony block scoping mode they are block scoped, so they
3468  // are not hoisted.
3469  //
3470  // One tricky case are function declarations in a local sloppy-mode eval:
3471  // their declaration is hoisted, but they still see the local scope. E.g.,
3472  //
3473  // function() {
3474  // var x = 0
3475  // try { throw 1 } catch (x) { eval("function g() { return x }") }
3476  // return g()
3477  // }
3478  //
3479  // needs to return 1. To distinguish such cases, we need to detect
3480  // (1) whether a function stems from a sloppy eval, and
3481  // (2) whether it actually hoists across the eval.
3482  // Unfortunately, we do not represent sloppy eval scopes, so we do not have
3483  // either information available directly, especially not when lazily compiling
3484  // a function like 'g'. We hence rely on the following invariants:
3485  // - (1) is the case iff the innermost scope of the deserialized scope chain
3486  // under which we compile is _not_ a declaration scope. This holds because
3487  // in all normal cases, function declarations are fully hoisted to a
3488  // declaration scope and compiled relative to that.
3489  // - (2) is the case iff the current declaration scope is still the original
3490  // one relative to the deserialized scope chain. Otherwise we must be
3491  // compiling a function in an inner declaration scope in the eval, e.g. a
3492  // nested function, and hoisting works normally relative to that.
3493  Scope* declaration_scope = scope_->DeclarationScope();
3494  Scope* original_declaration_scope = original_scope_->DeclarationScope();
3495  Scope* scope =
3496  function_type == FunctionLiteral::DECLARATION &&
3497  (!allow_harmony_scoping() || strict_mode() == SLOPPY) &&
3498  (original_scope_ == original_declaration_scope ||
3499  declaration_scope != original_declaration_scope)
3500  ? NewScope(declaration_scope, FUNCTION_SCOPE)
3502  ZoneList<Statement*>* body = NULL;
3503  int materialized_literal_count = -1;
3504  int expected_property_count = -1;
3505  int handler_count = 0;
3506  FunctionLiteral::ParameterFlag duplicate_parameters =
3507  FunctionLiteral::kNoDuplicateParameters;
3508  FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
3509  ? FunctionLiteral::kIsParenthesized
3510  : FunctionLiteral::kNotParenthesized;
3511  AstProperties ast_properties;
3512  BailoutReason dont_optimize_reason = kNoReason;
3513  // Parse function body.
3514  {
3515  FunctionState function_state(&function_state_, &scope_, scope, zone(),
3517  info()->ast_node_id_gen());
3518  scope_->SetScopeName(function_name);
3519 
3520  if (is_generator) {
3521  // For generators, allocating variables in contexts is currently a win
3522  // because it minimizes the work needed to suspend and resume an
3523  // activation.
3524  scope_->ForceContextAllocation();
3525 
3526  // Calling a generator returns a generator object. That object is stored
3527  // in a temporary variable, a definition that is used by "yield"
3528  // expressions. This also marks the FunctionState as a generator.
3529  Variable* temp = scope_->DeclarationScope()->NewTemporary(
3530  ast_value_factory()->dot_generator_object_string());
3531  function_state.set_generator_object_variable(temp);
3532  }
3533 
3534  // FormalParameterList ::
3535  // '(' (Identifier)*[','] ')'
3536  Expect(Token::LPAREN, CHECK_OK);
3537  scope->set_start_position(scanner()->location().beg_pos);
3538 
3539  // We don't yet know if the function will be strict, so we cannot yet
3540  // produce errors for parameter names or duplicates. However, we remember
3541  // the locations of these errors if they occur and produce the errors later.
3542  Scanner::Location eval_args_error_log = Scanner::Location::invalid();
3543  Scanner::Location dupe_error_loc = Scanner::Location::invalid();
3545 
3546  bool done = arity_restriction == FunctionLiteral::GETTER_ARITY ||
3547  (peek() == Token::RPAREN &&
3548  arity_restriction != FunctionLiteral::SETTER_ARITY);
3549  while (!done) {
3550  bool is_strict_reserved = false;
3551  const AstRawString* param_name =
3552  ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
3553 
3554  // Store locations for possible future error reports.
3555  if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) {
3556  eval_args_error_log = scanner()->location();
3557  }
3558  if (!reserved_loc.IsValid() && is_strict_reserved) {
3559  reserved_loc = scanner()->location();
3560  }
3561  if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) {
3562  duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
3563  dupe_error_loc = scanner()->location();
3564  }
3565 
3566  Variable* var = scope_->DeclareParameter(param_name, VAR);
3567  if (scope->strict_mode() == SLOPPY) {
3568  // TODO(sigurds) Mark every parameter as maybe assigned. This is a
3569  // conservative approximation necessary to account for parameters
3570  // that are assigned via the arguments array.
3571  var->set_maybe_assigned();
3572  }
3573 
3574  num_parameters++;
3575  if (num_parameters > Code::kMaxArguments) {
3576  ReportMessage("too_many_parameters");
3577  *ok = false;
3578  return NULL;
3579  }
3580  if (arity_restriction == FunctionLiteral::SETTER_ARITY) break;
3581  done = (peek() == Token::RPAREN);
3582  if (!done) Expect(Token::COMMA, CHECK_OK);
3583  }
3584  Expect(Token::RPAREN, CHECK_OK);
3585 
3586  Expect(Token::LBRACE, CHECK_OK);
3587 
3588  // If we have a named function expression, we add a local variable
3589  // declaration to the body of the function with the name of the
3590  // function and let it refer to the function itself (closure).
3591  // NOTE: We create a proxy and resolve it here so that in the
3592  // future we can change the AST to only refer to VariableProxies
3593  // instead of Variables and Proxis as is the case now.
3594  Variable* fvar = NULL;
3595  Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
3596  if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
3597  if (allow_harmony_scoping() && strict_mode() == STRICT) {
3598  fvar_init_op = Token::INIT_CONST;
3599  }
3600  VariableMode fvar_mode =
3602  ? CONST : CONST_LEGACY;
3603  DCHECK(function_name != NULL);
3604  fvar = new (zone())
3605  Variable(scope_, function_name, fvar_mode, true /* is valid LHS */,
3608  VariableProxy* proxy = factory()->NewVariableProxy(fvar);
3609  VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
3610  proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
3611  scope_->DeclareFunctionVar(fvar_declaration);
3612  }
3613 
3614  // Determine if the function can be parsed lazily. Lazy parsing is different
3615  // from lazy compilation; we need to parse more eagerly than we compile.
3616 
3617  // We can only parse lazily if we also compile lazily. The heuristics for
3618  // lazy compilation are:
3619  // - It must not have been prohibited by the caller to Parse (some callers
3620  // need a full AST).
3621  // - The outer scope must allow lazy compilation of inner functions.
3622  // - The function mustn't be a function expression with an open parenthesis
3623  // before; we consider that a hint that the function will be called
3624  // immediately, and it would be a waste of time to make it lazily
3625  // compiled.
3626  // These are all things we can know at this point, without looking at the
3627  // function itself.
3628 
3629  // In addition, we need to distinguish between these cases:
3630  // (function foo() {
3631  // bar = function() { return 1; }
3632  // })();
3633  // and
3634  // (function foo() {
3635  // var a = 1;
3636  // bar = function() { return a; }
3637  // })();
3638 
3639  // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
3640  // parenthesis before the function means that it will be called
3641  // immediately). The inner function *must* be parsed eagerly to resolve the
3642  // possible reference to the variable in foo's scope. However, it's possible
3643  // that it will be compiled lazily.
3644 
3645  // To make this additional case work, both Parser and PreParser implement a
3646  // logic where only top-level functions will be parsed lazily.
3647  bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
3648  scope_->AllowsLazyCompilation() &&
3650  parenthesized_function_ = false; // The bit was set for this function only.
3651 
3652  if (is_lazily_parsed) {
3653  SkipLazyFunctionBody(function_name, &materialized_literal_count,
3654  &expected_property_count, CHECK_OK);
3655  } else {
3656  body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
3658  materialized_literal_count = function_state.materialized_literal_count();
3659  expected_property_count = function_state.expected_property_count();
3660  handler_count = function_state.handler_count();
3661  }
3662 
3663  // Validate strict mode.
3664  // Concise methods use StrictFormalParameters.
3665  if (strict_mode() == STRICT || IsConciseMethod(kind)) {
3667  name_is_strict_reserved,
3668  function_name_location,
3669  eval_args_error_log,
3670  dupe_error_loc,
3671  reserved_loc,
3672  CHECK_OK);
3673  }
3674  if (strict_mode() == STRICT) {
3676  scope->end_position(),
3677  CHECK_OK);
3678  }
3679  ast_properties = *factory()->visitor()->ast_properties();
3680  dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
3681 
3682  if (allow_harmony_scoping() && strict_mode() == STRICT) {
3684  }
3685  }
3686 
3687  FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
3688  function_name, ast_value_factory(), scope, body,
3689  materialized_literal_count, expected_property_count, handler_count,
3690  num_parameters, duplicate_parameters, function_type,
3691  FunctionLiteral::kIsFunction, parenthesized, kind, pos);
3692  function_literal->set_function_token_position(function_token_pos);
3693  function_literal->set_ast_properties(&ast_properties);
3694  function_literal->set_dont_optimize_reason(dont_optimize_reason);
3695 
3696  if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
3697  return function_literal;
3698 }
3699 
3700 
3701 void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
3702  int* materialized_literal_count,
3703  int* expected_property_count,
3704  bool* ok) {
3705  int function_block_pos = position();
3707  // If we have cached data, we use it to skip parsing the function body. The
3708  // data contains the information we need to construct the lazy function.
3709  FunctionEntry entry =
3710  cached_parse_data_->GetFunctionEntry(function_block_pos);
3711  // Check that cached data is valid.
3712  CHECK(entry.is_valid());
3713  // End position greater than end of stream is safe, and hard to check.
3714  CHECK(entry.end_pos() > function_block_pos);
3715  scanner()->SeekForward(entry.end_pos() - 1);
3716 
3717  scope_->set_end_position(entry.end_pos());
3718  Expect(Token::RBRACE, ok);
3719  if (!*ok) {
3720  return;
3721  }
3722  total_preparse_skipped_ += scope_->end_position() - function_block_pos;
3723  *materialized_literal_count = entry.literal_count();
3724  *expected_property_count = entry.property_count();
3725  scope_->SetStrictMode(entry.strict_mode());
3726  } else {
3727  // With no cached data, we partially parse the function, without building an
3728  // AST. This gathers the data needed to build a lazy function.
3729  SingletonLogger logger;
3730  PreParser::PreParseResult result =
3732  if (result == PreParser::kPreParseStackOverflow) {
3733  // Propagate stack overflow.
3735  *ok = false;
3736  return;
3737  }
3738  if (logger.has_error()) {
3740  Scanner::Location(logger.start(), logger.end()),
3741  logger.message(), logger.argument_opt(), logger.is_reference_error());
3742  *ok = false;
3743  return;
3744  }
3745  scope_->set_end_position(logger.end());
3746  Expect(Token::RBRACE, ok);
3747  if (!*ok) {
3748  return;
3749  }
3750  total_preparse_skipped_ += scope_->end_position() - function_block_pos;
3751  *materialized_literal_count = logger.literals();
3752  *expected_property_count = logger.properties();
3753  scope_->SetStrictMode(logger.strict_mode());
3755  DCHECK(log_);
3756  // Position right after terminal '}'.
3757  int body_end = scanner()->location().end_pos;
3758  log_->LogFunction(function_block_pos, body_end,
3759  *materialized_literal_count,
3760  *expected_property_count,
3761  scope_->strict_mode());
3762  }
3763  }
3764 }
3765 
3766 
3768  const AstRawString* function_name, int pos, Variable* fvar,
3769  Token::Value fvar_init_op, bool is_generator, bool* ok) {
3770  // Everything inside an eagerly parsed function will be parsed eagerly
3771  // (see comment above).
3772  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3773  ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone());
3774  if (fvar != NULL) {
3775  VariableProxy* fproxy = scope_->NewUnresolved(
3776  factory(), function_name, Interface::NewConst());
3777  fproxy->BindTo(fvar);
3778  body->Add(factory()->NewExpressionStatement(
3779  factory()->NewAssignment(fvar_init_op,
3780  fproxy,
3781  factory()->NewThisFunction(pos),
3784  }
3785 
3786  // For generators, allocate and yield an iterator on function entry.
3787  if (is_generator) {
3788  ZoneList<Expression*>* arguments =
3789  new(zone()) ZoneList<Expression*>(0, zone());
3790  CallRuntime* allocation = factory()->NewCallRuntime(
3791  ast_value_factory()->empty_string(),
3792  Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject), arguments,
3793  pos);
3794  VariableProxy* init_proxy = factory()->NewVariableProxy(
3795  function_state_->generator_object_variable());
3796  Assignment* assignment = factory()->NewAssignment(
3797  Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
3798  VariableProxy* get_proxy = factory()->NewVariableProxy(
3799  function_state_->generator_object_variable());
3800  Yield* yield = factory()->NewYield(
3801  get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
3802  body->Add(factory()->NewExpressionStatement(
3803  yield, RelocInfo::kNoPosition), zone());
3804  }
3805 
3806  ParseSourceElements(body, Token::RBRACE, false, false, NULL, CHECK_OK);
3807 
3808  if (is_generator) {
3809  VariableProxy* get_proxy = factory()->NewVariableProxy(
3810  function_state_->generator_object_variable());
3811  Expression* undefined =
3812  factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
3813  Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal,
3815  body->Add(factory()->NewExpressionStatement(
3816  yield, RelocInfo::kNoPosition), zone());
3817  }
3818 
3819  Expect(Token::RBRACE, CHECK_OK);
3820  scope_->set_end_position(scanner()->location().end_pos);
3821 
3822  return body;
3823 }
3824 
3825 
3827  SingletonLogger* logger) {
3828  // This function may be called on a background thread too; record only the
3829  // main thread preparse times.
3830  if (pre_parse_timer_ != NULL) {
3832  }
3833  DCHECK_EQ(Token::LBRACE, scanner()->current_token());
3834 
3835  if (reusable_preparser_ == NULL) {
3847  }
3848  PreParser::PreParseResult result =
3850  is_generator(),
3851  logger);
3852  if (pre_parse_timer_ != NULL) {
3854  }
3855  return result;
3856 }
3857 
3858 
3860  // CallRuntime ::
3861  // '%' Identifier Arguments
3862 
3863  int pos = peek_position();
3864  Expect(Token::MOD, CHECK_OK);
3865  // Allow "eval" or "arguments" for backward compatibility.
3868 
3869  if (extension_ != NULL) {
3870  // The extension structures are only accessible while parsing the
3871  // very first time not when reparsing because of lazy compilation.
3872  scope_->DeclarationScope()->ForceEagerCompilation();
3873  }
3874 
3875  const Runtime::Function* function = Runtime::FunctionForName(name->string());
3876 
3877  // Check for built-in IS_VAR macro.
3878  if (function != NULL &&
3879  function->intrinsic_type == Runtime::RUNTIME &&
3880  function->function_id == Runtime::kIS_VAR) {
3881  // %IS_VAR(x) evaluates to x if x is a variable,
3882  // leads to a parse error otherwise. Could be implemented as an
3883  // inline function %_IS_VAR(x) to eliminate this special case.
3884  if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3885  return args->at(0);
3886  } else {
3887  ReportMessage("not_isvar");
3888  *ok = false;
3889  return NULL;
3890  }
3891  }
3892 
3893  // Check that the expected number of arguments are being passed.
3894  if (function != NULL &&
3895  function->nargs != -1 &&
3896  function->nargs != args->length()) {
3897  ReportMessage("illegal_access");
3898  *ok = false;
3899  return NULL;
3900  }
3901 
3902  // Check that the function is defined if it's an inline runtime call.
3903  if (function == NULL && name->FirstCharacter() == '_') {
3904  ParserTraits::ReportMessage("not_defined", name);
3905  *ok = false;
3906  return NULL;
3907  }
3908 
3909  // We have a valid intrinsics call or a call to a builtin.
3910  return factory()->NewCallRuntime(name, function, args, pos);
3911 }
3912 
3913 
3915  return factory()->NewUndefinedLiteral(position);
3916 }
3917 
3918 
3921  if (decl != NULL) {
3922  // In harmony mode we treat conflicting variable bindinds as early
3923  // errors. See ES5 16 for a definition of early errors.
3924  const AstRawString* name = decl->proxy()->raw_name();
3925  int position = decl->proxy()->position();
3929  ParserTraits::ReportMessageAt(location, "var_redeclaration", name);
3930  *ok = false;
3931  }
3932 }
3933 
3934 
3935 // ----------------------------------------------------------------------------
3936 // Parser support
3937 
3938 
3940  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3941  BreakableStatement* stat = t->node()->AsBreakableStatement();
3942  if (stat != NULL && ContainsLabel(stat->labels(), label))
3943  return true;
3944  }
3945  return false;
3946 }
3947 
3948 
3950  bool* ok) {
3951  bool anonymous = label == NULL;
3952  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3953  BreakableStatement* stat = t->node()->AsBreakableStatement();
3954  if (stat == NULL) continue;
3955  if ((anonymous && stat->is_target_for_anonymous()) ||
3956  (!anonymous && ContainsLabel(stat->labels(), label))) {
3957  RegisterTargetUse(stat->break_target(), t->previous());
3958  return stat;
3959  }
3960  }
3961  return NULL;
3962 }
3963 
3964 
3966  bool* ok) {
3967  bool anonymous = label == NULL;
3968  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3969  IterationStatement* stat = t->node()->AsIterationStatement();
3970  if (stat == NULL) continue;
3971 
3973  if (anonymous || ContainsLabel(stat->labels(), label)) {
3974  RegisterTargetUse(stat->continue_target(), t->previous());
3975  return stat;
3976  }
3977  }
3978  return NULL;
3979 }
3980 
3981 
3982 void Parser::RegisterTargetUse(Label* target, Target* stop) {
3983  // Register that a break target found at the given stop in the
3984  // target stack has been used from the top of the target stack. Add
3985  // the break target to any TargetCollectors passed on the stack.
3986  for (Target* t = target_stack_; t != stop; t = t->previous()) {
3987  TargetCollector* collector = t->node()->AsTargetCollector();
3988  if (collector != NULL) collector->AddTarget(target, zone());
3989  }
3990 }
3991 
3992 
3994  if (scanner_.source_url()->length() > 0) {
3996  info_->script()->set_source_url(*source_url);
3997  }
3998  if (scanner_.source_mapping_url()->length() > 0) {
3999  Handle<String> source_mapping_url =
4001  info_->script()->set_source_mapping_url(*source_mapping_url);
4002  }
4003 }
4004 
4005 
4007  DCHECK(ast_value_factory()->IsInternalized());
4008  if (has_pending_error_) {
4011  Factory* factory = isolate()->factory();
4012  bool has_arg =
4014  Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
4015  if (pending_error_arg_ != NULL) {
4016  Handle<String> arg_string = pending_error_arg_->string();
4017  elements->set(0, *arg_string);
4018  } else if (pending_error_char_arg_ != NULL) {
4019  Handle<String> arg_string =
4020  factory->NewStringFromUtf8(CStrVector(pending_error_char_arg_))
4021  .ToHandleChecked();
4022  elements->set(0, *arg_string);
4023  }
4025 
4026  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
4027  Handle<Object> error;
4028  MaybeHandle<Object> maybe_error =
4030  ? factory->NewReferenceError(pending_error_message_, array)
4031  : factory->NewSyntaxError(pending_error_message_, array);
4032  if (maybe_error.ToHandle(&error)) isolate()->Throw(*error, &location);
4033  }
4034 }
4035 
4036 
4038  // Internalize strings.
4040 
4041  // Error processing.
4042  if (info()->function() == NULL) {
4043  if (stack_overflow()) {
4044  isolate()->StackOverflow();
4045  } else {
4047  }
4048  }
4049 
4050  // Move statistics to Isolate.
4051  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
4052  ++feature) {
4053  for (int i = 0; i < use_counts_[feature]; ++i) {
4055  }
4056  }
4057  isolate()->counters()->total_preparse_skipped()->Increment(
4059 }
4060 
4061 
4062 // ----------------------------------------------------------------------------
4063 // Regular expressions
4064 
4065 
4066 RegExpParser::RegExpParser(FlatStringReader* in,
4067  Handle<String>* error,
4068  bool multiline,
4069  Zone* zone)
4070  : isolate_(zone->isolate()),
4071  zone_(zone),
4072  error_(error),
4073  captures_(NULL),
4074  in_(in),
4075  current_(kEndMarker),
4076  next_pos_(0),
4077  capture_count_(0),
4078  has_more_(true),
4079  multiline_(multiline),
4080  simple_(false),
4081  contains_anchor_(false),
4082  is_scanned_for_captures_(false),
4083  failed_(false) {
4084  Advance();
4085 }
4086 
4087 
4088 uc32 RegExpParser::Next() {
4089  if (has_next()) {
4090  return in()->Get(next_pos_);
4091  } else {
4092  return kEndMarker;
4093  }
4094 }
4095 
4096 
4097 void RegExpParser::Advance() {
4098  if (next_pos_ < in()->length()) {
4099  StackLimitCheck check(isolate());
4100  if (check.HasOverflowed()) {
4102  } else if (zone()->excess_allocation()) {
4103  ReportError(CStrVector("Regular expression too large"));
4104  } else {
4105  current_ = in()->Get(next_pos_);
4106  next_pos_++;
4107  }
4108  } else {
4109  current_ = kEndMarker;
4110  has_more_ = false;
4111  }
4112 }
4113 
4114 
4115 void RegExpParser::Reset(int pos) {
4116  next_pos_ = pos;
4117  has_more_ = (pos < in()->length());
4118  Advance();
4119 }
4120 
4121 
4122 void RegExpParser::Advance(int dist) {
4123  next_pos_ += dist - 1;
4124  Advance();
4125 }
4126 
4127 
4128 bool RegExpParser::simple() {
4129  return simple_;
4130 }
4131 
4132 
4133 RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4134  failed_ = true;
4135  *error_ = isolate()->factory()->NewStringFromAscii(message).ToHandleChecked();
4136  // Zip to the end to make sure the no more input is read.
4137  current_ = kEndMarker;
4138  next_pos_ = in()->length();
4139  return NULL;
4140 }
4141 
4142 
4143 // Pattern ::
4144 // Disjunction
4145 RegExpTree* RegExpParser::ParsePattern() {
4146  RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4147  DCHECK(!has_more());
4148  // If the result of parsing is a literal string atom, and it has the
4149  // same length as the input, then the atom is identical to the input.
4150  if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
4151  simple_ = true;
4152  }
4153  return result;
4154 }
4155 
4156 
4157 // Disjunction ::
4158 // Alternative
4159 // Alternative | Disjunction
4160 // Alternative ::
4161 // [empty]
4162 // Term Alternative
4163 // Term ::
4164 // Assertion
4165 // Atom
4166 // Atom Quantifier
4167 RegExpTree* RegExpParser::ParseDisjunction() {
4168  // Used to store current state while parsing subexpressions.
4169  RegExpParserState initial_state(NULL, INITIAL, 0, zone());
4170  RegExpParserState* stored_state = &initial_state;
4171  // Cache the builder in a local variable for quick access.
4172  RegExpBuilder* builder = initial_state.builder();
4173  while (true) {
4174  switch (current()) {
4175  case kEndMarker:
4176  if (stored_state->IsSubexpression()) {
4177  // Inside a parenthesized group when hitting end of input.
4178  ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4179  }
4180  DCHECK_EQ(INITIAL, stored_state->group_type());
4181  // Parsing completed successfully.
4182  return builder->ToRegExp();
4183  case ')': {
4184  if (!stored_state->IsSubexpression()) {
4185  ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
4186  }
4187  DCHECK_NE(INITIAL, stored_state->group_type());
4188 
4189  Advance();
4190  // End disjunction parsing and convert builder content to new single
4191  // regexp atom.
4192  RegExpTree* body = builder->ToRegExp();
4193 
4194  int end_capture_index = captures_started();
4195 
4196  int capture_index = stored_state->capture_index();
4197  SubexpressionType group_type = stored_state->group_type();
4198 
4199  // Restore previous state.
4200  stored_state = stored_state->previous_state();
4201  builder = stored_state->builder();
4202 
4203  // Build result of subexpression.
4204  if (group_type == CAPTURE) {
4205  RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
4206  captures_->at(capture_index - 1) = capture;
4207  body = capture;
4208  } else if (group_type != GROUPING) {
4209  DCHECK(group_type == POSITIVE_LOOKAHEAD ||
4210  group_type == NEGATIVE_LOOKAHEAD);
4211  bool is_positive = (group_type == POSITIVE_LOOKAHEAD);
4212  body = new(zone()) RegExpLookahead(body,
4213  is_positive,
4214  end_capture_index - capture_index,
4215  capture_index);
4216  }
4217  builder->AddAtom(body);
4218  // For compatability with JSC and ES3, we allow quantifiers after
4219  // lookaheads, and break in all cases.
4220  break;
4221  }
4222  case '|': {
4223  Advance();
4224  builder->NewAlternative();
4225  continue;
4226  }
4227  case '*':
4228  case '+':
4229  case '?':
4230  return ReportError(CStrVector("Nothing to repeat"));
4231  case '^': {
4232  Advance();
4233  if (multiline_) {
4234  builder->AddAssertion(
4235  new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
4236  } else {
4237  builder->AddAssertion(
4238  new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
4239  set_contains_anchor();
4240  }
4241  continue;
4242  }
4243  case '$': {
4244  Advance();
4245  RegExpAssertion::AssertionType assertion_type =
4246  multiline_ ? RegExpAssertion::END_OF_LINE :
4247  RegExpAssertion::END_OF_INPUT;
4248  builder->AddAssertion(new(zone()) RegExpAssertion(assertion_type));
4249  continue;
4250  }
4251  case '.': {
4252  Advance();
4253  // everything except \x0a, \x0d, \u2028 and \u2029
4254  ZoneList<CharacterRange>* ranges =
4255  new(zone()) ZoneList<CharacterRange>(2, zone());
4256  CharacterRange::AddClassEscape('.', ranges, zone());
4257  RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
4258  builder->AddAtom(atom);
4259  break;
4260  }
4261  case '(': {
4262  SubexpressionType subexpr_type = CAPTURE;
4263  Advance();
4264  if (current() == '?') {
4265  switch (Next()) {
4266  case ':':
4267  subexpr_type = GROUPING;
4268  break;
4269  case '=':
4270  subexpr_type = POSITIVE_LOOKAHEAD;
4271  break;
4272  case '!':
4273  subexpr_type = NEGATIVE_LOOKAHEAD;
4274  break;
4275  default:
4276  ReportError(CStrVector("Invalid group") CHECK_FAILED);
4277  break;
4278  }
4279  Advance(2);
4280  } else {
4281  if (captures_ == NULL) {
4282  captures_ = new(zone()) ZoneList<RegExpCapture*>(2, zone());
4283  }
4284  if (captures_started() >= kMaxCaptures) {
4285  ReportError(CStrVector("Too many captures") CHECK_FAILED);
4286  }
4287  captures_->Add(NULL, zone());
4288  }
4289  // Store current state and begin new disjunction parsing.
4290  stored_state = new(zone()) RegExpParserState(stored_state, subexpr_type,
4291  captures_started(), zone());
4292  builder = stored_state->builder();
4293  continue;
4294  }
4295  case '[': {
4296  RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
4297  builder->AddAtom(atom);
4298  break;
4299  }
4300  // Atom ::
4301  // \ AtomEscape
4302  case '\\':
4303  switch (Next()) {
4304  case kEndMarker:
4305  return ReportError(CStrVector("\\ at end of pattern"));
4306  case 'b':
4307  Advance(2);
4308  builder->AddAssertion(
4309  new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
4310  continue;
4311  case 'B':
4312  Advance(2);
4313  builder->AddAssertion(
4314  new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
4315  continue;
4316  // AtomEscape ::
4317  // CharacterClassEscape
4318  //
4319  // CharacterClassEscape :: one of
4320  // d D s S w W
4321  case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4322  uc32 c = Next();
4323  Advance(2);
4324  ZoneList<CharacterRange>* ranges =
4325  new(zone()) ZoneList<CharacterRange>(2, zone());
4326  CharacterRange::AddClassEscape(c, ranges, zone());
4327  RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
4328  builder->AddAtom(atom);
4329  break;
4330  }
4331  case '1': case '2': case '3': case '4': case '5': case '6':
4332  case '7': case '8': case '9': {
4333  int index = 0;
4334  if (ParseBackReferenceIndex(&index)) {
4335  RegExpCapture* capture = NULL;
4336  if (captures_ != NULL && index <= captures_->length()) {
4337  capture = captures_->at(index - 1);
4338  }
4339  if (capture == NULL) {
4340  builder->AddEmpty();
4341  break;
4342  }
4343  RegExpTree* atom = new(zone()) RegExpBackReference(capture);
4344  builder->AddAtom(atom);
4345  break;
4346  }
4347  uc32 first_digit = Next();
4348  if (first_digit == '8' || first_digit == '9') {
4349  // Treat as identity escape
4350  builder->AddCharacter(first_digit);
4351  Advance(2);
4352  break;
4353  }
4354  }
4355  // FALLTHROUGH
4356  case '0': {
4357  Advance();
4358  uc32 octal = ParseOctalLiteral();
4359  builder->AddCharacter(octal);
4360  break;
4361  }
4362  // ControlEscape :: one of
4363  // f n r t v
4364  case 'f':
4365  Advance(2);
4366  builder->AddCharacter('\f');
4367  break;
4368  case 'n':
4369  Advance(2);
4370  builder->AddCharacter('\n');
4371  break;
4372  case 'r':
4373  Advance(2);
4374  builder->AddCharacter('\r');
4375  break;
4376  case 't':
4377  Advance(2);
4378  builder->AddCharacter('\t');
4379  break;
4380  case 'v':
4381  Advance(2);
4382  builder->AddCharacter('\v');
4383  break;
4384  case 'c': {
4385  Advance();
4386  uc32 controlLetter = Next();
4387  // Special case if it is an ASCII letter.
4388  // Convert lower case letters to uppercase.
4389  uc32 letter = controlLetter & ~('a' ^ 'A');
4390  if (letter < 'A' || 'Z' < letter) {
4391  // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4392  // This is outside the specification. We match JSC in
4393  // reading the backslash as a literal character instead
4394  // of as starting an escape.
4395  builder->AddCharacter('\\');
4396  } else {
4397  Advance(2);
4398  builder->AddCharacter(controlLetter & 0x1f);
4399  }
4400  break;
4401  }
4402  case 'x': {
4403  Advance(2);
4404  uc32 value;
4405  if (ParseHexEscape(2, &value)) {
4406  builder->AddCharacter(value);
4407  } else {
4408  builder->AddCharacter('x');
4409  }
4410  break;
4411  }
4412  case 'u': {
4413  Advance(2);
4414  uc32 value;
4415  if (ParseHexEscape(4, &value)) {
4416  builder->AddCharacter(value);
4417  } else {
4418  builder->AddCharacter('u');
4419  }
4420  break;
4421  }
4422  default:
4423  // Identity escape.
4424  builder->AddCharacter(Next());
4425  Advance(2);
4426  break;
4427  }
4428  break;
4429  case '{': {
4430  int dummy;
4431  if (ParseIntervalQuantifier(&dummy, &dummy)) {
4432  ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4433  }
4434  // fallthrough
4435  }
4436  default:
4437  builder->AddCharacter(current());
4438  Advance();
4439  break;
4440  } // end switch(current())
4441 
4442  int min;
4443  int max;
4444  switch (current()) {
4445  // QuantifierPrefix ::
4446  // *
4447  // +
4448  // ?
4449  // {
4450  case '*':
4451  min = 0;
4452  max = RegExpTree::kInfinity;
4453  Advance();
4454  break;
4455  case '+':
4456  min = 1;
4457  max = RegExpTree::kInfinity;
4458  Advance();
4459  break;
4460  case '?':
4461  min = 0;
4462  max = 1;
4463  Advance();
4464  break;
4465  case '{':
4466  if (ParseIntervalQuantifier(&min, &max)) {
4467  if (max < min) {
4468  ReportError(CStrVector("numbers out of order in {} quantifier.")
4469  CHECK_FAILED);
4470  }
4471  break;
4472  } else {
4473  continue;
4474  }
4475  default:
4476  continue;
4477  }
4478  RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY;
4479  if (current() == '?') {
4480  quantifier_type = RegExpQuantifier::NON_GREEDY;
4481  Advance();
4482  } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
4483  // FLAG_regexp_possessive_quantifier is a debug-only flag.
4484  quantifier_type = RegExpQuantifier::POSSESSIVE;
4485  Advance();
4486  }
4487  builder->AddQuantifierToAtom(min, max, quantifier_type);
4488  }
4489 }
4490 
4491 
4492 #ifdef DEBUG
4493 // Currently only used in an DCHECK.
4494 static bool IsSpecialClassEscape(uc32 c) {
4495  switch (c) {
4496  case 'd': case 'D':
4497  case 's': case 'S':
4498  case 'w': case 'W':
4499  return true;
4500  default:
4501  return false;
4502  }
4503 }
4504 #endif
4505 
4506 
4507 // In order to know whether an escape is a backreference or not we have to scan
4508 // the entire regexp and find the number of capturing parentheses. However we
4509 // don't want to scan the regexp twice unless it is necessary. This mini-parser
4510 // is called when needed. It can see the difference between capturing and
4511 // noncapturing parentheses and can skip character classes and backslash-escaped
4512 // characters.
4513 void RegExpParser::ScanForCaptures() {
4514  // Start with captures started previous to current position
4515  int capture_count = captures_started();
4516  // Add count of captures after this position.
4517  int n;
4518  while ((n = current()) != kEndMarker) {
4519  Advance();
4520  switch (n) {
4521  case '\\':
4522  Advance();
4523  break;
4524  case '[': {
4525  int c;
4526  while ((c = current()) != kEndMarker) {
4527  Advance();
4528  if (c == '\\') {
4529  Advance();
4530  } else {
4531  if (c == ']') break;
4532  }
4533  }
4534  break;
4535  }
4536  case '(':
4537  if (current() != '?') capture_count++;
4538  break;
4539  }
4540  }
4541  capture_count_ = capture_count;
4542  is_scanned_for_captures_ = true;
4543 }
4544 
4545 
4546 bool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4547  DCHECK_EQ('\\', current());
4548  DCHECK('1' <= Next() && Next() <= '9');
4549  // Try to parse a decimal literal that is no greater than the total number
4550  // of left capturing parentheses in the input.
4551  int start = position();
4552  int value = Next() - '0';
4553  Advance(2);
4554  while (true) {
4555  uc32 c = current();
4556  if (IsDecimalDigit(c)) {
4557  value = 10 * value + (c - '0');
4558  if (value > kMaxCaptures) {
4559  Reset(start);
4560  return false;
4561  }
4562  Advance();
4563  } else {
4564  break;
4565  }
4566  }
4567  if (value > captures_started()) {
4568  if (!is_scanned_for_captures_) {
4569  int saved_position = position();
4570  ScanForCaptures();
4571  Reset(saved_position);
4572  }
4573  if (value > capture_count_) {
4574  Reset(start);
4575  return false;
4576  }
4577  }
4578  *index_out = value;
4579  return true;
4580 }
4581 
4582 
4583 // QuantifierPrefix ::
4584 // { DecimalDigits }
4585 // { DecimalDigits , }
4586 // { DecimalDigits , DecimalDigits }
4587 //
4588 // Returns true if parsing succeeds, and set the min_out and max_out
4589 // values. Values are truncated to RegExpTree::kInfinity if they overflow.
4590 bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4591  DCHECK_EQ(current(), '{');
4592  int start = position();
4593  Advance();
4594  int min = 0;
4595  if (!IsDecimalDigit(current())) {
4596  Reset(start);
4597  return false;
4598  }
4599  while (IsDecimalDigit(current())) {
4600  int next = current() - '0';
4601  if (min > (RegExpTree::kInfinity - next) / 10) {
4602  // Overflow. Skip past remaining decimal digits and return -1.
4603  do {
4604  Advance();
4605  } while (IsDecimalDigit(current()));
4607  break;
4608  }
4609  min = 10 * min + next;
4610  Advance();
4611  }
4612  int max = 0;
4613  if (current() == '}') {
4614  max = min;
4615  Advance();
4616  } else if (current() == ',') {
4617  Advance();
4618  if (current() == '}') {
4619  max = RegExpTree::kInfinity;
4620  Advance();
4621  } else {
4622  while (IsDecimalDigit(current())) {
4623  int next = current() - '0';
4624  if (max > (RegExpTree::kInfinity - next) / 10) {
4625  do {
4626  Advance();
4627  } while (IsDecimalDigit(current()));
4628  max = RegExpTree::kInfinity;
4629  break;
4630  }
4631  max = 10 * max + next;
4632  Advance();
4633  }
4634  if (current() != '}') {
4635  Reset(start);
4636  return false;
4637  }
4638  Advance();
4639  }
4640  } else {
4641  Reset(start);
4642  return false;
4643  }
4644  *min_out = min;
4645  *max_out = max;
4646  return true;
4647 }
4648 
4649 
4650 uc32 RegExpParser::ParseOctalLiteral() {
4651  DCHECK(('0' <= current() && current() <= '7') || current() == kEndMarker);
4652  // For compatibility with some other browsers (not all), we parse
4653  // up to three octal digits with a value below 256.
4654  uc32 value = current() - '0';
4655  Advance();
4656  if ('0' <= current() && current() <= '7') {
4657  value = value * 8 + current() - '0';
4658  Advance();
4659  if (value < 32 && '0' <= current() && current() <= '7') {
4660  value = value * 8 + current() - '0';
4661  Advance();
4662  }
4663  }
4664  return value;
4665 }
4666 
4667 
4668 bool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4669  int start = position();
4670  uc32 val = 0;
4671  bool done = false;
4672  for (int i = 0; !done; i++) {
4673  uc32 c = current();
4674  int d = HexValue(c);
4675  if (d < 0) {
4676  Reset(start);
4677  return false;
4678  }
4679  val = val * 16 + d;
4680  Advance();
4681  if (i == length - 1) {
4682  done = true;
4683  }
4684  }
4685  *value = val;
4686  return true;
4687 }
4688 
4689 
4690 uc32 RegExpParser::ParseClassCharacterEscape() {
4691  DCHECK(current() == '\\');
4692  DCHECK(has_next() && !IsSpecialClassEscape(Next()));
4693  Advance();
4694  switch (current()) {
4695  case 'b':
4696  Advance();
4697  return '\b';
4698  // ControlEscape :: one of
4699  // f n r t v
4700  case 'f':
4701  Advance();
4702  return '\f';
4703  case 'n':
4704  Advance();
4705  return '\n';
4706  case 'r':
4707  Advance();
4708  return '\r';
4709  case 't':
4710  Advance();
4711  return '\t';
4712  case 'v':
4713  Advance();
4714  return '\v';
4715  case 'c': {
4716  uc32 controlLetter = Next();
4717  uc32 letter = controlLetter & ~('A' ^ 'a');
4718  // For compatibility with JSC, inside a character class
4719  // we also accept digits and underscore as control characters.
4720  if ((controlLetter >= '0' && controlLetter <= '9') ||
4721  controlLetter == '_' ||
4722  (letter >= 'A' && letter <= 'Z')) {
4723  Advance(2);
4724  // Control letters mapped to ASCII control characters in the range
4725  // 0x00-0x1f.
4726  return controlLetter & 0x1f;
4727  }
4728  // We match JSC in reading the backslash as a literal
4729  // character instead of as starting an escape.
4730  return '\\';
4731  }
4732  case '0': case '1': case '2': case '3': case '4': case '5':
4733  case '6': case '7':
4734  // For compatibility, we interpret a decimal escape that isn't
4735  // a back reference (and therefore either \0 or not valid according
4736  // to the specification) as a 1..3 digit octal character code.
4737  return ParseOctalLiteral();
4738  case 'x': {
4739  Advance();
4740  uc32 value;
4741  if (ParseHexEscape(2, &value)) {
4742  return value;
4743  }
4744  // If \x is not followed by a two-digit hexadecimal, treat it
4745  // as an identity escape.
4746  return 'x';
4747  }
4748  case 'u': {
4749  Advance();
4750  uc32 value;
4751  if (ParseHexEscape(4, &value)) {
4752  return value;
4753  }
4754  // If \u is not followed by a four-digit hexadecimal, treat it
4755  // as an identity escape.
4756  return 'u';
4757  }
4758  default: {
4759  // Extended identity escape. We accept any character that hasn't
4760  // been matched by a more specific case, not just the subset required
4761  // by the ECMAScript specification.
4762  uc32 result = current();
4763  Advance();
4764  return result;
4765  }
4766  }
4767  return 0;
4768 }
4769 
4770 
4771 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4772  DCHECK_EQ(0, *char_class);
4773  uc32 first = current();
4774  if (first == '\\') {
4775  switch (Next()) {
4776  case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4777  *char_class = Next();
4778  Advance(2);
4779  return CharacterRange::Singleton(0); // Return dummy value.
4780  }
4781  case kEndMarker:
4782  return ReportError(CStrVector("\\ at end of pattern"));
4783  default:
4784  uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4785  return CharacterRange::Singleton(c);
4786  }
4787  } else {
4788  Advance();
4789  return CharacterRange::Singleton(first);
4790  }
4791 }
4792 
4793 
4794 static const uc16 kNoCharClass = 0;
4795 
4796 // Adds range or pre-defined character class to character ranges.
4797 // If char_class is not kInvalidClass, it's interpreted as a class
4798 // escape (i.e., 's' means whitespace, from '\s').
4799 static inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
4800  uc16 char_class,
4801  CharacterRange range,
4802  Zone* zone) {
4803  if (char_class != kNoCharClass) {
4804  CharacterRange::AddClassEscape(char_class, ranges, zone);
4805  } else {
4806  ranges->Add(range, zone);
4807  }
4808 }
4809 
4810 
4811 RegExpTree* RegExpParser::ParseCharacterClass() {
4812  static const char* kUnterminated = "Unterminated character class";
4813  static const char* kRangeOutOfOrder = "Range out of order in character class";
4814 
4815  DCHECK_EQ(current(), '[');
4816  Advance();
4817  bool is_negated = false;
4818  if (current() == '^') {
4819  is_negated = true;
4820  Advance();
4821  }
4822  ZoneList<CharacterRange>* ranges =
4823  new(zone()) ZoneList<CharacterRange>(2, zone());
4824  while (has_more() && current() != ']') {
4825  uc16 char_class = kNoCharClass;
4826  CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
4827  if (current() == '-') {
4828  Advance();
4829  if (current() == kEndMarker) {
4830  // If we reach the end we break out of the loop and let the
4831  // following code report an error.
4832  break;
4833  } else if (current() == ']') {
4834  AddRangeOrEscape(ranges, char_class, first, zone());
4835  ranges->Add(CharacterRange::Singleton('-'), zone());
4836  break;
4837  }
4838  uc16 char_class_2 = kNoCharClass;
4839  CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
4840  if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
4841  // Either end is an escaped character class. Treat the '-' verbatim.
4842  AddRangeOrEscape(ranges, char_class, first, zone());
4843  ranges->Add(CharacterRange::Singleton('-'), zone());
4844  AddRangeOrEscape(ranges, char_class_2, next, zone());
4845  continue;
4846  }
4847  if (first.from() > next.to()) {
4848  return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4849  }
4850  ranges->Add(CharacterRange::Range(first.from(), next.to()), zone());
4851  } else {
4852  AddRangeOrEscape(ranges, char_class, first, zone());
4853  }
4854  }
4855  if (!has_more()) {
4856  return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4857  }
4858  Advance();
4859  if (ranges->length() == 0) {
4860  ranges->Add(CharacterRange::Everything(), zone());
4861  is_negated = !is_negated;
4862  }
4863  return new(zone()) RegExpCharacterClass(ranges, is_negated);
4864 }
4865 
4866 
4867 // ----------------------------------------------------------------------------
4868 // The Parser interface.
4869 
4870 bool RegExpParser::ParseRegExp(FlatStringReader* input,
4871  bool multiline,
4872  RegExpCompileData* result,
4873  Zone* zone) {
4874  DCHECK(result != NULL);
4875  RegExpParser parser(input, &result->error, multiline, zone);
4876  RegExpTree* tree = parser.ParsePattern();
4877  if (parser.failed()) {
4878  DCHECK(tree == NULL);
4879  DCHECK(!result->error.is_null());
4880  } else {
4881  DCHECK(tree != NULL);
4882  DCHECK(result->error.is_null());
4883  result->tree = tree;
4884  int capture_count = parser.captures_started();
4885  result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
4886  result->contains_anchor = parser.contains_anchor();
4887  result->capture_count = capture_count;
4888  }
4889  return !parser.failed();
4890 }
4891 
4892 
4894  DCHECK(info()->function() == NULL);
4895  FunctionLiteral* result = NULL;
4896  pre_parse_timer_ = isolate()->counters()->pre_parse();
4897  if (FLAG_trace_parse || allow_natives_syntax() || extension_ != NULL) {
4898  // If intrinsics are allowed, the Parser cannot operate independent of the
4899  // V8 heap because of Runtime. Tell the string table to internalize strings
4900  // and values right after they're created.
4902  }
4903 
4904  if (info()->is_lazy()) {
4905  DCHECK(!info()->is_eval());
4906  if (info()->shared_info()->is_function()) {
4907  result = ParseLazy();
4908  } else {
4909  result = ParseProgram();
4910  }
4911  } else {
4912  SetCachedData();
4913  result = ParseProgram();
4914  }
4915  info()->SetFunction(result);
4916 
4917  Internalize();
4918  DCHECK(ast_value_factory()->IsInternalized());
4919  return (result != NULL);
4920 }
4921 
4922 
4924  DCHECK(info()->function() == NULL);
4925  FunctionLiteral* result = NULL;
4927 
4928  CompleteParserRecorder recorder;
4930  log_ = &recorder;
4931  }
4932 
4933  DCHECK(info()->source_stream() != NULL);
4934  ExternalStreamingStream stream(info()->source_stream(),
4935  info()->source_stream_encoding());
4936  scanner_.Initialize(&stream);
4937  DCHECK(info()->context().is_null() || info()->context()->IsNativeContext());
4938 
4939  // When streaming, we don't know the length of the source until we have parsed
4940  // it. The raw data can be UTF-8, so we wouldn't know the source length until
4941  // we have decoded it anyway even if we knew the raw data length (which we
4942  // don't). We work around this by storing all the scopes which need their end
4943  // position set at the end of the script (the top scope and possible eval
4944  // scopes) and set their end position after we know the script length.
4945  Scope* top_scope = NULL;
4946  Scope* eval_scope = NULL;
4947  result = DoParseProgram(info(), &top_scope, &eval_scope);
4948 
4949  top_scope->set_end_position(scanner()->location().end_pos);
4950  if (eval_scope != NULL) {
4951  eval_scope->set_end_position(scanner()->location().end_pos);
4952  }
4953 
4954  info()->SetFunction(result);
4955 
4956  // We cannot internalize on a background thread; a foreground task will take
4957  // care of calling Parser::Internalize just before compilation.
4958 
4960  if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
4961  log_ = NULL;
4962  }
4963 }
4964 } } // namespace v8::internal
UseCounterFeature
Features reported via the SetUseCounterCallback callback.
Definition: v8.h:4486
@ kUseCounterFeatureCount
Definition: v8.h:4488
@ kUseAsm
Definition: v8.h:4487
@ kProduceParserCache
Definition: v8.h:1161
@ kConsumeParserCache
Definition: v8.h:1162
@ kNoCompileOptions
Definition: v8.h:1160
virtual MaterializedLiteral * AsMaterializedLiteral()
Definition: ast.h:235
int position() const
Definition: ast.h:218
const unsigned char * raw_data() const
virtual int length() const OVERRIDE
Handle< String > string() const
void Internalize(Isolate *isolate)
const AstRawString * GetOneByteString(Vector< const uint8_t > literal)
const AstRawString * GetString(Handle< String > literal)
Target(Target **variable, AstNode *node)
Definition: parser.cc:286
TargetScope(Target **variable)
Definition: parser.cc:307
ZoneList< const AstRawString * > * labels() const
Definition: ast.h:410
virtual BreakableStatement * AsBreakableStatement() FINAL OVERRIDE
Definition: ast.h:413
bool is_target_for_anonymous() const
Definition: ast.h:421
static CharacterRange Range(uc16 from, uc16 to)
Definition: jsregexp.h:251
static CharacterRange Singleton(uc16 value)
Definition: jsregexp.h:248
static CharacterRange Everything()
Definition: jsregexp.h:255
static void AddClassEscape(uc16 type, ZoneList< CharacterRange > *ranges, Zone *zone)
Definition: jsregexp.cc:5233
static const int kMaxArguments
Definition: objects.h:5445
AstNode::IdGen * ast_node_id_gen()
Definition: compiler.h:395
ScriptCompiler::ExternalSourceStream * source_stream() const
Definition: compiler.h:121
ScriptData ** cached_data() const
Definition: compiler.h:117
Handle< Script > script() const
Definition: compiler.h:113
void SetGlobalScope(Scope *global_scope)
Definition: compiler.h:235
Handle< Context > context() const
Definition: compiler.h:127
void SetFunction(FunctionLiteral *literal)
Definition: compiler.h:230
AstValueFactory * ast_value_factory() const
Definition: compiler.h:388
void SetAstValueFactory(AstValueFactory *ast_value_factory, bool owned=true)
Definition: compiler.h:389
StrictMode strict_mode() const
Definition: compiler.h:104
ParseRestriction parse_restriction() const
Definition: compiler.h:225
Handle< SharedFunctionInfo > shared_info() const
Definition: compiler.h:112
static Handle< FixedArray > GetElements(Handle< FixedArray > value)
Definition: parser.cc:3369
static LiteralType GetLiteralType(Handle< FixedArray > value)
Definition: parser.cc:3362
static bool IsCompileTimeValue(Expression *expression)
Definition: parser.cc:3331
static Handle< FixedArray > GetValue(Isolate *isolate, Expression *expression)
Definition: parser.cc:3338
void OnCompileError(Handle< Script > script)
Definition: debug.cc:2562
VariableMode mode() const
Definition: ast.h:490
virtual InitializationFlag initialization() const =0
VariableProxy * proxy() const
Definition: ast.h:489
virtual bool IsPropertyName() const
Definition: ast.h:334
unsigned parenthesization_level() const
Definition: ast.h:357
void Initialize(Expression *each, Expression *subject, Statement *body)
Definition: ast.h:896
void PushVariableName(const AstRawString *name)
void AddFunction(FunctionLiteral *func_to_infer)
void PushEnclosingName(const AstRawString *name)
void PushLiteralName(const AstRawString *name)
void Add(const AstRawString *name, Interface *interface, Zone *zone, bool *ok)
Definition: interface.h:63
static Interface * NewValue()
Definition: interface.h:44
static Interface * NewUnknown(Zone *zone)
Definition: interface.h:40
static Interface * NewModule(Zone *zone)
Definition: interface.h:54
static Interface * NewConst()
Definition: interface.h:49
void CountUsage(v8::Isolate::UseCounterFeature feature)
Definition: isolate.cc:2358
static const char *const kStackOverflowMessage
Definition: isolate.h:820
Object * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:832
Counters * counters()
Definition: isolate.h:857
Object * StackOverflow()
Definition: isolate.cc:773
Factory * factory()
Definition: isolate.h:982
virtual IterationStatement * AsIterationStatement() FINAL OVERRIDE
Definition: ast.h:728
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
T & at(int i) const
Definition: list.h:69
Vector< const T > ToConstVector()
Definition: list.h:83
Handle< String > Internalize(Isolate *isolate) const
Definition: scanner.cc:23
Block * body() const
Definition: ast.h:630
Interface * interface() const
Definition: ast.h:629
unsigned Version()
Definition: parser.cc:247
unsigned * Data()
Definition: parser.h:75
FunctionEntry GetFunctionEntry(int start)
Definition: parser.cc:186
int Length() const
Definition: parser.h:84
IdentifierT ParseIdentifierName(bool *ok)
Definition: preparser.h:1684
ExpressionT ParseClassLiteral(IdentifierT name, Scanner::Location function_name_location, bool name_is_strict_reserved, int pos, bool *ok)
Definition: preparser.h:2721
bool Check(Token::Value token)
Definition: preparser.h:319
IdentifierT ParseIdentifierOrStrictReservedWord(bool *is_strict_reserved, bool *ok)
Definition: preparser.h:1664
Traits::Type::Zone * zone() const
Definition: preparser.h:291
void Expect(Token::Value token, bool *ok)
Definition: preparser.h:328
AstNode::IdGen * ast_node_id_gen() const
Definition: preparser.h:292
FuncNameInferrer * fni_
Definition: preparser.h:580
AstNode::IdGen * ast_node_id_gen_
Definition: preparser.h:595
void ReportMessageAt(Scanner::Location location, const char *message, bool is_reference_error=false)
Definition: preparser.h:450
IdentifierT ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool *ok)
Definition: preparser.h:1637
Traits::Type::ExpressionList ParseArguments(bool *ok)
Definition: preparser.h:2106
void CheckOctalLiteral(int beg_pos, int end_pos, bool *ok)
Definition: preparser.h:381
bool CheckContextualKeyword(Vector< const char > keyword)
Definition: preparser.h:361
void set_allow_harmony_numeric_literals(bool allow)
Definition: preparser.h:117
void set_allow_harmony_object_literals(bool allow)
Definition: preparser.h:121
ExpressionT ParseAssignmentExpression(bool accept_IN, bool *ok)
Definition: preparser.h:2137
bool stack_overflow() const
Definition: preparser.h:288
ExpressionT CheckAndRewriteReferenceExpression(ExpressionT expression, Scanner::Location location, const char *message, bool *ok)
Definition: preparser.h:2782
void ReportMessage(const char *message, const char *arg=NULL, bool is_reference_error=false)
Definition: preparser.h:444
ExpressionT ParseExpression(bool accept_IN, bool *ok)
Definition: preparser.h:1870
Scanner * scanner() const
Definition: preparser.h:285
void CheckStrictFunctionNameAndParameters(IdentifierT function_name, bool function_name_is_strict_reserved, const Scanner::Location &function_name_loc, const Scanner::Location &eval_args_error_loc, const Scanner::Location &dupe_error_loc, const Scanner::Location &reserved_loc, bool *ok)
Definition: preparser.h:394
void ExpectContextualKeyword(Vector< const char > keyword, bool *ok)
Definition: preparser.h:370
void Consume(Token::Value token)
Definition: preparser.h:312
Traits::Type::Factory * factory()
Definition: preparser.h:436
void ReportUnexpectedToken(Token::Value token)
Definition: preparser.h:1608
virtual void LogFunction(int start, int end, int literals, int properties, StrictMode strict_mode)=0
ParserBase< ParserTraits > * parser_
Definition: parser.cc:359
Checkpoint(ParserBase< ParserTraits > *parser)
Definition: parser.cc:348
static bool IsThisProperty(Expression *expression)
Definition: parser.cc:380
const AstRawString * GetSymbol(Scanner *scanner)
Definition: parser.cc:634
Expression * NewThrowReferenceError(const char *type, int pos)
Definition: parser.cc:538
static void CheckAssigningFunctionLiteralToProperty(Expression *left, Expression *right)
Definition: parser.cc:406
void ReportMessage(const char *message, const char *arg=NULL, bool is_reference_error=false)
Definition: parser.cc:599
Expression * ParseV8Intrinsic(bool *ok)
Definition: parser.cc:739
Expression * ExpressionFromString(int pos, Scanner *scanner, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:711
bool IsPrototype(const AstRawString *identifier) const
Definition: parser.cc:370
const AstRawString * GetNextSymbol(Scanner *scanner)
Definition: parser.cc:651
Expression * NewThrowSyntaxError(const char *type, const AstRawString *arg, int pos)
Definition: parser.cc:545
bool IsConstructor(const AstRawString *identifier) const
Definition: parser.cc:375
int DeclareArrowParametersFromExpression(Expression *expression, Scope *scope, Scanner::Location *dupe_loc, bool *ok)
Definition: parser.cc:3426
bool IsEvalOrArguments(const AstRawString *identifier) const
Definition: parser.cc:364
Expression * NewThrowError(const AstRawString *constructor, const char *type, const AstRawString *arg, int pos)
Definition: parser.cc:559
Expression * NewThrowTypeError(const char *type, const AstRawString *arg, int pos)
Definition: parser.cc:552
Expression * ThisExpression(Scope *scope, AstNodeFactory< AstConstructionVisitor > *factory, int pos=RelocInfo::kNoPosition)
Definition: parser.cc:656
void PushPropertyName(FuncNameInferrer *fni, Expression *expression)
Definition: parser.cc:395
void ReportMessageAt(Scanner::Location source_location, const char *message, const char *arg=NULL, bool is_reference_error=false)
Definition: parser.cc:580
AstValueFactory * ast_value_factory()
Definition: parser.h:895
Expression * ClassLiteral(const AstRawString *name, Expression *extends, Expression *constructor, ZoneList< ObjectLiteral::Property * > *properties, int pos, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:668
static Expression * MarkExpressionAsAssigned(Expression *expression)
Definition: parser.cc:426
Literal * ExpressionFromLiteral(Token::Value token, int pos, Scanner *scanner, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:675
Expression * ExpressionFromIdentifier(const AstRawString *name, int pos, Scope *scope, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:697
const AstRawString * GetNumberAsSymbol(Scanner *scanner)
Definition: parser.cc:642
Expression * BuildUnaryExpression(Expression *expression, Token::Value op, int pos, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:494
bool ShortcutNumericLiteralBinaryExpression(Expression **x, Expression *y, Token::Value op, int pos, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:434
void CheckPossibleEvalCall(Expression *expression, Scope *scope)
Definition: parser.cc:416
Expression * SuperReference(Scope *scope, AstNodeFactory< AstConstructionVisitor > *factory, int pos=RelocInfo::kNoPosition)
Definition: parser.cc:661
Expression * GetIterator(Expression *iterable, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:720
FunctionLiteral * ParseFunctionLiteral(const AstRawString *name, Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind, int function_token_position, FunctionLiteral::FunctionType type, FunctionLiteral::ArityRestriction arity_restriction, bool *ok)
Definition: parser.cc:744
Literal * GetLiteralTheHole(int position, AstNodeFactory< AstConstructionVisitor > *factory)
Definition: parser.cc:733
bool IsFutureStrictReserved(const AstRawString *identifier) const
Definition: parser.h:856
static bool IsIdentifier(Expression *expression)
Definition: parser.cc:389
CompilationInfo * info_
Definition: parser.h:838
ScriptCompiler::CompileOptions compile_options() const
Definition: parser.h:693
IterationStatement * LookupContinueTarget(const AstRawString *label, bool *ok)
Definition: parser.cc:3965
Statement * ParseExpressionOrLabelledStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:2400
Block * ParseScopedBlock(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:2022
Statement * ParseReturnStatement(bool *ok)
Definition: parser.cc:2552
Block * ParseBlock(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:1995
Scope * DeclarationScope(VariableMode mode)
Definition: parser.h:696
Statement * ParseBlockElement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:1553
Scope * NewScope(Scope *parent, ScopeType type)
Definition: parser.cc:269
bool TargetStackContainsLabel(const AstRawString *label)
Definition: parser.cc:3939
int use_counts_[v8::Isolate::kUseCounterFeatureCount]
Definition: parser.h:850
IfStatement * ParseIfStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:2463
FunctionLiteral * ParseFunctionLiteral(const AstRawString *name, Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind, int function_token_position, FunctionLiteral::FunctionType type, FunctionLiteral::ArityRestriction arity_restriction, bool *ok)
Definition: parser.cc:3436
Statement * ParseModuleElement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:1139
Statement * ParseContinueStatement(bool *ok)
Definition: parser.cc:2486
void RegisterTargetUse(Label *target, Target *stop)
Definition: parser.cc:3982
void CheckConflictingVarDeclarations(Scope *scope, bool *ok)
Definition: parser.cc:3919
Block * ParseImportDeclaration(bool *ok)
Definition: parser.cc:1406
Expression * ParseV8Intrinsic(bool *ok)
Definition: parser.cc:3859
Statement * ParseNativeDeclaration(bool *ok)
Definition: parser.cc:1878
Block * ParseVariableDeclarations(VariableDeclarationContext var_context, VariableDeclarationProperties *decl_props, ZoneList< const AstRawString * > *names, const AstRawString **out, bool *ok)
Definition: parser.cc:2076
SwitchStatement * ParseSwitchStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:2657
Statement * ParseExportDeclaration(bool *ok)
Definition: parser.cc:1460
WhileStatement * ParseWhileStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:2837
Module * ParseModulePath(bool *ok)
Definition: parser.cc:1310
void ThrowPendingError()
Definition: parser.cc:4006
Block * ParseVariableStatement(VariableDeclarationContext var_context, ZoneList< const AstRawString * > *names, bool *ok)
Definition: parser.cc:2057
BreakableStatement * LookupBreakTarget(const AstRawString *label, bool *ok)
Definition: parser.cc:3949
VariableProxy * NewUnresolved(const AstRawString *name, VariableMode mode, Interface *interface)
Definition: parser.cc:1705
Handle< Script > script() const
Definition: parser.h:681
void SetCachedData()
Definition: parser.cc:257
Target * target_stack_
Definition: parser.h:835
FunctionLiteral * ParseLazy()
Definition: parser.cc:948
void HandleSourceURLComments()
Definition: parser.cc:3993
Literal * GetLiteralUndefined(int position)
Definition: parser.cc:3914
void * ParseSourceElements(ZoneList< Statement * > *processor, int end_token, bool is_eval, bool is_global, Scope **ad_hoc_eval_scope, bool *ok)
Definition: parser.cc:1050
bool pending_error_is_reference_error_
Definition: parser.h:846
CaseClause * ParseCaseClause(bool *default_seen_ptr, bool *ok)
Definition: parser.cc:2624
Module * ParseModuleVariable(bool *ok)
Definition: parser.cc:1345
PreParser::PreParseResult ParseLazyFunctionBodyWithPreParser(SingletonLogger *logger)
Definition: parser.cc:3826
const AstRawString * pending_error_arg_
Definition: parser.h:844
void Declare(Declaration *declaration, bool resolve, bool *ok)
Definition: parser.cc:1717
Statement * ParseStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:1586
void ParseOnBackground()
Definition: parser.cc:4923
Statement * ParseForStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:3097
Module * ParseModuleUrl(bool *ok)
Definition: parser.cc:1364
bool has_pending_error_
Definition: parser.h:841
Statement * ParseClassDeclaration(ZoneList< const AstRawString * > *names, bool *ok)
Definition: parser.cc:1954
bool inside_with() const
Definition: parser.h:692
Statement * ParseWithStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:2594
ParseData * cached_parse_data_
Definition: parser.h:836
FunctionLiteral * DoParseProgram(CompilationInfo *info, Scope **scope, Scope **ad_hoc_eval_scope)
Definition: parser.cc:861
FunctionLiteral * ParseProgram()
Definition: parser.cc:792
HistogramTimer * pre_parse_timer_
Definition: parser.h:852
Statement * DesugarLetBindingsInForStatement(Scope *inner_scope, ZoneList< const AstRawString * > *names, ForStatement *loop, Statement *init, Expression *cond, Statement *next, Statement *body, bool *ok)
Definition: parser.cc:2938
const char * pending_error_char_arg_
Definition: parser.h:845
CompilationInfo * info() const
Definition: parser.h:680
void SkipLazyFunctionBody(const AstRawString *function_name, int *materialized_literal_count, int *expected_property_count, bool *ok)
Definition: parser.cc:3701
Scanner scanner_
Definition: parser.h:832
Scope * original_scope_
Definition: parser.h:834
bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode *visit_mode)
Definition: parser.cc:2856
DebuggerStatement * ParseDebuggerStatement(bool *ok)
Definition: parser.cc:3317
ZoneList< Statement * > * ParseEagerFunctionBody(const AstRawString *function_name, int pos, Variable *fvar, Token::Value fvar_init_op, bool is_generator, bool *ok)
Definition: parser.cc:3767
void InitializeForEachStatement(ForEachStatement *stmt, Expression *each, Expression *subject, Statement *body)
Definition: parser.cc:2869
Statement * ParseBreakStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:2515
DoWhileStatement * ParseDoWhileStatement(ZoneList< const AstRawString * > *labels, bool *ok)
Definition: parser.cc:2809
static const int kMaxNumFunctionLocals
Definition: parser.h:658
Scanner::Location pending_error_location_
Definition: parser.h:842
Statement * ParseModuleDeclaration(ZoneList< const AstRawString * > *names, bool *ok)
Definition: parser.cc:1193
Statement * ParseFunctionDeclaration(ZoneList< const AstRawString * > *names, bool *ok)
Definition: parser.cc:1917
Module * ParseModuleLiteral(bool *ok)
Definition: parser.cc:1257
Parser(CompilationInfo *info, ParseInfo *parse_info)
Definition: parser.cc:755
AstValueFactory * ast_value_factory() const
Definition: parser.h:682
const char * pending_error_message_
Definition: parser.h:843
Module * ParseModule(bool *ok)
Definition: parser.cc:1230
int total_preparse_skipped_
Definition: parser.h:851
Statement * ParseThrowStatement(bool *ok)
Definition: parser.cc:2685
Module * ParseModuleSpecifier(bool *ok)
Definition: parser.cc:1393
TryStatement * ParseTryStatement(bool *ok)
Definition: parser.cc:2704
Isolate * isolate()
Definition: parser.h:679
PreParser * reusable_preparser_
Definition: parser.h:833
PreParseResult PreParseLazyFunction(StrictMode strict_mode, bool is_generator, ParserRecorder *log)
Definition: preparser.cc:121
void AddCharacter(uc16 character)
Definition: parser.cc:66
void AddAtom(RegExpTree *tree)
Definition: parser.cc:81
ZoneList< uc16 > * characters_
Definition: parser.h:202
Zone * zone() const
Definition: parser.h:198
BufferedZoneList< RegExpTree, 2 > alternatives_
Definition: parser.h:205
void AddAssertion(RegExpTree *tree)
Definition: parser.cc:97
RegExpBuilder(Zone *zone)
Definition: parser.cc:26
BufferedZoneList< RegExpTree, 2 > text_
Definition: parser.h:204
BufferedZoneList< RegExpTree, 2 > terms_
Definition: parser.h:203
void AddQuantifierToAtom(int min, int max, RegExpQuantifier::QuantifierType type)
Definition: parser.cc:139
RegExpTree * ToRegExp()
Definition: parser.cc:126
static const int kInfinity
Definition: ast.h:2597
virtual int max_match()=0
virtual bool IsTextElement()
Definition: ast.h:2602
static const int kNoPosition
Definition: assembler.h:317
static const Function * FunctionForId(FunctionId id)
Definition: runtime.cc:9312
static const Function * FunctionForName(Handle< String > name)
Definition: runtime.cc:9290
void SeekForward(int pos)
Definition: scanner.cc:660
void Initialize(Utf16CharacterStream *source)
Definition: scanner.cc:43
Location peek_location() const
Definition: scanner.h:363
const LiteralBuffer * source_url() const
Definition: scanner.h:462
const LiteralBuffer * source_mapping_url() const
Definition: scanner.h:463
const AstRawString * NextSymbol(AstValueFactory *ast_value_factory)
Definition: scanner.cc:1203
Location location() const
Definition: scanner.h:356
const AstRawString * CurrentSymbol(AstValueFactory *ast_value_factory)
Definition: scanner.cc:1195
void SetStrictMode(StrictMode strict_mode)
Definition: scopes.h:215
void set_end_position(int statement_pos)
Definition: scopes.h:247
bool is_global_scope() const
Definition: scopes.h:267
Variable * Lookup(const AstRawString *name)
Definition: scopes.cc:440
Variable * DeclareLocal(const AstRawString *name, VariableMode mode, InitializationFlag init_flag, MaybeAssignedFlag maybe_assigned_flag=kNotAssigned, Interface *interface=Interface::NewValue())
Definition: scopes.cc:461
void ForceEagerCompilation()
Definition: scopes.h:364
Variable * receiver()
Definition: scopes.h:305
VariableProxy * NewUnresolved(AstNodeFactory< Visitor > *factory, const AstRawString *name, Interface *interface=Interface::NewValue(), int position=RelocInfo::kNoPosition)
Definition: scopes.h:145
bool is_eval_scope() const
Definition: scopes.h:264
void SetIllegalRedeclaration(Expression *expression)
Definition: scopes.cc:530
bool is_function_scope() const
Definition: scopes.h:265
bool IsDeclared(const AstRawString *name)
Definition: scopes.h:399
Scope * DeclarationScope()
Definition: scopes.cc:737
void set_start_position(int statement_pos)
Definition: scopes.h:243
void RecordEvalCall()
Definition: scopes.h:212
bool is_block_scope() const
Definition: scopes.h:269
Scope * FinalizeBlockScope()
Definition: scopes.cc:345
StrictMode strict_mode() const
Definition: scopes.h:302
Declaration * CheckConflictingVarDeclarations()
Definition: scopes.cc:545
int end_position() const
Definition: scopes.h:246
Variable * DeclareParameter(const AstRawString *name, VariableMode mode)
Definition: scopes.cc:451
Interface * interface() const
Definition: scopes.h:336
void AddDeclaration(Declaration *declaration)
Definition: scopes.cc:525
static Scope * DeserializeScopeChain(Context *context, Scope *global_scope, Zone *zone)
Definition: scopes.cc:187
int start_position() const
Definition: scopes.h:242
bool is_module_scope() const
Definition: scopes.h:266
Variable * LookupLocal(const AstRawString *name)
Definition: scopes.cc:375
bool is_strict_eval_scope() const
Definition: scopes.h:275
StrictMode strict_mode() const
Definition: preparse-data.h:95
const char * argument_opt() const
int value() const
Definition: objects-inl.h:1316
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
static Handle< String > Flatten(Handle< String > string, PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:3354
void set_escaping_targets(ZoneList< Label * > *targets)
Definition: ast.h:1251
VariableMode mode() const
Definition: variables.h:73
Interface * interface() const
Definition: variables.h:129
void AllocateTo(Location location, int index)
Definition: variables.h:131
const AstRawString * raw_name() const
Definition: variables.h:72
Vector< T > SubVector(int from, int to)
Definition: vector.h:33
int length() const
Definition: vector.h:41
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS 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 enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions true
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS 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 mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
#define COMMA
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS 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 enable alignment of csp to bytes on platforms which prefer the register to always be NULL
enable harmony numeric enable harmony object literal extensions Optimize object Array shift
#define CASE(Name)
#define UNREACHABLE()
Definition: logging.h:30
#define CHECK(condition)
Definition: logging.h:36
#define DCHECK_NE(v1, v2)
Definition: logging.h:207
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
void USE(T)
Definition: macros.h:322
#define arraysize(array)
Definition: macros.h:86
Vector< const char > CStrVector(const char *data)
Definition: vector.h:158
static const uc16 kNoCharClass
Definition: parser.cc:4794
bool IsDecimalDigit(uc32 c)
uint32_t DoubleToUint32(double x)
Definition: conversions.h:93
@ kNeedsInitialization
Definition: globals.h:752
@ kCreatedInitialized
Definition: globals.h:753
static int min(int a, int b)
Definition: liveedit.cc:273
bool IsLexicalVariableMode(VariableMode mode)
Definition: globals.h:710
bool IsDeclaredVariableMode(VariableMode mode)
Definition: globals.h:705
kExpectedNofPropertiesOffset function_token_position
Definition: objects-inl.h:5513
bool IsGeneratorFunction(FunctionKind kind)
Definition: globals.h:799
bool IsConciseMethod(FunctionKind kind)
Definition: globals.h:805
@ kNotAssigned
Definition: globals.h:757
bool CheckAndDeclareArrowParameter(ParserTraits *traits, Expression *expression, Scope *scope, int *num_params, Scanner::Location *dupe_loc)
Definition: parser.cc:3374
bool IsImmutableVariableMode(VariableMode mode)
Definition: globals.h:715
int ArithmeticShiftRight(int x, int s)
Definition: utils.h:90
@ CONST_LEGACY
Definition: globals.h:671
void PrintF(const char *format,...)
Definition: utils.cc:80
int32_t DoubleToInt32(double x)
kFeedbackVectorOffset flag
Definition: objects-inl.h:5418
@ ONLY_SINGLE_FUNCTION_LITERAL
Definition: compiler.h:23
int HexValue(uc32 c)
Definition: scanner.h:31
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:121
uint16_t uc16
Definition: globals.h:184
@ FUNCTION_SCOPE
Definition: globals.h:647
@ MODULE_SCOPE
Definition: globals.h:648
@ GLOBAL_SCOPE
Definition: globals.h:649
int32_t uc32
Definition: globals.h:185
static bool ContainsLabel(ZoneList< const AstRawString * > *labels, const AstRawString *label)
Definition: parser.cc:2386
static void AddRangeOrEscape(ZoneList< CharacterRange > *ranges, uc16 char_class, CharacterRange range, Zone *zone)
Definition: parser.cc:4799
@ kNormalFunction
Definition: globals.h:776
@ kGeneratorFunction
Definition: globals.h:778
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define CHECK_OK
Definition: parser.cc:330
#define CHECK_FAILED
Definition: parser.cc:336
#define LAST(x)
Definition: parser.h:210
#define IN
@ STRING
static Location invalid()
Definition: scanner.h:337