| 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
|
|
|
|
|