[parser] Track names in VariableDeclarationParsingScope

This allows us to stop tracking variables_ in the preparser.

This currently makes us track slightly more variables than neccessary in the
case `for (var ...` since `var ... of` needs to check conflicts with out simple
catch variables. We should probably track the names through a ScopedPtrList
instead of a ZonePtrList anyway. Then it won't matter anymore.

Change-Id: I64e3f9ab13af8269456439cf15b0bc4d5b9e5380
Reviewed-on: https://chromium-review.googlesource.com/c/1421360
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58960}
This commit is contained in:
Toon Verwaest 2019-01-21 13:17:55 +01:00 committed by Commit Bot
parent 6c2e35b90b
commit 0d37b80d05
11 changed files with 126 additions and 225 deletions

View File

@ -1585,18 +1585,7 @@ class VariableProxy final : public Expression {
bit_field_ = IsRemovedFromUnresolvedField::update(bit_field_, true);
}
// Provides an access type for the ThreadedList used by the PreParsers
// expressions, lists, and formal parameters.
struct PreParserNext {
static VariableProxy** next(VariableProxy* t) {
return t->pre_parser_expr_next();
}
static VariableProxy** start(VariableProxy** head) { return head; }
};
// Provides an access type for the ThreadedList used by the PreParsers
// expressions, lists, and formal parameters.
// Provides filtered access to the unresolved variable proxy threaded list.
struct UnresolvedNext {
static VariableProxy** filter(VariableProxy** t) {
VariableProxy** n = t;
@ -1621,8 +1610,7 @@ class VariableProxy final : public Expression {
int start_position)
: Expression(start_position, kVariableProxy),
raw_name_(name),
next_unresolved_(nullptr),
pre_parser_expr_next_(nullptr) {
next_unresolved_(nullptr) {
bit_field_ |= IsThisField::encode(variable_kind == THIS_VARIABLE) |
IsAssignedField::encode(false) |
IsResolvedField::encode(false) |
@ -1651,9 +1639,6 @@ class VariableProxy final : public Expression {
V8_INLINE VariableProxy** next() { return &next_unresolved_; }
VariableProxy* next_unresolved_;
VariableProxy** pre_parser_expr_next() { return &pre_parser_expr_next_; }
VariableProxy* pre_parser_expr_next_;
friend base::ThreadedListTraits<VariableProxy>;
};

View File

@ -263,11 +263,13 @@ class VariableDeclarationParsingScope : public ExpressionScope<Types> {
typedef class ExpressionScope<Types> ExpressionScopeT;
typedef typename ExpressionScopeT::ScopeType ScopeType;
VariableDeclarationParsingScope(ParserT* parser, VariableMode mode)
VariableDeclarationParsingScope(ParserT* parser, VariableMode mode,
ZonePtrList<const AstRawString>* names)
: ExpressionScopeT(parser, IsLexicalVariableMode(mode)
? ExpressionScopeT::kLexicalDeclaration
: ExpressionScopeT::kVarDeclaration),
mode_(mode) {}
mode_(mode),
names_(names) {}
VariableProxy* Declare(VariableProxy* proxy) {
VariableKind kind = NORMAL_VARIABLE;
@ -275,6 +277,7 @@ class VariableDeclarationParsingScope : public ExpressionScope<Types> {
this->parser()->DeclareVariable(
proxy, kind, mode_, Variable::DefaultInitializationFlag(mode_),
this->parser()->scope(), &added, proxy->position());
if (names_) names_->Add(proxy->raw_name(), this->parser()->zone());
if (!this->IsLexicalDeclaration()) {
if (this->parser()->loop_nesting_depth() > 0) {
// Due to hoisting, the value of a 'var'-declared variable may actually
@ -310,6 +313,7 @@ class VariableDeclarationParsingScope : public ExpressionScope<Types> {
private:
VariableMode mode_;
ZonePtrList<const AstRawString>* names_;
DISALLOW_COPY_AND_ASSIGN(VariableDeclarationParsingScope);
};

View File

@ -1062,7 +1062,8 @@ class ParserBase {
int formals_end_pos);
void ParseVariableDeclarations(VariableDeclarationContext var_context,
DeclarationParsingResult* parsing_result);
DeclarationParsingResult* parsing_result,
ZonePtrList<const AstRawString>* names);
StatementT ParseAsyncFunctionDeclaration(
ZonePtrList<const AstRawString>* names, bool default_export);
StatementT ParseFunctionDeclaration();
@ -1157,6 +1158,39 @@ class ParserBase {
ZonePtrList<const AstRawString>* labels,
ZonePtrList<const AstRawString>* own_labels);
void DesugarBindingInForEachStatement(ForInfo* for_info, BlockT* body_block,
ExpressionT* each_variable) {
// 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.
bool is_for_var_of =
for_info->mode == ForEachStatement::ITERATE &&
for_info->parsing_result.descriptor.mode == VariableMode::kVar;
if (is_for_var_of) {
Scope* scope = this->scope();
while (scope != nullptr && !scope->is_declaration_scope()) {
if (scope->is_catch_scope()) {
auto name = 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)) {
impl()->ReportMessageAt(for_info->parsing_result.bindings_loc,
MessageTemplate::kVarRedeclaration, name);
}
}
scope = scope->outer_scope();
}
}
impl()->DesugarBindingInForEachStatement(for_info, body_block,
each_variable);
}
bool IsNextLetKeyword();
// Checks if the expression is a valid reference expression (e.g., on the
@ -3409,7 +3443,8 @@ void ParserBase<Impl>::ParseFormalParameterList(FormalParametersT* parameters) {
template <typename Impl>
void ParserBase<Impl>::ParseVariableDeclarations(
VariableDeclarationContext var_context,
DeclarationParsingResult* parsing_result) {
DeclarationParsingResult* parsing_result,
ZonePtrList<const AstRawString>* names) {
// VariableDeclarations ::
// ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
//
@ -3442,28 +3477,27 @@ void ParserBase<Impl>::ParseVariableDeclarations(
break;
}
VariableDeclarationParsingScope declaration(
impl(), parsing_result->descriptor.mode, names);
int bindings_start = peek_position();
do {
// Parse binding pattern.
FuncNameInferrerState fni_state(&fni_);
ExpressionT pattern = impl()->NullExpression();
int decl_pos = peek_position();
{
VariableDeclarationParsingScope declaration(
impl(), parsing_result->descriptor.mode);
pattern = ParseBindingPattern();
ExpressionT pattern = ParseBindingPattern();
if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
if (impl()->IsIdentifier(pattern)) {
if (impl()->IsLet(impl()->AsIdentifier(pattern))) {
impl()->ReportMessageAt(
Scanner::Location(bindings_start, end_position()),
MessageTemplate::kLetInLexicalBinding);
}
if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
if (impl()->IsIdentifier(pattern)) {
if (impl()->IsLet(impl()->AsIdentifier(pattern))) {
impl()->ReportMessageAt(
Scanner::Location(bindings_start, end_position()),
MessageTemplate::kLetInLexicalBinding);
}
}
}
Scanner::Location variable_loc = scanner()->location();
ExpressionT value = impl()->NullExpression();
@ -4681,9 +4715,9 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseVariableStatement(
// is inside an initializer block, it is ignored.
DeclarationParsingResult parsing_result;
ParseVariableDeclarations(var_context, &parsing_result);
ParseVariableDeclarations(var_context, &parsing_result, names);
ExpectSemicolon();
return impl()->BuildInitializationBlock(&parsing_result, names);
return impl()->BuildInitializationBlock(&parsing_result);
}
template <typename Impl>
@ -5166,8 +5200,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement() {
} else {
catch_info.variable = catch_info.scope->DeclareCatchVariableName(
ast_value_factory()->dot_catch_string());
VariableDeclarationParsingScope destructuring(impl(),
VariableMode::kLet);
VariableDeclarationParsingScope destructuring(
impl(), VariableMode::kLet, nullptr);
catch_info.pattern = ParseBindingPattern();
RETURN_IF_PARSE_ERROR;
catch_statements.Add(impl()->RewriteCatchPattern(&catch_info));
@ -5259,7 +5293,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
Scope* inner_block_scope = NewScope(BLOCK_SCOPE);
{
BlockState inner_state(&scope_, inner_block_scope);
ParseVariableDeclarations(kForStatement, &for_info.parsing_result);
ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
&for_info.bound_names);
}
DCHECK(IsLexicalVariableMode(for_info.parsing_result.descriptor.mode));
for_info.position = position();
@ -5279,8 +5314,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
inner_block_scope->set_start_position(scope()->start_position());
{
BlockState inner_state(&scope_, inner_block_scope);
StatementT init = impl()->BuildInitializationBlock(
&for_info.parsing_result, &for_info.bound_names);
StatementT init =
impl()->BuildInitializationBlock(&for_info.parsing_result);
result = ParseStandardForLoopWithLexicalDeclarations(
stmt_pos, init, &for_info, labels, own_labels);
@ -5293,7 +5328,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
StatementT init = impl()->NullStatement();
if (peek() == Token::VAR) {
ParseVariableDeclarations(kForStatement, &for_info.parsing_result);
ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
&for_info.bound_names);
DCHECK_EQ(for_info.parsing_result.descriptor.mode, VariableMode::kVar);
for_info.position = scanner()->location().beg_pos;
@ -5302,7 +5338,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
own_labels, scope());
}
init = impl()->BuildInitializationBlock(&for_info.parsing_result, nullptr);
init = impl()->BuildInitializationBlock(&for_info.parsing_result);
} else if (peek() != Token::SEMICOLON) {
// The initializer does not contain declarations.
int lhs_beg_pos = peek_position();
@ -5407,8 +5443,7 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
}
impl()->RecordIterationStatementSourceRange(loop, body_range);
impl()->DesugarBindingInForEachStatement(for_info, &body_block,
&each_variable);
DesugarBindingInForEachStatement(for_info, &body_block, &each_variable);
body_block->statements()->Add(body, zone());
if (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode)) {
@ -5599,7 +5634,8 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
{
BlockState inner_state(&scope_, inner_block_scope);
ParseVariableDeclarations(kForStatement, &for_info.parsing_result);
ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
&for_info.bound_names);
}
for_info.position = scanner()->location().beg_pos;
@ -5663,8 +5699,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
if (has_declarations) {
BlockT body_block = impl()->NullBlock();
impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
&each_variable);
DesugarBindingInForEachStatement(&for_info, &body_block, &each_variable);
body_block->statements()->Add(body, zone());
body_block->set_scope(scope()->FinalizeBlockScope());
body = body_block;

View File

@ -1407,12 +1407,11 @@ void Parser::Declare(Declaration* declaration, VariableProxy* proxy,
}
Statement* Parser::BuildInitializationBlock(
DeclarationParsingResult* parsing_result,
ZonePtrList<const AstRawString>* names) {
DeclarationParsingResult* parsing_result) {
ScopedPtrList<Statement> statements(pointer_buffer());
for (const auto& declaration : parsing_result->declarations) {
InitializeVariables(&statements, parsing_result->descriptor.kind,
&declaration, names);
&declaration);
}
return factory()->NewBlock(true, statements);
}
@ -1603,7 +1602,7 @@ Block* Parser::RewriteCatchPattern(CatchInfo* catch_info) {
factory()->NewVariableProxy(catch_info->variable));
ScopedPtrList<Statement> init_statements(pointer_buffer());
InitializeVariables(&init_statements, NORMAL_VARIABLE, &decl, nullptr);
InitializeVariables(&init_statements, NORMAL_VARIABLE, &decl);
return factory()->NewBlock(true, init_statements);
}
@ -1825,42 +1824,8 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
for_info->parsing_result.declarations[0];
Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
ScopedPtrList<Statement> each_initialization_statements(pointer_buffer());
{
decl.initializer = factory()->NewVariableProxy(temp);
bool is_for_var_of =
for_info->mode == ForEachStatement::ITERATE &&
for_info->parsing_result.descriptor.mode == VariableMode::kVar;
bool collect_names =
IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
is_for_var_of;
InitializeVariables(&each_initialization_statements, NORMAL_VARIABLE, &decl,
collect_names ? &for_info->bound_names : nullptr);
// 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);
}
}
catch_scope = catch_scope->outer_scope();
}
}
}
decl.initializer = factory()->NewVariableProxy(temp);
InitializeVariables(&each_initialization_statements, NORMAL_VARIABLE, &decl);
*body_block = factory()->NewBlock(3, false);
(*body_block)
@ -2658,8 +2623,7 @@ Block* Parser::BuildParameterInitializationBlock(
DeclarationParsingResult::Declaration decl(
parameter->pattern, parameter->initializer_end_position, initial_value);
InitializeVariables(param_init_statements, PARAMETER_VARIABLE, &decl,
nullptr);
InitializeVariables(param_init_statements, PARAMETER_VARIABLE, &decl);
if (param_init_statements != &init_statements) {
DCHECK_EQ(param_init_statements,

View File

@ -315,8 +315,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
location(location) {}
};
ZonePtrList<const NamedImport>* ParseNamedImports(int pos);
Statement* BuildInitializationBlock(DeclarationParsingResult* parsing_result,
ZonePtrList<const AstRawString>* names);
Statement* BuildInitializationBlock(DeclarationParsingResult* parsing_result);
void DeclareLabel(ZonePtrList<const AstRawString>** labels,
ZonePtrList<const AstRawString>** own_labels,
VariableProxy* expr);
@ -381,8 +380,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
friend class PatternRewriter;
void InitializeVariables(
ScopedPtrList<Statement>* statements, VariableKind kind,
const DeclarationParsingResult::Declaration* declaration,
ZonePtrList<const AstRawString>* names);
const DeclarationParsingResult::Declaration* declaration);
Block* RewriteForVarInLegacy(const ForInfo& for_info);
void DesugarBindingInForEachStatement(ForInfo* for_info, Block** body_block,
@ -742,13 +740,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void ReportMessageAt(Scanner::Location source_location,
MessageTemplate message, const char* arg = nullptr,
ParseErrorType error_type = kSyntaxError) {
if (stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a
// stack overflow. The isolate allows only one pending exception at at
// time
// and we want to report the stack overflow later.
return;
}
pending_error_handler()->ReportMessageAt(source_location.beg_pos,
source_location.end_pos, message,
arg, error_type);
@ -762,13 +753,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void ReportMessageAt(Scanner::Location source_location,
MessageTemplate message, const AstRawString* arg,
ParseErrorType error_type = kSyntaxError) {
if (stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a
// stack overflow. The isolate allows only one pending exception at at
// time
// and we want to report the stack overflow later.
return;
}
pending_error_handler()->ReportMessageAt(source_location.beg_pos,
source_location.end_pos, message,
arg, error_type);

View File

@ -40,17 +40,14 @@ class PatternRewriter final : public AstVisitor<PatternRewriter> {
static void InitializeVariables(
Parser* parser, VariableKind kind,
const Parser::DeclarationParsingResult::Declaration* declaration,
ZonePtrList<const AstRawString>* names);
const Parser::DeclarationParsingResult::Declaration* declaration);
private:
PatternRewriter(Parser* parser, VariableKind kind,
ZonePtrList<const AstRawString>* names,
int initializer_position = kNoSourcePosition,
bool declares_parameter_containing_sloppy_eval = false)
: parser_(parser),
kind_(kind),
names_(names),
initializer_position_(initializer_position),
declares_parameter_containing_sloppy_eval_(
declares_parameter_containing_sloppy_eval) {}
@ -90,7 +87,6 @@ class PatternRewriter final : public AstVisitor<PatternRewriter> {
Parser* const parser_;
VariableKind kind_;
ZonePtrList<const AstRawString>* names_;
const int initializer_position_;
const bool declares_parameter_containing_sloppy_eval_;
@ -99,10 +95,9 @@ class PatternRewriter final : public AstVisitor<PatternRewriter> {
void Parser::InitializeVariables(
ScopedPtrList<Statement>* statements, VariableKind kind,
const DeclarationParsingResult::Declaration* declaration,
ZonePtrList<const AstRawString>* names) {
const DeclarationParsingResult::Declaration* declaration) {
if (has_error()) return;
PatternRewriter::InitializeVariables(this, kind, declaration, names);
PatternRewriter::InitializeVariables(this, kind, declaration);
if (declaration->initializer) {
int pos = declaration->value_beg_position;
@ -117,10 +112,9 @@ void Parser::InitializeVariables(
void PatternRewriter::InitializeVariables(
Parser* parser, VariableKind kind,
const Parser::DeclarationParsingResult::Declaration* declaration,
ZonePtrList<const AstRawString>* names) {
const Parser::DeclarationParsingResult::Declaration* declaration) {
PatternRewriter rewriter(
parser, kind, names, declaration->initializer_position,
parser, kind, declaration->initializer_position,
kind == PARAMETER_VARIABLE && parser->scope()->is_block_scope());
rewriter.RecurseIntoSubpattern(declaration->pattern);
@ -154,9 +148,6 @@ void PatternRewriter::VisitVariableProxy(VariableProxy* proxy) {
parser_->ReportMessage(MessageTemplate::kTooManyVariables);
return;
}
if (names_) {
names_->Add(proxy->raw_name(), zone());
}
}
// When an extra declaration scope needs to be inserted to account for

View File

@ -419,18 +419,5 @@ PreParserExpression PreParser::ExpressionFromIdentifier(
return PreParserExpression::FromIdentifier(name, proxy, zone());
}
void PreParser::InitializeVariables(
const DeclarationParsingResult::Declaration* declaration,
ZonePtrList<const AstRawString>* names) {
if (names && declaration->pattern.variables_ != nullptr) {
for (auto variable : *(declaration->pattern.variables_)) {
// This is only necessary if there is an initializer, but we don't have
// that information here. Consequently, the preparser sometimes says
// maybe-assigned where the parser (correctly) says never-assigned.
names->Add(variable->raw_name(), zone());
}
}
}
} // namespace internal
} // namespace v8

View File

@ -96,34 +96,26 @@ class PreParserIdentifier {
class PreParserExpression {
public:
using VariableZoneThreadedListType =
ZoneThreadedList<VariableProxy, VariableProxy::PreParserNext>;
PreParserExpression()
: code_(TypeField::encode(kNull)), variables_(nullptr) {}
PreParserExpression() : code_(TypeField::encode(kNull)) {}
static PreParserExpression Null() { return PreParserExpression(); }
static PreParserExpression Failure() {
return PreParserExpression(TypeField::encode(kFailure));
}
static PreParserExpression Default(
VariableZoneThreadedListType* variables = nullptr) {
return PreParserExpression(TypeField::encode(kExpression), variables);
static PreParserExpression Default() {
return PreParserExpression(TypeField::encode(kExpression));
}
static PreParserExpression Spread(const PreParserExpression& expression) {
return PreParserExpression(TypeField::encode(kSpreadExpression),
expression.variables_);
return PreParserExpression(TypeField::encode(kSpreadExpression));
}
static PreParserExpression FromIdentifier(const PreParserIdentifier& id,
VariableProxy* variable,
Zone* zone) {
PreParserExpression expression(TypeField::encode(kIdentifierExpression) |
IdentifierTypeField::encode(id.type_));
expression.AddVariable(variable, zone);
return expression;
return PreParserExpression(TypeField::encode(kIdentifierExpression) |
IdentifierTypeField::encode(id.type_));
}
static PreParserExpression BinaryOperation(const PreParserExpression& left,
@ -133,27 +125,21 @@ class PreParserExpression {
return PreParserExpression(TypeField::encode(kExpression));
}
static PreParserExpression Assignment(
VariableZoneThreadedListType* variables) {
static PreParserExpression Assignment() {
return PreParserExpression(TypeField::encode(kExpression) |
ExpressionTypeField::encode(kAssignment),
variables);
ExpressionTypeField::encode(kAssignment));
}
static PreParserExpression NewTargetExpression() {
return PreParserExpression::Default();
}
static PreParserExpression ObjectLiteral(
VariableZoneThreadedListType* variables) {
return PreParserExpression(TypeField::encode(kObjectLiteralExpression),
variables);
static PreParserExpression ObjectLiteral() {
return PreParserExpression(TypeField::encode(kObjectLiteralExpression));
}
static PreParserExpression ArrayLiteral(
VariableZoneThreadedListType* variables) {
return PreParserExpression(TypeField::encode(kArrayLiteralExpression),
variables);
static PreParserExpression ArrayLiteral() {
return PreParserExpression(TypeField::encode(kArrayLiteralExpression));
}
static PreParserExpression StringLiteral() {
@ -363,20 +349,8 @@ class PreParserExpression {
kAssignment
};
explicit PreParserExpression(
uint32_t expression_code,
VariableZoneThreadedListType* variables = nullptr)
: code_(expression_code), variables_(variables) {}
void AddVariable(VariableProxy* variable, Zone* zone) {
if (variable == nullptr) {
return;
}
if (variables_ == nullptr) {
variables_ = new (zone) VariableZoneThreadedListType();
}
variables_->Add(variable);
}
explicit PreParserExpression(uint32_t expression_code)
: code_(expression_code) {}
// The first three bits are for the Type.
typedef BitField<Type, 0, 3> TypeField;
@ -398,10 +372,6 @@ class PreParserExpression {
HasCoverInitializedNameField;
uint32_t code_;
// If the PreParser is used in the variable tracking mode, PreParserExpression
// accumulates variables in that expression.
VariableZoneThreadedListType* variables_;
friend class PreParser;
friend class PreParserFactory;
friend class PreParserExpressionList;
@ -434,29 +404,17 @@ class PreParserScopedStatementList {
// the like. If the PreParser is used in variable tracking mode, it needs to
// build lists of variables though.
class PreParserExpressionList {
using VariableZoneThreadedListType =
ZoneThreadedList<VariableProxy, VariableProxy::PreParserNext>;
public:
explicit PreParserExpressionList(std::vector<void*>* buffer)
: length_(0), variables_(nullptr) {}
explicit PreParserExpressionList(std::vector<void*>* buffer) : length_(0) {}
int length() const { return length_; }
void Add(const PreParserExpression& expression) {
if (expression.variables_ != nullptr) {
if (variables_ == nullptr) {
variables_ = expression.variables_;
} else {
variables_->Append(std::move(*expression.variables_));
}
}
++length_;
}
private:
int length_;
VariableZoneThreadedListType* variables_;
friend class PreParser;
friend class PreParserFactory;
@ -588,7 +546,7 @@ class PreParserFactory {
}
PreParserExpression NewArrayLiteral(const PreParserExpressionList& values,
int first_spread_index, int pos) {
return PreParserExpression::ArrayLiteral(values.variables_);
return PreParserExpression::ArrayLiteral();
}
PreParserExpression NewClassLiteralProperty(const PreParserExpression& key,
const PreParserExpression& value,
@ -602,17 +560,17 @@ class PreParserFactory {
const PreParserExpression& value,
ObjectLiteralProperty::Kind kind,
bool is_computed_name) {
return PreParserExpression::Default(value.variables_);
return PreParserExpression::Default();
}
PreParserExpression NewObjectLiteralProperty(const PreParserExpression& key,
const PreParserExpression& value,
bool is_computed_name) {
return PreParserExpression::Default(value.variables_);
return PreParserExpression::Default();
}
PreParserExpression NewObjectLiteral(
const PreParserExpressionList& properties, int boilerplate_properties,
int pos, bool has_rest_property) {
return PreParserExpression::ObjectLiteral(properties.variables_);
return PreParserExpression::ObjectLiteral();
}
PreParserExpression NewVariableProxy(void* variable) {
return PreParserExpression::Default();
@ -654,7 +612,7 @@ class PreParserFactory {
const PreParserExpression& right, int pos) {
// Identifiers need to be tracked since this might be a parameter with a
// default value inside an arrow function parameter list.
return PreParserExpression::Assignment(left.variables_);
return PreParserExpression::Assignment();
}
PreParserExpression NewYield(const PreParserExpression& expression, int pos,
Suspend::OnAbruptResume on_abrupt_resume) {
@ -1109,10 +1067,6 @@ class PreParser : public ParserBase<PreParser> {
const PreParserScopedStatementList* body, PreParserStatement block,
const PreParserExpression& return_value) {}
void InitializeVariables(
const DeclarationParsingResult::Declaration* declaration,
ZonePtrList<const AstRawString>* names);
V8_INLINE void DeclareLabel(ZonePtrList<const AstRawString>** labels,
ZonePtrList<const AstRawString>** own_labels,
const PreParserExpression& expr) {
@ -1426,11 +1380,7 @@ class PreParser : public ParserBase<PreParser> {
}
V8_INLINE PreParserStatement
BuildInitializationBlock(DeclarationParsingResult* parsing_result,
ZonePtrList<const AstRawString>* names) {
for (auto declaration : parsing_result->declarations) {
InitializeVariables(&declaration, names);
}
BuildInitializationBlock(DeclarationParsingResult* parsing_result) {
return PreParserStatement::Default();
}
@ -1441,16 +1391,6 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE void DesugarBindingInForEachStatement(
ForInfo* for_info, PreParserStatement* body_block,
PreParserExpression* each_variable) {
DCHECK_EQ(1, for_info->parsing_result.declarations.size());
bool is_for_var_of =
for_info->mode == ForEachStatement::ITERATE &&
for_info->parsing_result.descriptor.mode == VariableMode::kVar;
bool collect_names =
IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
is_for_var_of;
InitializeVariables(&for_info->parsing_result.declarations[0],
collect_names ? &for_info->bound_names : nullptr);
}
V8_INLINE PreParserBlock CreateForEachStatementTDZ(PreParserBlock init_block,
@ -1530,6 +1470,15 @@ class PreParser : public ParserBase<PreParser> {
UNREACHABLE();
}
void ReportMessageAt(Scanner::Location source_location,
MessageTemplate message, const AstRawString* arg,
ParseErrorType error_type = kSyntaxError) {
pending_error_handler()->ReportMessageAt(source_location.beg_pos,
source_location.end_pos, message,
arg, error_type);
scanner()->set_parser_error();
}
// "null" return type creators.
V8_INLINE static PreParserIdentifier NullIdentifier() {
return PreParserIdentifier::Null();
@ -1665,7 +1614,7 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE PreParserExpression
ExpressionListToExpression(const PreParserExpressionList& args) {
return PreParserExpression::Default(args.variables_);
return PreParserExpression::Default();
}
V8_INLINE void SetFunctionNameFromPropertyName(

View File

@ -128,14 +128,6 @@ void ZoneList<T>::Iterate(Visitor* visitor) {
for (int i = 0; i < length_; i++) visitor->Apply(&data_[i]);
}
template <typename T>
bool ZoneList<T>::Contains(const T& elm) const {
for (int i = 0; i < length_; i++) {
if (data_[i] == elm) return true;
}
return false;
}
template <typename T>
template <typename CompareFunction>
void ZoneList<T>::Sort(CompareFunction cmp) {

View File

@ -277,7 +277,12 @@ class ZoneList final {
// Drops all but the first 'pos' elements from the list.
V8_INLINE void Rewind(int pos);
inline bool Contains(const T& elm) const;
inline bool Contains(const T& elm) const {
for (int i = 0; i < length_; i++) {
if (data_[i] == elm) return true;
}
return false;
}
// Iterate through all list entries, starting at index 0.
template <class Visitor>

View File

@ -0,0 +1,5 @@
// Copyright 2019 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.
assertThrows("try { } catch (e) { var e; for (var e of []) {} }")