// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/parsing/parser.h"

#include <algorithm>
#include <memory>

#include "src/api.h"
#include "src/ast/ast-expression-rewriter.h"
#include "src/ast/ast-function-literal-id-reindexer.h"
#include "src/ast/ast-traversal-visitor.h"
#include "src/ast/ast.h"
#include "src/bailout-reason.h"
#include "src/base/platform/platform.h"
#include "src/char-predicates-inl.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "src/messages.h"
#include "src/objects-inl.h"
#include "src/parsing/duplicate-finder.h"
#include "src/parsing/expression-scope-reparenter.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/rewriter.h"
#include "src/runtime/runtime.h"
#include "src/string-stream.h"
#include "src/tracing/trace-event.h"

namespace v8 {
namespace internal {

ScriptData::ScriptData(const byte* data, int length)
    : owns_data_(false), rejected_(false), data_(data), length_(length) {
  if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) {
    byte* copy = NewArray<byte>(length);
    DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment));
    CopyBytes(copy, data, length);
    data_ = copy;
    AcquireDataOwnership();
  }
}

FunctionEntry ParseData::GetFunctionEntry(int start) {
  // The current pre-data entry must be a FunctionEntry with the given
  // start position.
  if ((function_index_ + FunctionEntry::kSize <= Length()) &&
      (static_cast<int>(Data()[function_index_]) == start)) {
    int index = function_index_;
    function_index_ += FunctionEntry::kSize;
    Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
    return FunctionEntry(subvector);
  }
  return FunctionEntry();
}


int ParseData::FunctionCount() {
  int functions_size = FunctionsSize();
  if (functions_size < 0) return 0;
  if (functions_size % FunctionEntry::kSize != 0) return 0;
  return functions_size / FunctionEntry::kSize;
}


bool ParseData::IsSane() {
  if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false;
  // Check that the header data is valid and doesn't specify
  // point to positions outside the store.
  int data_length = Length();
  if (data_length < PreparseDataConstants::kHeaderSize) return false;
  if (Magic() != PreparseDataConstants::kMagicNumber) return false;
  if (Version() != PreparseDataConstants::kCurrentVersion) return false;
  // Check that the space allocated for function entries is sane.
  int functions_size = FunctionsSize();
  if (functions_size < 0) return false;
  if (functions_size % FunctionEntry::kSize != 0) return false;
  // Check that the total size has room for header and function entries.
  int minimum_size =
      PreparseDataConstants::kHeaderSize + functions_size;
  if (data_length < minimum_size) return false;
  return true;
}


void ParseData::Initialize() {
  // Prepares state for use.
  int data_length = Length();
  if (data_length >= PreparseDataConstants::kHeaderSize) {
    function_index_ = PreparseDataConstants::kHeaderSize;
  }
}


unsigned ParseData::Magic() {
  return Data()[PreparseDataConstants::kMagicOffset];
}


unsigned ParseData::Version() {
  return Data()[PreparseDataConstants::kVersionOffset];
}


int ParseData::FunctionsSize() {
  return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
}

// Helper for putting parts of the parse results into a temporary zone when
// parsing inner function bodies.
class DiscardableZoneScope {
 public:
  DiscardableZoneScope(Parser* parser, Zone* temp_zone, bool use_temp_zone)
      : fni_(parser->ast_value_factory_, temp_zone),
        parser_(parser),
        prev_fni_(parser->fni_),
        prev_zone_(parser->zone_),
        prev_allow_lazy_(parser->allow_lazy_),
        prev_temp_zoned_(parser->temp_zoned_) {
    if (use_temp_zone) {
      DCHECK(!parser_->temp_zoned_);
      parser_->allow_lazy_ = false;
      parser_->temp_zoned_ = true;
      parser_->fni_ = &fni_;
      parser_->zone_ = temp_zone;
      parser_->factory()->set_zone(temp_zone);
      if (parser_->reusable_preparser_ != nullptr) {
        parser_->reusable_preparser_->zone_ = temp_zone;
        parser_->reusable_preparser_->factory()->set_zone(temp_zone);
      }
    }
  }
  void Reset() {
    parser_->fni_ = prev_fni_;
    parser_->zone_ = prev_zone_;
    parser_->factory()->set_zone(prev_zone_);
    parser_->allow_lazy_ = prev_allow_lazy_;
    parser_->temp_zoned_ = prev_temp_zoned_;
    if (parser_->reusable_preparser_ != nullptr) {
      parser_->reusable_preparser_->zone_ = prev_zone_;
      parser_->reusable_preparser_->factory()->set_zone(prev_zone_);
    }
  }
  ~DiscardableZoneScope() { Reset(); }

 private:
  FuncNameInferrer fni_;
  Parser* parser_;
  FuncNameInferrer* prev_fni_;
  Zone* prev_zone_;
  bool prev_allow_lazy_;
  bool prev_temp_zoned_;

  DISALLOW_COPY_AND_ASSIGN(DiscardableZoneScope);
};

void Parser::SetCachedData(ParseInfo* info) {
  DCHECK_NULL(cached_parse_data_);
  if (consume_cached_parse_data()) {
    if (allow_lazy_) {
      cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
      if (cached_parse_data_ != nullptr) return;
    }
    compile_options_ = ScriptCompiler::kNoCompileOptions;
  }
}

FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
                                            bool call_super, int pos,
                                            int end_pos) {
  int expected_property_count = -1;
  const int parameter_count = 0;

  FunctionKind kind = call_super ? FunctionKind::kDefaultDerivedConstructor
                                 : FunctionKind::kDefaultBaseConstructor;
  DeclarationScope* function_scope = NewFunctionScope(kind);
  SetLanguageMode(function_scope, LanguageMode::kStrict);
  // Set start and end position to the same value
  function_scope->set_start_position(pos);
  function_scope->set_end_position(pos);
  ZoneList<Statement*>* body = nullptr;

  {
    FunctionState function_state(&function_state_, &scope_, function_scope);

    body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
    if (call_super) {
      // Create a SuperCallReference and handle in BytecodeGenerator.
      auto constructor_args_name = ast_value_factory()->empty_string();
      bool is_duplicate;
      bool is_rest = true;
      bool is_optional = false;
      Variable* constructor_args = function_scope->DeclareParameter(
          constructor_args_name, TEMPORARY, is_optional, is_rest, &is_duplicate,
          ast_value_factory(), pos);

      ZoneList<Expression*>* args =
          new (zone()) ZoneList<Expression*>(1, zone());
      Spread* spread_args = factory()->NewSpread(
          factory()->NewVariableProxy(constructor_args), pos, pos);

      args->Add(spread_args, zone());
      Expression* super_call_ref = NewSuperCallReference(pos);
      Expression* call = factory()->NewCall(super_call_ref, args, pos);
      body->Add(factory()->NewReturnStatement(call, pos), zone());
    }

    expected_property_count = function_state.expected_property_count();
  }

  FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
      name, function_scope, body, expected_property_count, parameter_count,
      parameter_count, FunctionLiteral::kNoDuplicateParameters,
      FunctionLiteral::kAnonymousExpression, default_eager_compile_hint(), pos,
      true, GetNextFunctionLiteralId());

  return function_literal;
}

// ----------------------------------------------------------------------------
// The CHECK_OK macro is a convenient macro to enforce error
// handling for functions that may fail (by returning !*ok).
//
// CAUTION: This macro appends extra statements after a call,
// thus it must never be used where only a single statement
// is correct (e.g. an if statement branch w/o braces)!

#define CHECK_OK_VALUE(x) ok); \
  if (!*ok) return x;          \
  ((void)0
#define DUMMY )  // to make indentation work
#undef DUMMY

#define CHECK_OK CHECK_OK_VALUE(nullptr)
#define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())

#define CHECK_FAILED /**/); \
  if (failed_) return nullptr;  \
  ((void)0
#define DUMMY )  // to make indentation work
#undef DUMMY

// ----------------------------------------------------------------------------
// Implementation of Parser

bool Parser::ShortcutNumericLiteralBinaryExpression(Expression** x,
                                                    Expression* y,
                                                    Token::Value op, int pos) {
  if ((*x)->IsNumberLiteral() && y->IsNumberLiteral()) {
    double x_val = (*x)->AsLiteral()->AsNumber();
    double y_val = y->AsLiteral()->AsNumber();
    switch (op) {
      case Token::ADD:
        *x = factory()->NewNumberLiteral(x_val + y_val, pos);
        return true;
      case Token::SUB:
        *x = factory()->NewNumberLiteral(x_val - y_val, pos);
        return true;
      case Token::MUL:
        *x = factory()->NewNumberLiteral(x_val * y_val, pos);
        return true;
      case Token::DIV:
        *x = factory()->NewNumberLiteral(x_val / y_val, pos);
        return true;
      case Token::BIT_OR: {
        int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
        *x = factory()->NewNumberLiteral(value, pos);
        return true;
      }
      case Token::BIT_AND: {
        int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
        *x = factory()->NewNumberLiteral(value, pos);
        return true;
      }
      case Token::BIT_XOR: {
        int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
        *x = factory()->NewNumberLiteral(value, pos);
        return true;
      }
      case Token::SHL: {
        int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
        *x = factory()->NewNumberLiteral(value, pos);
        return true;
      }
      case Token::SHR: {
        uint32_t shift = DoubleToInt32(y_val) & 0x1f;
        uint32_t value = DoubleToUint32(x_val) >> shift;
        *x = factory()->NewNumberLiteral(value, pos);
        return true;
      }
      case Token::SAR: {
        uint32_t shift = DoubleToInt32(y_val) & 0x1f;
        int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
        *x = factory()->NewNumberLiteral(value, pos);
        return true;
      }
      case Token::EXP: {
        double value = Pow(x_val, y_val);
        int int_value = static_cast<int>(value);
        *x = factory()->NewNumberLiteral(
            int_value == value && value != -0.0 ? int_value : value, pos);
        return true;
      }
      default:
        break;
    }
  }
  return false;
}

bool Parser::CollapseNaryExpression(Expression** x, Expression* y,
                                    Token::Value op, int pos) {
  // Filter out unsupported ops.
  if (!Token::IsBinaryOp(op) || op == Token::EXP) return false;

  // Convert *x into an nary operation with the given op, returning false if
  // this is not possible.
  NaryOperation* nary = nullptr;
  if ((*x)->IsBinaryOperation()) {
    BinaryOperation* binop = (*x)->AsBinaryOperation();
    if (binop->op() != op) return false;

    nary = factory()->NewNaryOperation(op, binop->left(), 2);
    nary->AddSubsequent(binop->right(), binop->position());
    *x = nary;
  } else if ((*x)->IsNaryOperation()) {
    nary = (*x)->AsNaryOperation();
    if (nary->op() != op) return false;
  } else {
    return false;
  }

  // Append our current expression to the nary operation.
  // TODO(leszeks): Do some literal collapsing here if we're appending Smi or
  // String literals.
  nary->AddSubsequent(y, pos);
  return true;
}

Expression* Parser::BuildUnaryExpression(Expression* expression,
                                         Token::Value op, int pos) {
  DCHECK_NOT_NULL(expression);
  const Literal* literal = expression->AsLiteral();
  if (literal != nullptr) {
    if (op == Token::NOT) {
      // Convert the literal to a boolean condition and negate it.
      return factory()->NewBooleanLiteral(literal->ToBooleanIsFalse(), pos);
    } else if (literal->IsNumberLiteral()) {
      // Compute some expressions involving only number literals.
      double value = literal->AsNumber();
      switch (op) {
        case Token::ADD:
          return expression;
        case Token::SUB:
          return factory()->NewNumberLiteral(-value, pos);
        case Token::BIT_NOT:
          return factory()->NewNumberLiteral(~DoubleToInt32(value), pos);
        default:
          break;
      }
    }
  }
  return factory()->NewUnaryOperation(op, expression, pos);
}

Expression* Parser::NewThrowError(Runtime::FunctionId id,
                                  MessageTemplate::Template message,
                                  const AstRawString* arg, int pos) {
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
  args->Add(factory()->NewSmiLiteral(message, pos), zone());
  args->Add(factory()->NewStringLiteral(arg, pos), zone());
  CallRuntime* call_constructor = factory()->NewCallRuntime(id, args, pos);
  return factory()->NewThrow(call_constructor, pos);
}

Expression* Parser::NewSuperPropertyReference(int pos) {
  // this_function[home_object_symbol]
  VariableProxy* this_function_proxy =
      NewUnresolved(ast_value_factory()->this_function_string(), pos);
  Expression* home_object_symbol_literal = factory()->NewSymbolLiteral(
      AstSymbol::kHomeObjectSymbol, kNoSourcePosition);
  Expression* home_object = factory()->NewProperty(
      this_function_proxy, home_object_symbol_literal, pos);
  return factory()->NewSuperPropertyReference(
      ThisExpression(pos)->AsVariableProxy(), home_object, pos);
}

Expression* Parser::NewSuperCallReference(int pos) {
  VariableProxy* new_target_proxy =
      NewUnresolved(ast_value_factory()->new_target_string(), pos);
  VariableProxy* this_function_proxy =
      NewUnresolved(ast_value_factory()->this_function_string(), pos);
  return factory()->NewSuperCallReference(
      ThisExpression(pos)->AsVariableProxy(), new_target_proxy,
      this_function_proxy, pos);
}

Expression* Parser::NewTargetExpression(int pos) {
  auto proxy = NewUnresolved(ast_value_factory()->new_target_string(), pos);
  proxy->set_is_new_target();
  return proxy;
}

Expression* Parser::FunctionSentExpression(int pos) {
  // We desugar function.sent into %_GeneratorGetInputOrDebugPos(generator).
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
  VariableProxy* generator = factory()->NewVariableProxy(
      function_state_->scope()->generator_object_var());
  args->Add(generator, zone());
  return factory()->NewCallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos,
                                   args, pos);
}

Expression* Parser::ImportMetaExpression(int pos) {
  return factory()->NewCallRuntime(
      Runtime::kInlineGetImportMetaObject,
      new (zone()) ZoneList<Expression*>(0, zone()), pos);
}

Literal* Parser::ExpressionFromLiteral(Token::Value token, int pos) {
  switch (token) {
    case Token::NULL_LITERAL:
      return factory()->NewNullLiteral(pos);
    case Token::TRUE_LITERAL:
      return factory()->NewBooleanLiteral(true, pos);
    case Token::FALSE_LITERAL:
      return factory()->NewBooleanLiteral(false, pos);
    case Token::SMI: {
      uint32_t value = scanner()->smi_value();
      return factory()->NewSmiLiteral(value, pos);
    }
    case Token::NUMBER: {
      double value = scanner()->DoubleValue();
      return factory()->NewNumberLiteral(value, pos);
    }
    case Token::BIGINT:
      return factory()->NewBigIntLiteral(
          AstBigInt(scanner()->CurrentLiteralAsCString(zone())), pos);
    default:
      DCHECK(false);
  }
  return nullptr;
}

Expression* Parser::NewV8Intrinsic(const AstRawString* name,
                                   ZoneList<Expression*>* args, int pos,
                                   bool* ok) {
  if (extension_ != nullptr) {
    // The extension structures are only accessible while parsing the
    // very first time, not when reparsing because of lazy compilation.
    GetClosureScope()->ForceEagerCompilation();
  }

  DCHECK(name->is_one_byte());
  const Runtime::Function* function =
      Runtime::FunctionForName(name->raw_data(), name->length());

  if (function != nullptr) {
    // Check for possible name clash.
    DCHECK_EQ(Context::kNotFound,
              Context::IntrinsicIndexForName(name->raw_data(), name->length()));
    // Check for built-in IS_VAR macro.
    if (function->function_id == Runtime::kIS_VAR) {
      DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
      // %IS_VAR(x) evaluates to x if x is a variable,
      // leads to a parse error otherwise.  Could be implemented as an
      // inline function %_IS_VAR(x) to eliminate this special case.
      if (args->length() == 1 && args->at(0)->AsVariableProxy() != nullptr) {
        return args->at(0);
      } else {
        ReportMessage(MessageTemplate::kNotIsvar);
        *ok = false;
        return nullptr;
      }
    }

    // Check that the expected number of arguments are being passed.
    if (function->nargs != -1 && function->nargs != args->length()) {
      ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
      *ok = false;
      return nullptr;
    }

    return factory()->NewCallRuntime(function, args, pos);
  }

  int context_index =
      Context::IntrinsicIndexForName(name->raw_data(), name->length());

  // Check that the function is defined.
  if (context_index == Context::kNotFound) {
    ReportMessage(MessageTemplate::kNotDefined, name);
    *ok = false;
    return nullptr;
  }

  return factory()->NewCallRuntime(context_index, args, pos);
}

Parser::Parser(ParseInfo* info)
    : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
                         info->extension(), info->GetOrCreateAstValueFactory(),
                         info->runtime_call_stats(), info->is_module(),
                         info->pending_error_handler(), true),
      scanner_(info->unicode_cache(), use_counts_),
      reusable_preparser_(nullptr),
      mode_(PARSE_EAGERLY),  // Lazy mode must be set explicitly.
      source_range_map_(info->source_range_map()),
      target_stack_(nullptr),
      compile_options_(info->compile_options()),
      cached_parse_data_(nullptr),
      total_preparse_skipped_(0),
      temp_zoned_(false),
      log_(nullptr),
      consumed_preparsed_scope_data_(info->consumed_preparsed_scope_data()),
      parameters_end_pos_(info->parameters_end_pos()) {
  // Even though we were passed ParseInfo, we should not store it in
  // Parser - this makes sure that Isolate is not accidentally accessed via
  // ParseInfo during background parsing.
  DCHECK_NOT_NULL(info->character_stream());
  // Determine if functions can be lazily compiled. This is necessary to
  // allow some of our builtin JS files to be lazily compiled. These
  // builtins cannot be handled lazily by the parser, since we have to know
  // if a function uses the special natives syntax, which is something the
  // parser records.
  // If the debugger requests compilation for break points, we cannot be
  // aggressive about lazy compilation, because it might trigger compilation
  // of functions without an outer context when setting a breakpoint through
  // Debug::FindSharedFunctionInfoInScript
  // We also compile eagerly for kProduceExhaustiveCodeCache.
  bool can_compile_lazily = FLAG_lazy && !info->is_eager();

  set_default_eager_compile_hint(can_compile_lazily
                                     ? FunctionLiteral::kShouldLazyCompile
                                     : FunctionLiteral::kShouldEagerCompile);
  allow_lazy_ = FLAG_lazy && info->allow_lazy_parsing() && !info->is_native() &&
                info->extension() == nullptr && can_compile_lazily;
  set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
  set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
  set_allow_harmony_function_sent(FLAG_harmony_function_sent);
  set_allow_harmony_class_fields(FLAG_harmony_class_fields);
  set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import);
  set_allow_harmony_import_meta(FLAG_harmony_import_meta);
  set_allow_harmony_async_iteration(FLAG_harmony_async_iteration);
  set_allow_harmony_template_escapes(FLAG_harmony_template_escapes);
  set_allow_harmony_bigint(FLAG_harmony_bigint);
  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
       ++feature) {
    use_counts_[feature] = 0;
  }
}

void Parser::DeserializeScopeChain(
    ParseInfo* info, MaybeHandle<ScopeInfo> maybe_outer_scope_info) {
  // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
  // context, which will have the "this" binding for script scopes.
  DeclarationScope* script_scope = NewScriptScope();
  info->set_script_scope(script_scope);
  Scope* scope = script_scope;
  Handle<ScopeInfo> outer_scope_info;
  if (maybe_outer_scope_info.ToHandle(&outer_scope_info)) {
    DCHECK(ThreadId::Current().Equals(
        outer_scope_info->GetIsolate()->thread_id()));
    scope = Scope::DeserializeScopeChain(
        zone(), *outer_scope_info, script_scope, ast_value_factory(),
        Scope::DeserializationMode::kScopesOnly);
  }
  original_scope_ = scope;
}

