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