Chromium Code Reviews| Index: src/parsing/rewriter.cc |
| diff --git a/src/parsing/rewriter.cc b/src/parsing/rewriter.cc |
| index 57009bd20707af3260e2e6e367d72eef374dffb6..5a6651c61f070f3703dc0d69464a8078c9f90c88 100644 |
| --- a/src/parsing/rewriter.cc |
| +++ b/src/parsing/rewriter.cc |
| @@ -20,6 +20,7 @@ class Processor final : public AstVisitor<Processor> { |
| result_assigned_(false), |
| replacement_(nullptr), |
| is_set_(false), |
| + breakable_(false), |
| zone_(ast_value_factory->zone()), |
| closure_scope_(closure_scope), |
| factory_(ast_value_factory) { |
| @@ -33,6 +34,7 @@ class Processor final : public AstVisitor<Processor> { |
| result_assigned_(false), |
| replacement_(nullptr), |
| is_set_(false), |
| + breakable_(false), |
| zone_(ast_value_factory->zone()), |
| closure_scope_(closure_scope), |
| factory_(ast_value_factory) { |
| @@ -77,6 +79,22 @@ class Processor final : public AstVisitor<Processor> { |
| // was hoping for. |
| bool is_set_; |
| + bool breakable_; |
| + |
| + class BreakableScope final { |
| + public: |
| + explicit BreakableScope(Processor* processor, bool breakable = true) |
| + : processor_(processor), previous_(processor->breakable_) { |
| + processor->breakable_ = processor->breakable_ || breakable; |
| + } |
| + |
| + ~BreakableScope() { processor_->breakable_ = previous_; } |
| + |
| + private: |
| + Processor* processor_; |
| + bool previous_; |
| + }; |
| + |
| Zone* zone_; |
| DeclarationScope* closure_scope_; |
| AstNodeFactory factory_; |
| @@ -106,7 +124,8 @@ Statement* Processor::AssignUndefinedBefore(Statement* s) { |
| void Processor::Process(ZoneList<Statement*>* statements) { |
| - for (int i = statements->length() - 1; i >= 0; --i) { |
| + for (int i = statements->length() - 1; i >= 0 && (breakable_ || !is_set_); |
|
adamk
2016/10/20 15:39:06
That's quite a fancy for loop, please add a commen
|
| + --i) { |
| Visit(statements->at(i)); |
| statements->Set(i, replacement_); |
| } |
| @@ -122,7 +141,10 @@ void Processor::VisitBlock(Block* node) { |
| // with some JS VMs: For instance, using smjs, print(eval('var x = 7')) |
| // returns 'undefined'. To obtain the same behavior with v8, we need |
| // to prevent rewriting in that case. |
| - if (!node->ignore_completion_value()) Process(node->statements()); |
| + if (!node->ignore_completion_value()) { |
| + BreakableScope scope(this, node->labels() != nullptr); |
| + Process(node->statements()); |
| + } |
| replacement_ = node; |
| } |
| @@ -157,6 +179,7 @@ void Processor::VisitIfStatement(IfStatement* node) { |
| void Processor::VisitIterationStatement(IterationStatement* node) { |
| + BreakableScope scope(this); |
| // Rewrite the body. |
| bool set_after = is_set_; |
| is_set_ = false; // We are in a loop, so we can't rely on [set_after]. |
| @@ -253,6 +276,7 @@ void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { |
| void Processor::VisitSwitchStatement(SwitchStatement* node) { |
| + BreakableScope scope(this); |
| // Rewrite statements in all case clauses (in reverse order). |
| ZoneList<CaseClause*>* clauses = node->cases(); |
| bool set_after = is_set_; |