namespace {

void MaybeResetCharacterStream(ParseInfo* info, FunctionLiteral* literal) {
  // Don't reset the character stream if there is an asm.js module since it will
  // be used again by the asm-parser.
  if (!FLAG_stress_validate_asm &&
      (literal == nullptr || !literal->scope()->ContainsAsmModule())) {
    info->ResetCharacterStream();
  }
}

}  // namespace

FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
  // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
  // see comment for HistogramTimerScope class.

  // It's OK to use the Isolate & counters here, since this function is only
  // called in the main thread.
  DCHECK(parsing_on_main_thread_);
  RuntimeCallTimerScope runtime_timer(
      runtime_call_stats_, info->is_eval() ? &RuntimeCallStats::ParseEval
                                           : &RuntimeCallStats::ParseProgram);
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseProgram");
  base::ElapsedTimer timer;
  if (FLAG_trace_parse) {
    timer.Start();
  }
  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());

  // Initialize parser state.
  ParserLogger logger;

  if (produce_cached_parse_data()) {
    if (allow_lazy_) {
      log_ = &logger;
    } else {
      compile_options_ = ScriptCompiler::kNoCompileOptions;
    }
  } else if (consume_cached_parse_data()) {
    cached_parse_data_->Initialize();
  }

  DeserializeScopeChain(info, info->maybe_outer_scope_info());

  scanner_.Initialize(info->character_stream(), info->is_module());
  FunctionLiteral* result = DoParseProgram(info);
  MaybeResetCharacterStream(info, result);

  HandleSourceURLComments(isolate, info->script());

  if (FLAG_trace_parse && result != nullptr) {
    double ms = timer.Elapsed().InMillisecondsF();
    if (info->is_eval()) {
      PrintF("[parsing eval");
    } else if (info->script()->name()->IsString()) {
      String* name = String::cast(info->script()->name());
      std::unique_ptr<char[]> name_chars = name->ToCString();
      PrintF("[parsing script: %s", name_chars.get());
    } else {
      PrintF("[parsing script");
    }
    PrintF(" - took %0.3f ms]\n", ms);
  }
  if (produce_cached_parse_data() && result != nullptr) {
    *info->cached_data() = logger.GetScriptData();
  }
  log_ = nullptr;
  return result;
}


FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
  // Note that this function can be called from the main thread or from a
  // background thread. We should not access anything Isolate / heap dependent
  // via ParseInfo, and also not pass it forward.
  DCHECK_NULL(scope_);
  DCHECK_NULL(target_stack_);

  ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY);
  ResetFunctionLiteralId();
  DCHECK(info->function_literal_id() == FunctionLiteral::kIdTypeTopLevel ||
         info->function_literal_id() == FunctionLiteral::kIdTypeInvalid);

  FunctionLiteral* result = nullptr;
  {
    Scope* outer = original_scope_;
    DCHECK_NOT_NULL(outer);
    if (info->is_eval()) {
      outer = NewEvalScope(outer);
    } else if (parsing_module_) {
      DCHECK_EQ(outer, info->script_scope());
      outer = NewModuleScope(info->script_scope());
    }

    DeclarationScope* scope = outer->AsDeclarationScope();

    scope->set_start_position(0);

    FunctionState function_state(&function_state_, &scope_, scope);

    ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
    bool ok = true;
    int beg_pos = scanner()->location().beg_pos;
    if (parsing_module_) {
      DCHECK(info->is_module());
      // Declare the special module parameter.
      auto name = ast_value_factory()->empty_string();
      bool is_duplicate = false;
      bool is_rest = false;
      bool is_optional = false;
      auto var =
          scope->DeclareParameter(name, VAR, is_optional, is_rest,
                                  &is_duplicate, ast_value_factory(), beg_pos);
      DCHECK(!is_duplicate);
      var->AllocateTo(VariableLocation::PARAMETER, 0);

      PrepareGeneratorVariables();
      scope->ForceContextAllocation();
      Expression* initial_yield =
          BuildInitialYield(kNoSourcePosition, kGeneratorFunction);
      body->Add(
          factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
          zone());

      ParseModuleItemList(body, &ok);
      ok = ok && module()->Validate(this->scope()->AsModuleScope(),
                                    pending_error_handler(), zone());
    } else {
      // Don't count the mode in the use counters--give the program a chance
      // to enable script-wide strict mode below.
      this->scope()->SetLanguageMode(info->language_mode());
      ParseStatementList(body, Token::EOS, &ok);
    }

    // The parser will peek but not consume EOS.  Our scope logically goes all
    // the way to the EOS, though.
    scope->set_end_position(scanner()->peek_location().beg_pos);

    if (ok && is_strict(language_mode())) {
      CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
    }
    if (ok && is_sloppy(language_mode())) {
      // TODO(littledan): Function bindings on the global object that modify
      // pre-existing bindings should be made writable, enumerable and
      // nonconfigurable if possible, whereas this code will leave attributes
      // unchanged if the property already exists.
      InsertSloppyBlockFunctionVarBindings(scope);
    }
    if (ok) {
      CheckConflictingVarDeclarations(scope, &ok);
    }

    if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
      if (body->length() != 1 ||
          !body->at(0)->IsExpressionStatement() ||
          !body->at(0)->AsExpressionStatement()->
              expression()->IsFunctionLiteral()) {
        ReportMessage(MessageTemplate::kSingleFunctionLiteral);
        ok = false;
      }
    }

    if (ok) {
      RewriteDestructuringAssignments();
      int parameter_count = parsing_module_ ? 1 : 0;
      result = factory()->NewScriptOrEvalFunctionLiteral(
          scope, body, function_state.expected_property_count(),
          parameter_count);
    }
  }

  info->set_max_function_literal_id(GetLastFunctionLiteralId());

  // Make sure the target stack is empty.
  DCHECK_NULL(target_stack_);

  return result;
}

FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info,
                                       Handle<SharedFunctionInfo> shared_info) {
  // It's OK to use the Isolate & counters here, since this function is only
  // called in the main thread.
  DCHECK(parsing_on_main_thread_);
  RuntimeCallTimerScope runtime_timer(runtime_call_stats_,
                                      &RuntimeCallStats::ParseFunction);
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseFunction");
  base::ElapsedTimer timer;
  if (FLAG_trace_parse) {
    timer.Start();
  }
  DeserializeScopeChain(info, info->maybe_outer_scope_info());
  DCHECK_EQ(factory()->zone(), info->zone());

  // Initialize parser state.
  Handle<String> name(shared_info->name());
  info->set_function_name(ast_value_factory()->GetString(name));
  scanner_.Initialize(info->character_stream(), info->is_module());

  FunctionLiteral* result = DoParseFunction(info, info->function_name());
  MaybeResetCharacterStream(info, result);
  if (result != nullptr) {
    Handle<String> inferred_name(shared_info->inferred_name());
    result->set_inferred_name(inferred_name);
  }

  if (FLAG_trace_parse && result != nullptr) {
    double ms = timer.Elapsed().InMillisecondsF();
    // We need to make sure that the debug-name is available.
    ast_value_factory()->Internalize(isolate);
    std::unique_ptr<char[]> name_chars = result->debug_name()->ToCString();
    PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
  }
  return result;
}

static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) {
  if (info->is_declaration()) {
    return FunctionLiteral::kDeclaration;
  } else if (info->is_named_expression()) {
    return FunctionLiteral::kNamedExpression;
  } else if (IsConciseMethod(info->function_kind()) ||
             IsAccessorFunction(info->function_kind())) {
    return FunctionLiteral::kAccessorOrMethod;
  }
  return FunctionLiteral::kAnonymousExpression;
}

FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
                                         const AstRawString* raw_name) {
  DCHECK_NOT_NULL(raw_name);
  DCHECK_NULL(scope_);
  DCHECK_NULL(target_stack_);

  DCHECK(ast_value_factory());
  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
  fni_->PushEnclosingName(raw_name);

  ResetFunctionLiteralId();
  DCHECK_LT(0, info->function_literal_id());
  SkipFunctionLiterals(info->function_literal_id() - 1);

  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);

  // Place holder for the result.
  FunctionLiteral* result = nullptr;

  {
    // Parse the function literal.
    Scope* outer = original_scope_;
    DeclarationScope* outer_function = outer->GetClosureScope();
    DCHECK(outer);
    FunctionState function_state(&function_state_, &scope_, outer_function);
    BlockState block_state(&scope_, outer);
    DCHECK(is_sloppy(outer->language_mode()) ||
           is_strict(info->language_mode()));
    FunctionLiteral::FunctionType function_type = ComputeFunctionType(info);
    FunctionKind kind = info->function_kind();
    bool ok = true;

    if (IsArrowFunction(kind)) {
      if (IsAsyncFunction(kind)) {
        DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
        if (!Check(Token::ASYNC)) {
          CHECK(stack_overflow());
          return nullptr;
        }
        if (!(peek_any_identifier() || peek() == Token::LPAREN)) {
          CHECK(stack_overflow());
          return nullptr;
        }
      }

      // TODO(adamk): We should construct this scope from the ScopeInfo.
      DeclarationScope* scope = NewFunctionScope(kind);

      // This bit only needs to be explicitly set because we're
      // not passing the ScopeInfo to the Scope constructor.
      SetLanguageMode(scope, info->language_mode());

      scope->set_start_position(info->start_position());
      ExpressionClassifier formals_classifier(this);
      ParserFormalParameters formals(scope);
      int rewritable_length =
          function_state.destructuring_assignments_to_rewrite().length();
      {
        // Parsing patterns as variable reference expression creates
        // NewUnresolved references in current scope. Enter arrow function
        // scope for formal parameter parsing.
        BlockState block_state(&scope_, scope);
        if (Check(Token::LPAREN)) {
          // '(' StrictFormalParameters ')'
          ParseFormalParameterList(&formals, &ok);
          if (ok) ok = Check(Token::RPAREN);
        } else {
          // BindingIdentifier
          ParseFormalParameter(&formals, &ok);
          if (ok) {
            DeclareFormalParameters(formals.scope, formals.params,
                                    formals.is_simple);
          }
        }
      }

      if (ok) {
        if (GetLastFunctionLiteralId() != info->function_literal_id() - 1) {
          // If there were FunctionLiterals in the parameters, we need to
          // renumber them to shift down so the next function literal id for
          // the arrow function is the one requested.
          AstFunctionLiteralIdReindexer reindexer(
              stack_limit_,
              (info->function_literal_id() - 1) - GetLastFunctionLiteralId());
          for (auto p : formals.params) {
            if (p->pattern != nullptr) reindexer.Reindex(p->pattern);
            if (p->initializer != nullptr) reindexer.Reindex(p->initializer);
          }
          ResetFunctionLiteralId();
          SkipFunctionLiterals(info->function_literal_id() - 1);
        }

        // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
        // not be observable, or else the preparser would have failed.
        Expression* expression =
            ParseArrowFunctionLiteral(true, formals, rewritable_length, &ok);
        if (ok) {
          // Scanning must end at the same position that was recorded
          // previously. If not, parsing has been interrupted due to a stack
          // overflow, at which point the partially parsed arrow function
          // concise body happens to be a valid expression. This is a problem
          // only for arrow functions with single expression bodies, since there
          // is no end token such as "}" for normal functions.
          if (scanner()->location().end_pos == info->end_position()) {
            // The pre-parser saw an arrow function here, so the full parser
            // must produce a FunctionLiteral.
            DCHECK(expression->IsFunctionLiteral());
            result = expression->AsFunctionLiteral();
            // Rewrite destructuring assignments in the parameters. (The ones
            // inside the function body are rewritten by
            // ParseArrowFunctionLiteral.)
            RewriteDestructuringAssignments();
          } else {
            ok = false;
          }
        }
      }
    } else if (IsDefaultConstructor(kind)) {
      DCHECK_EQ(scope(), outer);
      result = DefaultConstructor(raw_name, IsDerivedConstructor(kind),
                                  info->start_position(), info->end_position());
    } else {
      result = ParseFunctionLiteral(
          raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck, kind,
          kNoSourcePosition, function_type, info->language_mode(), &ok);
    }
    // Make sure the results agree.
    DCHECK(ok == (result != nullptr));
  }

  // Make sure the target stack is empty.
  DCHECK_NULL(target_stack_);
  DCHECK_IMPLIES(result,
                 info->function_literal_id() == result->function_literal_id());
  return result;
}

Statement* Parser::ParseModuleItem(bool* ok) {
  // ecma262/#prod-ModuleItem
  // ModuleItem :
  //    ImportDeclaration
  //    ExportDeclaration
  //    StatementListItem

  Token::Value next = peek();

  if (next == Token::EXPORT) {
    return ParseExportDeclaration(ok);
  }

  if (next == Token::IMPORT) {
    // We must be careful not to parse a dynamic import expression as an import
    // declaration. Same for import.meta expressions.
    Token::Value peek_ahead = PeekAhead();
    if ((!allow_harmony_dynamic_import() || peek_ahead != Token::LPAREN) &&
        (!allow_harmony_import_meta() || peek_ahead != Token::PERIOD)) {
      ParseImportDeclaration(CHECK_OK);
      return factory()->NewEmptyStatement(kNoSourcePosition);
    }
  }

  return ParseStatementListItem(ok);
}


void Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) {
  // ecma262/#prod-Module
  // Module :
  //    ModuleBody?
  //
  // ecma262/#prod-ModuleItemList
  // ModuleBody :
  //    ModuleItem*

  DCHECK(scope()->is_module_scope());
  while (peek() != Token::EOS) {
    Statement* stat = ParseModuleItem(CHECK_OK_VOID);
    if (stat && !stat->IsEmpty()) {
      body->Add(stat, zone());
    }
  }
}


const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
  // ModuleSpecifier :
  //    StringLiteral

  Expect(Token::STRING, CHECK_OK);
  return GetSymbol();
}


void Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
                               ZoneList<Scanner::Location>* export_locations,
                               ZoneList<const AstRawString*>* local_names,
                               Scanner::Location* reserved_loc, bool* ok) {
  // ExportClause :
  //   '{' '}'
  //   '{' ExportsList '}'
  //   '{' ExportsList ',' '}'
  //
  // ExportsList :
  //   ExportSpecifier
  //   ExportsList ',' ExportSpecifier
  //
  // ExportSpecifier :
  //   IdentifierName
  //   IdentifierName 'as' IdentifierName

  Expect(Token::LBRACE, CHECK_OK_VOID);

  Token::Value name_tok;
  while ((name_tok = peek()) != Token::RBRACE) {
    // Keep track of the first reserved word encountered in case our
    // caller needs to report an error.
    if (!reserved_loc->IsValid() &&
        !Token::IsIdentifier(name_tok, LanguageMode::kStrict, false,
                             parsing_module_)) {
      *reserved_loc = scanner()->location();
    }
    const AstRawString* local_name = ParseIdentifierName(CHECK_OK_VOID);
    const AstRawString* export_name = nullptr;
    Scanner::Location location = scanner()->location();
    if (CheckContextualKeyword(Token::AS)) {
      export_name = ParseIdentifierName(CHECK_OK_VOID);
      // Set the location to the whole "a as b" string, so that it makes sense
      // both for errors due to "a" and for errors due to "b".
      location.end_pos = scanner()->location().end_pos;
    }
    if (export_name == nullptr) {
      export_name = local_name;
    }
    export_names->Add(export_name, zone());
    local_names->Add(local_name, zone());
    export_locations->Add(location, zone());
    if (peek() == Token::RBRACE) break;
    Expect(Token::COMMA, CHECK_OK_VOID);
  }

  Expect(Token::RBRACE, CHECK_OK_VOID);
}


ZoneList<const Parser::NamedImport*>* Parser::ParseNamedImports(
    int pos, bool* ok) {
  // NamedImports :
  //   '{' '}'
  //   '{' ImportsList '}'
  //   '{' ImportsList ',' '}'
  //
  // ImportsList :
  //   ImportSpecifier
  //   ImportsList ',' ImportSpecifier
  //
  // ImportSpecifier :
  //   BindingIdentifier
  //   IdentifierName 'as' BindingIdentifier

  Expect(Token::LBRACE, CHECK_OK);

  auto result = new (zone()) ZoneList<const NamedImport*>(1, zone());
  while (peek() != Token::RBRACE) {
    const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
    const AstRawString* local_name = import_name;
    Scanner::Location location = scanner()->location();
    // In the presence of 'as', the left-side of the 'as' can
    // be any IdentifierName. But without 'as', it must be a valid
    // BindingIdentifier.
    if (CheckContextualKeyword(Token::AS)) {
      local_name = ParseIdentifierName(CHECK_OK);
    }
    if (!Token::IsIdentifier(scanner()->current_token(), LanguageMode::kStrict,
                             false, parsing_module_)) {
      *ok = false;
      ReportMessage(MessageTemplate::kUnexpectedReserved);
      return nullptr;
    } else if (IsEvalOrArguments(local_name)) {
      *ok = false;
      ReportMessage(MessageTemplate::kStrictEvalArguments);
      return nullptr;
    }

    DeclareVariable(local_name, CONST, kNeedsInitialization, position(),
                    CHECK_OK);

    NamedImport* import =
        new (zone()) NamedImport(import_name, local_name, location);
    result->Add(import, zone());

    if (peek() == Token::RBRACE) break;
    Expect(Token::COMMA, CHECK_OK);
  }

  Expect(Token::RBRACE, CHECK_OK);
  return result;
}


void Parser::ParseImportDeclaration(bool* ok) {
  // ImportDeclaration :
  //   'import' ImportClause 'from' ModuleSpecifier ';'
  //   'import' ModuleSpecifier ';'
  //
  // ImportClause :
  //   ImportedDefaultBinding
  //   NameSpaceImport
  //   NamedImports
  //   ImportedDefaultBinding ',' NameSpaceImport
  //   ImportedDefaultBinding ',' NamedImports
  //
  // NameSpaceImport :
  //   '*' 'as' ImportedBinding

  int pos = peek_position();
  Expect(Token::IMPORT, CHECK_OK_VOID);

  Token::Value tok = peek();

  // 'import' ModuleSpecifier ';'
  if (tok == Token::STRING) {
    Scanner::Location specifier_loc = scanner()->peek_location();
    const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK_VOID);
    ExpectSemicolon(CHECK_OK_VOID);
    module()->AddEmptyImport(module_specifier, specifier_loc);
    return;
  }

  // Parse ImportedDefaultBinding if present.
  const AstRawString* import_default_binding = nullptr;
  Scanner::Location import_default_binding_loc;
  if (tok != Token::MUL && tok != Token::LBRACE) {
    import_default_binding =
        ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK_VOID);
    import_default_binding_loc = scanner()->location();
    DeclareVariable(import_default_binding, CONST, kNeedsInitialization, pos,
                    CHECK_OK_VOID);
  }

  // Parse NameSpaceImport or NamedImports if present.
  const AstRawString* module_namespace_binding = nullptr;
  Scanner::Location module_namespace_binding_loc;
  const ZoneList<const NamedImport*>* named_imports = nullptr;
  if (import_default_binding == nullptr || Check(Token::COMMA)) {
    switch (peek()) {
      case Token::MUL: {
        Consume(Token::MUL);
        ExpectContextualKeyword(Token::AS, CHECK_OK_VOID);
        module_namespace_binding =
            ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK_VOID);
        module_namespace_binding_loc = scanner()->location();
        DeclareVariable(module_namespace_binding, CONST, kCreatedInitialized,
                        pos, CHECK_OK_VOID);
        break;
      }

      case Token::LBRACE:
        named_imports = ParseNamedImports(pos, CHECK_OK_VOID);
        break;

      default:
        *ok = false;
        ReportUnexpectedToken(scanner()->current_token());
        return;
    }
  }

  ExpectContextualKeyword(Token::FROM, CHECK_OK_VOID);
  Scanner::Location specifier_loc = scanner()->peek_location();
  const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK_VOID);
  ExpectSemicolon(CHECK_OK_VOID);

  // Now that we have all the information, we can make the appropriate
  // declarations.

  // TODO(neis): Would prefer to call DeclareVariable for each case below rather
  // than above and in ParseNamedImports, but then a possible error message
  // would point to the wrong location.  Maybe have a DeclareAt version of
  // Declare that takes a location?

  if (module_namespace_binding != nullptr) {
    module()->AddStarImport(module_namespace_binding, module_specifier,
                            module_namespace_binding_loc, specifier_loc,
                            zone());
  }

  if (import_default_binding != nullptr) {
    module()->AddImport(ast_value_factory()->default_string(),
                        import_default_binding, module_specifier,
                        import_default_binding_loc, specifier_loc, zone());
  }

  if (named_imports != nullptr) {
    if (named_imports->length() == 0) {
      module()->AddEmptyImport(module_specifier, specifier_loc);
    } else {
      for (int i = 0; i < named_imports->length(); ++i) {
        const NamedImport* import = named_imports->at(i);
        module()->AddImport(import->import_name, import->local_name,
                            module_specifier, import->location, specifier_loc,
                            zone());
      }
    }
  }
}


