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 "src/zone/zone.h" 9 10 namespace v8 { 11 namespace internal { 12 13 class AstRawString; 14 class AstString; 15 class AstValueFactory; 16 class FunctionLiteral; 17 18 enum class InferName { kYes, kNo }; 19 20 // FuncNameInferrer is a stateful class that is used to perform name 21 // inference for anonymous functions during static analysis of source code. 22 // Inference is performed in cases when an anonymous function is assigned 23 // to a variable or a property (see test-func-name-inference.cc for examples.) 24 // 25 // The basic idea is that during parsing of LHSs of certain expressions 26 // (assignments, declarations, object literals) we collect name strings, 27 // and during parsing of the RHS, a function literal can be collected. After 28 // parsing the RHS we can infer a name for function literals that do not have 29 // a name. 30 class FuncNameInferrer : public ZoneObject { 31 public: 32 FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone); 33 34 // To enter function name inference state, put a FuncNameInferrer::State 35 // on the stack. 36 class State { 37 public: State(FuncNameInferrer * fni)38 explicit State(FuncNameInferrer* fni) : fni_(fni) { 39 if (fni_ != nullptr) fni_->Enter(); 40 } ~State()41 ~State() { 42 if (fni_ != nullptr) fni_->Leave(); 43 } 44 45 private: 46 FuncNameInferrer* fni_; 47 48 DISALLOW_COPY_AND_ASSIGN(State); 49 }; 50 51 // Returns whether we have entered name collection state. IsOpen()52 bool IsOpen() const { return !entries_stack_.is_empty(); } 53 54 // Pushes an enclosing the name of enclosing function onto names stack. 55 void PushEnclosingName(const AstRawString* name); 56 57 // Pushes an encountered name onto names stack when in collection state. 58 void PushLiteralName(const AstRawString* name); 59 60 void PushVariableName(const AstRawString* name); 61 62 // Adds a function to infer name for. AddFunction(FunctionLiteral * func_to_infer)63 void AddFunction(FunctionLiteral* func_to_infer) { 64 if (IsOpen()) { 65 funcs_to_infer_.Add(func_to_infer, zone()); 66 } 67 } 68 RemoveLastFunction()69 void RemoveLastFunction() { 70 if (IsOpen() && !funcs_to_infer_.is_empty()) { 71 funcs_to_infer_.RemoveLast(); 72 } 73 } 74 75 void RemoveAsyncKeywordFromEnd(); 76 77 // Infers a function name and leaves names collection state. Infer()78 void Infer() { 79 DCHECK(IsOpen()); 80 if (!funcs_to_infer_.is_empty()) { 81 InferFunctionsNames(); 82 } 83 } 84 85 private: 86 enum NameType { 87 kEnclosingConstructorName, 88 kLiteralName, 89 kVariableName 90 }; 91 struct Name { NameName92 Name(const AstRawString* name, NameType type) : name(name), type(type) {} 93 const AstRawString* name; 94 NameType type; 95 }; 96 Enter()97 void Enter() { entries_stack_.Add(names_stack_.length(), zone()); } 98 Leave()99 void Leave() { 100 DCHECK(IsOpen()); 101 names_stack_.Rewind(entries_stack_.RemoveLast()); 102 if (entries_stack_.is_empty()) funcs_to_infer_.Clear(); 103 } 104 zone()105 Zone* zone() const { return zone_; } 106 107 // Constructs a full name in dotted notation from gathered names. 108 const AstString* MakeNameFromStack(); 109 110 // A helper function for MakeNameFromStack. 111 const AstString* MakeNameFromStackHelper(int pos, 112 const AstString* prev); 113 114 // Performs name inferring for added functions. 115 void InferFunctionsNames(); 116 117 AstValueFactory* ast_value_factory_; 118 ZoneList<int> entries_stack_; 119 ZoneList<Name> names_stack_; 120 ZoneList<FunctionLiteral*> funcs_to_infer_; 121 Zone* zone_; 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