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