• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2009 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 #ifndef V8_PARSING_FUNC_NAME_INFERRER_H_
6 #define V8_PARSING_FUNC_NAME_INFERRER_H_
7 
8 #include <vector>
9 
10 #include "src/base/macros.h"
11 #include "src/utils/pointer-with-payload.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 class AstConsString;
17 class AstRawString;
18 class AstValueFactory;
19 class FunctionLiteral;
20 
21 enum class InferName { kYes, kNo };
22 
23 template <>
24 struct PointerWithPayloadTraits<AstRawString> {
25   static constexpr int value = 2;
26 };
27 
28 // FuncNameInferrer is a stateful class that is used to perform name
29 // inference for anonymous functions during static analysis of source code.
30 // Inference is performed in cases when an anonymous function is assigned
31 // to a variable or a property (see test-func-name-inference.cc for examples.)
32 //
33 // The basic idea is that during parsing of LHSs of certain expressions
34 // (assignments, declarations, object literals) we collect name strings,
35 // and during parsing of the RHS, a function literal can be collected. After
36 // parsing the RHS we can infer a name for function literals that do not have
37 // a name.
38 class FuncNameInferrer {
39  public:
40   explicit FuncNameInferrer(AstValueFactory* ast_value_factory);
41 
42   // To enter function name inference state, put a FuncNameInferrer::State
43   // on the stack.
44   class State {
45    public:
46     explicit State(FuncNameInferrer* fni)
47         : fni_(fni), top_(fni->names_stack_.size()) {
48       ++fni_->scope_depth_;
49     }
50     ~State() {
51       DCHECK(fni_->IsOpen());
52       fni_->names_stack_.resize(top_);
53       --fni_->scope_depth_;
54     }
55 
56    private:
57     FuncNameInferrer* fni_;
58     size_t top_;
59 
60     DISALLOW_COPY_AND_ASSIGN(State);
61   };
62 
63   // Returns whether we have entered name collection state.
64   bool IsOpen() const { return scope_depth_ > 0; }
65 
66   // Pushes an enclosing the name of enclosing function onto names stack.
67   void PushEnclosingName(const AstRawString* name);
68 
69   // Pushes an encountered name onto names stack when in collection state.
70   void PushLiteralName(const AstRawString* name);
71 
72   void PushVariableName(const AstRawString* name);
73 
74   // Adds a function to infer name for.
75   void AddFunction(FunctionLiteral* func_to_infer) {
76     if (IsOpen()) {
77       funcs_to_infer_.push_back(func_to_infer);
78     }
79   }
80 
81   void RemoveLastFunction() {
82     if (IsOpen() && !funcs_to_infer_.empty()) funcs_to_infer_.pop_back();
83   }
84 
85   void RemoveAsyncKeywordFromEnd();
86 
87   // Infers a function name and leaves names collection state.
88   void Infer() {
89     DCHECK(IsOpen());
90     if (!funcs_to_infer_.empty()) InferFunctionsNames();
91   }
92 
93  private:
94   enum NameType : uint8_t {
95     kEnclosingConstructorName,
96     kLiteralName,
97     kVariableName
98   };
99   struct Name {
100     // Needed for names_stack_.resize()
101     Name() { UNREACHABLE(); }
102     Name(const AstRawString* name, NameType type)
103         : name_and_type_(name, type) {}
104 
105     PointerWithPayload<const AstRawString, NameType, 2> name_and_type_;
106     inline const AstRawString* name() const {
107       return name_and_type_.GetPointer();
108     }
109     inline NameType type() const { return name_and_type_.GetPayload(); }
110   };
111 
112   // Constructs a full name in dotted notation from gathered names.
113   AstConsString* MakeNameFromStack();
114 
115   // Performs name inferring for added functions.
116   void InferFunctionsNames();
117 
118   AstValueFactory* ast_value_factory_;
119   std::vector<Name> names_stack_;
120   std::vector<FunctionLiteral*> funcs_to_infer_;
121   size_t scope_depth_ = 0;
122 
123   DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
124 };
125 
126 
127 }  // namespace internal
128 }  // namespace v8
129 
130 #endif  // V8_PARSING_FUNC_NAME_INFERRER_H_
131