Statement* Parser::ParseExportDefault(bool* ok) {
  //  Supports the following productions, starting after the 'default' token:
  //    'export' 'default' HoistableDeclaration
  //    'export' 'default' ClassDeclaration
  //    'export' 'default' AssignmentExpression[In] ';'

  Expect(Token::DEFAULT, CHECK_OK);
  Scanner::Location default_loc = scanner()->location();

  ZoneList<const AstRawString*> local_names(1, zone());
  Statement* result = nullptr;
  switch (peek()) {
    case Token::FUNCTION:
      result = ParseHoistableDeclaration(&local_names, true, CHECK_OK);
      break;

    case Token::CLASS:
      Consume(Token::CLASS);
      result = ParseClassDeclaration(&local_names, true, CHECK_OK);
      break;

    case Token::ASYNC:
      if (PeekAhead() == Token::FUNCTION &&
          !scanner()->HasAnyLineTerminatorAfterNext()) {
        Consume(Token::ASYNC);
        result = ParseAsyncFunctionDeclaration(&local_names, true, CHECK_OK);
        break;
      }
    /* falls through */

    default: {
      int pos = position();
      ExpressionClassifier classifier(this);
      Expression* value = ParseAssignmentExpression(true, CHECK_OK);
      RewriteNonPattern(CHECK_OK);
      SetFunctionName(value, ast_value_factory()->default_string());

      const AstRawString* local_name =
          ast_value_factory()->star_default_star_string();
      local_names.Add(local_name, zone());

      // It's fine to declare this as CONST because the user has no way of
      // writing to it.
      Declaration* decl = DeclareVariable(local_name, CONST, pos, CHECK_OK);
      decl->proxy()->var()->set_initializer_position(position());

      Assignment* assignment = factory()->NewAssignment(
          Token::INIT, decl->proxy(), value, kNoSourcePosition);
      result = IgnoreCompletion(
          factory()->NewExpressionStatement(assignment, kNoSourcePosition));

      ExpectSemicolon(CHECK_OK);
      break;
    }
  }

  DCHECK_EQ(local_names.length(), 1);
  module()->AddExport(local_names.first(),
                      ast_value_factory()->default_string(), default_loc,
                      zone());

  DCHECK_NOT_NULL(result);
  return result;
}

Statement* Parser::ParseExportDeclaration(bool* ok) {
  // ExportDeclaration:
  //    'export' '*' 'from' ModuleSpecifier ';'
  //    'export' ExportClause ('from' ModuleSpecifier)? ';'
  //    'export' VariableStatement
  //    'export' Declaration
  //    'export' 'default' ... (handled in ParseExportDefault)

  Expect(Token::EXPORT, CHECK_OK);
  int pos = position();

  Statement* result = nullptr;
  ZoneList<const AstRawString*> names(1, zone());
  Scanner::Location loc = scanner()->peek_location();
  switch (peek()) {
    case Token::DEFAULT:
      return ParseExportDefault(ok);

    case Token::MUL: {
      Consume(Token::MUL);
      loc = scanner()->location();
      ExpectContextualKeyword(Token::FROM, CHECK_OK);
      Scanner::Location specifier_loc = scanner()->peek_location();
      const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
      ExpectSemicolon(CHECK_OK);
      module()->AddStarExport(module_specifier, loc, specifier_loc, zone());
      return factory()->NewEmptyStatement(pos);
    }

    case Token::LBRACE: {
      // There are two cases here:
      //
      // 'export' ExportClause ';'
      // and
      // 'export' ExportClause FromClause ';'
      //
      // In the first case, the exported identifiers in ExportClause must
      // not be reserved words, while in the latter they may be. We
      // pass in a location that gets filled with the first reserved word
      // encountered, and then throw a SyntaxError if we are in the
      // non-FromClause case.
      Scanner::Location reserved_loc = Scanner::Location::invalid();
      ZoneList<const AstRawString*> export_names(1, zone());
      ZoneList<Scanner::Location> export_locations(1, zone());
      ZoneList<const AstRawString*> original_names(1, zone());
      ParseExportClause(&export_names, &export_locations, &original_names,
                        &reserved_loc, CHECK_OK);
      const AstRawString* module_specifier = nullptr;
      Scanner::Location specifier_loc;
      if (CheckContextualKeyword(Token::FROM)) {
        specifier_loc = scanner()->peek_location();
        module_specifier = ParseModuleSpecifier(CHECK_OK);
      } else if (reserved_loc.IsValid()) {
        // No FromClause, so reserved words are invalid in ExportClause.
        *ok = false;
        ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved);
        return nullptr;
      }
      ExpectSemicolon(CHECK_OK);
      const int length = export_names.length();
      DCHECK_EQ(length, original_names.length());
      DCHECK_EQ(length, export_locations.length());
      if (module_specifier == nullptr) {
        for (int i = 0; i < length; ++i) {
          module()->AddExport(original_names[i], export_names[i],
                              export_locations[i], zone());
        }
      } else if (length == 0) {
        module()->AddEmptyImport(module_specifier, specifier_loc);
      } else {
        for (int i = 0; i < length; ++i) {
          module()->AddExport(original_names[i], export_names[i],
                              module_specifier, export_locations[i],
                              specifier_loc, zone());
        }
      }
      return factory()->NewEmptyStatement(pos);
    }

    case Token::FUNCTION:
      result = ParseHoistableDeclaration(&names, false, CHECK_OK);
      break;

    case Token::CLASS:
      Consume(Token::CLASS);
      result = ParseClassDeclaration(&names, false, CHECK_OK);
      break;

    case Token::VAR:
    case Token::LET:
    case Token::CONST:
      result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
      break;

    case Token::ASYNC:
      // TODO(neis): Why don't we have the same check here as in
      // ParseStatementListItem?
      Consume(Token::ASYNC);
      result = ParseAsyncFunctionDeclaration(&names, false, CHECK_OK);
      break;

    default:
      *ok = false;
      ReportUnexpectedToken(scanner()->current_token());
      return nullptr;
  }
  loc.end_pos = scanner()->location().end_pos;

  ModuleDescriptor* descriptor = module();
  for (int i = 0; i < names.length(); ++i) {
    descriptor->AddExport(names[i], names[i], loc, zone());
  }

  DCHECK_NOT_NULL(result);
  return result;
}

VariableProxy* Parser::NewUnresolved(const AstRawString* name, int begin_pos,
                                     VariableKind kind) {
  return scope()->NewUnresolved(factory(), name, begin_pos, kind);
}

VariableProxy* Parser::NewUnresolved(const AstRawString* name) {
  return scope()->NewUnresolved(factory(), name, scanner()->location().beg_pos);
}

Declaration* Parser::DeclareVariable(const AstRawString* name,
                                     VariableMode mode, int pos, bool* ok) {
  return DeclareVariable(name, mode, Variable::DefaultInitializationFlag(mode),
                         pos, ok);
}

Declaration* Parser::DeclareVariable(const AstRawString* name,
                                     VariableMode mode, InitializationFlag init,
                                     int pos, bool* ok) {
  DCHECK_NOT_NULL(name);
  VariableProxy* proxy = factory()->NewVariableProxy(
      name, NORMAL_VARIABLE, scanner()->location().beg_pos);
  Declaration* declaration;
  if (mode == VAR && !scope()->is_declaration_scope()) {
    DCHECK(scope()->is_block_scope() || scope()->is_with_scope());
    declaration = factory()->NewNestedVariableDeclaration(proxy, scope(), pos);
  } else {
    declaration = factory()->NewVariableDeclaration(proxy, pos);
  }
  Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, ok, nullptr,
          scanner()->location().end_pos);
  if (!*ok) return nullptr;
  return declaration;
}

Variable* Parser::Declare(Declaration* declaration,
                          DeclarationDescriptor::Kind declaration_kind,
                          VariableMode mode, InitializationFlag init, bool* ok,
                          Scope* scope, int var_end_pos) {
  if (scope == nullptr) {
    scope = this->scope();
  }
  bool sloppy_mode_block_scope_function_redefinition = false;
  Variable* variable = scope->DeclareVariable(
      declaration, mode, init, &sloppy_mode_block_scope_function_redefinition,
      ok);
  if (!*ok) {
    // If we only have the start position of a proxy, we can't highlight the
    // whole variable name.  Pretend its length is 1 so that we highlight at
    // least the first character.
    Scanner::Location loc(declaration->proxy()->position(),
                          var_end_pos != kNoSourcePosition
                              ? var_end_pos
                              : declaration->proxy()->position() + 1);
    if (declaration_kind == DeclarationDescriptor::PARAMETER) {
      ReportMessageAt(loc, MessageTemplate::kParamDupe);
    } else {
      ReportMessageAt(loc, MessageTemplate::kVarRedeclaration,
                      declaration->proxy()->raw_name());
    }
    return nullptr;
  }
  if (sloppy_mode_block_scope_function_redefinition) {
    ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
  }
  return variable;
}

Block* Parser::BuildInitializationBlock(
    DeclarationParsingResult* parsing_result,
    ZoneList<const AstRawString*>* names, bool* ok) {
  Block* result = factory()->NewBlock(1, true);
  for (auto declaration : parsing_result->declarations) {
    DeclareAndInitializeVariables(result, &(parsing_result->descriptor),
                                  &declaration, names, CHECK_OK);
  }
  return result;
}

Statement* Parser::DeclareFunction(const AstRawString* variable_name,
                                   FunctionLiteral* function, VariableMode mode,
                                   int pos, bool is_sloppy_block_function,
                                   ZoneList<const AstRawString*>* names,
                                   bool* ok) {
  VariableProxy* proxy =
      factory()->NewVariableProxy(variable_name, NORMAL_VARIABLE);

  Declaration* declaration =
      factory()->NewFunctionDeclaration(proxy, function, pos);
  Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
          CHECK_OK);
  if (names) names->Add(variable_name, zone());
  if (is_sloppy_block_function) {
    SloppyBlockFunctionStatement* statement =
        factory()->NewSloppyBlockFunctionStatement();
    GetDeclarationScope()->DeclareSloppyBlockFunction(variable_name, scope(),
                                                      statement);
    return statement;
  }
  return factory()->NewEmptyStatement(kNoSourcePosition);
}

Statement* Parser::DeclareClass(const AstRawString* variable_name,
                                Expression* value,
                                ZoneList<const AstRawString*>* names,
                                int class_token_pos, int end_pos, bool* ok) {
  Declaration* decl =
      DeclareVariable(variable_name, LET, class_token_pos, CHECK_OK);
  decl->proxy()->var()->set_initializer_position(end_pos);
  if (names) names->Add(variable_name, zone());

  Assignment* assignment = factory()->NewAssignment(Token::INIT, decl->proxy(),
                                                    value, class_token_pos);
  return IgnoreCompletion(
      factory()->NewExpressionStatement(assignment, kNoSourcePosition));
}

Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) {
  // Make sure that the function containing the native declaration
  // isn't lazily compiled. The extension structures are only
  // accessible while parsing the first time not when reparsing
  // because of lazy compilation.
  GetClosureScope()->ForceEagerCompilation();

  // TODO(1240846): It's weird that native function declarations are
  // introduced dynamically when we meet their declarations, whereas
  // other functions are set up when entering the surrounding scope.
  Declaration* decl = DeclareVariable(name, VAR, pos, CHECK_OK);
  NativeFunctionLiteral* lit =
      factory()->NewNativeFunctionLiteral(name, extension_, kNoSourcePosition);
  return factory()->NewExpressionStatement(
      factory()->NewAssignment(Token::INIT, decl->proxy(), lit,
                               kNoSourcePosition),
      pos);
}

ZoneList<const AstRawString*>* Parser::DeclareLabel(
    ZoneList<const AstRawString*>* labels, VariableProxy* var, bool* ok) {
  DCHECK(IsIdentifier(var));
  const AstRawString* label = var->raw_name();
  // TODO(1240780): We don't check for redeclaration of labels
  // during preparsing since keeping track of the set of active
  // labels requires nontrivial changes to the way scopes are
  // structured.  However, these are probably changes we want to
  // make later anyway so we should go back and fix this then.
  if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
    ReportMessage(MessageTemplate::kLabelRedeclaration, label);
    *ok = false;
    return nullptr;
  }
  if (labels == nullptr) {
    labels = new (zone()) ZoneList<const AstRawString*>(1, zone());
  }
  labels->Add(label, zone());
  // Remove the "ghost" variable that turned out to be a label
  // from the top scope. This way, we don't try to resolve it
  // during the scope processing.
  scope()->RemoveUnresolved(var);
  return labels;
}

bool Parser::ContainsLabel(ZoneList<const AstRawString*>* labels,
                           const AstRawString* label) {
  DCHECK_NOT_NULL(label);
  if (labels != nullptr) {
    for (int i = labels->length(); i-- > 0;) {
      if (labels->at(i) == label) return true;
    }
  }
  return false;
}

Block* Parser::IgnoreCompletion(Statement* statement) {
  Block* block = factory()->NewBlock(1, true);
  block->statements()->Add(statement, zone());
  return block;
}

Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
  if (IsDerivedConstructor(function_state_->kind())) {
    // For subclass constructors we need to return this in case of undefined;
    // other primitive values trigger an exception in the ConstructStub.
    //
    //   return expr;
    //
    // Is rewritten as:
    //
    //   return (temp = expr) === undefined ? this : temp;

    // temp = expr
    Variable* temp = NewTemporary(ast_value_factory()->empty_string());
    Assignment* assign = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);

    // temp === undefined
    Expression* is_undefined = factory()->NewCompareOperation(
        Token::EQ_STRICT, assign,
        factory()->NewUndefinedLiteral(kNoSourcePosition), pos);

    // is_undefined ? this : temp
    return_value =
        factory()->NewConditional(is_undefined, ThisExpression(pos),
                                  factory()->NewVariableProxy(temp), pos);
  }
  return return_value;
}

Expression* Parser::RewriteDoExpression(Block* body, int pos, bool* ok) {
  Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
  DoExpression* expr = factory()->NewDoExpression(body, result, pos);
  if (!Rewriter::Rewrite(this, GetClosureScope(), expr, ast_value_factory())) {
    *ok = false;
    return nullptr;
  }
  return expr;
}

Statement* Parser::RewriteSwitchStatement(SwitchStatement* switch_statement,
                                          Scope* scope) {
  // In order to get the CaseClauses to execute in their own lexical scope,
  // but without requiring downstream code to have special scope handling
  // code for switch statements, desugar into blocks as follows:
  // {  // To group the statements--harmless to evaluate Expression in scope
  //   .tag_variable = Expression;
  //   {  // To give CaseClauses a scope
  //     switch (.tag_variable) { CaseClause* }
  //   }
  // }
  DCHECK_NOT_NULL(scope);
  DCHECK(scope->is_block_scope());
  DCHECK_GE(switch_statement->position(), scope->start_position());
  DCHECK_LT(switch_statement->position(), scope->end_position());

  Block* switch_block = factory()->NewBlock(2, false);

  Expression* tag = switch_statement->tag();
  Variable* tag_variable =
      NewTemporary(ast_value_factory()->dot_switch_tag_string());
  Assignment* tag_assign = factory()->NewAssignment(
      Token::ASSIGN, factory()->NewVariableProxy(tag_variable), tag,
      tag->position());
  // Wrap with IgnoreCompletion so the tag isn't returned as the completion
  // value, in case the switch statements don't have a value.
  Statement* tag_statement = IgnoreCompletion(
      factory()->NewExpressionStatement(tag_assign, kNoSourcePosition));
  switch_block->statements()->Add(tag_statement, zone());

  switch_statement->set_tag(factory()->NewVariableProxy(tag_variable));
  Block* cases_block = factory()->NewBlock(1, false);
  cases_block->statements()->Add(switch_statement, zone());
  cases_block->set_scope(scope);
  switch_block->statements()->Add(cases_block, zone());
  return switch_block;
}

void Parser::RewriteCatchPattern(CatchInfo* catch_info, bool* ok) {
  if (catch_info->name == nullptr) {
    DCHECK_NOT_NULL(catch_info->pattern);
    catch_info->name = ast_value_factory()->dot_catch_string();
  }
  Variable* catch_variable =
      catch_info->scope->DeclareLocal(catch_info->name, VAR);
  if (catch_info->pattern != nullptr) {
    DeclarationDescriptor descriptor;
    descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
    descriptor.scope = scope();
    descriptor.mode = LET;
    descriptor.declaration_pos = catch_info->pattern->position();
    descriptor.initialization_pos = catch_info->pattern->position();

    // Initializer position for variables declared by the pattern.
    const int initializer_position = position();

    DeclarationParsingResult::Declaration decl(
        catch_info->pattern, initializer_position,
        factory()->NewVariableProxy(catch_variable));

    catch_info->init_block = factory()->NewBlock(8, true);
    DeclareAndInitializeVariables(catch_info->init_block, &descriptor, &decl,
                                  &catch_info->bound_names, ok);
  } else {
    catch_info->bound_names.Add(catch_info->name, zone());
  }
}

void Parser::ValidateCatchBlock(const CatchInfo& catch_info, bool* ok) {
  // Check for `catch(e) { let e; }` and similar errors.
  Scope* inner_block_scope = catch_info.inner_block->scope();
  if (inner_block_scope != nullptr) {
    Declaration* decl = inner_block_scope->CheckLexDeclarationsConflictingWith(
        catch_info.bound_names);
    if (decl != nullptr) {
      const AstRawString* name = decl->proxy()->raw_name();
      int position = decl->proxy()->position();
      Scanner::Location location =
          position == kNoSourcePosition
              ? Scanner::Location::invalid()
              : Scanner::Location(position, position + 1);
      ReportMessageAt(location, MessageTemplate::kVarRedeclaration, name);
      *ok = false;
    }
  }
}

Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
                                       const SourceRange& catch_range,
                                       Block* finally_block,
                                       const SourceRange& finally_range,
                                       const CatchInfo& catch_info, int pos) {
  // Simplify the AST nodes by converting:
  //   'try B0 catch B1 finally B2'
  // to:
  //   'try { try B0 catch B1 } finally B2'

  if (catch_block != nullptr && finally_block != nullptr) {
    // If we have both, create an inner try/catch.
    DCHECK_NOT_NULL(catch_info.scope);
    TryCatchStatement* statement;
    statement = factory()->NewTryCatchStatement(try_block, catch_info.scope,
                                                catch_block, kNoSourcePosition);
    RecordTryCatchStatementSourceRange(statement, catch_range);

    try_block = factory()->NewBlock(1, false);
    try_block->statements()->Add(statement, zone());
    catch_block = nullptr;  // Clear to indicate it's been handled.
  }

  if (catch_block != nullptr) {
    DCHECK_NULL(finally_block);
    DCHECK_NOT_NULL(catch_info.scope);
    TryCatchStatement* stmt = factory()->NewTryCatchStatement(
        try_block, catch_info.scope, catch_block, pos);
    RecordTryCatchStatementSourceRange(stmt, catch_range);
    return stmt;
  } else {
    DCHECK_NOT_NULL(finally_block);
    TryFinallyStatement* stmt =
        factory()->NewTryFinallyStatement(try_block, finally_block, pos);
    RecordTryFinallyStatementSourceRange(stmt, finally_range);
    return stmt;
  }
}

void Parser::ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind,
                                                  ZoneList<Statement*>* body,
                                                  bool* ok) {
  // For ES6 Generators, we just prepend the initial yield.
  Expression* initial_yield = BuildInitialYield(pos, kind);
  body->Add(factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
            zone());
  ParseStatementList(body, Token::RBRACE, ok);
}

