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