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 |