void Parser::ParseAndRewriteAsyncGeneratorFunctionBody(
    int pos, FunctionKind kind, ZoneList<Statement*>* body, bool* ok) {
  // For ES2017 Async Generators, we produce:
  //
  // try {
  //   InitialYield;
  //   ...body...;
  //   return undefined; // See comment below
  // } catch (.catch) {
  //   %AsyncGeneratorReject(generator, .catch);
  // } finally {
  //   %_GeneratorClose(generator);
  // }
  //
  // - InitialYield yields the actual generator object.
  // - Any return statement inside the body will have its argument wrapped
  //   in an iterator result object with a "done" property set to `true`.
  // - If the generator terminates for whatever reason, we must close it.
  //   Hence the finally clause.
  // - BytecodeGenerator performs special handling for ReturnStatements in
  //   async generator functions, resolving the appropriate Promise with an
  //   "done" iterator result object containing a Promise-unwrapped value.
  DCHECK(IsAsyncGeneratorFunction(kind));

  Block* try_block = factory()->NewBlock(3, false);
  Expression* initial_yield = BuildInitialYield(pos, kind);
  try_block->statements()->Add(
      factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
      zone());
  ParseStatementList(try_block->statements(), Token::RBRACE, ok);
  if (!*ok) return;

  // Don't create iterator result for async generators, as the resume methods
  // will create it.
  Statement* final_return = BuildReturnStatement(
      factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
  try_block->statements()->Add(final_return, zone());

  // For AsyncGenerators, a top-level catch block will reject the Promise.
  Scope* catch_scope = NewHiddenCatchScope();

  ZoneList<Expression*>* reject_args =
      new (zone()) ZoneList<Expression*>(2, zone());
  reject_args->Add(factory()->NewVariableProxy(
                       function_state_->scope()->generator_object_var()),
                   zone());
  reject_args->Add(factory()->NewVariableProxy(catch_scope->catch_variable()),
                   zone());

  Expression* reject_call = factory()->NewCallRuntime(
      Runtime::kInlineAsyncGeneratorReject, reject_args, kNoSourcePosition);
  Block* catch_block = IgnoreCompletion(
      factory()->NewReturnStatement(reject_call, kNoSourcePosition));

  TryStatement* try_catch = factory()->NewTryCatchStatementForAsyncAwait(
      try_block, catch_scope, catch_block, kNoSourcePosition);

  try_block = factory()->NewBlock(1, false);
  try_block->statements()->Add(try_catch, zone());

  Block* finally_block = factory()->NewBlock(1, false);
  ZoneList<Expression*>* close_args =
      new (zone()) ZoneList<Expression*>(1, zone());
  VariableProxy* call_proxy = factory()->NewVariableProxy(
      function_state_->scope()->generator_object_var());
  close_args->Add(call_proxy, zone());
  Expression* close_call = factory()->NewCallRuntime(
      Runtime::kInlineGeneratorClose, close_args, kNoSourcePosition);
  finally_block->statements()->Add(
      factory()->NewExpressionStatement(close_call, kNoSourcePosition), zone());

  body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
                                              kNoSourcePosition),
            zone());
}

void Parser::CreateFunctionNameAssignment(
    const AstRawString* function_name, int pos,
    FunctionLiteral::FunctionType function_type,
    DeclarationScope* function_scope, ZoneList<Statement*>* result, int index) {
  if (function_type == FunctionLiteral::kNamedExpression) {
    StatementT statement = factory()->NewEmptyStatement(kNoSourcePosition);
    if (function_scope->LookupLocal(function_name) == nullptr) {
      // Now that we know the language mode, we can create the const assignment
      // in the previously reserved spot.
      DCHECK_EQ(function_scope, scope());
      Variable* fvar = function_scope->DeclareFunctionVar(function_name);
      VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
      statement = factory()->NewExpressionStatement(
          factory()->NewAssignment(Token::INIT, fproxy,
                                   factory()->NewThisFunction(pos),
                                   kNoSourcePosition),
          kNoSourcePosition);
    }
    result->Set(index, statement);
  }
}

// [if (IteratorType == kNormal)]
//     !%_IsJSReceiver(result = iterator.next()) &&
//         %ThrowIteratorResultNotAnObject(result)
// [else if (IteratorType == kAsync)]
//     !%_IsJSReceiver(result = Await(iterator.next())) &&
//         %ThrowIteratorResultNotAnObject(result)
// [endif]
Expression* Parser::BuildIteratorNextResult(Expression* iterator,
                                            Variable* result, IteratorType type,
                                            int pos) {
  Expression* next_literal = factory()->NewStringLiteral(
      ast_value_factory()->next_string(), kNoSourcePosition);
  Expression* next_property =
      factory()->NewProperty(iterator, next_literal, kNoSourcePosition);
  ZoneList<Expression*>* next_arguments =
      new (zone()) ZoneList<Expression*>(0, zone());
  Expression* next_call =
      factory()->NewCall(next_property, next_arguments, kNoSourcePosition);
  if (type == IteratorType::kAsync) {
    next_call = factory()->NewAwait(next_call, pos);
  }
  Expression* result_proxy = factory()->NewVariableProxy(result);
  Expression* left =
      factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);

  // %_IsJSReceiver(...)
  ZoneList<Expression*>* is_spec_object_args =
      new (zone()) ZoneList<Expression*>(1, zone());
  is_spec_object_args->Add(left, zone());
  Expression* is_spec_object_call = factory()->NewCallRuntime(
      Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);

  // %ThrowIteratorResultNotAnObject(result)
  Expression* result_proxy_again = factory()->NewVariableProxy(result);
  ZoneList<Expression*>* throw_arguments =
      new (zone()) ZoneList<Expression*>(1, zone());
  throw_arguments->Add(result_proxy_again, zone());
  Expression* throw_call = factory()->NewCallRuntime(
      Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);

  return factory()->NewBinaryOperation(
      Token::AND,
      factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
      throw_call, pos);
}

Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt,
                                              Expression* each,
                                              Expression* subject,
                                              Statement* body) {
  ForOfStatement* for_of = stmt->AsForOfStatement();
  if (for_of != nullptr) {
    const bool finalize = true;
    return InitializeForOfStatement(for_of, each, subject, body, finalize,
                                    IteratorType::kNormal, each->position());
  } else {
    if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
      Variable* temp = NewTemporary(ast_value_factory()->empty_string());
      VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
      Expression* assign_each =
          RewriteDestructuringAssignment(factory()->NewAssignment(
              Token::ASSIGN, each, temp_proxy, kNoSourcePosition));
      auto block = factory()->NewBlock(2, false);
      block->statements()->Add(
          factory()->NewExpressionStatement(assign_each, kNoSourcePosition),
          zone());
      block->statements()->Add(body, zone());
      body = block;
      each = factory()->NewVariableProxy(temp);
    }
    MarkExpressionAsAssigned(each);
    stmt->AsForInStatement()->Initialize(each, subject, body);
  }
  return stmt;
}

// Special case for legacy for
//
//    for (var x = initializer in enumerable) body
//
// An initialization block of the form
//
//    {
//      x = initializer;
//    }
//
// is returned in this case.  It has reserved space for two statements,
// so that (later on during parsing), the equivalent of
//
//   for (x in enumerable) body
//
// is added as a second statement to it.
Block* Parser::RewriteForVarInLegacy(const ForInfo& for_info) {
  const DeclarationParsingResult::Declaration& decl =
      for_info.parsing_result.declarations[0];
  if (!IsLexicalVariableMode(for_info.parsing_result.descriptor.mode) &&
      decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
    ++use_counts_[v8::Isolate::kForInInitializer];
    const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name();
    VariableProxy* single_var = NewUnresolved(name);
    Block* init_block = factory()->NewBlock(2, true);
    init_block->statements()->Add(
        factory()->NewExpressionStatement(
            factory()->NewAssignment(Token::ASSIGN, single_var,
                                     decl.initializer, kNoSourcePosition),
            kNoSourcePosition),
        zone());
    return init_block;
  }
  return nullptr;
}

// Rewrite a for-in/of statement of the form
//
//   for (let/const/var x in/of e) b
//
// into
//
//   {
//     var temp;
//     for (temp in/of e) {
//       let/const/var x = temp;
//       b;
//     }
//     let x;  // for TDZ
//   }
void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
                                              Block** body_block,
                                              Expression** each_variable,
                                              bool* ok) {
  DCHECK_EQ(1, for_info->parsing_result.declarations.size());
  DeclarationParsingResult::Declaration& decl =
      for_info->parsing_result.declarations[0];
  Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
  auto each_initialization_block = factory()->NewBlock(1, true);
  {
    auto descriptor = for_info->parsing_result.descriptor;
    descriptor.declaration_pos = kNoSourcePosition;
    descriptor.initialization_pos = kNoSourcePosition;
    descriptor.scope = scope();
    decl.initializer = factory()->NewVariableProxy(temp);

    bool is_for_var_of =
        for_info->mode == ForEachStatement::ITERATE &&
        for_info->parsing_result.descriptor.mode == VariableMode::VAR;
    bool collect_names =
        IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
        is_for_var_of;

    DeclareAndInitializeVariables(
        each_initialization_block, &descriptor, &decl,
        collect_names ? &for_info->bound_names : nullptr, CHECK_OK_VOID);

    // Annex B.3.5 prohibits the form
    // `try {} catch(e) { for (var e of {}); }`
    // So if we are parsing a statement like `for (var ... of ...)`
    // we need to walk up the scope chain and look for catch scopes
    // which have a simple binding, then compare their binding against
    // all of the names declared in the init of the for-of we're
    // parsing.
    if (is_for_var_of) {
      Scope* catch_scope = scope();
      while (catch_scope != nullptr && !catch_scope->is_declaration_scope()) {
        if (catch_scope->is_catch_scope()) {
          auto name = catch_scope->catch_variable()->raw_name();
          // If it's a simple binding and the name is declared in the for loop.
          if (name != ast_value_factory()->dot_catch_string() &&
              for_info->bound_names.Contains(name)) {
            ReportMessageAt(for_info->parsing_result.bindings_loc,
                            MessageTemplate::kVarRedeclaration, name);
            *ok = false;
            return;
          }
        }
        catch_scope = catch_scope->outer_scope();
      }
    }
  }

  *body_block = factory()->NewBlock(3, false);
  (*body_block)->statements()->Add(each_initialization_block, zone());
  *each_variable = factory()->NewVariableProxy(temp, for_info->position);
}

// Create a TDZ for any lexically-bound names in for in/of statements.
Block* Parser::CreateForEachStatementTDZ(Block* init_block,
                                         const ForInfo& for_info, bool* ok) {
  if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) {
    DCHECK_NULL(init_block);

    init_block = factory()->NewBlock(1, false);

    for (int i = 0; i < for_info.bound_names.length(); ++i) {
      // TODO(adamk): This needs to be some sort of special
      // INTERNAL variable that's invisible to the debugger
      // but visible to everything else.
      Declaration* tdz_decl = DeclareVariable(for_info.bound_names[i], LET,
                                              kNoSourcePosition, CHECK_OK);
      tdz_decl->proxy()->var()->set_initializer_position(position());
    }
  }
  return init_block;
}

Statement* Parser::InitializeForOfStatement(
    ForOfStatement* for_of, Expression* each, Expression* iterable,
    Statement* body, bool finalize, IteratorType type, int next_result_pos) {
  // Create the auxiliary expressions needed for iterating over the iterable,
  // and initialize the given ForOfStatement with them.
  // If finalize is true, also instrument the loop with code that performs the
  // proper ES6 iterator finalization.  In that case, the result is not
  // immediately a ForOfStatement.
  const int nopos = kNoSourcePosition;
  auto avfactory = ast_value_factory();

  Variable* iterator = NewTemporary(avfactory->dot_iterator_string());
  Variable* result = NewTemporary(avfactory->dot_result_string());
  Variable* completion = NewTemporary(avfactory->empty_string());

  // iterator = GetIterator(iterable, type)
  Expression* assign_iterator;
  {
    assign_iterator = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(iterator),
        factory()->NewGetIterator(iterable, type, iterable->position()),
        iterable->position());
  }

  // [if (IteratorType == kNormal)]
  //     !%_IsJSReceiver(result = iterator.next()) &&
  //         %ThrowIteratorResultNotAnObject(result)
  // [else if (IteratorType == kAsync)]
  //     !%_IsJSReceiver(result = Await(iterator.next())) &&
  //         %ThrowIteratorResultNotAnObject(result)
  // [endif]
  Expression* next_result;
  {
    Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
    next_result =
        BuildIteratorNextResult(iterator_proxy, result, type, next_result_pos);
  }

  // result.done
  Expression* result_done;
  {
    Expression* done_literal = factory()->NewStringLiteral(
        ast_value_factory()->done_string(), kNoSourcePosition);
    Expression* result_proxy = factory()->NewVariableProxy(result);
    result_done =
        factory()->NewProperty(result_proxy, done_literal, kNoSourcePosition);
  }

  // result.value
  Expression* result_value;
  {
    Expression* value_literal =
        factory()->NewStringLiteral(avfactory->value_string(), nopos);
    Expression* result_proxy = factory()->NewVariableProxy(result);
    result_value = factory()->NewProperty(result_proxy, value_literal, nopos);
  }

  // {{tmp = #result_value, completion = kAbruptCompletion, tmp}}
  // Expression* result_value (gets overwritten)
  if (finalize) {
    Variable* tmp = NewTemporary(avfactory->empty_string());
    Expression* save_result = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(tmp), result_value, nopos);

    Expression* set_completion_abrupt = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(completion),
        factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);

    result_value = factory()->NewBinaryOperation(Token::COMMA, save_result,
                                                 set_completion_abrupt, nopos);
    result_value = factory()->NewBinaryOperation(
        Token::COMMA, result_value, factory()->NewVariableProxy(tmp), nopos);
  }

  // each = #result_value;
  Expression* assign_each;
  {
    assign_each =
        factory()->NewAssignment(Token::ASSIGN, each, result_value, nopos);
    if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
      assign_each = RewriteDestructuringAssignment(assign_each->AsAssignment());
    }
  }

  // {{completion = kNormalCompletion;}}
  Statement* set_completion_normal;
  if (finalize) {
    Expression* proxy = factory()->NewVariableProxy(completion);
    Expression* assignment = factory()->NewAssignment(
        Token::ASSIGN, proxy,
        factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);

    set_completion_normal =
        IgnoreCompletion(factory()->NewExpressionStatement(assignment, nopos));
  }

  // { #loop-body; #set_completion_normal }
  // Statement* body (gets overwritten)
  if (finalize) {
    Block* block = factory()->NewBlock(2, false);
    block->statements()->Add(body, zone());
    block->statements()->Add(set_completion_normal, zone());
    body = block;
  }

  for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
                     assign_each);
  return finalize ? FinalizeForOfStatement(for_of, completion, type, nopos)
                  : for_of;
}

Statement* Parser::DesugarLexicalBindingsInForStatement(
    ForStatement* loop, Statement* init, Expression* cond, Statement* next,
    Statement* body, Scope* inner_scope, const ForInfo& for_info, bool* ok) {
  // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
  // copied into a new environment.  Moreover, the "next" statement must be
  // evaluated not in the environment of the just completed iteration but in
  // that of the upcoming one.  We achieve this with the following desugaring.
  // Extra care is needed to preserve the completion value of the original loop.
  //
  // We are given a for statement of the form
  //
  //  labels: for (let/const x = i; cond; next) body
  //
  // and rewrite it as follows.  Here we write {{ ... }} for init-blocks, ie.,
  // blocks whose ignore_completion_value_ flag is set.
  //
  //  {
  //    let/const x = i;
  //    temp_x = x;
  //    first = 1;
  //    undefined;
  //    outer: for (;;) {
  //      let/const x = temp_x;
  //      {{ if (first == 1) {
  //           first = 0;
  //         } else {
  //           next;
  //         }
  //         flag = 1;
  //         if (!cond) break;
  //      }}
  //      labels: for (; flag == 1; flag = 0, temp_x = x) {
  //        body
  //      }
  //      {{ if (flag == 1)  // Body used break.
  //           break;
  //      }}
  //    }
  //  }

  DCHECK_GT(for_info.bound_names.length(), 0);
  ZoneList<Variable*> temps(for_info.bound_names.length(), zone());

  Block* outer_block =
      factory()->NewBlock(for_info.bound_names.length() + 4, false);

  // Add statement: let/const x = i.
  outer_block->statements()->Add(init, zone());

  const AstRawString* temp_name = ast_value_factory()->dot_for_string();

  // For each lexical variable x:
  //   make statement: temp_x = x.
  for (int i = 0; i < for_info.bound_names.length(); i++) {
    VariableProxy* proxy = NewUnresolved(for_info.bound_names[i]);
    Variable* temp = NewTemporary(temp_name);
    VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
    Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, temp_proxy,
                                                      proxy, kNoSourcePosition);
    Statement* assignment_statement =
        factory()->NewExpressionStatement(assignment, kNoSourcePosition);
    outer_block->statements()->Add(assignment_statement, zone());
    temps.Add(temp, zone());
  }

  Variable* first = nullptr;
  // Make statement: first = 1.
  if (next) {
    first = NewTemporary(temp_name);
    VariableProxy* first_proxy = factory()->NewVariableProxy(first);
    Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
    Assignment* assignment = factory()->NewAssignment(
        Token::ASSIGN, first_proxy, const1, kNoSourcePosition);
    Statement* assignment_statement =
        factory()->NewExpressionStatement(assignment, kNoSourcePosition);
    outer_block->statements()->Add(assignment_statement, zone());
  }

  // make statement: undefined;
  outer_block->statements()->Add(
      factory()->NewExpressionStatement(
          factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition),
      zone());

  // Make statement: outer: for (;;)
  // Note that we don't actually create the label, or set this loop up as an
  // explicit break target, instead handing it directly to those nodes that
  // need to know about it. This should be safe because we don't run any code
  // in this function that looks up break targets.
  ForStatement* outer_loop =
      factory()->NewForStatement(nullptr, kNoSourcePosition);
  outer_block->statements()->Add(outer_loop, zone());
  outer_block->set_scope(scope());

  Block* inner_block = factory()->NewBlock(3, false);
  {
    BlockState block_state(&scope_, inner_scope);

    Block* ignore_completion_block =
        factory()->NewBlock(for_info.bound_names.length() + 3, true);
    ZoneList<Variable*> inner_vars(for_info.bound_names.length(), zone());
    // For each let variable x:
    //    make statement: let/const x = temp_x.
    for (int i = 0; i < for_info.bound_names.length(); i++) {
      Declaration* decl = DeclareVariable(
          for_info.bound_names[i], for_info.parsing_result.descriptor.mode,
          kNoSourcePosition, CHECK_OK);
      inner_vars.Add(decl->proxy()->var(), zone());
      VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
      Assignment* assignment = factory()->NewAssignment(
          Token::INIT, decl->proxy(), temp_proxy, kNoSourcePosition);
      Statement* assignment_statement =
          factory()->NewExpressionStatement(assignment, kNoSourcePosition);
      int declaration_pos = for_info.parsing_result.descriptor.declaration_pos;
      DCHECK_NE(declaration_pos, kNoSourcePosition);
      decl->proxy()->var()->set_initializer_position(declaration_pos);
      ignore_completion_block->statements()->Add(assignment_statement, zone());
    }

    // Make statement: if (first == 1) { first = 0; } else { next; }
    if (next) {
      DCHECK(first);
      Expression* compare = nullptr;
      // Make compare expression: first == 1.
      {
        Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
        VariableProxy* first_proxy = factory()->NewVariableProxy(first);
        compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
                                                 kNoSourcePosition);
      }
      Statement* clear_first = nullptr;
      // Make statement: first = 0.
      {
        VariableProxy* first_proxy = factory()->NewVariableProxy(first);
        Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition);
        Assignment* assignment = factory()->NewAssignment(
            Token::ASSIGN, first_proxy, const0, kNoSourcePosition);
        clear_first =
            factory()->NewExpressionStatement(assignment, kNoSourcePosition);
      }
      Statement* clear_first_or_next = factory()->NewIfStatement(
          compare, clear_first, next, kNoSourcePosition);
      ignore_completion_block->statements()->Add(clear_first_or_next, zone());
    }

    Variable* flag = NewTemporary(temp_name);
    // Make statement: flag = 1.
    {
      VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
      Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
      Assignment* assignment = factory()->NewAssignment(
          Token::ASSIGN, flag_proxy, const1, kNoSourcePosition);
      Statement* assignment_statement =
          factory()->NewExpressionStatement(assignment, kNoSourcePosition);
      ignore_completion_block->statements()->Add(assignment_statement, zone());
    }

    // Make statement: if (!cond) break.
    if (cond) {
      Statement* stop =
          factory()->NewBreakStatement(outer_loop, kNoSourcePosition);
      Statement* noop = factory()->NewEmptyStatement(kNoSourcePosition);
      ignore_completion_block->statements()->Add(
          factory()->NewIfStatement(cond, noop, stop, cond->position()),
          zone());
    }

    inner_block->statements()->Add(ignore_completion_block, zone());
    // Make cond expression for main loop: flag == 1.
    Expression* flag_cond = nullptr;
    {
      Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
      VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
      flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
                                                 kNoSourcePosition);
    }

    // Create chain of expressions "flag = 0, temp_x = x, ..."
    Statement* compound_next_statement = nullptr;
    {
      Expression* compound_next = nullptr;
      // Make expression: flag = 0.
      {
        VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
        Expression* const0 = factory()->NewSmiLiteral(0, kNoSourcePosition);
        compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy,
                                                 const0, kNoSourcePosition);
      }

      // Make the comma-separated list of temp_x = x assignments.
      int inner_var_proxy_pos = scanner()->location().beg_pos;
      for (int i = 0; i < for_info.bound_names.length(); i++) {
        VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
        VariableProxy* proxy =
            factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
        Assignment* assignment = factory()->NewAssignment(
            Token::ASSIGN, temp_proxy, proxy, kNoSourcePosition);
        compound_next = factory()->NewBinaryOperation(
            Token::COMMA, compound_next, assignment, kNoSourcePosition);
      }

      compound_next_statement =
          factory()->NewExpressionStatement(compound_next, kNoSourcePosition);
    }

    // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
    // Note that we re-use the original loop node, which retains its labels
    // and ensures that any break or continue statements in body point to
    // the right place.
    loop->Initialize(nullptr, flag_cond, compound_next_statement, body);
    inner_block->statements()->Add(loop, zone());

    // Make statement: {{if (flag == 1) break;}}
    {
      Expression* compare = nullptr;
      // Make compare expresion: flag == 1.
      {
        Expression* const1 = factory()->NewSmiLiteral(1, kNoSourcePosition);
        VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
        compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
                                                 kNoSourcePosition);
      }
      Statement* stop =
          factory()->NewBreakStatement(outer_loop, kNoSourcePosition);
      Statement* empty = factory()->NewEmptyStatement(kNoSourcePosition);
      Statement* if_flag_break =
          factory()->NewIfStatement(compare, stop, empty, kNoSourcePosition);
      inner_block->statements()->Add(IgnoreCompletion(if_flag_break), zone());
    }

    inner_block->set_scope(inner_scope);
  }

  outer_loop->Initialize(nullptr, nullptr, nullptr, inner_block);

  return outer_block;
}

