Chromium Code Reviews| Index: src/parsing/parser.cc |
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
| index 968c78e205df01e0dc581008535d60760dbbb781..397b075e3615c0152fc345ecebc4049f9115de5b 100644 |
| --- a/src/parsing/parser.cc |
| +++ b/src/parsing/parser.cc |
| @@ -6,6 +6,7 @@ |
| #include "src/api.h" |
| #include "src/ast/ast.h" |
| +#include "src/ast/ast-expression-visitor.h" |
| #include "src/ast/ast-literal-reindexer.h" |
| #include "src/ast/scopeinfo.h" |
| #include "src/bailout-reason.h" |
| @@ -920,6 +921,8 @@ Parser::Parser(ParseInfo* info) |
| set_allow_harmony_rest_parameters(FLAG_harmony_rest_parameters); |
| set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); |
| set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind); |
| + set_allow_harmony_destructuring_assignment( |
| + FLAG_harmony_destructuring_assignment); |
| set_allow_strong_mode(FLAG_strong_mode); |
| set_allow_legacy_const(FLAG_legacy_const); |
| set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); |
| @@ -1090,6 +1093,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { |
| } |
| if (ok) { |
| + ParserTraits::RewriteDestructuringAssignments(); |
| result = factory()->NewFunctionLiteral( |
| ast_value_factory()->empty_string(), ast_value_factory(), scope_, |
| body, function_state.materialized_literal_count(), |
| @@ -4397,6 +4401,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
| allow_harmony_destructuring_bind()) { |
| CheckConflictingVarDeclarations(scope, CHECK_OK); |
| } |
| + |
| + if (body) { |
| + // If body can be inspected, rewrite queued destructuring assignments |
| + ParserTraits::RewriteDestructuringAssignments(); |
| + } |
| } |
| bool has_duplicate_parameters = |
| @@ -4525,6 +4534,40 @@ Statement* Parser::BuildAssertIsCoercible(Variable* var) { |
| } |
| +class InitializerRewriter : public AstExpressionVisitor { |
| + public: |
| + InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser, |
| + Scope* scope) |
| + : AstExpressionVisitor(stack_limit, root), |
| + parser_(parser), |
| + scope_(scope) {} |
| + |
| + private: |
| + void VisitExpression(Expression* expr) { |
| + RewritableExpression* rw = expr->AsRewritableExpression(); |
|
adamk
2015/12/01 22:42:56
Naming nit: I like "to_rewrite" better than "rw".
|
| + if (!rw || |
|
adamk
2015/12/01 22:42:56
to_rewrite == nullptr
|
| + !rw->IsRewritableAs(RewritableExpression::kDestructuringAssignment)) { |
|
adamk
2015/12/01 22:42:56
It's checks like this that I don't see as terribly
caitp (gmail)
2015/12/01 22:51:00
the check is checking 2 things: 1, that it's "poss
adamk
2015/12/01 22:54:23
Right, sorry, there is that second case. Even so,
|
| + return; |
| + } |
| + |
| + bool ok = true; |
| + Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, rw, scope_, |
| + &ok); |
| + DCHECK(ok); |
| + } |
| + |
| + private: |
| + Parser* parser_; |
| + Scope* scope_; |
| +}; |
| + |
| + |
| +void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) { |
| + InitializerRewriter rewriter(stack_limit_, expr, this, scope); |
| + rewriter.Run(); |
| +} |
| + |
| + |
| Block* Parser::BuildParameterInitializationBlock( |
| const ParserFormalParameters& parameters, bool* ok) { |
| DCHECK(!parameters.is_simple); |
| @@ -4557,6 +4600,10 @@ Block* Parser::BuildParameterInitializationBlock( |
| if (parameter.initializer != nullptr) { |
| // IS_UNDEFINED($param) ? initializer : $param |
| DCHECK(!parameter.is_rest); |
| + |
| + // Ensure initializer is rewritten |
| + RewriteParameterInitializer(parameter.initializer, scope_); |
| + |
| auto condition = factory()->NewCompareOperation( |
| Token::EQ_STRICT, |
| factory()->NewVariableProxy(parameters.scope->parameter(i)), |
| @@ -6460,5 +6507,42 @@ void Parser::RaiseLanguageMode(LanguageMode mode) { |
| static_cast<LanguageMode>(scope_->language_mode() | mode)); |
| } |
| + |
| +void ParserTraits::RewriteDestructuringAssignments() { |
| + parser_->RewriteDestructuringAssignments(); |
| +} |
| + |
| + |
| +void Parser::RewriteDestructuringAssignments() { |
| + FunctionState* func = function_state_; |
| + if (!allow_harmony_destructuring_assignment()) return; |
| + const List<DestructuringAssignment>& assignments = |
| + func->destructuring_assignments_to_rewrite(); |
| + for (int i = assignments.length() - 1; i >= 0; --i) { |
| + // Rewrite list in reverse, so that nested assignment patterns are rewritten |
| + // correctly. |
| + DestructuringAssignment pair = assignments.at(i); |
| + RewritableExpression* rw = pair.assignment->AsRewritableExpression(); |
|
adamk
2015/12/01 22:42:56
Like the old name better here too
|
| + Scope* scope = pair.scope; |
| + DCHECK_NOT_NULL(rw); |
| + if (rw->IsRewritableAs(RewritableExpression::kDestructuringAssignment)) { |
| + bool ok = true; |
| + PatternRewriter::RewriteDestructuringAssignment(this, rw, scope, &ok); |
| + DCHECK(ok); |
| + } |
| + } |
| +} |
| + |
| + |
| +void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
| + DCHECK(expr->IsRewritableExpression()); |
| + DCHECK(expr->AsRewritableExpression()->expression()->IsAssignment()); |
|
adamk
2015/12/01 22:42:56
This, too, will go away if you just use the C++ ty
|
| + DCHECK(expr->AsRewritableExpression()->hints() & |
| + RewritableExpression::kDestructuringAssignment); |
| + parser_->function_state_->AddDestructuringAssignment( |
| + Parser::DestructuringAssignment(expr, parser_->scope_)); |
| +} |
| + |
| + |
| } // namespace internal |
| } // namespace v8 |