1 // Copyright 2012 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_BUILTINS_ACCESSORS_H_ 6 #define V8_BUILTINS_ACCESSORS_H_ 7 8 #include "include/v8-local-handle.h" 9 #include "src/base/bit-field.h" 10 #include "src/common/globals.h" 11 #include "src/objects/property-details.h" 12 #include "src/utils/allocation.h" 13 14 namespace v8 { 15 namespace internal { 16 17 // Forward declarations. 18 class AccessorInfo; 19 template <typename T> 20 class Handle; 21 class FieldIndex; 22 class JavaScriptFrame; 23 24 // The list of accessor descriptors. This is a second-order macro 25 // taking a macro to be applied to all accessor descriptor names. 26 // V(accessor_name, AccessorName, GetterSideEffectType, SetterSideEffectType) 27 #define ACCESSOR_INFO_LIST_GENERATOR(V, _) \ 28 V(_, arguments_iterator, ArgumentsIterator, kHasNoSideEffect, \ 29 kHasSideEffectToReceiver) \ 30 V(_, array_length, ArrayLength, kHasNoSideEffect, kHasSideEffectToReceiver) \ 31 V(_, bound_function_length, BoundFunctionLength, kHasNoSideEffect, \ 32 kHasSideEffectToReceiver) \ 33 V(_, bound_function_name, BoundFunctionName, kHasNoSideEffect, \ 34 kHasSideEffectToReceiver) \ 35 V(_, error_stack, ErrorStack, kHasSideEffectToReceiver, \ 36 kHasSideEffectToReceiver) \ 37 V(_, function_arguments, FunctionArguments, kHasNoSideEffect, \ 38 kHasSideEffectToReceiver) \ 39 V(_, function_caller, FunctionCaller, kHasNoSideEffect, \ 40 kHasSideEffectToReceiver) \ 41 V(_, function_name, FunctionName, kHasNoSideEffect, \ 42 kHasSideEffectToReceiver) \ 43 V(_, function_length, FunctionLength, kHasNoSideEffect, \ 44 kHasSideEffectToReceiver) \ 45 V(_, function_prototype, FunctionPrototype, kHasNoSideEffect, \ 46 kHasSideEffectToReceiver) \ 47 V(_, string_length, StringLength, kHasNoSideEffect, \ 48 kHasSideEffectToReceiver) \ 49 V(_, wrapped_function_length, WrappedFunctionLength, kHasNoSideEffect, \ 50 kHasSideEffectToReceiver) \ 51 V(_, wrapped_function_name, WrappedFunctionName, kHasNoSideEffect, \ 52 kHasSideEffectToReceiver) 53 54 #define ACCESSOR_SETTER_LIST(V) \ 55 V(ArrayLengthSetter) \ 56 V(ErrorStackSetter) \ 57 V(FunctionPrototypeSetter) \ 58 V(ModuleNamespaceEntrySetter) \ 59 V(ReconfigureToDataProperty) 60 61 // Accessors contains all predefined proxy accessors. 62 63 class Accessors : public AllStatic { 64 public: 65 #define ACCESSOR_GETTER_DECLARATION(_, accessor_name, AccessorName, ...) \ 66 static void AccessorName##Getter( \ 67 v8::Local<v8::Name> name, \ 68 const v8::PropertyCallbackInfo<v8::Value>& info); 69 ACCESSOR_INFO_LIST_GENERATOR(ACCESSOR_GETTER_DECLARATION, /* not used */) 70 #undef ACCESSOR_GETTER_DECLARATION 71 72 #define ACCESSOR_SETTER_DECLARATION(accessor_name) \ 73 static void accessor_name( \ 74 v8::Local<v8::Name> name, v8::Local<v8::Value> value, \ 75 const v8::PropertyCallbackInfo<v8::Boolean>& info); 76 ACCESSOR_SETTER_LIST(ACCESSOR_SETTER_DECLARATION) 77 #undef ACCESSOR_SETTER_DECLARATION 78 79 static constexpr int kAccessorInfoCount = 80 #define COUNT_ACCESSOR(...) +1 81 ACCESSOR_INFO_LIST_GENERATOR(COUNT_ACCESSOR, /* not used */); 82 #undef COUNT_ACCESSOR 83 84 static constexpr int kAccessorSetterCount = 85 #define COUNT_ACCESSOR(...) +1 86 ACCESSOR_SETTER_LIST(COUNT_ACCESSOR); 87 #undef COUNT_ACCESSOR 88 89 static void ModuleNamespaceEntryGetter( 90 v8::Local<v8::Name> name, 91 const v8::PropertyCallbackInfo<v8::Value>& info); 92 static Handle<AccessorInfo> MakeModuleNamespaceEntryInfo(Isolate* isolate, 93 Handle<String> name); 94 95 // Accessor function called directly from the runtime system. Returns the 96 // newly materialized arguments object for the given {frame}. Note that for 97 // optimized frames it is possible to specify an {inlined_jsframe_index}. 98 static Handle<JSObject> FunctionGetArguments(JavaScriptFrame* frame, 99 int inlined_jsframe_index); 100 101 // Returns true for properties that are accessors to object fields. 102 // If true, the matching FieldIndex is returned through |field_index|. 103 static bool IsJSObjectFieldAccessor(Isolate* isolate, Handle<Map> map, 104 Handle<Name> name, 105 FieldIndex* field_index); 106 107 static MaybeHandle<Object> ReplaceAccessorWithDataProperty( 108 Isolate* isolate, Handle<Object> receiver, Handle<JSObject> holder, 109 Handle<Name> name, Handle<Object> value); 110 111 // Create an AccessorInfo. The setter is optional (can be nullptr). 112 // 113 // Note that the type of setter is AccessorNameBooleanSetterCallback instead 114 // of v8::AccessorNameSetterCallback. The difference is that the former can 115 // set a (boolean) return value. The setter should roughly follow the same 116 // conventions as many of the internal methods in objects.cc: 117 // - The return value is unset iff there was an exception. 118 // - If the ShouldThrow argument is true, the return value must not be false. 119 using AccessorNameBooleanSetterCallback = 120 void (*)(Local<v8::Name> property, Local<v8::Value> value, 121 const PropertyCallbackInfo<v8::Boolean>& info); 122 123 V8_EXPORT_PRIVATE static Handle<AccessorInfo> MakeAccessor( 124 Isolate* isolate, Handle<Name> name, AccessorNameGetterCallback getter, 125 AccessorNameBooleanSetterCallback setter); 126 127 private: 128 #define ACCESSOR_INFO_DECLARATION(_, accessor_name, AccessorName, ...) \ 129 static Handle<AccessorInfo> Make##AccessorName##Info(Isolate* isolate); 130 ACCESSOR_INFO_LIST_GENERATOR(ACCESSOR_INFO_DECLARATION, /* not used */) 131 #undef ACCESSOR_INFO_DECLARATION 132 133 friend class Heap; 134 }; 135 136 } // namespace internal 137 } // namespace v8 138 139 #endif // V8_BUILTINS_ACCESSORS_H_ 140