void Parser::AddArrowFunctionFormalParameters(
    ParserFormalParameters* parameters, Expression* expr, int end_pos,
    bool* ok) {
  // ArrowFunctionFormals ::
  //    Nary(Token::COMMA, VariableProxy*, Tail)
  //    Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
  //    Tail
  // NonTailArrowFunctionFormals ::
  //    Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy)
  //    VariableProxy
  // Tail ::
  //    VariableProxy
  //    Spread(VariableProxy)
  //
  // We need to visit the parameters in left-to-right order
  //

  // For the Nary case, we simply visit the parameters in a loop.
  if (expr->IsNaryOperation()) {
    NaryOperation* nary = expr->AsNaryOperation();
    // The classifier has already run, so we know that the expression is a valid
    // arrow function formals production.
    DCHECK_EQ(nary->op(), Token::COMMA);
    // Each op position is the end position of the *previous* expr, with the
    // second (i.e. first "subsequent") op position being the end position of
    // the first child expression.
    Expression* next = nary->first();
    for (size_t i = 0; i < nary->subsequent_length(); ++i) {
      AddArrowFunctionFormalParameters(
          parameters, next, nary->subsequent_op_position(i), CHECK_OK_VOID);
      next = nary->subsequent(i);
    }
    AddArrowFunctionFormalParameters(parameters, next, end_pos, CHECK_OK_VOID);
    return;
  }

  // For the binary case, we recurse on the left-hand side of binary comma
  // expressions.
  if (expr->IsBinaryOperation()) {
    BinaryOperation* binop = expr->AsBinaryOperation();
    // The classifier has already run, so we know that the expression is a valid
    // arrow function formals production.
    DCHECK_EQ(binop->op(), Token::COMMA);
    Expression* left = binop->left();
    Expression* right = binop->right();
    int comma_pos = binop->position();
    AddArrowFunctionFormalParameters(parameters, left, comma_pos,
                                     CHECK_OK_VOID);
    // LHS of comma expression should be unparenthesized.
    expr = right;
  }

  // Only the right-most expression may be a rest parameter.
  DCHECK(!parameters->has_rest);

  bool is_rest = expr->IsSpread();
  if (is_rest) {
    expr = expr->AsSpread()->expression();
    parameters->has_rest = true;
  }
  DCHECK_IMPLIES(parameters->is_simple, !is_rest);
  DCHECK_IMPLIES(parameters->is_simple, expr->IsVariableProxy());

  Expression* initializer = nullptr;
  if (expr->IsAssignment()) {
    if (expr->IsRewritableExpression()) {
      // This expression was parsed as a possible destructuring assignment.
      // Mark it as already-rewritten to avoid an unnecessary visit later.
      expr->AsRewritableExpression()->set_rewritten();
    }
    Assignment* assignment = expr->AsAssignment();
    DCHECK(!assignment->IsCompoundAssignment());
    initializer = assignment->value();
    expr = assignment->target();
  }

  AddFormalParameter(parameters, expr, initializer,
                     end_pos, is_rest);
}

void Parser::DeclareArrowFunctionFormalParameters(
    ParserFormalParameters* parameters, Expression* expr,
    const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
    bool* ok) {
  if (expr->IsEmptyParentheses()) return;

  AddArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos,
                                   CHECK_OK_VOID);

  if (parameters->arity > Code::kMaxArguments) {
    ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
    *ok = false;
    return;
  }

  bool has_duplicate = false;
  DeclareFormalParameters(parameters->scope, parameters->params,
                          parameters->is_simple, &has_duplicate);
  if (has_duplicate) {
    *duplicate_loc = scanner()->location();
  }
  DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
}

void Parser::PrepareGeneratorVariables() {
  // The code produced for generators relies on forced context allocation of
  // parameters (it does not restore the frame's parameters upon resume).
  function_state_->scope()->ForceContextAllocationForParameters();

  // Calling a generator returns a generator object.  That object is stored
  // in a temporary variable, a definition that is used by "yield"
  // expressions.
  function_state_->scope()->DeclareGeneratorObjectVar(
      ast_value_factory()->dot_generator_object_string());
}

FunctionLiteral* Parser::ParseFunctionLiteral(
    const AstRawString* function_name, Scanner::Location function_name_location,
    FunctionNameValidity function_name_validity, FunctionKind kind,
    int function_token_pos, FunctionLiteral::FunctionType function_type,
    LanguageMode language_mode, bool* ok) {
  // Function ::
  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
  //
  // Getter ::
  //   '(' ')' '{' FunctionBody '}'
  //
  // Setter ::
  //   '(' PropertySetParameterList ')' '{' FunctionBody '}'

  int pos = function_token_pos == kNoSourcePosition ? peek_position()
                                                    : function_token_pos;

  // Anonymous functions were passed either the empty symbol or a null
  // handle as the function name.  Remember if we were passed a non-empty
  // handle to decide whether to invoke function name inference.
  bool should_infer_name = function_name == nullptr;

  // We want a non-null handle as the function name by default. We will handle
  // the "function does not have a shared name" case later.
  if (should_infer_name) {
    function_name = ast_value_factory()->empty_string();
  }

  FunctionLiteral::EagerCompileHint eager_compile_hint =
      function_state_->next_function_is_likely_called()
          ? FunctionLiteral::kShouldEagerCompile
          : default_eager_compile_hint();

  // Determine if the function can be parsed lazily. Lazy parsing is
  // different from lazy compilation; we need to parse more eagerly than we
  // compile.

  // We can only parse lazily if we also compile lazily. The heuristics for lazy
  // compilation are:
  // - It must not have been prohibited by the caller to Parse (some callers
  //   need a full AST).
  // - The outer scope must allow lazy compilation of inner functions.
  // - The function mustn't be a function expression with an open parenthesis
  //   before; we consider that a hint that the function will be called
  //   immediately, and it would be a waste of time to make it lazily
  //   compiled.
  // These are all things we can know at this point, without looking at the
  // function itself.

  // We separate between lazy parsing top level functions and lazy parsing inner
  // functions, because the latter needs to do more work. In particular, we need
  // to track unresolved variables to distinguish between these cases:
  // (function foo() {
  //   bar = function() { return 1; }
  //  })();
  // and
  // (function foo() {
  //   var a = 1;
  //   bar = function() { return a; }
  //  })();

  // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
  // parenthesis before the function means that it will be called
  // immediately). bar can be parsed lazily, but we need to parse it in a mode
  // that tracks unresolved variables.
  DCHECK_IMPLIES(parse_lazily(), FLAG_lazy);
  DCHECK_IMPLIES(parse_lazily(), allow_lazy_);
  DCHECK_IMPLIES(parse_lazily(), extension_ == nullptr);

  const bool is_lazy =
      eager_compile_hint == FunctionLiteral::kShouldLazyCompile;
  const bool is_top_level =
      impl()->AllowsLazyParsingWithoutUnresolvedVariables();
  const bool is_lazy_top_level_function = is_lazy && is_top_level;
  const bool is_lazy_inner_function = is_lazy && !is_top_level;
  const bool is_expression =
      function_type == FunctionLiteral::kAnonymousExpression ||
      function_type == FunctionLiteral::kNamedExpression;

  RuntimeCallTimerScope runtime_timer(
      runtime_call_stats_,
      parsing_on_main_thread_
          ? &RuntimeCallStats::ParseFunctionLiteral
          : &RuntimeCallStats::ParseBackgroundFunctionLiteral);

  // Determine whether we can still lazy parse the inner function.
  // The preconditions are:
  // - Lazy compilation has to be enabled.
  // - Neither V8 natives nor native function declarations can be allowed,
  //   since parsing one would retroactively force the function to be
  //   eagerly compiled.
  // - The invoker of this parser can't depend on the AST being eagerly
  //   built (either because the function is about to be compiled, or
  //   because the AST is going to be inspected for some reason).
  // - Because of the above, we can't be attempting to parse a
  //   FunctionExpression; even without enclosing parentheses it might be
  //   immediately invoked.
  // - The function literal shouldn't be hinted to eagerly compile.

  // Inner functions will be parsed using a temporary Zone. After parsing, we
  // will migrate unresolved variable into a Scope in the main Zone.

  const bool should_preparse_inner =
      parse_lazily() && FLAG_lazy_inner_functions && is_lazy_inner_function &&
      (!is_expression || FLAG_aggressive_lazy_inner_functions);

  // This may be modified later to reflect preparsing decision taken
  bool should_preparse =
      (parse_lazily() && is_lazy_top_level_function) || should_preparse_inner;

  ZoneList<Statement*>* body = nullptr;
  int expected_property_count = -1;
  int num_parameters = -1;
  int function_length = -1;
  bool has_duplicate_parameters = false;
  int function_literal_id = GetNextFunctionLiteralId();
  ProducedPreParsedScopeData* produced_preparsed_scope_data = nullptr;

  Zone* outer_zone = zone();
  DeclarationScope* scope;

  {
    // Temporary zones can nest. When we migrate free variables (see below), we
    // need to recreate them in the previous Zone.
    AstNodeFactory previous_zone_ast_node_factory(ast_value_factory(), zone());

    // Open a new zone scope, which sets our AstNodeFactory to allocate in the
    // new temporary zone if the preconditions are satisfied, and ensures that
    // the previous zone is always restored after parsing the body. To be able
    // to do scope analysis correctly after full parsing, we migrate needed
    // information when the function is parsed.
    Zone temp_zone(zone()->allocator(), ZONE_NAME);
    DiscardableZoneScope zone_scope(this, &temp_zone, should_preparse);

    // This Scope lives in the main zone. We'll migrate data into that zone
    // later.
    scope = NewFunctionScope(kind, outer_zone);
    SetLanguageMode(scope, language_mode);
#ifdef DEBUG
    scope->SetScopeName(function_name);
    if (should_preparse) scope->set_needs_migration();
#endif

    Expect(Token::LPAREN, CHECK_OK);
    scope->set_start_position(scanner()->location().beg_pos);

    // Eager or lazy parse? If is_lazy_top_level_function, we'll parse
    // lazily. We'll call SkipFunction, which may decide to
    // abort lazy parsing if it suspects that wasn't a good idea. If so (in
    // which case the parser is expected to have backtracked), or if we didn't
    // try to lazy parse in the first place, we'll have to parse eagerly.
    if (should_preparse) {
      DCHECK(parse_lazily());
      DCHECK(is_lazy_top_level_function || is_lazy_inner_function);
      Scanner::BookmarkScope bookmark(scanner());
      bookmark.Set();
      LazyParsingResult result = SkipFunction(
          function_name, kind, function_type, scope, &num_parameters,
          &produced_preparsed_scope_data, is_lazy_inner_function,
          is_lazy_top_level_function, CHECK_OK);

      if (result == kLazyParsingAborted) {
        DCHECK(is_lazy_top_level_function);
        bookmark.Apply();
        // This is probably an initialization function. Inform the compiler it
        // should also eager-compile this function.
        eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
        scope->ResetAfterPreparsing(ast_value_factory(), true);
        zone_scope.Reset();
        // Trigger eager (re-)parsing, just below this block.
        should_preparse = false;
      }
    }

    if (should_preparse) {
      scope->AnalyzePartially(&previous_zone_ast_node_factory);
    } else {
      body = ParseFunction(function_name, pos, kind, function_type, scope,
                           &num_parameters, &function_length,
                           &has_duplicate_parameters, &expected_property_count,
                           CHECK_OK);
    }

    DCHECK_EQ(should_preparse, temp_zoned_);
    if (V8_UNLIKELY(FLAG_trace_preparse)) {
      PrintF("  [%s]: %i-%i %.*s\n",
             should_preparse ? (is_top_level ? "Preparse no-resolution"
                                             : "Preparse resolution")
                             : "Full parse",
             scope->start_position(), scope->end_position(),
             function_name->byte_length(), function_name->raw_data());
    }
    if (V8_UNLIKELY(FLAG_runtime_stats)) {
      if (should_preparse) {
        RuntimeCallStats::CounterId counter_id =
            parsing_on_main_thread_
                ? &RuntimeCallStats::PreParseWithVariableResolution
                : &RuntimeCallStats::PreParseBackgroundWithVariableResolution;
        if (is_top_level) {
          counter_id =
              parsing_on_main_thread_
                  ? &RuntimeCallStats::PreParseNoVariableResolution
                  : &RuntimeCallStats::PreParseBackgroundNoVariableResolution;
        }
        RuntimeCallStats::CorrectCurrentCounterId(runtime_call_stats_,
                                                  counter_id);
      }
    }

    // Validate function name. We can do this only after parsing the function,
    // since the function can declare itself strict.
    language_mode = scope->language_mode();
    CheckFunctionName(language_mode, function_name, function_name_validity,
                      function_name_location, CHECK_OK);

    if (is_strict(language_mode)) {
      CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
                              CHECK_OK);
    }
    CheckConflictingVarDeclarations(scope, CHECK_OK);
  }  // DiscardableZoneScope goes out of scope.

  FunctionLiteral::ParameterFlag duplicate_parameters =
      has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
                               : FunctionLiteral::kNoDuplicateParameters;

  // Note that the FunctionLiteral needs to be created in the main Zone again.
  FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
      function_name, scope, body, expected_property_count, num_parameters,
      function_length, duplicate_parameters, function_type, eager_compile_hint,
      pos, true, function_literal_id, produced_preparsed_scope_data);
  function_literal->set_function_token_position(function_token_pos);

  if (should_infer_name) {
    DCHECK_NOT_NULL(fni_);
    fni_->AddFunction(function_literal);
  }
  return function_literal;
}

Parser::LazyParsingResult Parser::SkipFunction(
    const AstRawString* function_name, FunctionKind kind,
    FunctionLiteral::FunctionType function_type,
    DeclarationScope* function_scope, int* num_parameters,
    ProducedPreParsedScopeData** produced_preparsed_scope_data,
    bool is_inner_function, bool may_abort, bool* ok) {
  FunctionState function_state(&function_state_, &scope_, function_scope);

  DCHECK_NE(kNoSourcePosition, function_scope->start_position());
  DCHECK_EQ(kNoSourcePosition, parameters_end_pos_);
  if (produce_cached_parse_data()) CHECK(log_);

  DCHECK_IMPLIES(IsArrowFunction(kind),
                 scanner()->current_token() == Token::ARROW);

  // Inner functions are not part of the cached data.
  if (!is_inner_function && consume_cached_parse_data() &&
      !cached_parse_data_->rejected()) {
    // If we have cached data, we use it to skip parsing the function. The data
    // contains the information we need to construct the lazy function.
    FunctionEntry entry =
        cached_parse_data_->GetFunctionEntry(function_scope->start_position());
    // Check that cached data is valid. If not, mark it as invalid (the embedder
    // handles it). Note that end position greater than end of stream is safe,
    // and hard to check.
    if (entry.is_valid() &&
        entry.end_pos() > function_scope->start_position()) {
      total_preparse_skipped_ += entry.end_pos() - position();
      function_scope->set_end_position(entry.end_pos());
      scanner()->SeekForward(entry.end_pos() - 1);
      Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
      *num_parameters = entry.num_parameters();
      SetLanguageMode(function_scope, entry.language_mode());
      if (entry.uses_super_property())
        function_scope->RecordSuperPropertyUsage();
      SkipFunctionLiterals(entry.num_inner_functions());
      return kLazyParsingComplete;
    }
    cached_parse_data_->Reject();
  }

  // FIXME(marja): There are 3 ways to skip functions now. Unify them.
  DCHECK_NOT_NULL(consumed_preparsed_scope_data_);
  if (consumed_preparsed_scope_data_->HasData()) {
    DCHECK(FLAG_preparser_scope_analysis);
    int end_position;
    LanguageMode language_mode;
    int num_inner_functions;
    bool uses_super_property;
    *produced_preparsed_scope_data =
        consumed_preparsed_scope_data_->GetDataForSkippableFunction(
            main_zone(), function_scope->start_position(), &end_position,
            num_parameters, &num_inner_functions, &uses_super_property,
            &language_mode);

    function_scope->outer_scope()->SetMustUsePreParsedScopeData();
    function_scope->set_is_skipped_function(true);
    function_scope->set_end_position(end_position);
    scanner()->SeekForward(end_position - 1);
    Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
    SetLanguageMode(function_scope, language_mode);
    if (uses_super_property) {
      function_scope->RecordSuperPropertyUsage();
    }
    SkipFunctionLiterals(num_inner_functions);
    return kLazyParsingComplete;
  }

  // With no cached data, we partially parse the function, without building an
  // AST. This gathers the data needed to build a lazy function.
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");

  // Aborting inner function preparsing would leave scopes in an inconsistent
  // state; we don't parse inner functions in the abortable mode anyway.
  DCHECK(!is_inner_function || !may_abort);

  PreParser::PreParseResult result = reusable_preparser()->PreParseFunction(
      function_name, kind, function_type, function_scope, is_inner_function,
      may_abort, use_counts_, produced_preparsed_scope_data);

  // Return immediately if pre-parser decided to abort parsing.
  if (result == PreParser::kPreParseAbort) return kLazyParsingAborted;
  if (result == PreParser::kPreParseStackOverflow) {
    // Propagate stack overflow.
    set_stack_overflow();
    *ok = false;
    return kLazyParsingComplete;
  }
  if (pending_error_handler()->has_pending_error()) {
    *ok = false;
    return kLazyParsingComplete;
  }
  PreParserLogger* logger = reusable_preparser()->logger();
  function_scope->set_end_position(logger->end());
  Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
  total_preparse_skipped_ +=
      function_scope->end_position() - function_scope->start_position();
  *num_parameters = logger->num_parameters();
  SkipFunctionLiterals(logger->num_inner_functions());
  if (!is_inner_function && produce_cached_parse_data()) {
    DCHECK(log_);
    log_->LogFunction(function_scope->start_position(),
                      function_scope->end_position(), *num_parameters,
                      language_mode(), function_scope->NeedsHomeObject(),
                      logger->num_inner_functions());
  }
  return kLazyParsingComplete;
}

