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