v8/src/parsing/preparser.cc

1298 lines
43 KiB
C++
Raw Normal View History

// Copyright 2011 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 <cmath>
#include "src/allocation.h"
#include "src/base/logging.h"
#include "src/conversions-inl.h"
#include "src/conversions.h"
#include "src/globals.h"
#include "src/hashmap.h"
#include "src/list.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/preparse-data.h"
#include "src/parsing/preparse-data-format.h"
#include "src/parsing/preparser.h"
#include "src/unicode.h"
#include "src/utils.h"
namespace v8 {
namespace internal {
void PreParserTraits::ReportMessageAt(Scanner::Location location,
MessageTemplate::Template message,
const char* arg,
ParseErrorType error_type) {
ReportMessageAt(location.beg_pos, location.end_pos, message, arg, error_type);
}
void PreParserTraits::ReportMessageAt(int start_pos, int end_pos,
MessageTemplate::Template message,
const char* arg,
ParseErrorType error_type) {
pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg, error_type);
}
PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
return PreParserIdentifier::FutureReserved();
} else if (scanner->current_token() ==
Token::FUTURE_STRICT_RESERVED_WORD) {
return PreParserIdentifier::FutureStrictReserved();
} else if (scanner->current_token() == Token::LET) {
return PreParserIdentifier::Let();
} else if (scanner->current_token() == Token::STATIC) {
return PreParserIdentifier::Static();
} else if (scanner->current_token() == Token::YIELD) {
return PreParserIdentifier::Yield();
}
if (scanner->UnescapedLiteralMatches("eval", 4)) {
return PreParserIdentifier::Eval();
}
if (scanner->UnescapedLiteralMatches("arguments", 9)) {
return PreParserIdentifier::Arguments();
}
if (scanner->UnescapedLiteralMatches("undefined", 9)) {
return PreParserIdentifier::Undefined();
}
if (scanner->LiteralMatches("prototype", 9)) {
return PreParserIdentifier::Prototype();
}
if (scanner->LiteralMatches("constructor", 11)) {
return PreParserIdentifier::Constructor();
}
return PreParserIdentifier::Default();
}
PreParserIdentifier PreParserTraits::GetNumberAsSymbol(Scanner* scanner) {
return PreParserIdentifier::Default();
}
PreParserExpression PreParserTraits::ExpressionFromString(
int pos, Scanner* scanner, PreParserFactory* factory) {
if (scanner->UnescapedLiteralMatches("use strict", 10)) {
return PreParserExpression::UseStrictStringLiteral();
} else if (scanner->UnescapedLiteralMatches("use strong", 10)) {
return PreParserExpression::UseStrongStringLiteral();
}
return PreParserExpression::StringLiteral();
}
PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
return pre_parser_->ParseV8Intrinsic(ok);
}
PreParserExpression PreParserTraits::ParseFunctionLiteral(
PreParserIdentifier name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_position, FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok) {
return pre_parser_->ParseFunctionLiteral(
name, function_name_location, function_name_validity, kind,
function_token_position, type, arity_restriction, language_mode, ok);
}
PreParser::PreParseResult PreParser::PreParseLazyFunction(
LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters,
ParserRecorder* log, Scanner::BookmarkScope* bookmark) {
log_ = log;
// Lazy functions always have trivial outer scopes (no with/catch scopes).
Scope* top_scope = NewScope(scope_, SCRIPT_SCOPE);
PreParserFactory top_factory(NULL);
FunctionState top_state(&function_state_, &scope_, top_scope, kNormalFunction,
&top_factory);
scope_->SetLanguageMode(language_mode);
Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
if (!has_simple_parameters) function_scope->SetHasNonSimpleParameters();
PreParserFactory function_factory(NULL);
FunctionState function_state(&function_state_, &scope_, function_scope, kind,
&function_factory);
DCHECK_EQ(Token::LBRACE, scanner()->current_token());
bool ok = true;
int start_position = peek_position();
ParseLazyFunctionLiteralBody(&ok, bookmark);
if (bookmark && bookmark->HasBeenReset()) {
// Do nothing, as we've just aborted scanning this function.
} else if (stack_overflow()) {
return kPreParseStackOverflow;
} else if (!ok) {
ReportUnexpectedToken(scanner()->current_token());
} else {
DCHECK_EQ(Token::RBRACE, scanner()->peek());
if (is_strict(scope_->language_mode())) {
int end_pos = scanner()->location().end_pos;
CheckStrictOctalLiteral(start_position, end_pos, &ok);
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
if (!ok) return kPreParseSuccess;
if (is_strong(scope_->language_mode()) && IsSubclassConstructor(kind)) {
if (!function_state.super_location().IsValid()) {
ReportMessageAt(Scanner::Location(start_position, start_position + 1),
MessageTemplate::kStrongSuperCallMissing,
kReferenceError);
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
return kPreParseSuccess;
}
}
}
}
return kPreParseSuccess;
}
PreParserExpression PreParserTraits::ParseClassLiteral(
PreParserIdentifier name, Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos, bool* ok) {
return pre_parser_->ParseClassLiteral(name, class_name_location,
name_is_strict_reserved, pos, ok);
}
// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
// See preparser-data.h for the data.
// The PreParser checks that the syntax follows the grammar for JavaScript,
// and collects some information about the program along the way.
// The grammar check is only performed in order to understand the program
// sufficiently to deduce some information about it, that can be used
// to speed up later parsing. Finding errors is not the goal of pre-parsing,
// rather it is to speed up properly written and correct programs.
// That means that contextual checks (like a label being declared where
// it is used) are generally omitted.
PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
// ECMA 262 6th Edition
// StatementListItem[Yield, Return] :
// Statement[?Yield, ?Return]
// Declaration[?Yield]
//
// Declaration[Yield] :
// HoistableDeclaration[?Yield]
// ClassDeclaration[?Yield]
// LexicalDeclaration[In, ?Yield]
//
// HoistableDeclaration[Yield, Default] :
// FunctionDeclaration[?Yield, ?Default]
// GeneratorDeclaration[?Yield, ?Default]
//
// LexicalDeclaration[In, Yield] :
// LetOrConst BindingList[?In, ?Yield] ;
switch (peek()) {
case Token::FUNCTION:
return ParseFunctionDeclaration(ok);
case Token::CLASS:
return ParseClassDeclaration(ok);
case Token::CONST:
if (allow_const()) {
return ParseVariableStatement(kStatementListItem, ok);
}
break;
case Token::LET:
if (IsNextLetKeyword()) {
return ParseVariableStatement(kStatementListItem, ok);
}
break;
default:
break;
}
return ParseStatement(ok);
}
void PreParser::ParseStatementList(int end_token, bool* ok,
Scanner::BookmarkScope* bookmark) {
// SourceElements ::
// (Statement)* <end_token>
// Bookkeeping for trial parse if bookmark is set:
DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
bool maybe_reset = bookmark != nullptr;
int count_statements = 0;
bool directive_prologue = true;
while (peek() != end_token) {
if (directive_prologue && peek() != Token::STRING) {
directive_prologue = false;
}
bool starts_with_identifier = peek() == Token::IDENTIFIER;
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
Scanner::Location token_loc = scanner()->peek_location();
Scanner::Location old_this_loc = function_state_->this_location();
Scanner::Location old_super_loc = function_state_->super_location();
Statement statement = ParseStatementListItem(ok);
if (!*ok) return;
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
if (is_strong(language_mode()) && scope_->is_function_scope() &&
IsClassConstructor(function_state_->kind())) {
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
Scanner::Location this_loc = function_state_->this_location();
Scanner::Location super_loc = function_state_->super_location();
if (this_loc.beg_pos != old_this_loc.beg_pos &&
this_loc.beg_pos != token_loc.beg_pos) {
ReportMessageAt(this_loc, MessageTemplate::kStrongConstructorThis);
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
*ok = false;
return;
}
if (super_loc.beg_pos != old_super_loc.beg_pos &&
super_loc.beg_pos != token_loc.beg_pos) {
ReportMessageAt(super_loc, MessageTemplate::kStrongConstructorSuper);
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
*ok = false;
return;
}
}
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
if (directive_prologue) {
bool use_strict_found = statement.IsUseStrictLiteral();
bool use_strong_found =
statement.IsUseStrongLiteral() && allow_strong_mode();
if (use_strict_found) {
scope_->SetLanguageMode(
static_cast<LanguageMode>(scope_->language_mode() | STRICT));
} else if (use_strong_found) {
scope_->SetLanguageMode(static_cast<LanguageMode>(
scope_->language_mode() | STRONG));
if (IsClassConstructor(function_state_->kind())) {
// "use strong" cannot occur in a class constructor body, to avoid
// unintuitive strong class object semantics.
PreParserTraits::ReportMessageAt(
token_loc, MessageTemplate::kStrongConstructorDirective);
*ok = false;
return;
}
} else if (!statement.IsStringLiteral()) {
directive_prologue = false;
}
if ((use_strict_found || use_strong_found) &&
!scope_->HasSimpleParameters()) {
// TC39 deemed "use strict" directives to be an error when occurring
// in the body of a function with non-simple parameter list, on
// 29/7/2015. https://goo.gl/ueA7Ln
//
// In V8, this also applies to "use strong " directives.
PreParserTraits::ReportMessageAt(
token_loc, MessageTemplate::kIllegalLanguageModeDirective,
use_strict_found ? "use strict" : "use strong");
*ok = false;
return;
}
}
// If we're allowed to reset to a bookmark, we will do so when we see a long
// and trivial function.
// Our current definition of 'long and trivial' is:
// - over 200 statements
// - all starting with an identifier (i.e., no if, for, while, etc.)
if (maybe_reset && (!starts_with_identifier ||
++count_statements > kLazyParseTrialLimit)) {
if (count_statements > kLazyParseTrialLimit) {
bookmark->Reset();
return;
}
maybe_reset = false;
}
}
}
#define CHECK_OK ok); \
if (!*ok) return Statement::Default(); \
((void)0
#define DUMMY ) // to make indentation work
#undef DUMMY
PreParser::Statement PreParser::ParseStatement(bool* ok) {
// Statement ::
// EmptyStatement
// ...
if (peek() == Token::SEMICOLON) {
Next();
return Statement::Default();
}
return ParseSubStatement(ok);
}
PreParser::Statement PreParser::ParseSubStatement(bool* ok) {
// Statement ::
// Block
// VariableStatement
// EmptyStatement
// ExpressionStatement
// IfStatement
// IterationStatement
// ContinueStatement
// BreakStatement
// ReturnStatement
// WithStatement
// LabelledStatement
// SwitchStatement
// ThrowStatement
// TryStatement
// DebuggerStatement
// Note: Since labels can only be used by 'break' and 'continue'
// statements, which themselves are only valid within blocks,
// iterations or 'switch' statements (i.e., BreakableStatements),
// labels can be simply ignored in all other cases; except for
// trivial labeled break statements 'label: break label' which is
// parsed into an empty statement.
// Keep the source position of the statement
switch (peek()) {
case Token::LBRACE:
return ParseBlock(ok);
case Token::SEMICOLON:
if (is_strong(language_mode())) {
PreParserTraits::ReportMessageAt(scanner()->peek_location(),
MessageTemplate::kStrongEmpty);
*ok = false;
return Statement::Default();
}
Next();
return Statement::Default();
case Token::IF:
return ParseIfStatement(ok);
case Token::DO:
return ParseDoWhileStatement(ok);
case Token::WHILE:
return ParseWhileStatement(ok);
case Token::FOR:
return ParseForStatement(ok);
case Token::CONTINUE:
return ParseContinueStatement(ok);
case Token::BREAK:
return ParseBreakStatement(ok);
case Token::RETURN:
return ParseReturnStatement(ok);
case Token::WITH:
return ParseWithStatement(ok);
case Token::SWITCH:
return ParseSwitchStatement(ok);
case Token::THROW:
return ParseThrowStatement(ok);
case Token::TRY:
return ParseTryStatement(ok);
case Token::FUNCTION: {
Scanner::Location start_location = scanner()->peek_location();
Statement statement = ParseFunctionDeclaration(CHECK_OK);
Scanner::Location end_location = scanner()->location();
if (is_strict(language_mode())) {
PreParserTraits::ReportMessageAt(start_location.beg_pos,
end_location.end_pos,
MessageTemplate::kStrictFunction);
*ok = false;
return Statement::Default();
} else {
return statement;
}
}
case Token::DEBUGGER:
return ParseDebuggerStatement(ok);
case Token::VAR:
return ParseVariableStatement(kStatement, ok);
case Token::CONST:
// In ES6 CONST is not allowed as a Statement, only as a
// LexicalDeclaration, however we continue to allow it in sloppy mode for
// backwards compatibility.
if (is_sloppy(language_mode()) && allow_legacy_const()) {
return ParseVariableStatement(kStatement, ok);
}
// Fall through.
default:
return ParseExpressionOrLabelledStatement(ok);
}
}
PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
// GeneratorDeclaration ::
// 'function' '*' Identifier '(' FormalParameterListopt ')'
// '{' FunctionBody '}'
Expect(Token::FUNCTION, CHECK_OK);
int pos = position();
bool is_generator = Check(Token::MUL);
bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
ParseFunctionLiteral(name, scanner()->location(),
is_strict_reserved ? kFunctionNameIsStrictReserved
: kFunctionNameValidityUnknown,
is_generator ? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction,
pos, FunctionLiteral::kDeclaration,
FunctionLiteral::kNormalArity, language_mode(),
CHECK_OK);
return Statement::FunctionDeclaration();
}
PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
Expect(Token::CLASS, CHECK_OK);
if (!allow_harmony_sloppy() && is_sloppy(language_mode())) {
ReportMessage(MessageTemplate::kSloppyLexical);
*ok = false;
return Statement::Default();
}
int pos = position();
bool is_strict_reserved = false;
Identifier name =
ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
ParseClassLiteral(name, scanner()->location(), is_strict_reserved, pos,
CHECK_OK);
return Statement::Default();
}
PreParser::Statement PreParser::ParseBlock(bool* ok) {
// Block ::
// '{' StatementList '}'
Expect(Token::LBRACE, CHECK_OK);
Statement final = Statement::Default();
while (peek() != Token::RBRACE) {
final = ParseStatementListItem(CHECK_OK);
}
Expect(Token::RBRACE, ok);
return final;
}
PreParser::Statement PreParser::ParseVariableStatement(
VariableDeclarationContext var_context,
bool* ok) {
// VariableStatement ::
// VariableDeclarations ';'
Statement result = ParseVariableDeclarations(
var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return result;
}
// If the variable declaration declares exactly one non-const
// variable, then *var is set to that variable. In all other cases,
// *var is untouched; in particular, it is the caller's responsibility
// to initialize it properly. This mechanism is also used for the parsing
// of 'for-in' loops.
PreParser::Statement PreParser::ParseVariableDeclarations(
VariableDeclarationContext var_context, int* num_decl, bool* is_lexical,
bool* is_binding_pattern, Scanner::Location* first_initializer_loc,
Scanner::Location* bindings_loc, bool* ok) {
// VariableDeclarations ::
// ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
//
// The ES6 Draft Rev3 specifies the following grammar for const declarations
//
// ConstDeclaration ::
// const ConstBinding (',' ConstBinding)* ';'
// ConstBinding ::
// Identifier '=' AssignmentExpression
//
// TODO(ES6):
// ConstBinding ::
// BindingPattern '=' AssignmentExpression
bool require_initializer = false;
bool lexical = false;
bool is_pattern = false;
if (peek() == Token::VAR) {
if (is_strong(language_mode())) {
Scanner::Location location = scanner()->peek_location();
ReportMessageAt(location, MessageTemplate::kStrongVar);
*ok = false;
return Statement::Default();
}
Consume(Token::VAR);
} else if (peek() == Token::CONST && allow_const()) {
// TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
//
// ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
//
// * It is a Syntax Error if the code that matches this production is not
// contained in extended code.
//
// However disallowing const in sloppy mode will break compatibility with
// existing pages. Therefore we keep allowing const with the old
// non-harmony semantics in sloppy mode.
Consume(Token::CONST);
if (is_strict(language_mode()) ||
(allow_harmony_sloppy() && !allow_legacy_const())) {
DCHECK(var_context != kStatement);
require_initializer = true;
lexical = true;
}
} else if (peek() == Token::LET && allow_let()) {
Consume(Token::LET);
DCHECK(var_context != kStatement);
lexical = true;
} else {
*ok = false;
return Statement::Default();
}
// The scope of a var/const declared variable anywhere inside a function
// is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
// of a let declared variable is the scope of the immediately enclosing
// block.
int nvars = 0; // the number of variables declared
int bindings_start = peek_position();
do {
// Parse binding pattern.
if (nvars > 0) Consume(Token::COMMA);
int decl_pos = peek_position();
PreParserExpression pattern = PreParserExpression::Default();
{
ExpressionClassifier pattern_classifier;
Token::Value next = peek();
pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
ValidateBindingPattern(&pattern_classifier, CHECK_OK);
if (lexical) {
ValidateLetPattern(&pattern_classifier, CHECK_OK);
}
if (!allow_harmony_destructuring_bind() && !pattern.IsIdentifier()) {
ReportUnexpectedToken(next);
*ok = false;
return Statement::Default();
}
}
is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral();
Scanner::Location variable_loc = scanner()->location();
nvars++;
if (Check(Token::ASSIGN)) {
ExpressionClassifier classifier;
ParseAssignmentExpression(var_context != kForStatement, &classifier,
CHECK_OK);
ValidateExpression(&classifier, CHECK_OK);
variable_loc.end_pos = scanner()->location().end_pos;
if (first_initializer_loc && !first_initializer_loc->IsValid()) {
*first_initializer_loc = variable_loc;
}
} else if ((require_initializer || is_pattern) &&
(var_context != kForStatement || !PeekInOrOf())) {
PreParserTraits::ReportMessageAt(
Scanner::Location(decl_pos, scanner()->location().end_pos),
MessageTemplate::kDeclarationMissingInitializer,
is_pattern ? "destructuring" : "const");
*ok = false;
return Statement::Default();
}
} while (peek() == Token::COMMA);
if (bindings_loc) {
*bindings_loc =
Scanner::Location(bindings_start, scanner()->location().end_pos);
}
if (num_decl != nullptr) *num_decl = nvars;
if (is_lexical != nullptr) *is_lexical = lexical;
if (is_binding_pattern != nullptr) *is_binding_pattern = is_pattern;
return Statement::Default();
}
PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
// ExpressionStatement | LabelledStatement ::
// Expression ';'
// Identifier ':' Statement
switch (peek()) {
case Token::FUNCTION:
case Token::LBRACE:
UNREACHABLE(); // Always handled by the callers.
case Token::CLASS:
ReportUnexpectedToken(Next());
*ok = false;
return Statement::Default();
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
case Token::THIS:
if (!FLAG_strong_this) break;
// Fall through.
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
case Token::SUPER:
if (is_strong(language_mode()) &&
IsClassConstructor(function_state_->kind())) {
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
bool is_this = peek() == Token::THIS;
Expression expr = Expression::Default();
ExpressionClassifier classifier;
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
if (is_this) {
expr = ParseStrongInitializationExpression(&classifier, CHECK_OK);
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
} else {
expr = ParseStrongSuperCallExpression(&classifier, CHECK_OK);
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
}
ValidateExpression(&classifier, CHECK_OK);
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
switch (peek()) {
case Token::SEMICOLON:
Consume(Token::SEMICOLON);
break;
case Token::RBRACE:
case Token::EOS:
break;
default:
if (!scanner()->HasAnyLineTerminatorBeforeNext()) {
ReportMessageAt(function_state_->this_location(),
is_this
? MessageTemplate::kStrongConstructorThis
: MessageTemplate::kStrongConstructorSuper);
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
*ok = false;
return Statement::Default();
}
}
return Statement::ExpressionStatement(expr);
}
break;
// TODO(arv): Handle `let [`
// https://code.google.com/p/v8/issues/detail?id=3847
default:
break;
}
bool starts_with_identifier = peek_any_identifier();
ExpressionClassifier classifier;
Expression expr = ParseExpression(true, &classifier, CHECK_OK);
ValidateExpression(&classifier, CHECK_OK);
// Even if the expression starts with an identifier, it is not necessarily an
// identifier. For example, "foo + bar" starts with an identifier but is not
// an identifier.
if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
// Expression is a single identifier, and not, e.g., a parenthesized
// identifier.
DCHECK(!expr.AsIdentifier().IsFutureReserved());
DCHECK(is_sloppy(language_mode()) ||
!IsFutureStrictReserved(expr.AsIdentifier()));
Consume(Token::COLON);
Statement statement = ParseStatement(ok);
return statement.IsJumpStatement() ? Statement::Default() : statement;
// Preparsing is disabled for extensions (because the extension details
// aren't passed to lazily compiled functions), so we don't
// accept "native function" in the preparser.
}
// Parsed expression statement.
// Detect attempts at 'let' declarations in sloppy mode.
if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
is_sloppy(language_mode()) && expr.IsIdentifier() &&
expr.AsIdentifier().IsLet()) {
ReportMessage(MessageTemplate::kSloppyLexical, NULL);
*ok = false;
return Statement::Default();
}
ExpectSemicolon(CHECK_OK);
return Statement::ExpressionStatement(expr);
}
PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
// IfStatement ::
// 'if' '(' Expression ')' Statement ('else' Statement)?
Expect(Token::IF, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
Statement stat = ParseSubStatement(CHECK_OK);
if (peek() == Token::ELSE) {
Next();
Statement else_stat = ParseSubStatement(CHECK_OK);
stat = (stat.IsJumpStatement() && else_stat.IsJumpStatement()) ?
Statement::Jump() : Statement::Default();
} else {
stat = Statement::Default();
}
return stat;
}
PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
// ContinueStatement ::
// 'continue' [no line terminator] Identifier? ';'
Expect(Token::CONTINUE, CHECK_OK);
Token::Value tok = peek();
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON &&
tok != Token::RBRACE &&
tok != Token::EOS) {
Make strict more error messages about "eval" and "arguments" less specific. We used to have error messages which provide context, like "Variable name may not be eval or arguments in strict mode", but for other illegal words we only have non-context specific error messages like "Unexpected reserved word". Providing the context makes the code unnecessarily complex, since every individual place must remember to check for eval or arguments. This CL produces a unified error message ("Unexpected eval or arguments in strict mode"), and puts the error reporting to (Pre)Parser::ParseIdentifier. Notes: - The module feature is so experimental, that I decided to not allow "eval" or "arguments" as module-related identifiers in the strict mode (even though this check wasn't there before). - Unfortunately, there were some inconsistencies, since it was the responsibility of the caller of ParseIdentifier to check "eval" and "arguments" and some places didn't have the check for no good reason. This CL is supposed to keep backward compatibility and *not* introduce any new errors. - ECMA allows "eval" and "arguments" as labels even in strict mode. (Syntax: "LabelledStatement: Identifier : Statement", and no strict mode restrictions on Identifier are listed.) - Tests which compare error message strings will fail, and need to be updated. BUG=3126 LOG=N R=ulan@chromium.org Review URL: https://codereview.chromium.org/152813005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19112 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-02-05 16:26:48 +00:00
// ECMA allows "eval" or "arguments" as labels even in strict mode.
ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
return Statement::Jump();
}
PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
// BreakStatement ::
// 'break' [no line terminator] Identifier? ';'
Expect(Token::BREAK, CHECK_OK);
Token::Value tok = peek();
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON &&
tok != Token::RBRACE &&
tok != Token::EOS) {
Make strict more error messages about "eval" and "arguments" less specific. We used to have error messages which provide context, like "Variable name may not be eval or arguments in strict mode", but for other illegal words we only have non-context specific error messages like "Unexpected reserved word". Providing the context makes the code unnecessarily complex, since every individual place must remember to check for eval or arguments. This CL produces a unified error message ("Unexpected eval or arguments in strict mode"), and puts the error reporting to (Pre)Parser::ParseIdentifier. Notes: - The module feature is so experimental, that I decided to not allow "eval" or "arguments" as module-related identifiers in the strict mode (even though this check wasn't there before). - Unfortunately, there were some inconsistencies, since it was the responsibility of the caller of ParseIdentifier to check "eval" and "arguments" and some places didn't have the check for no good reason. This CL is supposed to keep backward compatibility and *not* introduce any new errors. - ECMA allows "eval" and "arguments" as labels even in strict mode. (Syntax: "LabelledStatement: Identifier : Statement", and no strict mode restrictions on Identifier are listed.) - Tests which compare error message strings will fail, and need to be updated. BUG=3126 LOG=N R=ulan@chromium.org Review URL: https://codereview.chromium.org/152813005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19112 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-02-05 16:26:48 +00:00
// ECMA allows "eval" or "arguments" as labels even in strict mode.
ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
return Statement::Jump();
}
PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
// ReturnStatement ::
// 'return' [no line terminator] Expression? ';'
// Consume the return token. It is necessary to do before
// reporting any errors on it, because of the way errors are
// reported (underlining).
Expect(Token::RETURN, CHECK_OK);
function_state_->set_return_location(scanner()->location());
// An ECMAScript program is considered syntactically incorrect if it
// contains a return statement that is not within the body of a
// function. See ECMA-262, section 12.9, page 67.
// This is not handled during preparsing.
Token::Value tok = peek();
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON &&
tok != Token::RBRACE &&
tok != Token::EOS) {
if (is_strong(language_mode()) &&
IsClassConstructor(function_state_->kind())) {
int pos = peek_position();
ReportMessageAt(Scanner::Location(pos, pos + 1),
MessageTemplate::kStrongConstructorReturnValue);
*ok = false;
return Statement::Default();
}
ParseExpression(true, CHECK_OK);
}
ExpectSemicolon(CHECK_OK);
return Statement::Jump();
}
PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
// WithStatement ::
// 'with' '(' Expression ')' Statement
Expect(Token::WITH, CHECK_OK);
if (is_strict(language_mode())) {
ReportMessageAt(scanner()->location(), MessageTemplate::kStrictWith);
*ok = false;
return Statement::Default();
}
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
Scope* with_scope = NewScope(scope_, WITH_SCOPE);
BlockState block_state(&scope_, with_scope);
ParseSubStatement(CHECK_OK);
return Statement::Default();
}
PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
Expect(Token::SWITCH, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
Expect(Token::LBRACE, CHECK_OK);
Token::Value token = peek();
while (token != Token::RBRACE) {
if (token == Token::CASE) {
Expect(Token::CASE, CHECK_OK);
ParseExpression(true, CHECK_OK);
} else {
Expect(Token::DEFAULT, CHECK_OK);
}
Expect(Token::COLON, CHECK_OK);
token = peek();
Statement statement = Statement::Jump();
while (token != Token::CASE &&
token != Token::DEFAULT &&
token != Token::RBRACE) {
statement = ParseStatementListItem(CHECK_OK);
token = peek();
}
if (is_strong(language_mode()) && !statement.IsJumpStatement() &&
token != Token::RBRACE) {
ReportMessageAt(scanner()->location(),
MessageTemplate::kStrongSwitchFallthrough);
*ok = false;
return Statement::Default();
}
}
Expect(Token::RBRACE, ok);
return Statement::Default();
}
PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
Expect(Token::DO, CHECK_OK);
ParseSubStatement(CHECK_OK);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, ok);
if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
return Statement::Default();
}
PreParser::Statement PreParser::ParseWhileStatement(bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
ParseSubStatement(ok);
return Statement::Default();
}
PreParser::Statement PreParser::ParseForStatement(bool* ok) {
// ForStatement ::
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
Expect(Token::FOR, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
bool is_let_identifier_expression = false;
if (peek() != Token::SEMICOLON) {
ForEachStatement::VisitMode mode;
if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
(peek() == Token::LET && IsNextLetKeyword())) {
int decl_count;
bool is_lexical;
bool is_binding_pattern;
Scanner::Location first_initializer_loc = Scanner::Location::invalid();
Scanner::Location bindings_loc = Scanner::Location::invalid();
ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical,
&is_binding_pattern, &first_initializer_loc,
&bindings_loc, CHECK_OK);
if (CheckInOrOf(&mode, ok)) {
if (!*ok) return Statement::Default();
if (decl_count != 1) {
PreParserTraits::ReportMessageAt(
bindings_loc, MessageTemplate::kForInOfLoopMultiBindings,
ForEachStatement::VisitModeString(mode));
*ok = false;
return Statement::Default();
}
if (first_initializer_loc.IsValid() &&
(is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
is_lexical || is_binding_pattern)) {
PreParserTraits::ReportMessageAt(
first_initializer_loc, MessageTemplate::kForInOfLoopInitializer,
ForEachStatement::VisitModeString(mode));
*ok = false;
return Statement::Default();
}
if (mode == ForEachStatement::ITERATE) {
ExpressionClassifier classifier;
Expression enumerable =
ParseAssignmentExpression(true, &classifier, CHECK_OK);
PreParserTraits::RewriteNonPattern(enumerable, &classifier, CHECK_OK);
} else {
ParseExpression(true, CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
ParseSubStatement(CHECK_OK);
return Statement::Default();
}
} else {
int lhs_beg_pos = peek_position();
ExpressionClassifier classifier;
Expression lhs = ParseExpression(false, &classifier, CHECK_OK);
int lhs_end_pos = scanner()->location().end_pos;
is_let_identifier_expression =
lhs.IsIdentifier() && lhs.AsIdentifier().IsLet();
bool is_for_each = CheckInOrOf(&mode, ok);
if (!*ok) return Statement::Default();
bool is_destructuring = is_for_each &&
allow_harmony_destructuring_assignment() &&
(lhs->IsArrayLiteral() || lhs->IsObjectLiteral());
if (is_destructuring) {
ValidateAssignmentPattern(&classifier, CHECK_OK);
} else {
ValidateExpression(&classifier, CHECK_OK);
}
if (is_for_each) {
if (!is_destructuring) {
lhs = CheckAndRewriteReferenceExpression(
lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
kSyntaxError, CHECK_OK);
}
if (mode == ForEachStatement::ITERATE) {
ExpressionClassifier classifier;
Expression enumerable =
ParseAssignmentExpression(true, &classifier, CHECK_OK);
PreParserTraits::RewriteNonPattern(enumerable, &classifier, CHECK_OK);
} else {
ParseExpression(true, CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
ParseSubStatement(CHECK_OK);
return Statement::Default();
}
}
}
// Parsed initializer at this point.
// Detect attempts at 'let' declarations in sloppy mode.
if (!allow_harmony_sloppy_let() && peek() == Token::IDENTIFIER &&
is_sloppy(language_mode()) && is_let_identifier_expression) {
ReportMessage(MessageTemplate::kSloppyLexical, NULL);
*ok = false;
return Statement::Default();
}
Expect(Token::SEMICOLON, CHECK_OK);
if (peek() != Token::SEMICOLON) {
ParseExpression(true, CHECK_OK);
}
Expect(Token::SEMICOLON, CHECK_OK);
if (peek() != Token::RPAREN) {
ParseExpression(true, CHECK_OK);
}
Expect(Token::RPAREN, CHECK_OK);
ParseSubStatement(ok);
return Statement::Default();
}
PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
// ThrowStatement ::
// 'throw' [no line terminator] Expression ';'
Expect(Token::THROW, CHECK_OK);
if (scanner()->HasAnyLineTerminatorBeforeNext()) {
ReportMessageAt(scanner()->location(), MessageTemplate::kNewlineAfterThrow);
*ok = false;
return Statement::Default();
}
ParseExpression(true, CHECK_OK);
ExpectSemicolon(ok);
return Statement::Jump();
}
PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
// TryStatement ::
// 'try' Block Catch
// 'try' Block Finally
// 'try' Block Catch Finally
//
// Catch ::
// 'catch' '(' Identifier ')' Block
//
// Finally ::
// 'finally' Block
Expect(Token::TRY, CHECK_OK);
ParseBlock(CHECK_OK);
Token::Value tok = peek();
if (tok != Token::CATCH && tok != Token::FINALLY) {
ReportMessageAt(scanner()->location(), MessageTemplate::kNoCatchOrFinally);
*ok = false;
return Statement::Default();
}
if (tok == Token::CATCH) {
Consume(Token::CATCH);
Expect(Token::LPAREN, CHECK_OK);
ExpressionClassifier pattern_classifier;
ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
ValidateBindingPattern(&pattern_classifier, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
{
// TODO(adamk): Make this CATCH_SCOPE
Scope* with_scope = NewScope(scope_, WITH_SCOPE);
BlockState block_state(&scope_, with_scope);
ParseBlock(CHECK_OK);
}
tok = peek();
}
if (tok == Token::FINALLY) {
Consume(Token::FINALLY);
ParseBlock(CHECK_OK);
}
return Statement::Default();
}
PreParser::Statement PreParser::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 if a
// break point is present.
// DebuggerStatement ::
// 'debugger' ';'
Expect(Token::DEBUGGER, CHECK_OK);
ExpectSemicolon(ok);
return Statement::Default();
}
#undef CHECK_OK
#define CHECK_OK ok); \
if (!*ok) return Expression::Default(); \
((void)0
#define DUMMY ) // to make indentation work
#undef DUMMY
PreParser::Expression PreParser::ParseFunctionLiteral(
Identifier function_name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_pos, FunctionLiteral::FunctionType function_type,
FunctionLiteral::ArityRestriction arity_restriction,
LanguageMode language_mode, bool* ok) {
// Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}'
// Parse function body.
bool outer_is_script_scope = scope_->is_script_scope();
Scope* function_scope = NewScope(scope_, FUNCTION_SCOPE, kind);
function_scope->SetLanguageMode(language_mode);
PreParserFactory factory(NULL);
FunctionState function_state(&function_state_, &scope_, function_scope, kind,
&factory);
DuplicateFinder duplicate_finder(scanner()->unicode_cache());
ExpressionClassifier formals_classifier(&duplicate_finder);
Expect(Token::LPAREN, CHECK_OK);
int start_position = scanner()->location().beg_pos;
function_scope->set_start_position(start_position);
PreParserFormalParameters formals(function_scope);
ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
int formals_end_position = scanner()->location().end_pos;
CheckArityRestrictions(formals.arity, arity_restriction,
formals.has_rest, start_position,
formals_end_position, CHECK_OK);
// See Parser::ParseFunctionLiteral for more information about lazy parsing
// and lazy compilation.
bool is_lazily_parsed =
(outer_is_script_scope && allow_lazy() && !parenthesized_function_);
parenthesized_function_ = false;
Expect(Token::LBRACE, CHECK_OK);
if (is_lazily_parsed) {
ParseLazyFunctionLiteralBody(CHECK_OK);
} else {
ParseStatementList(Token::RBRACE, CHECK_OK);
}
Expect(Token::RBRACE, CHECK_OK);
// Parsing the body may change the language mode in our scope.
language_mode = function_scope->language_mode();
// Validate name and parameter names. We can do this only after parsing the
// function, since the function can declare itself strict.
CheckFunctionName(language_mode, function_name, function_name_validity,
function_name_location, CHECK_OK);
const bool allow_duplicate_parameters =
is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
ValidateFormalParameters(&formals_classifier, language_mode,
allow_duplicate_parameters, CHECK_OK);
if (is_strict(language_mode)) {
int end_position = scanner()->location().end_pos;
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
}
if (is_strong(language_mode) && IsSubclassConstructor(kind)) {
Revert of Revert of [strong] checking of this & super in constructors (patchset #1 id:1 of https://codereview.chromium.org/1105453002/) Reason for revert: Was an infrastructure problem. Original issue's description: > Revert of [strong] checking of this & super in constructors (patchset #7 id:110001 of https://codereview.chromium.org/1024063002/) > > Reason for revert: > [Sheriff] Breaks mac gc stress: > http://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/1024 > > Original issue's description: > > [strong] checking of this & super in constructors > > > > R=dslomov@chromium.org, marja@chromium.org > > BUG=v8:3956 > > LOG=N > > > > Enforces for constructors that > > - the only use of 'super' is the super constructor call > > - the only use of 'this' is a property assignment > > - both of these must happen at the top-level of the body > > - 'this' may only be assigned after the 'super' call > > - 'return' may only be used after the last assignment to 'this' > > > > Not yet working for arrow functions (there might be deeper bugs with those). > > > > Committed: https://crrev.com/580d66bcda66220d2f3062ac58daf925436df74c > > Cr-Commit-Position: refs/heads/master@{#27977} > > TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:3956 TBR=dslomov@chromium.org,marja@chromium.org,conradw@chromium.org,rossberg@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:3956 Review URL: https://codereview.chromium.org/1073103004 Cr-Commit-Position: refs/heads/master@{#28001}
2015-04-22 11:04:25 +00:00
if (!function_state.super_location().IsValid()) {
ReportMessageAt(function_name_location,
MessageTemplate::kStrongSuperCallMissing,
kReferenceError);
*ok = false;
return Expression::Default();
}
}
return Expression::Default();
}
void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
Scanner::BookmarkScope* bookmark) {
int body_start = position();
ParseStatementList(Token::RBRACE, ok, bookmark);
if (!*ok) return;
if (bookmark && bookmark->HasBeenReset()) return;
// Position right after terminal '}'.
DCHECK_EQ(Token::RBRACE, scanner()->peek());
int body_end = scanner()->peek_location().end_pos;
log_->LogFunction(body_start, body_end,
function_state_->materialized_literal_count(),
function_state_->expected_property_count(), language_mode(),
scope_->uses_super_property(), scope_->calls_eval());
}
PreParserExpression PreParser::ParseClassLiteral(
PreParserIdentifier name, Scanner::Location class_name_location,
bool name_is_strict_reserved, int pos, bool* ok) {
// All parts of a ClassDeclaration and ClassExpression are strict code.
if (name_is_strict_reserved) {
ReportMessageAt(class_name_location,
MessageTemplate::kUnexpectedStrictReserved);
*ok = false;
return EmptyExpression();
}
if (IsEvalOrArguments(name)) {
ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
*ok = false;
return EmptyExpression();
}
LanguageMode class_language_mode = language_mode();
if (is_strong(class_language_mode) && IsUndefined(name)) {
ReportMessageAt(class_name_location, MessageTemplate::kStrongUndefined);
*ok = false;
return EmptyExpression();
}
Scope* scope = NewScope(scope_, BLOCK_SCOPE);
BlockState block_state(&scope_, scope);
scope_->SetLanguageMode(
static_cast<LanguageMode>(class_language_mode | STRICT));
// TODO(marja): Make PreParser use scope names too.
// scope_->SetScopeName(name);
bool has_extends = Check(Token::EXTENDS);
if (has_extends) {
ExpressionClassifier classifier;
ParseLeftHandSideExpression(&classifier, CHECK_OK);
ValidateExpression(&classifier, CHECK_OK);
}
ClassLiteralChecker checker(this);
bool has_seen_constructor = false;
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
if (Check(Token::SEMICOLON)) continue;
const bool in_class = true;
const bool is_static = false;
bool is_computed_name = false; // Classes do not care about computed
// property names here.
Identifier name;
ExpressionClassifier classifier;
ParsePropertyDefinition(&checker, in_class, has_extends, is_static,
&is_computed_name, &has_seen_constructor,
&classifier, &name, CHECK_OK);
ValidateExpression(&classifier, CHECK_OK);
}
Expect(Token::RBRACE, CHECK_OK);
return Expression::Default();
}
PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
// CallRuntime ::
// '%' Identifier Arguments
Expect(Token::MOD, CHECK_OK);
if (!allow_natives()) {
*ok = false;
return Expression::Default();
}
Make strict more error messages about "eval" and "arguments" less specific. We used to have error messages which provide context, like "Variable name may not be eval or arguments in strict mode", but for other illegal words we only have non-context specific error messages like "Unexpected reserved word". Providing the context makes the code unnecessarily complex, since every individual place must remember to check for eval or arguments. This CL produces a unified error message ("Unexpected eval or arguments in strict mode"), and puts the error reporting to (Pre)Parser::ParseIdentifier. Notes: - The module feature is so experimental, that I decided to not allow "eval" or "arguments" as module-related identifiers in the strict mode (even though this check wasn't there before). - Unfortunately, there were some inconsistencies, since it was the responsibility of the caller of ParseIdentifier to check "eval" and "arguments" and some places didn't have the check for no good reason. This CL is supposed to keep backward compatibility and *not* introduce any new errors. - ECMA allows "eval" and "arguments" as labels even in strict mode. (Syntax: "LabelledStatement: Identifier : Statement", and no strict mode restrictions on Identifier are listed.) - Tests which compare error message strings will fail, and need to be updated. BUG=3126 LOG=N R=ulan@chromium.org Review URL: https://codereview.chromium.org/152813005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19112 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2014-02-05 16:26:48 +00:00
// Allow "eval" or "arguments" for backward compatibility.
ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
Scanner::Location spread_pos;
ExpressionClassifier classifier;
ParseArguments(&spread_pos, &classifier, ok);
ValidateExpression(&classifier, CHECK_OK);
DCHECK(!spread_pos.IsValid());
return Expression::Default();
}
PreParserExpression PreParser::ParseDoExpression(bool* ok) {
// AssignmentExpression ::
// do '{' StatementList '}'
Expect(Token::DO, CHECK_OK);
Expect(Token::LBRACE, CHECK_OK);
Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
{
BlockState block_state(&scope_, block_scope);
while (peek() != Token::RBRACE) {
ParseStatementListItem(CHECK_OK);
}
Expect(Token::RBRACE, CHECK_OK);
return PreParserExpression::Default();
}
}
#undef CHECK_OK
} // namespace internal
} // namespace v8