Statement* Parser::BuildAssertIsCoercible(Variable* var,
                                          ObjectLiteral* pattern) {
  // if (var === null || var === undefined)
  //     throw /* type error kNonCoercible) */;
  auto source_position = pattern->position();
  const AstRawString* property = ast_value_factory()->empty_string();
  MessageTemplate::Template msg = MessageTemplate::kNonCoercible;
  for (ObjectLiteralProperty* literal_property : *pattern->properties()) {
    Expression* key = literal_property->key();
    if (key->IsPropertyName()) {
      property = key->AsLiteral()->AsRawPropertyName();
      msg = MessageTemplate::kNonCoercibleWithProperty;
      source_position = key->position();
      break;
    }
  }

  Expression* condition = factory()->NewBinaryOperation(
      Token::OR,
      factory()->NewCompareOperation(
          Token::EQ_STRICT, factory()->NewVariableProxy(var),
          factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition),
      factory()->NewCompareOperation(
          Token::EQ_STRICT, factory()->NewVariableProxy(var),
          factory()->NewNullLiteral(kNoSourcePosition), kNoSourcePosition),
      kNoSourcePosition);
  Expression* throw_type_error =
      NewThrowTypeError(msg, property, source_position);
  IfStatement* if_statement = factory()->NewIfStatement(
      condition,
      factory()->NewExpressionStatement(throw_type_error, kNoSourcePosition),
      factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition);
  return if_statement;
}

class InitializerRewriter final
    : public AstTraversalVisitor<InitializerRewriter> {
 public:
  InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser)
      : AstTraversalVisitor(stack_limit, root), parser_(parser) {}

 private:
  // This is required so that the overriden Visit* methods can be
  // called by the base class (template).
  friend class AstTraversalVisitor<InitializerRewriter>;

  // Just rewrite destructuring assignments wrapped in RewritableExpressions.
  void VisitRewritableExpression(RewritableExpression* to_rewrite) {
    if (to_rewrite->is_rewritten()) return;
    parser_->RewriteDestructuringAssignment(to_rewrite);
    AstTraversalVisitor::VisitRewritableExpression(to_rewrite);
  }

  // Code in function literals does not need to be eagerly rewritten, it will be
  // rewritten when scheduled.
  void VisitFunctionLiteral(FunctionLiteral* expr) {}

  Parser* parser_;
};

void Parser::RewriteParameterInitializer(Expression* expr) {
  InitializerRewriter rewriter(stack_limit_, expr, this);
  rewriter.Run();
}


Block* Parser::BuildParameterInitializationBlock(
    const ParserFormalParameters& parameters, bool* ok) {
  DCHECK(!parameters.is_simple);
  DCHECK(scope()->is_function_scope());
  DCHECK_EQ(scope(), parameters.scope);
  Block* init_block = factory()->NewBlock(1, true);
  int index = 0;
  for (auto parameter : parameters.params) {
    DeclarationDescriptor descriptor;
    descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
    descriptor.scope = scope();
    descriptor.mode = LET;
    descriptor.declaration_pos = parameter->pattern->position();
    // The position that will be used by the AssignmentExpression
    // which copies from the temp parameter to the pattern.
    //
    // TODO(adamk): Should this be kNoSourcePosition, since
    // it's just copying from a temp var to the real param var?
    descriptor.initialization_pos = parameter->pattern->position();
    Expression* initial_value =
        factory()->NewVariableProxy(parameters.scope->parameter(index));
    if (parameter->initializer != nullptr) {
      // IS_UNDEFINED($param) ? initializer : $param

      // Ensure initializer is rewritten
      RewriteParameterInitializer(parameter->initializer);

      auto condition = factory()->NewCompareOperation(
          Token::EQ_STRICT,
          factory()->NewVariableProxy(parameters.scope->parameter(index)),
          factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
      initial_value = factory()->NewConditional(
          condition, parameter->initializer, initial_value, kNoSourcePosition);
      descriptor.initialization_pos = parameter->initializer->position();
    }

    Scope* param_scope = scope();
    Block* param_block = init_block;
    if (!parameter->is_simple() &&
        scope()->AsDeclarationScope()->calls_sloppy_eval()) {
      param_scope = NewVarblockScope();
      param_scope->set_start_position(descriptor.initialization_pos);
      param_scope->set_end_position(parameter->initializer_end_position);
      param_scope->RecordEvalCall();
      param_block = factory()->NewBlock(8, true);
      param_block->set_scope(param_scope);
      // Pass the appropriate scope in so that PatternRewriter can appropriately
      // rewrite inner initializers of the pattern to param_scope
      descriptor.scope = param_scope;
      // Rewrite the outer initializer to point to param_scope
      ReparentExpressionScope(stack_limit(), initial_value, param_scope);
    }

    BlockState block_state(&scope_, param_scope);
    DeclarationParsingResult::Declaration decl(
        parameter->pattern, parameter->initializer_end_position, initial_value);
    DeclareAndInitializeVariables(param_block, &descriptor, &decl, nullptr,
                                  CHECK_OK);

    if (param_block != init_block) {
      param_scope = param_scope->FinalizeBlockScope();
      if (param_scope != nullptr) {
        CheckConflictingVarDeclarations(param_scope, CHECK_OK);
      }
      init_block->statements()->Add(param_block, zone());
    }
    ++index;
  }
  return init_block;
}

Scope* Parser::NewHiddenCatchScope() {
  Scope* catch_scope = NewScopeWithParent(scope(), CATCH_SCOPE);
  catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
  catch_scope->set_is_hidden();
  return catch_scope;
}

Block* Parser::BuildRejectPromiseOnException(Block* inner_block) {
  // .promise = %AsyncFunctionPromiseCreate();
  // try {
  //   <inner_block>
  // } catch (.catch) {
  //   %RejectPromise(.promise, .catch);
  //   return .promise;
  // } finally {
  //   %AsyncFunctionPromiseRelease(.promise);
  // }
  Block* result = factory()->NewBlock(2, true);

  // .promise = %AsyncFunctionPromiseCreate();
  Statement* set_promise;
  {
    Expression* create_promise = factory()->NewCallRuntime(
        Context::ASYNC_FUNCTION_PROMISE_CREATE_INDEX,
        new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition);
    Assignment* assign_promise = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(PromiseVariable()),
        create_promise, kNoSourcePosition);
    set_promise =
        factory()->NewExpressionStatement(assign_promise, kNoSourcePosition);
  }
  result->statements()->Add(set_promise, zone());

  // catch (.catch) { return %RejectPromise(.promise, .catch), .promise }
  Scope* catch_scope = NewHiddenCatchScope();

  Expression* promise_reject = BuildRejectPromise(
      factory()->NewVariableProxy(catch_scope->catch_variable()),
      kNoSourcePosition);
  Block* catch_block = IgnoreCompletion(
      factory()->NewReturnStatement(promise_reject, kNoSourcePosition));

  TryStatement* try_catch_statement =
      factory()->NewTryCatchStatementForAsyncAwait(
          inner_block, catch_scope, catch_block, kNoSourcePosition);

  // There is no TryCatchFinally node, so wrap it in an outer try/finally
  Block* outer_try_block = IgnoreCompletion(try_catch_statement);

  // finally { %AsyncFunctionPromiseRelease(.promise) }
  Block* finally_block;
  {
    ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
    args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
    Expression* call_promise_release = factory()->NewCallRuntime(
        Context::ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, args, kNoSourcePosition);
    Statement* promise_release = factory()->NewExpressionStatement(
        call_promise_release, kNoSourcePosition);
    finally_block = IgnoreCompletion(promise_release);
  }

  Statement* try_finally_statement = factory()->NewTryFinallyStatement(
      outer_try_block, finally_block, kNoSourcePosition);

  result->statements()->Add(try_finally_statement, zone());
  return result;
}

Expression* Parser::BuildResolvePromise(Expression* value, int pos) {
  // %ResolvePromise(.promise, value), .promise
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
  args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
  args->Add(value, zone());
  Expression* call_runtime =
      factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos);
  return factory()->NewBinaryOperation(
      Token::COMMA, call_runtime,
      factory()->NewVariableProxy(PromiseVariable()), pos);
}

Expression* Parser::BuildRejectPromise(Expression* value, int pos) {
  // %promise_internal_reject(.promise, value, false), .promise
  // Disables the additional debug event for the rejection since a debug event
  // already happened for the exception that got us here.
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(3, zone());
  args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
  args->Add(value, zone());
  args->Add(factory()->NewBooleanLiteral(false, pos), zone());
  Expression* call_runtime = factory()->NewCallRuntime(
      Context::PROMISE_INTERNAL_REJECT_INDEX, args, pos);
  return factory()->NewBinaryOperation(
      Token::COMMA, call_runtime,
      factory()->NewVariableProxy(PromiseVariable()), pos);
}

Variable* Parser::PromiseVariable() {
  // Based on the various compilation paths, there are many different code
  // paths which may be the first to access the Promise temporary. Whichever
  // comes first should create it and stash it in the FunctionState.
  Variable* promise = function_state_->scope()->promise_var();
  if (promise == nullptr) {
    promise = function_state_->scope()->DeclarePromiseVar(
        ast_value_factory()->empty_string());
  }
  return promise;
}

Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
  Expression* yield_result = factory()->NewVariableProxy(
      function_state_->scope()->generator_object_var());
  // The position of the yield is important for reporting the exception
  // caused by calling the .throw method on a generator suspended at the
  // initial yield (i.e. right after generator instantiation).
  return factory()->NewYield(yield_result, scope()->start_position(),
                             Suspend::kOnExceptionThrow);
}

ZoneList<Statement*>* Parser::ParseFunction(
    const AstRawString* function_name, int pos, FunctionKind kind,
    FunctionLiteral::FunctionType function_type,
    DeclarationScope* function_scope, int* num_parameters, int* function_length,
    bool* has_duplicate_parameters, int* expected_property_count, bool* ok) {
  ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY);

  FunctionState function_state(&function_state_, &scope_, function_scope);

  DuplicateFinder duplicate_finder;
  ExpressionClassifier formals_classifier(this, &duplicate_finder);

  int expected_parameters_end_pos = parameters_end_pos_;
  if (expected_parameters_end_pos != kNoSourcePosition) {
    // This is the first function encountered in a CreateDynamicFunction eval.
    parameters_end_pos_ = kNoSourcePosition;
    // The function name should have been ignored, giving us the empty string
    // here.
    DCHECK_EQ(function_name, ast_value_factory()->empty_string());
  }

  ParserFormalParameters formals(function_scope);
  ParseFormalParameterList(&formals, CHECK_OK);
  if (expected_parameters_end_pos != kNoSourcePosition) {
    // Check for '(' or ')' shenanigans in the parameter string for dynamic
    // functions.
    int position = peek_position();
    if (position < expected_parameters_end_pos) {
      ReportMessageAt(Scanner::Location(position, position + 1),
                      MessageTemplate::kArgStringTerminatesParametersEarly);
      *ok = false;
      return nullptr;
    } else if (position > expected_parameters_end_pos) {
      ReportMessageAt(Scanner::Location(expected_parameters_end_pos - 2,
                                        expected_parameters_end_pos),
                      MessageTemplate::kUnexpectedEndOfArgString);
      *ok = false;
      return nullptr;
    }
  }
  Expect(Token::RPAREN, CHECK_OK);
  int formals_end_position = scanner()->location().end_pos;
  *num_parameters = formals.num_parameters();
  *function_length = formals.function_length;

  CheckArityRestrictions(formals.arity, kind, formals.has_rest,
                         function_scope->start_position(), formals_end_position,
                         CHECK_OK);
  Expect(Token::LBRACE, CHECK_OK);

  ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(8, zone());
  ParseFunctionBody(body, function_name, pos, formals, kind, function_type, ok);

  // Validate parameter names. We can do this only after parsing the function,
  // since the function can declare itself strict.
  const bool allow_duplicate_parameters =
      is_sloppy(function_scope->language_mode()) && formals.is_simple &&
      !IsConciseMethod(kind);
  ValidateFormalParameters(function_scope->language_mode(),
                           allow_duplicate_parameters, CHECK_OK);

  RewriteDestructuringAssignments();

  *has_duplicate_parameters =
      !classifier()->is_valid_formal_parameter_list_without_duplicates();

  *expected_property_count = function_state.expected_property_count();
  return body;
}

void Parser::DeclareClassVariable(const AstRawString* name,
                                  ClassInfo* class_info, int class_token_pos,
                                  bool* ok) {
#ifdef DEBUG
  scope()->SetScopeName(name);
#endif

  if (name != nullptr) {
    VariableProxy* proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE);
    Declaration* declaration =
        factory()->NewVariableDeclaration(proxy, class_token_pos);
    class_info->variable =
        Declare(declaration, DeclarationDescriptor::NORMAL, CONST,
                Variable::DefaultInitializationFlag(CONST), ok);
  }
}

namespace {

const AstRawString* ClassFieldVariableName(AstValueFactory* ast_value_factory,
                                           int index) {
  std::string name = ".class-field-" + std::to_string(index);
  return ast_value_factory->GetOneByteString(name.c_str());
}

}  // namespace

// This method declares a property of the given class.  It updates the
// following fields of class_info, as appropriate:
//   - constructor
//   - properties
void Parser::DeclareClassProperty(const AstRawString* class_name,
                                  ClassLiteralProperty* property,
                                  ClassLiteralProperty::Kind kind,
                                  bool is_static, bool is_constructor,
                                  ClassInfo* class_info, bool* ok) {
  if (is_constructor) {
    DCHECK(!class_info->constructor);
    class_info->constructor = property->value()->AsFunctionLiteral();
    DCHECK_NOT_NULL(class_info->constructor);
    class_info->constructor->set_raw_name(
        class_name != nullptr ? ast_value_factory()->NewConsString(class_name)
                              : nullptr);
    return;
  }

  if (property->kind() == ClassLiteralProperty::FIELD && is_static) {
    DCHECK(allow_harmony_class_fields());
    class_info->static_fields->Add(property, zone());
    if (property->is_computed_name()) {
      int index = class_info->static_fields->length();
      // We create a synthetic variable name here so that scope
      // analysis doesn't dedupe the vars.
      //
      // TODO(gsathya): Ideally, this should just bypass scope
      // analysis and allocate a slot directly on the context. We
      // should just store this index in the AST, instead of storing
      // the variable.
      const AstRawString* synthetic_name =
          ClassFieldVariableName(ast_value_factory(), index);
      VariableProxy* proxy =
          factory()->NewVariableProxy(synthetic_name, NORMAL_VARIABLE);
      Declaration* declaration =
          factory()->NewVariableDeclaration(proxy, kNoSourcePosition);
      Variable* computed_name_var =
          Declare(declaration, DeclarationDescriptor::NORMAL, CONST,
                  Variable::DefaultInitializationFlag(CONST), ok);
      // Force context allocation because the computed property
      // variable will accessed from inside the initializer
      // function. We don't actually create a VariableProxy in the
      // initializer function scope referring to this variable so
      // scope analysis is unable to figure this out for us.
      computed_name_var->ForceContextAllocation();
      property->set_computed_name_var(computed_name_var);
      class_info->properties->Add(property, zone());
    }
  } else {
    class_info->properties->Add(property, zone());
  }
}

// This method generates a ClassLiteral AST node.
// It uses the following fields of class_info:
//   - constructor (if missing, it updates it with a default constructor)
//   - proxy
//   - extends
//   - properties
//   - has_name_static_property
//   - has_static_computed_names
Expression* Parser::RewriteClassLiteral(Scope* block_scope,
                                        const AstRawString* name,
                                        ClassInfo* class_info, int pos,
                                        int end_pos, bool* ok) {
  DCHECK_NOT_NULL(block_scope);
  DCHECK_EQ(block_scope->scope_type(), BLOCK_SCOPE);
  DCHECK_EQ(block_scope->language_mode(), LanguageMode::kStrict);

  bool has_extends = class_info->extends != nullptr;
  bool has_default_constructor = class_info->constructor == nullptr;
  if (has_default_constructor) {
    class_info->constructor =
        DefaultConstructor(name, has_extends, pos, end_pos);
  }

  if (name != nullptr) {
    DCHECK_NOT_NULL(class_info->variable);
    class_info->variable->set_initializer_position(end_pos);
  }

  FunctionLiteral* static_fields_initializer = nullptr;
  if (class_info->has_static_class_fields) {
    // function() { .. static class fields initializer .. }
    ZoneList<Statement*>* statements = NewStatementList(1);
    InitializeClassFieldsStatement* class_fields =
        factory()->NewInitializeClassFieldsStatement(
            class_info->static_fields,
            class_info->field_scope->NeedsHomeObject(), kNoSourcePosition);
    statements->Add(class_fields, zone());
    static_fields_initializer = factory()->NewFunctionLiteral(
        ast_value_factory()->empty_string(), class_info->field_scope,
        statements, 0, 0, 0, FunctionLiteral::kNoDuplicateParameters,
        FunctionLiteral::kAnonymousExpression,
        FunctionLiteral::kShouldEagerCompile,
        class_info->field_scope->start_position(), true,
        GetNextFunctionLiteralId());
  }

  ClassLiteral* class_literal = factory()->NewClassLiteral(
      block_scope, class_info->variable, class_info->extends,
      class_info->constructor, class_info->properties,
      static_fields_initializer, pos, end_pos,
      class_info->has_name_static_property,
      class_info->has_static_computed_names, class_info->is_anonymous);

  AddFunctionForNameInference(class_info->constructor);
  return class_literal;
}

void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
  Declaration* decl = scope->CheckConflictingVarDeclarations();
  if (decl != nullptr) {
    // In ES6, conflicting variable bindings are early errors.
    const AstRawString* name = decl->proxy()->raw_name();
    int position = decl->proxy()->position();
    Scanner::Location location =
        position == kNoSourcePosition
            ? Scanner::Location::invalid()
            : Scanner::Location(position, position + 1);
    ReportMessageAt(location, MessageTemplate::kVarRedeclaration, name);
    *ok = false;
  }
}


void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
  // For each var-binding that shadows a parameter, insert an assignment
  // initializing the variable with the parameter.
  Scope* inner_scope = inner_block->scope();
  DCHECK(inner_scope->is_declaration_scope());
  Scope* function_scope = inner_scope->outer_scope();
  DCHECK(function_scope->is_function_scope());
  BlockState block_state(&scope_, inner_scope);
  for (Declaration* decl : *inner_scope->declarations()) {
    if (decl->proxy()->var()->mode() != VAR || !decl->IsVariableDeclaration()) {
      continue;
    }
    const AstRawString* name = decl->proxy()->raw_name();
    Variable* parameter = function_scope->LookupLocal(name);
    if (parameter == nullptr) continue;
    VariableProxy* to = NewUnresolved(name);
    VariableProxy* from = factory()->NewVariableProxy(parameter);
    Expression* assignment =
        factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition);
    Statement* statement =
        factory()->NewExpressionStatement(assignment, kNoSourcePosition);
    inner_block->statements()->InsertAt(0, statement, zone());
  }
}

