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-chunk-list.h" 9 #include "src/zone/zone.h" 10 11 namespace v8 { 12 namespace internal { 13 14 class AstConsString; 15 class AstRawString; 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_.push_back(func_to_infer); 67 } 68 } 69 RemoveLastFunction()70 void RemoveLastFunction() { 71 if (IsOpen() && !funcs_to_infer_.is_empty()) { 72 funcs_to_infer_.pop_back(); 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_.push_back(names_stack_.size()); } 99 100 void Leave(); 101 zone()102 Zone* zone() const { return zone_; } 103 104 // Constructs a full name in dotted notation from gathered names. 105 const AstConsString* MakeNameFromStack(); 106 107 // Performs name inferring for added functions. 108 void InferFunctionsNames(); 109 110 AstValueFactory* ast_value_factory_; 111 ZoneChunkList<size_t> entries_stack_; 112 ZoneChunkList<Name> names_stack_; 113 ZoneChunkList<FunctionLiteral*> funcs_to_infer_; 114 Zone* zone_; 115 116 DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer); 117 }; 118 119 120 } // namespace internal 121 } // namespace v8 122 123 #endif // V8_PARSING_FUNC_NAME_INFERRER_H_ 124