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