void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
  // For the outermost eval scope, we cannot hoist during parsing: let
  // declarations in the surrounding scope may prevent hoisting, but the
  // information is unaccessible during parsing. In this case, we hoist later in
  // DeclarationScope::Analyze.
  if (scope->is_eval_scope() && scope->outer_scope() == original_scope_) {
    return;
  }
  scope->HoistSloppyBlockFunctions(factory());
}

// ----------------------------------------------------------------------------
// Parser support

bool Parser::TargetStackContainsLabel(const AstRawString* label) {
  for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
    if (ContainsLabel(t->statement()->labels(), label)) return true;
  }
  return false;
}


BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
                                              bool* ok) {
  bool anonymous = label == nullptr;
  for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
    BreakableStatement* stat = t->statement();
    if ((anonymous && stat->is_target_for_anonymous()) ||
        (!anonymous && ContainsLabel(stat->labels(), label))) {
      return stat;
    }
  }
  return nullptr;
}


IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
                                                 bool* ok) {
  bool anonymous = label == nullptr;
  for (ParserTarget* t = target_stack_; t != nullptr; t = t->previous()) {
    IterationStatement* stat = t->statement()->AsIterationStatement();
    if (stat == nullptr) continue;

    DCHECK(stat->is_target_for_anonymous());
    if (anonymous || ContainsLabel(stat->labels(), label)) {
      return stat;
    }
  }
  return nullptr;
}


void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
  Handle<String> source_url = scanner_.SourceUrl(isolate);
  if (!source_url.is_null()) {
    script->set_source_url(*source_url);
  }
  Handle<String> source_mapping_url = scanner_.SourceMappingUrl(isolate);
  if (!source_mapping_url.is_null()) {
    script->set_source_mapping_url(*source_mapping_url);
  }
}

void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) {
  // Move statistics to Isolate.
  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
       ++feature) {
    if (use_counts_[feature] > 0) {
      isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
    }
  }
  if (scanner_.FoundHtmlComment()) {
    isolate->CountUsage(v8::Isolate::kHtmlComment);
    if (script->line_offset() == 0 && script->column_offset() == 0) {
      isolate->CountUsage(v8::Isolate::kHtmlCommentInExternalScript);
    }
  }
  isolate->counters()->total_preparse_skipped()->Increment(
      total_preparse_skipped_);
}

void Parser::ParseOnBackground(ParseInfo* info) {
  parsing_on_main_thread_ = false;

  DCHECK_NULL(info->literal());
  FunctionLiteral* result = nullptr;

  ParserLogger logger;
  if (produce_cached_parse_data()) {
    if (allow_lazy_) {
      log_ = &logger;
    } else {
      compile_options_ = ScriptCompiler::kNoCompileOptions;
    }
  }

  scanner_.Initialize(info->character_stream(), info->is_module());
  DCHECK(info->maybe_outer_scope_info().is_null());

  DCHECK(original_scope_);

  // When streaming, we don't know the length of the source until we have parsed
  // it. The raw data can be UTF-8, so we wouldn't know the source length until
  // we have decoded it anyway even if we knew the raw data length (which we
  // don't). We work around this by storing all the scopes which need their end
  // position set at the end of the script (the top scope and possible eval
  // scopes) and set their end position after we know the script length.
  if (info->is_toplevel()) {
    fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
    result = DoParseProgram(info);
  } else {
    result = DoParseFunction(info, info->function_name());
  }
  MaybeResetCharacterStream(info, result);

  info->set_literal(result);

  // We cannot internalize on a background thread; a foreground task will take
  // care of calling AstValueFactory::Internalize just before compilation.

  if (produce_cached_parse_data()) {
    if (result != nullptr) *info->cached_data() = logger.GetScriptData();
    log_ = nullptr;
  }
  if (FLAG_runtime_stats &
      v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) {
    auto value = v8::tracing::TracedValue::Create();
    runtime_call_stats_->Dump(value.get());
    TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.runtime_stats"),
                         "V8.RuntimeStats", TRACE_EVENT_SCOPE_THREAD,
                         "runtime-call-stats", std::move(value));
  }
}

Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
  return new (zone()) TemplateLiteral(zone(), pos);
}

void Parser::AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
                             bool tail) {
  DCHECK(should_cook || allow_harmony_template_escapes());
  int end = scanner()->location().end_pos - (tail ? 1 : 2);
  const AstRawString* raw = scanner()->CurrentRawSymbol(ast_value_factory());
  if (should_cook) {
    const AstRawString* cooked = scanner()->CurrentSymbol(ast_value_factory());
    (*state)->AddTemplateSpan(cooked, raw, end, zone());
  } else {
    (*state)->AddTemplateSpan(nullptr, raw, end, zone());
  }
}


void Parser::AddTemplateExpression(TemplateLiteralState* state,
                                   Expression* expression) {
  (*state)->AddExpression(expression, zone());
}


Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
                                         Expression* tag) {
  TemplateLiteral* lit = *state;
  int pos = lit->position();
  const ZoneList<const AstRawString*>* cooked_strings = lit->cooked();
  const ZoneList<const AstRawString*>* raw_strings = lit->raw();
  const ZoneList<Expression*>* expressions = lit->expressions();
  DCHECK_EQ(cooked_strings->length(), raw_strings->length());
  DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);

  if (!tag) {
    Expression* first_string =
        factory()->NewStringLiteral(cooked_strings->at(0), kNoSourcePosition);
    if (expressions->length() == 0) return first_string;

    // Build N-ary addition op to simplify code-generation.
    // TODO(leszeks): Could we just store this expression in the
    // TemplateLiteralState and build it as we go?
    NaryOperation* expr = factory()->NewNaryOperation(
        Token::ADD, first_string, 2 * expressions->length());

    int i = 0;
    while (i < expressions->length()) {
      Expression* sub = expressions->at(i++);
      const AstRawString* cooked_str = cooked_strings->at(i);
      DCHECK_NOT_NULL(cooked_str);

      // Let middle be ToString(sub).
      ZoneList<Expression*>* args =
          new (zone()) ZoneList<Expression*>(1, zone());
      args->Add(sub, zone());
      Expression* sub_to_string = factory()->NewCallRuntime(
          Runtime::kInlineToString, args, sub->position());

      expr->AddSubsequent(sub_to_string, sub->position());
      expr->AddSubsequent(
          factory()->NewStringLiteral(cooked_str, kNoSourcePosition),
          sub->position());
    }
    return expr;
  } else {
    // GetTemplateObject
    const int32_t hash = ComputeTemplateLiteralHash(lit);
    Expression* template_object =
        factory()->NewGetTemplateObject(cooked_strings, raw_strings, hash, pos);

    // Call TagFn
    ZoneList<Expression*>* call_args =
        new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
    call_args->Add(template_object, zone());
    call_args->AddAll(*expressions, zone());
    return factory()->NewTaggedTemplate(tag, call_args, pos);
  }
}

namespace {

// http://burtleburtle.net/bob/hash/integer.html
uint32_t HalfAvalance(uint32_t a) {
  a = (a + 0x479ab41d) + (a << 8);
  a = (a ^ 0xe4aa10ce) ^ (a >> 5);
  a = (a + 0x9942f0a6) - (a << 14);
  a = (a ^ 0x5aedd67d) ^ (a >> 3);
  a = (a + 0x17bea992) + (a << 7);
  return a;
}

}  // namespace

int32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
  const ZoneList<const AstRawString*>* raw_strings = lit->raw();
  int total = raw_strings->length();
  DCHECK_GT(total, 0);

  uint32_t running_hash = 0;

  for (int index = 0; index < total; ++index) {
    if (index) {
      running_hash = StringHasher::ComputeRunningHashOneByte(
          running_hash, "${}", 3);
    }

    const AstRawString* raw_string = raw_strings->at(index);
    if (raw_string->is_one_byte()) {
      const char* data = reinterpret_cast<const char*>(raw_string->raw_data());
      running_hash = StringHasher::ComputeRunningHashOneByte(
          running_hash, data, raw_string->length());
    } else {
      const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
      running_hash = StringHasher::ComputeRunningHash(running_hash, data,
                                                      raw_string->length());
    }
  }

  // Pass {running_hash} throught a decent 'half avalance' hash function
  // and take the most significant bits (in Smi range).
  return static_cast<int32_t>(HalfAvalance(running_hash)) >>
         (sizeof(int32_t) * CHAR_BIT - kSmiValueSize);
}

namespace {

bool OnlyLastArgIsSpread(ZoneList<Expression*>* args) {
  for (int i = 0; i < args->length() - 1; i++) {
    if (args->at(i)->IsSpread()) {
      return false;
    }
  }
  return args->at(args->length() - 1)->IsSpread();
}

}  // namespace

ZoneList<Expression*>* Parser::PrepareSpreadArguments(
    ZoneList<Expression*>* list) {
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
  if (list->length() == 1) {
    // Spread-call with single spread argument produces an InternalArray
    // containing the values from the array.
    //
    // Function is called or constructed with the produced array of arguments
    //
    // EG: Apply(Func, Spread(spread0))
    ZoneList<Expression*>* spread_list =
        new (zone()) ZoneList<Expression*>(0, zone());
    spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
    args->Add(factory()->NewCallRuntime(Runtime::kSpreadIterablePrepare,
                                        spread_list, kNoSourcePosition),
              zone());
    return args;
  } else {
    // Spread-call with multiple arguments produces array literals for each
    // sequences of unspread arguments, and converts each spread iterable to
    // an Internal array. Finally, all of these produced arrays are flattened
    // into a single InternalArray, containing the arguments for the call.
    //
    // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
    //                         Spread(spread1), [unspread2, unspread3]))
    int i = 0;
    int n = list->length();
    while (i < n) {
      if (!list->at(i)->IsSpread()) {
        ZoneList<Expression*>* unspread =
            new (zone()) ZoneList<Expression*>(1, zone());

        // Push array of unspread parameters
        while (i < n && !list->at(i)->IsSpread()) {
          unspread->Add(list->at(i++), zone());
        }
        args->Add(factory()->NewArrayLiteral(unspread, kNoSourcePosition),
                  zone());

        if (i == n) break;
      }

      // Push eagerly spread argument
      ZoneList<Expression*>* spread_list =
          new (zone()) ZoneList<Expression*>(1, zone());
      spread_list->Add(list->at(i++)->AsSpread()->expression(), zone());
      args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
                                          spread_list, kNoSourcePosition),
                zone());
    }

    list = new (zone()) ZoneList<Expression*>(1, zone());
    list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args,
                                        kNoSourcePosition),
              zone());
    return list;
  }
  UNREACHABLE();
}

Expression* Parser::SpreadCall(Expression* function,
                               ZoneList<Expression*>* args, int pos,
                               Call::PossiblyEval is_possibly_eval) {
  // Handle this case in BytecodeGenerator.
  if (OnlyLastArgIsSpread(args)) {
    return factory()->NewCall(function, args, pos);
  }

  if (function->IsSuperCallReference()) {
    // Super calls
    // $super_constructor = %_GetSuperConstructor(<this-function>)
    // %reflect_construct($super_constructor, args, new.target)

    args = PrepareSpreadArguments(args);
    ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
    tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
    Expression* super_constructor = factory()->NewCallRuntime(
        Runtime::kInlineGetSuperConstructor, tmp, pos);
    args->InsertAt(0, super_constructor, zone());
    args->Add(function->AsSuperCallReference()->new_target_var(), zone());
    return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
                                     pos);
  } else {
    args = PrepareSpreadArguments(args);
    if (function->IsProperty()) {
      // Method calls
      if (function->AsProperty()->IsSuperAccess()) {
        Expression* home = ThisExpression(kNoSourcePosition);
        args->InsertAt(0, function, zone());
        args->InsertAt(1, home, zone());
      } else {
        Variable* temp = NewTemporary(ast_value_factory()->empty_string());
        VariableProxy* obj = factory()->NewVariableProxy(temp);
        Assignment* assign_obj = factory()->NewAssignment(
            Token::ASSIGN, obj, function->AsProperty()->obj(),
            kNoSourcePosition);
        function = factory()->NewProperty(
            assign_obj, function->AsProperty()->key(), kNoSourcePosition);
        args->InsertAt(0, function, zone());
        obj = factory()->NewVariableProxy(temp);
        args->InsertAt(1, obj, zone());
      }
    } else {
      // Non-method calls
      args->InsertAt(0, function, zone());
      args->InsertAt(1, factory()->NewUndefinedLiteral(kNoSourcePosition),
                     zone());
    }
    return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
  }
}

Expression* Parser::SpreadCallNew(Expression* function,
                                  ZoneList<Expression*>* args, int pos) {
  if (OnlyLastArgIsSpread(args)) {
    // Handle in BytecodeGenerator.
    return factory()->NewCallNew(function, args, pos);
  }
  args = PrepareSpreadArguments(args);
  args->InsertAt(0, function, zone());

  return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
}


void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
  v8::Isolate::UseCounterFeature feature;
  if (is_sloppy(mode))
    feature = v8::Isolate::kSloppyMode;
  else if (is_strict(mode))
    feature = v8::Isolate::kStrictMode;
  else
    UNREACHABLE();
  ++use_counts_[feature];
  scope->SetLanguageMode(mode);
}

void Parser::SetAsmModule() {
  // Store the usage count; The actual use counter on the isolate is
  // incremented after parsing is done.
  ++use_counts_[v8::Isolate::kUseAsm];
  DCHECK(scope()->is_declaration_scope());
  scope()->AsDeclarationScope()->set_asm_module();
}

Expression* Parser::ExpressionListToExpression(ZoneList<Expression*>* args) {
  Expression* expr = args->at(0);
  for (int i = 1; i < args->length(); ++i) {
    expr = factory()->NewBinaryOperation(Token::COMMA, expr, args->at(i),
                                         expr->position());
  }
  return expr;
}

// This method completes the desugaring of the body of async_function.
void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block,
                                      Expression* return_value, bool* ok) {
  // function async_function() {
  //   .generator_object = %CreateJSGeneratorObject();
  //   BuildRejectPromiseOnException({
  //     ... block ...
  //     return %ResolvePromise(.promise, expr), .promise;
  //   })
  // }

  return_value = BuildResolvePromise(return_value, return_value->position());
  block->statements()->Add(
      factory()->NewReturnStatement(return_value, return_value->position()),
      zone());
  block = BuildRejectPromiseOnException(block);
  body->Add(block, zone());
}

class NonPatternRewriter : public AstExpressionRewriter {
 public:
  NonPatternRewriter(uintptr_t stack_limit, Parser* parser)
      : AstExpressionRewriter(stack_limit), parser_(parser) {}
  ~NonPatternRewriter() override {}

 private:
  bool RewriteExpression(Expression* expr) override {
    if (expr->IsRewritableExpression()) return true;
    // Rewrite only what could have been a pattern but is not.
    if (expr->IsArrayLiteral()) {
      // Spread rewriting in array literals.
      ArrayLiteral* lit = expr->AsArrayLiteral();
      VisitExpressions(lit->values());
      replacement_ = parser_->RewriteSpreads(lit);
      return false;
    }
    if (expr->IsObjectLiteral()) {
      return true;
    }
    if (expr->IsBinaryOperation() &&
        expr->AsBinaryOperation()->op() == Token::COMMA) {
      return true;
    }
    // Everything else does not need rewriting.
    return false;
  }

  void VisitLiteralProperty(LiteralProperty* property) override {
    if (property == nullptr) return;
    // Do not rewrite (computed) key expressions
    AST_REWRITE_PROPERTY(Expression, property, value);
  }

  Parser* parser_;
};

void Parser::RewriteNonPattern(bool* ok) {
  ValidateExpression(CHECK_OK_VOID);
  auto non_patterns_to_rewrite = function_state_->non_patterns_to_rewrite();
  int begin = classifier()->GetNonPatternBegin();
  int end = non_patterns_to_rewrite->length();
  if (begin < end) {
    NonPatternRewriter rewriter(stack_limit_, this);
    for (int i = begin; i < end; i++) {
      DCHECK(non_patterns_to_rewrite->at(i)->IsRewritableExpression());
      rewriter.Rewrite(non_patterns_to_rewrite->at(i));
    }
    non_patterns_to_rewrite->Rewind(begin);
  }
}


void Parser::RewriteDestructuringAssignments() {
  const auto& assignments =
      function_state_->destructuring_assignments_to_rewrite();
  for (int i = assignments.length() - 1; i >= 0; --i) {
    // Rewrite list in reverse, so that nested assignment patterns are rewritten
    // correctly.
    const DestructuringAssignment& pair = assignments.at(i);
    RewritableExpression* to_rewrite =
        pair.assignment->AsRewritableExpression();
    DCHECK_NOT_NULL(to_rewrite);
    if (!to_rewrite->is_rewritten()) {
      // Since this function is called at the end of parsing the program,
      // pair.scope may already have been removed by FinalizeBlockScope in the
      // meantime.
      Scope* scope = pair.scope->GetUnremovedScope();
      BlockState block_state(&scope_, scope);
      RewriteDestructuringAssignment(to_rewrite);
    }
  }
}

Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
                                          int pos) {
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
  args->Add(left, zone());
  args->Add(right, zone());
  return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
}

Expression* Parser::RewriteAssignExponentiation(Expression* left,
                                                Expression* right, int pos) {
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
  if (left->IsVariableProxy()) {
    VariableProxy* lhs = left->AsVariableProxy();

    Expression* result;
    DCHECK_NOT_NULL(lhs->raw_name());
    result = ExpressionFromIdentifier(lhs->raw_name(), lhs->position());
    args->Add(left, zone());
    args->Add(right, zone());
    Expression* call =
        factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
    return factory()->NewAssignment(Token::ASSIGN, result, call, pos);
  } else if (left->IsProperty()) {
    Property* prop = left->AsProperty();
    auto temp_obj = NewTemporary(ast_value_factory()->empty_string());
    auto temp_key = NewTemporary(ast_value_factory()->empty_string());
    Expression* assign_obj = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(temp_obj), prop->obj(),
        kNoSourcePosition);
    Expression* assign_key = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(temp_key), prop->key(),
        kNoSourcePosition);
    args->Add(factory()->NewProperty(factory()->NewVariableProxy(temp_obj),
                                     factory()->NewVariableProxy(temp_key),
                                     left->position()),
              zone());
    args->Add(right, zone());
    Expression* call =
        factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
    Expression* target = factory()->NewProperty(
        factory()->NewVariableProxy(temp_obj),
        factory()->NewVariableProxy(temp_key), kNoSourcePosition);
    Expression* assign =
        factory()->NewAssignment(Token::ASSIGN, target, call, pos);
    return factory()->NewBinaryOperation(
        Token::COMMA, assign_obj,
        factory()->NewBinaryOperation(Token::COMMA, assign_key, assign, pos),
        pos);
  }
  UNREACHABLE();
}

Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
  // Array literals containing spreads are rewritten using do expressions, e.g.
  //    [1, 2, 3, ...x, 4, ...y, 5]
  // is roughly rewritten as:
  //    do {
  //      $R = [1, 2, 3];
  //      for ($i of x) %AppendElement($R, $i);
  //      %AppendElement($R, 4);
  //      for ($j of y) %AppendElement($R, $j);
  //      %AppendElement($R, 5);
  //      $R
  //    }
  // where $R, $i and $j are fresh temporary variables.
  ZoneList<Expression*>::iterator s = lit->FirstSpread();
  if (s == lit->EndValue()) return nullptr;  // no spread, no rewriting...
  Variable* result = NewTemporary(ast_value_factory()->dot_result_string());
  // NOTE: The value assigned to R is the whole original array literal,
  // spreads included. This will be fixed before the rewritten AST is returned.
  // $R = lit
  Expression* init_result = factory()->NewAssignment(
      Token::INIT, factory()->NewVariableProxy(result), lit, kNoSourcePosition);
  Block* do_block = factory()->NewBlock(16, false);
  do_block->statements()->Add(
      factory()->NewExpressionStatement(init_result, kNoSourcePosition),
      zone());
  // Traverse the array literal starting from the first spread.
  while (s != lit->EndValue()) {
    Expression* value = *s++;
    Spread* spread = value->AsSpread();
    if (spread == nullptr) {
      // If the element is not a spread, we're adding a single:
      // %AppendElement($R, value)
      // or, in case of a hole,
      // ++($R.length)
      if (!value->IsTheHoleLiteral()) {
        ZoneList<Expression*>* append_element_args = NewExpressionList(2);
        append_element_args->Add(factory()->NewVariableProxy(result), zone());
        append_element_args->Add(value, zone());
        do_block->statements()->Add(
            factory()->NewExpressionStatement(
                factory()->NewCallRuntime(Runtime::kAppendElement,
                                          append_element_args,
                                          kNoSourcePosition),
                kNoSourcePosition),
            zone());
      } else {
        Property* length_property = factory()->NewProperty(
            factory()->NewVariableProxy(result),
            factory()->NewStringLiteral(ast_value_factory()->length_string(),
                                        kNoSourcePosition),
            kNoSourcePosition);
        CountOperation* count_op = factory()->NewCountOperation(
            Token::INC, true /* prefix */, length_property, kNoSourcePosition);
        do_block->statements()->Add(
            factory()->NewExpressionStatement(count_op, kNoSourcePosition),
            zone());
      }
    } else {
      // If it's a spread, we're adding a for/of loop iterating through it.
      Variable* each = NewTemporary(ast_value_factory()->dot_for_string());
      Expression* subject = spread->expression();
      // %AppendElement($R, each)
      Statement* append_body;
      {
        ZoneList<Expression*>* append_element_args = NewExpressionList(2);
        append_element_args->Add(factory()->NewVariableProxy(result), zone());
        append_element_args->Add(factory()->NewVariableProxy(each), zone());
        append_body = factory()->NewExpressionStatement(
            factory()->NewCallRuntime(Runtime::kAppendElement,
                                      append_element_args, kNoSourcePosition),
            kNoSourcePosition);
      }
      // for (each of spread) %AppendElement($R, each)
      ForOfStatement* loop =
          factory()->NewForOfStatement(nullptr, kNoSourcePosition);
      const bool finalize = false;
      InitializeForOfStatement(loop, factory()->NewVariableProxy(each), subject,
                               append_body, finalize, IteratorType::kNormal);
      do_block->statements()->Add(loop, zone());
    }
  }
  // Now, rewind the original array literal to truncate everything from the
  // first spread (included) until the end. This fixes $R's initialization.
  lit->RewindSpreads();
  return factory()->NewDoExpression(do_block, result, lit->position());
}

