Line data Source code
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:
20 : Rewriter(uintptr_t stack_limit, Expression* initializer, Scope* param_scope)
21 : : AstTraversalVisitor(stack_limit, initializer),
22 1828 : 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 :
40 48 : void Rewriter::VisitFunctionLiteral(FunctionLiteral* function_literal) {
41 48 : function_literal->scope()->ReplaceOuterScope(param_scope_);
42 : }
43 :
44 :
45 0 : void Rewriter::VisitClassLiteral(ClassLiteral* class_literal) {
46 0 : if (class_literal->extends() != nullptr) {
47 0 : 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 0 : for (int i = 0; i < props->length(); ++i) {
53 0 : ClassLiteralProperty* prop = props->at(i);
54 0 : if (!prop->key()->IsLiteral()) {
55 0 : 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 0 : }
62 :
63 :
64 3820 : void Rewriter::VisitVariableProxy(VariableProxy* proxy) {
65 3820 : if (!proxy->is_resolved()) {
66 1457 : if (param_scope_->outer_scope()->RemoveUnresolved(proxy)) {
67 1457 : 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 3820 : }
75 :
76 :
77 0 : void Rewriter::VisitBlock(Block* stmt) {
78 0 : if (stmt->scope() != nullptr)
79 0 : stmt->scope()->ReplaceOuterScope(param_scope_);
80 : else
81 0 : VisitStatements(stmt->statements());
82 0 : }
83 :
84 :
85 0 : void Rewriter::VisitTryCatchStatement(TryCatchStatement* stmt) {
86 0 : Visit(stmt->try_block());
87 0 : stmt->scope()->ReplaceOuterScope(param_scope_);
88 0 : }
89 :
90 :
91 0 : void Rewriter::VisitWithStatement(WithStatement* stmt) {
92 0 : Visit(stmt->expression());
93 0 : stmt->scope()->ReplaceOuterScope(param_scope_);
94 0 : }
95 :
96 :
97 : } // anonymous namespace
98 :
99 1828 : 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 1828 : }
111 :
112 :
113 : } // namespace internal
114 : } // namespace v8
|