| Index: src/parsing/parser-base.h | 
| diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h | 
| index c31522e6a973eb7f57e08ecd17dc90413dedd028..07b031a65b254d3e6a7942b766d85b71a8f5d2f1 100644 | 
| --- a/src/parsing/parser-base.h | 
| +++ b/src/parsing/parser-base.h | 
| @@ -812,15 +812,13 @@ class ParserBase { | 
| } | 
| } | 
| // for now, this check just collects statistics. | 
| -  void CheckDecimalLiteralWithLeadingZero(int* use_counts, int beg_pos, | 
| -                                          int end_pos) { | 
| +  void CheckDecimalLiteralWithLeadingZero(int beg_pos, int end_pos) { | 
| Scanner::Location token_location = | 
| scanner()->decimal_with_leading_zero_position(); | 
| if (token_location.IsValid() && beg_pos <= token_location.beg_pos && | 
| token_location.end_pos <= end_pos) { | 
| scanner()->clear_decimal_with_leading_zero_position(); | 
| -      if (use_counts != nullptr) | 
| -        ++use_counts[v8::Isolate::kDecimalWithLeadingZeroInStrictMode]; | 
| +      impl()->CountUsage(v8::Isolate::kDecimalWithLeadingZeroInStrictMode); | 
| } | 
| } | 
|  | 
| @@ -1171,6 +1169,24 @@ class ParserBase { | 
| bool* ok); | 
| BlockT ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok); | 
|  | 
| +  // Parse a SubStatement in strict mode, or with an extra block scope in | 
| +  // sloppy mode to handle | 
| +  // ES#sec-functiondeclarations-in-ifstatement-statement-clauses | 
| +  // The legacy parameter indicates whether function declarations are | 
| +  // banned by the ES2015 specification in this location, and they are being | 
| +  // permitted here to match previous V8 behavior. | 
| +  StatementT ParseScopedStatement(ZoneList<const AstRawString*>* labels, | 
| +                                  bool legacy, bool* ok); | 
| + | 
| +  StatementT ParseVariableStatement(VariableDeclarationContext var_context, | 
| +                                    ZoneList<const AstRawString*>* names, | 
| +                                    bool* ok); | 
| + | 
| +  // Magical syntax support. | 
| +  ExpressionT ParseV8Intrinsic(bool* ok); | 
| + | 
| +  StatementT ParseDebuggerStatement(bool* ok); | 
| + | 
| bool IsNextLetKeyword(); | 
| bool IsTrivialExpression(); | 
|  | 
| @@ -1712,7 +1728,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression( | 
| case Token::MOD: | 
| if (allow_natives() || extension_ != NULL) { | 
| BindingPatternUnexpectedToken(); | 
| -        return impl()->ParseV8Intrinsic(ok); | 
| +        return ParseV8Intrinsic(ok); | 
| } | 
| break; | 
|  | 
| @@ -3443,10 +3459,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations( | 
| // FIXME(marja, nikolaos): Add an up-to-date comment about ES6 variable | 
| // declaration syntax. | 
|  | 
| -  DeclarationParsingResult temp_result; | 
| -  if (parsing_result == nullptr) { | 
| -    parsing_result = &temp_result; | 
| -  } | 
| +  DCHECK_NOT_NULL(parsing_result); | 
| parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL; | 
| parsing_result->descriptor.declaration_pos = peek_position(); | 
| parsing_result->descriptor.initialization_pos = peek_position(); | 
| @@ -3935,6 +3948,25 @@ void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, | 
| } | 
| } | 
|  | 
| +template <typename Impl> | 
| +typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseV8Intrinsic( | 
| +    bool* ok) { | 
| +  // CallRuntime :: | 
| +  //   '%' Identifier Arguments | 
| + | 
| +  int pos = peek_position(); | 
| +  Expect(Token::MOD, CHECK_OK); | 
| +  // Allow "eval" or "arguments" for backward compatibility. | 
| +  IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); | 
| +  Scanner::Location spread_pos; | 
| +  ExpressionClassifier classifier(this); | 
| +  ExpressionListT args = ParseArguments(&spread_pos, CHECK_OK); | 
| + | 
| +  DCHECK(!spread_pos.IsValid()); | 
| + | 
| +  return impl()->NewV8Intrinsic(name, args, pos, ok); | 
| +} | 
| + | 
| // Redefinition of CHECK_OK for parsing statements. | 
| #undef CHECK_OK | 
| #define CHECK_OK CHECK_OK_CUSTOM(NullStatement) | 
| @@ -4062,10 +4094,10 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatementListItem( | 
| return impl()->ParseClassDeclaration(nullptr, false, ok); | 
| case Token::VAR: | 
| case Token::CONST: | 
| -      return impl()->ParseVariableStatement(kStatementListItem, nullptr, ok); | 
| +      return ParseVariableStatement(kStatementListItem, nullptr, ok); | 
| case Token::LET: | 
| if (IsNextLetKeyword()) { | 
| -        return impl()->ParseVariableStatement(kStatementListItem, nullptr, ok); | 
| +        return ParseVariableStatement(kStatementListItem, nullptr, ok); | 
| } | 
| break; | 
| case Token::ASYNC: | 
| @@ -4159,9 +4191,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStatement( | 
| *ok = false; | 
| return impl()->NullStatement(); | 
| case Token::DEBUGGER: | 
| -      return impl()->ParseDebuggerStatement(ok); | 
| +      return ParseDebuggerStatement(ok); | 
| case Token::VAR: | 
| -      return impl()->ParseVariableStatement(kStatement, nullptr, ok); | 
| +      return ParseVariableStatement(kStatement, nullptr, ok); | 
| default: | 
| return impl()->ParseExpressionOrLabelledStatement(labels, allow_function, | 
| ok); | 
| @@ -4222,6 +4254,70 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseBlock( | 
| return body; | 
| } | 
|  | 
| +template <typename Impl> | 
| +typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseScopedStatement( | 
| +    ZoneList<const AstRawString*>* labels, bool legacy, bool* ok) { | 
| +  if (is_strict(language_mode()) || peek() != Token::FUNCTION || | 
| +      (legacy && allow_harmony_restrictive_declarations())) { | 
| +    return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok); | 
| +  } else { | 
| +    if (legacy) { | 
| +      impl()->CountUsage(v8::Isolate::kLegacyFunctionDeclaration); | 
| +    } | 
| +    // Make a block around the statement for a lexical binding | 
| +    // is introduced by a FunctionDeclaration. | 
| +    BlockState block_state(&scope_state_); | 
| +    block_state.set_start_position(scanner()->location().beg_pos); | 
| +    BlockT block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition); | 
| +    StatementT body = impl()->ParseFunctionDeclaration(CHECK_OK); | 
| +    block->statements()->Add(body, zone()); | 
| +    block_state.set_end_position(scanner()->location().end_pos); | 
| +    block->set_scope(block_state.FinalizedBlockScope()); | 
| +    return block; | 
| +  } | 
| +} | 
| + | 
| +template <typename Impl> | 
| +typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseVariableStatement( | 
| +    VariableDeclarationContext var_context, | 
| +    ZoneList<const AstRawString*>* names, bool* ok) { | 
| +  // VariableStatement :: | 
| +  //   VariableDeclarations ';' | 
| + | 
| +  // The scope of a var declared variable anywhere inside a function | 
| +  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | 
| +  // transform a source-level var declaration into a (Function) Scope | 
| +  // declaration, and rewrite the source-level initialization into an assignment | 
| +  // statement. We use a block to collect multiple assignments. | 
| +  // | 
| +  // We mark the block as initializer block because we don't want the | 
| +  // rewriter to add a '.result' assignment to such a block (to get compliant | 
| +  // behavior for code such as print(eval('var x = 7')), and for cosmetic | 
| +  // reasons when pretty-printing. Also, unless an assignment (initialization) | 
| +  // is inside an initializer block, it is ignored. | 
| + | 
| +  DeclarationParsingResult parsing_result; | 
| +  StatementT result = | 
| +      ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK); | 
| +  ExpectSemicolon(CHECK_OK); | 
| +  return result; | 
| +} | 
| + | 
| +template <typename Impl> | 
| +typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseDebuggerStatement( | 
| +    bool* ok) { | 
| +  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser | 
| +  // contexts this is used as a statement which invokes the debugger as i a | 
| +  // break point is present. | 
| +  // DebuggerStatement :: | 
| +  //   'debugger' ';' | 
| + | 
| +  int pos = peek_position(); | 
| +  Expect(Token::DEBUGGER, CHECK_OK); | 
| +  ExpectSemicolon(CHECK_OK); | 
| +  return factory()->NewDebuggerStatement(pos); | 
| +} | 
| + | 
| #undef CHECK_OK | 
| #undef CHECK_OK_CUSTOM | 
|  | 
|  |