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.h"
8 #include "src/ast/ast-expression-visitor.h"
9 #include "src/ast/scopes.h"
10 
11 namespace v8 {
12 namespace internal {
13 
14 namespace {
15 
16 
17 class Rewriter final : public AstExpressionVisitor {
18  public:
Rewriter(uintptr_t stack_limit,Expression * initializer,Scope * old_scope,Scope * new_scope)19   Rewriter(uintptr_t stack_limit, Expression* initializer, Scope* old_scope,
20            Scope* new_scope)
21       : AstExpressionVisitor(stack_limit, initializer),
22         old_scope_(old_scope),
23         new_scope_(new_scope) {}
24 
25  private:
VisitExpression(Expression * expr)26   void VisitExpression(Expression* expr) override {}
27 
28   void VisitFunctionLiteral(FunctionLiteral* expr) override;
29   void VisitClassLiteral(ClassLiteral* expr) override;
30   void VisitVariableProxy(VariableProxy* expr) override;
31 
32   Scope* old_scope_;
33   Scope* new_scope_;
34 };
35 
36 
VisitFunctionLiteral(FunctionLiteral * function_literal)37 void Rewriter::VisitFunctionLiteral(FunctionLiteral* function_literal) {
38   function_literal->scope()->ReplaceOuterScope(new_scope_);
39 }
40 
41 
VisitClassLiteral(ClassLiteral * class_literal)42 void Rewriter::VisitClassLiteral(ClassLiteral* class_literal) {
43   class_literal->scope()->ReplaceOuterScope(new_scope_);
44   if (class_literal->extends() != nullptr) {
45     Visit(class_literal->extends());
46   }
47   // No need to visit the constructor since it will have the class
48   // scope on its scope chain.
49   ZoneList<ObjectLiteralProperty*>* props = class_literal->properties();
50   for (int i = 0; i < props->length(); ++i) {
51     ObjectLiteralProperty* prop = props->at(i);
52     if (!prop->key()->IsLiteral()) {
53       Visit(prop->key());
54     }
55     // No need to visit the values, since all values are functions with
56     // the class scope on their scope chain.
57     DCHECK(prop->value()->IsFunctionLiteral());
58   }
59 }
60 
61 
VisitVariableProxy(VariableProxy * proxy)62 void Rewriter::VisitVariableProxy(VariableProxy* proxy) {
63   if (proxy->is_resolved()) {
64     Variable* var = proxy->var();
65     DCHECK_EQ(var->mode(), TEMPORARY);
66     if (old_scope_->RemoveTemporary(var)) {
67       var->set_scope(new_scope_);
68       new_scope_->AddTemporary(var);
69     }
70   } else if (old_scope_->RemoveUnresolved(proxy)) {
71     new_scope_->AddUnresolved(proxy);
72   }
73 }
74 
75 
76 }  // anonymous namespace
77 
78 
RewriteParameterInitializerScope(uintptr_t stack_limit,Expression * initializer,Scope * old_scope,Scope * new_scope)79 void RewriteParameterInitializerScope(uintptr_t stack_limit,
80                                       Expression* initializer, Scope* old_scope,
81                                       Scope* new_scope) {
82   Rewriter rewriter(stack_limit, initializer, old_scope, new_scope);
83   rewriter.Run();
84 }
85 
86 
87 }  // namespace internal
88 }  // namespace v8
89