Home | History | Annotate | Download | only in parsing
      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         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 void Rewriter::VisitFunctionLiteral(FunctionLiteral* function_literal) {
     41   function_literal->scope()->ReplaceOuterScope(param_scope_);
     42 }
     43 
     44 
     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 
     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 
     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 
     85 void Rewriter::VisitTryCatchStatement(TryCatchStatement* stmt) {
     86   Visit(stmt->try_block());
     87   stmt->scope()->ReplaceOuterScope(param_scope_);
     88 }
     89 
     90 
     91 void Rewriter::VisitWithStatement(WithStatement* stmt) {
     92   Visit(stmt->expression());
     93   stmt->scope()->ReplaceOuterScope(param_scope_);
     94 }
     95 
     96 
     97 }  // anonymous namespace
     98 
     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