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