void Parser::QueueDestructuringAssignmentForRewriting(Expression* expr) {
  DCHECK(expr->IsRewritableExpression());
  function_state_->AddDestructuringAssignment(
      DestructuringAssignment(expr, scope()));
}

void Parser::QueueNonPatternForRewriting(Expression* expr, bool* ok) {
  DCHECK(expr->IsRewritableExpression());
  function_state_->AddNonPatternForRewriting(expr, ok);
}

void Parser::SetFunctionNameFromPropertyName(LiteralProperty* property,
                                             const AstRawString* name,
                                             const AstRawString* prefix) {
  // Ensure that the function we are going to create has shared name iff
  // we are not going to set it later.
  if (property->NeedsSetFunctionName()) {
    name = nullptr;
    prefix = nullptr;
  } else {
    // If the property value is an anonymous function or an anonymous class or
    // a concise method or an accessor function which doesn't require the name
    // to be set then the shared name must be provided.
    DCHECK_IMPLIES(property->value()->IsAnonymousFunctionDefinition() ||
                       property->value()->IsConciseMethodDefinition() ||
                       property->value()->IsAccessorFunctionDefinition(),
                   name != nullptr);
  }

  Expression* value = property->value();
  SetFunctionName(value, name, prefix);
}

void Parser::SetFunctionNameFromPropertyName(ObjectLiteralProperty* property,
                                             const AstRawString* name,
                                             const AstRawString* prefix) {
  // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
  // of an object literal.
  // See ES #sec-__proto__-property-names-in-object-initializers.
  if (property->IsPrototype()) return;

  DCHECK(!property->value()->IsAnonymousFunctionDefinition() ||
         property->kind() == ObjectLiteralProperty::COMPUTED);

  SetFunctionNameFromPropertyName(static_cast<LiteralProperty*>(property), name,
                                  prefix);
}

void Parser::SetFunctionNameFromIdentifierRef(Expression* value,
                                              Expression* identifier) {
  if (!identifier->IsVariableProxy()) return;
  SetFunctionName(value, identifier->AsVariableProxy()->raw_name());
}

void Parser::SetFunctionName(Expression* value, const AstRawString* name,
                             const AstRawString* prefix) {
  if (!value->IsAnonymousFunctionDefinition() &&
      !value->IsConciseMethodDefinition() &&
      !value->IsAccessorFunctionDefinition()) {
    return;
  }
  auto function = value->AsFunctionLiteral();
  if (value->IsClassLiteral()) {
    function = value->AsClassLiteral()->constructor();
  }
  if (function != nullptr) {
    AstConsString* cons_name = nullptr;
    if (name != nullptr) {
      if (prefix != nullptr) {
        cons_name = ast_value_factory()->NewConsString(prefix, name);
      } else {
        cons_name = ast_value_factory()->NewConsString(name);
      }
    } else {
      DCHECK_NULL(prefix);
    }
    function->set_raw_name(cons_name);
  }
}

Statement* Parser::CheckCallable(Variable* var, Expression* error, int pos) {
  const int nopos = kNoSourcePosition;
  Statement* validate_var;
  {
    Expression* type_of = factory()->NewUnaryOperation(
        Token::TYPEOF, factory()->NewVariableProxy(var), nopos);
    Expression* function_literal = factory()->NewStringLiteral(
        ast_value_factory()->function_string(), nopos);
    Expression* condition = factory()->NewCompareOperation(
        Token::EQ_STRICT, type_of, function_literal, nopos);

    Statement* throw_call = factory()->NewExpressionStatement(error, pos);

    validate_var = factory()->NewIfStatement(
        condition, factory()->NewEmptyStatement(nopos), throw_call, nopos);
  }
  return validate_var;
}

void Parser::BuildIteratorClose(ZoneList<Statement*>* statements,
                                Variable* iterator, Variable* input,
                                Variable* var_output, IteratorType type) {
  //
  // This function adds four statements to [statements], corresponding to the
  // following code:
  //
  //   let iteratorReturn = iterator.return;
  //   if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
  //     return {value: input, done: true};
  //   }
  //   output = %_Call(iteratorReturn, iterator, input);
  //   if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
  //

  const int nopos = kNoSourcePosition;

  // let iteratorReturn = iterator.return;
  Variable* var_return = var_output;  // Reusing the output variable.
  Statement* get_return;
  {
    Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
    Expression* literal = factory()->NewStringLiteral(
        ast_value_factory()->return_string(), nopos);
    Expression* property =
        factory()->NewProperty(iterator_proxy, literal, nopos);
    Expression* return_proxy = factory()->NewVariableProxy(var_return);
    Expression* assignment =
        factory()->NewAssignment(Token::ASSIGN, return_proxy, property, nopos);
    get_return = factory()->NewExpressionStatement(assignment, nopos);
  }

  // if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
  //   return {value: input, done: true};
  // }
  Statement* check_return;
  {
    Expression* condition = factory()->NewCompareOperation(
        Token::EQ, factory()->NewVariableProxy(var_return),
        factory()->NewNullLiteral(nopos), nopos);

    Expression* value = factory()->NewVariableProxy(input);

    Statement* return_input = BuildReturnStatement(value, nopos);

    check_return = factory()->NewIfStatement(
        condition, return_input, factory()->NewEmptyStatement(nopos), nopos);
  }

  // output = %_Call(iteratorReturn, iterator, input);
  Statement* call_return;
  {
    auto args = new (zone()) ZoneList<Expression*>(3, zone());
    args->Add(factory()->NewVariableProxy(var_return), zone());
    args->Add(factory()->NewVariableProxy(iterator), zone());
    args->Add(factory()->NewVariableProxy(input), zone());

    Expression* call =
        factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
    if (type == IteratorType::kAsync) {
      call = factory()->NewAwait(call, nopos);
    }
    Expression* output_proxy = factory()->NewVariableProxy(var_output);
    Expression* assignment =
        factory()->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
    call_return = factory()->NewExpressionStatement(assignment, nopos);
  }

  // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
  Statement* validate_output;
  {
    Expression* is_receiver_call;
    {
      auto args = new (zone()) ZoneList<Expression*>(1, zone());
      args->Add(factory()->NewVariableProxy(var_output), zone());
      is_receiver_call =
          factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
    }

    Statement* throw_call;
    {
      auto args = new (zone()) ZoneList<Expression*>(1, zone());
      args->Add(factory()->NewVariableProxy(var_output), zone());
      Expression* call = factory()->NewCallRuntime(
          Runtime::kThrowIteratorResultNotAnObject, args, nopos);
      throw_call = factory()->NewExpressionStatement(call, nopos);
    }

    validate_output = factory()->NewIfStatement(
        is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
        nopos);
  }

  statements->Add(get_return, zone());
  statements->Add(check_return, zone());
  statements->Add(call_return, zone());
  statements->Add(validate_output, zone());
}

void Parser::FinalizeIteratorUse(Variable* completion, Expression* condition,
                                 Variable* iter, Block* iterator_use,
                                 Block* target, IteratorType type) {
  //
  // This function adds two statements to [target], corresponding to the
  // following code:
  //
  //   completion = kNormalCompletion;
  //   try {
  //     try {
  //       iterator_use
  //     } catch(e) {
  //       if (completion === kAbruptCompletion) completion = kThrowCompletion;
  //       %ReThrow(e);
  //     }
  //   } finally {
  //     if (condition) {
  //       #BuildIteratorCloseForCompletion(iter, completion)
  //     }
  //   }
  //

  const int nopos = kNoSourcePosition;

  // completion = kNormalCompletion;
  Statement* initialize_completion;
  {
    Expression* proxy = factory()->NewVariableProxy(completion);
    Expression* assignment = factory()->NewAssignment(
        Token::ASSIGN, proxy,
        factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
    initialize_completion =
        factory()->NewExpressionStatement(assignment, nopos);
  }

  // if (completion === kAbruptCompletion) completion = kThrowCompletion;
  Statement* set_completion_throw;
  {
    Expression* condition = factory()->NewCompareOperation(
        Token::EQ_STRICT, factory()->NewVariableProxy(completion),
        factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);

    Expression* proxy = factory()->NewVariableProxy(completion);
    Expression* assignment = factory()->NewAssignment(
        Token::ASSIGN, proxy,
        factory()->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
    Statement* statement = factory()->NewExpressionStatement(assignment, nopos);
    set_completion_throw = factory()->NewIfStatement(
        condition, statement, factory()->NewEmptyStatement(nopos), nopos);
  }

  // if (condition) {
  //   #BuildIteratorCloseForCompletion(iter, completion)
  // }
  Block* maybe_close;
  {
    Block* block = factory()->NewBlock(2, true);
    Expression* proxy = factory()->NewVariableProxy(completion);
    BuildIteratorCloseForCompletion(block->statements(), iter, proxy, type);
    DCHECK_EQ(block->statements()->length(), 2);

    maybe_close = IgnoreCompletion(factory()->NewIfStatement(
        condition, block, factory()->NewEmptyStatement(nopos), nopos));
  }

  // try { #try_block }
  // catch(e) {
  //   #set_completion_throw;
  //   %ReThrow(e);
  // }
  Statement* try_catch;
  {
    Scope* catch_scope = NewHiddenCatchScope();

    Statement* rethrow;
    // We use %ReThrow rather than the ordinary throw because we want to
    // preserve the original exception message.  This is also why we create a
    // TryCatchStatementForReThrow below (which does not clear the pending
    // message), rather than a TryCatchStatement.
    {
      auto args = new (zone()) ZoneList<Expression*>(1, zone());
      args->Add(factory()->NewVariableProxy(catch_scope->catch_variable()),
                zone());
      rethrow = factory()->NewExpressionStatement(
          factory()->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos);
    }

    Block* catch_block = factory()->NewBlock(2, false);
    catch_block->statements()->Add(set_completion_throw, zone());
    catch_block->statements()->Add(rethrow, zone());

    try_catch = factory()->NewTryCatchStatementForReThrow(
        iterator_use, catch_scope, catch_block, nopos);
  }

  // try { #try_catch } finally { #maybe_close }
  Statement* try_finally;
  {
    Block* try_block = factory()->NewBlock(1, false);
    try_block->statements()->Add(try_catch, zone());

    try_finally =
        factory()->NewTryFinallyStatement(try_block, maybe_close, nopos);
  }

  target->statements()->Add(initialize_completion, zone());
  target->statements()->Add(try_finally, zone());
}

void Parser::BuildIteratorCloseForCompletion(ZoneList<Statement*>* statements,
                                             Variable* iterator,
                                             Expression* completion,
                                             IteratorType type) {
  //
  // This function adds two statements to [statements], corresponding to the
  // following code:
  //
  //   let iteratorReturn = iterator.return;
  //   if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
  //     if (completion === kThrowCompletion) {
  //       if (!IS_CALLABLE(iteratorReturn)) {
  //         throw MakeTypeError(kReturnMethodNotCallable);
  //       }
  //       [if (IteratorType == kAsync)]
  //           try { Await(%_Call(iteratorReturn, iterator) } catch (_) { }
  //       [else]
  //           try { %_Call(iteratorReturn, iterator) } catch (_) { }
  //       [endif]
  //     } else {
  //       [if (IteratorType == kAsync)]
  //           let output = Await(%_Call(iteratorReturn, iterator));
  //       [else]
  //           let output = %_Call(iteratorReturn, iterator);
  //       [endif]
  //       if (!IS_RECEIVER(output)) {
  //         %ThrowIterResultNotAnObject(output);
  //       }
  //     }
  //   }
  //

  const int nopos = kNoSourcePosition;
  // let iteratorReturn = iterator.return;
  Variable* var_return = NewTemporary(ast_value_factory()->empty_string());
  Statement* get_return;
  {
    Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
    Expression* literal = factory()->NewStringLiteral(
        ast_value_factory()->return_string(), nopos);
    Expression* property =
        factory()->NewProperty(iterator_proxy, literal, nopos);
    Expression* return_proxy = factory()->NewVariableProxy(var_return);
    Expression* assignment =
        factory()->NewAssignment(Token::ASSIGN, return_proxy, property, nopos);
    get_return = factory()->NewExpressionStatement(assignment, nopos);
  }

  // if (!IS_CALLABLE(iteratorReturn)) {
  //   throw MakeTypeError(kReturnMethodNotCallable);
  // }
  Statement* check_return_callable;
  {
    Expression* throw_expr =
        NewThrowTypeError(MessageTemplate::kReturnMethodNotCallable,
                          ast_value_factory()->empty_string(), nopos);
    check_return_callable = CheckCallable(var_return, throw_expr, nopos);
  }

  // try { %_Call(iteratorReturn, iterator) } catch (_) { }
  Statement* try_call_return;
  {
    auto args = new (zone()) ZoneList<Expression*>(2, zone());
    args->Add(factory()->NewVariableProxy(var_return), zone());
    args->Add(factory()->NewVariableProxy(iterator), zone());

    Expression* call =
        factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);

    if (type == IteratorType::kAsync) {
      call = factory()->NewAwait(call, nopos);
    }

    Block* try_block = factory()->NewBlock(1, false);
    try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos),
                                 zone());

    Block* catch_block = factory()->NewBlock(0, false);
    Scope* catch_scope = NewHiddenCatchScope();
    try_call_return = factory()->NewTryCatchStatement(try_block, catch_scope,
                                                      catch_block, nopos);
  }

  // let output = %_Call(iteratorReturn, iterator);
  // if (!IS_RECEIVER(output)) {
  //   %ThrowIteratorResultNotAnObject(output);
  // }
  Block* validate_return;
  {
    Variable* var_output = NewTemporary(ast_value_factory()->empty_string());
    Statement* call_return;
    {
      auto args = new (zone()) ZoneList<Expression*>(2, zone());
      args->Add(factory()->NewVariableProxy(var_return), zone());
      args->Add(factory()->NewVariableProxy(iterator), zone());
      Expression* call =
          factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
      if (type == IteratorType::kAsync) {
        call = factory()->NewAwait(call, nopos);
      }

      Expression* output_proxy = factory()->NewVariableProxy(var_output);
      Expression* assignment =
          factory()->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
      call_return = factory()->NewExpressionStatement(assignment, nopos);
    }

    Expression* is_receiver_call;
    {
      auto args = new (zone()) ZoneList<Expression*>(1, zone());
      args->Add(factory()->NewVariableProxy(var_output), zone());
      is_receiver_call =
          factory()->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
    }

    Statement* throw_call;
    {
      auto args = new (zone()) ZoneList<Expression*>(1, zone());
      args->Add(factory()->NewVariableProxy(var_output), zone());
      Expression* call = factory()->NewCallRuntime(
          Runtime::kThrowIteratorResultNotAnObject, args, nopos);
      throw_call = factory()->NewExpressionStatement(call, nopos);
    }

    Statement* check_return = factory()->NewIfStatement(
        is_receiver_call, factory()->NewEmptyStatement(nopos), throw_call,
        nopos);

    validate_return = factory()->NewBlock(2, false);
    validate_return->statements()->Add(call_return, zone());
    validate_return->statements()->Add(check_return, zone());
  }

  // if (completion === kThrowCompletion) {
  //   #check_return_callable;
  //   #try_call_return;
  // } else {
  //   #validate_return;
  // }
  Statement* call_return_carefully;
  {
    Expression* condition = factory()->NewCompareOperation(
        Token::EQ_STRICT, completion,
        factory()->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);

    Block* then_block = factory()->NewBlock(2, false);
    then_block->statements()->Add(check_return_callable, zone());
    then_block->statements()->Add(try_call_return, zone());

    call_return_carefully = factory()->NewIfStatement(condition, then_block,
                                                      validate_return, nopos);
  }

  // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
  Statement* maybe_call_return;
  {
    Expression* condition = factory()->NewCompareOperation(
        Token::EQ, factory()->NewVariableProxy(var_return),
        factory()->NewNullLiteral(nopos), nopos);

    maybe_call_return = factory()->NewIfStatement(
        condition, factory()->NewEmptyStatement(nopos), call_return_carefully,
        nopos);
  }

  statements->Add(get_return, zone());
  statements->Add(maybe_call_return, zone());
}

Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
                                          Variable* var_completion,
                                          IteratorType type, int pos) {
  //
  // This function replaces the loop with the following wrapping:
  //
  //   completion = kNormalCompletion;
  //   try {
  //     try {
  //       #loop;
  //     } catch(e) {
  //       if (completion === kAbruptCompletion) completion = kThrowCompletion;
  //       %ReThrow(e);
  //     }
  //   } finally {
  //     if (!(completion === kNormalCompletion)) {
  //       #BuildIteratorCloseForCompletion(#iterator, completion)
  //     }
  //   }
  //
  // Note that the loop's body and its assign_each already contain appropriate
  // assignments to completion (see InitializeForOfStatement).
  //

  const int nopos = kNoSourcePosition;

  // !(completion === kNormalCompletion)
  Expression* closing_condition;
  {
    Expression* cmp = factory()->NewCompareOperation(
        Token::EQ_STRICT, factory()->NewVariableProxy(var_completion),
        factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
    closing_condition = factory()->NewUnaryOperation(Token::NOT, cmp, nopos);
  }

  Block* final_loop = factory()->NewBlock(2, false);
  {
    Block* try_block = factory()->NewBlock(1, false);
    try_block->statements()->Add(loop, zone());

    FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(),
                        try_block, final_loop, type);
  }

  return final_loop;
}

#undef CHECK_OK
#undef CHECK_OK_VOID
#undef CHECK_FAILED

}  // namespace internal
}  // namespace v8
