1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/parsing/parameter-initializer-rewriter.h" 6 7 #include "src/ast/ast-traversal-visitor.h" 8 #include "src/ast/ast.h" 9 #include "src/ast/scopes.h" 10 #include "src/objects-inl.h" 11 12 namespace v8 { 13 namespace internal { 14 15 namespace { 16 17 18 class Rewriter final : public AstTraversalVisitor<Rewriter> { 19 public: Rewriter(uintptr_t stack_limit,Expression * initializer,Scope * param_scope)20 Rewriter(uintptr_t stack_limit, Expression* initializer, Scope* param_scope) 21 : AstTraversalVisitor(stack_limit, initializer), 22 param_scope_(param_scope) {} 23 24 private: 25 // This is required so that the overriden Visit* methods can be 26 // called by the base class (template). 27 friend class AstTraversalVisitor<Rewriter>; 28 29 void VisitFunctionLiteral(FunctionLiteral* expr); 30 void VisitClassLiteral(ClassLiteral* expr); 31 void VisitVariableProxy(VariableProxy* expr); 32 33 void VisitBlock(Block* stmt); 34 void VisitTryCatchStatement(TryCatchStatement* stmt); 35 void VisitWithStatement(WithStatement* stmt); 36 37 Scope* param_scope_; 38 }; 39 VisitFunctionLiteral(FunctionLiteral * function_literal)40 void Rewriter::VisitFunctionLiteral(FunctionLiteral* function_literal) { 41 function_literal->scope()->ReplaceOuterScope(param_scope_); 42 } 43 44 VisitClassLiteral(ClassLiteral * class_literal)45 void Rewriter::VisitClassLiteral(ClassLiteral* class_literal) { 46 if (class_literal->extends() != nullptr) { 47 Visit(class_literal->extends()); 48 } 49 // No need to visit the constructor since it will have the class 50 // scope on its scope chain. 51 ZoneList<ClassLiteralProperty*>* props = class_literal->properties(); 52 for (int i = 0; i < props->length(); ++i) { 53 ClassLiteralProperty* prop = props->at(i); 54 if (!prop->key()->IsLiteral()) { 55 Visit(prop->key()); 56 } 57 // No need to visit the values, since all values are functions with 58 // the class scope on their scope chain. 59 DCHECK(prop->value()->IsFunctionLiteral()); 60 } 61 } 62 63 VisitVariableProxy(VariableProxy * proxy)64 void Rewriter::VisitVariableProxy(VariableProxy* proxy) { 65 if (!proxy->is_resolved()) { 66 if (param_scope_->outer_scope()->RemoveUnresolved(proxy)) { 67 param_scope_->AddUnresolved(proxy); 68 } 69 } else { 70 // Ensure that temporaries we find are already in the correct scope. 71 DCHECK(proxy->var()->mode() != TEMPORARY || 72 proxy->var()->scope() == param_scope_->GetClosureScope()); 73 } 74 } 75 76 VisitBlock(Block * stmt)77 void Rewriter::VisitBlock(Block* stmt) { 78 if (stmt->scope() != nullptr) 79 stmt->scope()->ReplaceOuterScope(param_scope_); 80 else 81 VisitStatements(stmt->statements()); 82 } 83 84 VisitTryCatchStatement(TryCatchStatement * stmt)85 void Rewriter::VisitTryCatchStatement(TryCatchStatement* stmt) { 86 Visit(stmt->try_block()); 87 stmt->scope()->ReplaceOuterScope(param_scope_); 88 } 89 90 VisitWithStatement(WithStatement * stmt)91 void Rewriter::VisitWithStatement(WithStatement* stmt) { 92 Visit(stmt->expression()); 93 stmt->scope()->ReplaceOuterScope(param_scope_); 94 } 95 96 97 } // anonymous namespace 98 ReparentParameterExpressionScope(uintptr_t stack_limit,Expression * expr,Scope * param_scope)99 void ReparentParameterExpressionScope(uintptr_t stack_limit, Expression* expr, 100 Scope* param_scope) { 101 // The only case that uses this code is block scopes for parameters containing 102 // sloppy eval. 103 DCHECK(param_scope->is_block_scope()); 104 DCHECK(param_scope->is_declaration_scope()); 105 DCHECK(param_scope->calls_sloppy_eval()); 106 DCHECK(param_scope->outer_scope()->is_function_scope()); 107 108 Rewriter rewriter(stack_limit, expr, param_scope); 109 rewriter.Run(); 110 } 111 112 113 } // namespace internal 114 } // namespace v8 115