• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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_API_ARGUMENTS_INL_H_
6 #define V8_API_ARGUMENTS_INL_H_
7 
8 #include "src/api-arguments.h"
9 
10 #include "src/api-inl.h"
11 #include "src/objects/api-callbacks.h"
12 #include "src/tracing/trace-event.h"
13 #include "src/vm-state-inl.h"
14 
15 namespace v8 {
16 namespace internal {
17 
CustomArgumentsBase(Isolate * isolate)18 CustomArgumentsBase::CustomArgumentsBase(Isolate* isolate)
19     : Relocatable(isolate) {}
20 
21 template <typename T>
22 template <typename V>
GetReturnValue(Isolate * isolate)23 Handle<V> CustomArguments<T>::GetReturnValue(Isolate* isolate) {
24   // Check the ReturnValue.
25   Object** handle = &this->begin()[kReturnValueOffset];
26   // Nothing was set, return empty handle as per previous behaviour.
27   if ((*handle)->IsTheHole(isolate)) return Handle<V>();
28   Handle<V> result = Handle<V>::cast(Handle<Object>(handle));
29   result->VerifyApiCallResultType();
30   return result;
31 }
32 
holder()33 inline JSObject* PropertyCallbackArguments::holder() {
34   return JSObject::cast(this->begin()[T::kHolderIndex]);
35 }
36 
holder()37 inline JSObject* FunctionCallbackArguments::holder() {
38   return JSObject::cast(this->begin()[T::kHolderIndex]);
39 }
40 
41 #define FOR_EACH_CALLBACK(F)                        \
42   F(Query, query, Object, v8::Integer, interceptor) \
43   F(Deleter, deleter, Object, v8::Boolean, Handle<Object>())
44 
45 #define DCHECK_NAME_COMPATIBLE(interceptor, name) \
46   DCHECK(interceptor->is_named());                \
47   DCHECK(!name->IsPrivate());                     \
48   DCHECK_IMPLIES(name->IsSymbol(), interceptor->can_intercept_symbols());
49 
50 #define PREPARE_CALLBACK_INFO(ISOLATE, F, RETURN_VALUE, API_RETURN_TYPE,     \
51                               CALLBACK_INFO)                                 \
52   if (ISOLATE->debug_execution_mode() == DebugInfo::kSideEffects &&          \
53       !ISOLATE->debug()->PerformSideEffectCheckForCallback(CALLBACK_INFO)) { \
54     return RETURN_VALUE();                                                   \
55   }                                                                          \
56   VMState<EXTERNAL> state(ISOLATE);                                          \
57   ExternalCallbackScope call_scope(ISOLATE, FUNCTION_ADDR(F));               \
58   PropertyCallbackInfo<API_RETURN_TYPE> callback_info(begin());
59 
60 #define CREATE_NAMED_CALLBACK(FUNCTION, TYPE, RETURN_TYPE, API_RETURN_TYPE,   \
61                               INFO_FOR_SIDE_EFFECT)                           \
62   Handle<RETURN_TYPE> PropertyCallbackArguments::CallNamed##FUNCTION(         \
63       Handle<InterceptorInfo> interceptor, Handle<Name> name) {               \
64     DCHECK_NAME_COMPATIBLE(interceptor, name);                                \
65     Isolate* isolate = this->isolate();                                       \
66     RuntimeCallTimerScope timer(                                              \
67         isolate, RuntimeCallCounterId::kNamed##FUNCTION##Callback);           \
68     GenericNamedProperty##FUNCTION##Callback f =                              \
69         ToCData<GenericNamedProperty##FUNCTION##Callback>(                    \
70             interceptor->TYPE());                                             \
71     PREPARE_CALLBACK_INFO(isolate, f, Handle<RETURN_TYPE>, API_RETURN_TYPE,   \
72                           INFO_FOR_SIDE_EFFECT);                              \
73     LOG(isolate,                                                              \
74         ApiNamedPropertyAccess("interceptor-named-" #TYPE, holder(), *name)); \
75     f(v8::Utils::ToLocal(name), callback_info);                               \
76     return GetReturnValue<RETURN_TYPE>(isolate);                              \
77   }
78 
79 FOR_EACH_CALLBACK(CREATE_NAMED_CALLBACK)
80 #undef CREATE_NAMED_CALLBACK
81 
82 #define CREATE_INDEXED_CALLBACK(FUNCTION, TYPE, RETURN_TYPE, API_RETURN_TYPE, \
83                                 INFO_FOR_SIDE_EFFECT)                         \
84   Handle<RETURN_TYPE> PropertyCallbackArguments::CallIndexed##FUNCTION(       \
85       Handle<InterceptorInfo> interceptor, uint32_t index) {                  \
86     DCHECK(!interceptor->is_named());                                         \
87     Isolate* isolate = this->isolate();                                       \
88     RuntimeCallTimerScope timer(                                              \
89         isolate, RuntimeCallCounterId::kIndexed##FUNCTION##Callback);         \
90     IndexedProperty##FUNCTION##Callback f =                                   \
91         ToCData<IndexedProperty##FUNCTION##Callback>(interceptor->TYPE());    \
92     PREPARE_CALLBACK_INFO(isolate, f, Handle<RETURN_TYPE>, API_RETURN_TYPE,   \
93                           INFO_FOR_SIDE_EFFECT);                              \
94     LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-" #TYPE,       \
95                                           holder(), index));                  \
96     f(index, callback_info);                                                  \
97     return GetReturnValue<RETURN_TYPE>(isolate);                              \
98   }
99 
FOR_EACH_CALLBACK(CREATE_INDEXED_CALLBACK)100 FOR_EACH_CALLBACK(CREATE_INDEXED_CALLBACK)
101 
102 #undef FOR_EACH_CALLBACK
103 #undef CREATE_INDEXED_CALLBACK
104 
105 Handle<Object> FunctionCallbackArguments::Call(CallHandlerInfo* handler) {
106   Isolate* isolate = this->isolate();
107   LOG(isolate, ApiObjectAccess("call", holder()));
108   RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kFunctionCallback);
109   v8::FunctionCallback f =
110       v8::ToCData<v8::FunctionCallback>(handler->callback());
111   if (isolate->debug_execution_mode() == DebugInfo::kSideEffects &&
112       !isolate->debug()->PerformSideEffectCheckForCallback(
113           handle(handler, isolate))) {
114     return Handle<Object>();
115   }
116   VMState<EXTERNAL> state(isolate);
117   ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
118   FunctionCallbackInfo<v8::Value> info(begin(), argv_, argc_);
119   f(info);
120   return GetReturnValue<Object>(isolate);
121 }
122 
CallNamedEnumerator(Handle<InterceptorInfo> interceptor)123 Handle<JSObject> PropertyCallbackArguments::CallNamedEnumerator(
124     Handle<InterceptorInfo> interceptor) {
125   DCHECK(interceptor->is_named());
126   LOG(isolate(), ApiObjectAccess("interceptor-named-enumerator", holder()));
127   RuntimeCallTimerScope timer(isolate(),
128                               RuntimeCallCounterId::kNamedEnumeratorCallback);
129   return CallPropertyEnumerator(interceptor);
130 }
131 
CallIndexedEnumerator(Handle<InterceptorInfo> interceptor)132 Handle<JSObject> PropertyCallbackArguments::CallIndexedEnumerator(
133     Handle<InterceptorInfo> interceptor) {
134   DCHECK(!interceptor->is_named());
135   LOG(isolate(), ApiObjectAccess("interceptor-indexed-enumerator", holder()));
136   RuntimeCallTimerScope timer(isolate(),
137                               RuntimeCallCounterId::kIndexedEnumeratorCallback);
138   return CallPropertyEnumerator(interceptor);
139 }
140 
CallNamedGetter(Handle<InterceptorInfo> interceptor,Handle<Name> name)141 Handle<Object> PropertyCallbackArguments::CallNamedGetter(
142     Handle<InterceptorInfo> interceptor, Handle<Name> name) {
143   DCHECK_NAME_COMPATIBLE(interceptor, name);
144   Isolate* isolate = this->isolate();
145   RuntimeCallTimerScope timer(isolate,
146                               RuntimeCallCounterId::kNamedGetterCallback);
147   LOG(isolate,
148       ApiNamedPropertyAccess("interceptor-named-getter", holder(), *name));
149   GenericNamedPropertyGetterCallback f =
150       ToCData<GenericNamedPropertyGetterCallback>(interceptor->getter());
151   return BasicCallNamedGetterCallback(f, name, interceptor);
152 }
153 
CallNamedDescriptor(Handle<InterceptorInfo> interceptor,Handle<Name> name)154 Handle<Object> PropertyCallbackArguments::CallNamedDescriptor(
155     Handle<InterceptorInfo> interceptor, Handle<Name> name) {
156   DCHECK_NAME_COMPATIBLE(interceptor, name);
157   Isolate* isolate = this->isolate();
158   RuntimeCallTimerScope timer(isolate,
159                               RuntimeCallCounterId::kNamedDescriptorCallback);
160   LOG(isolate,
161       ApiNamedPropertyAccess("interceptor-named-descriptor", holder(), *name));
162   GenericNamedPropertyDescriptorCallback f =
163       ToCData<GenericNamedPropertyDescriptorCallback>(
164           interceptor->descriptor());
165   return BasicCallNamedGetterCallback(f, name, interceptor);
166 }
167 
BasicCallNamedGetterCallback(GenericNamedPropertyGetterCallback f,Handle<Name> name,Handle<Object> info)168 Handle<Object> PropertyCallbackArguments::BasicCallNamedGetterCallback(
169     GenericNamedPropertyGetterCallback f, Handle<Name> name,
170     Handle<Object> info) {
171   DCHECK(!name->IsPrivate());
172   Isolate* isolate = this->isolate();
173   PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, v8::Value, info);
174   f(v8::Utils::ToLocal(name), callback_info);
175   return GetReturnValue<Object>(isolate);
176 }
177 
CallNamedSetter(Handle<InterceptorInfo> interceptor,Handle<Name> name,Handle<Object> value)178 Handle<Object> PropertyCallbackArguments::CallNamedSetter(
179     Handle<InterceptorInfo> interceptor, Handle<Name> name,
180     Handle<Object> value) {
181   DCHECK_NAME_COMPATIBLE(interceptor, name);
182   GenericNamedPropertySetterCallback f =
183       ToCData<GenericNamedPropertySetterCallback>(interceptor->setter());
184   Isolate* isolate = this->isolate();
185   RuntimeCallTimerScope timer(isolate,
186                               RuntimeCallCounterId::kNamedSetterCallback);
187   Handle<Object> side_effect_check_not_supported;
188   PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, v8::Value,
189                         side_effect_check_not_supported);
190   LOG(isolate,
191       ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
192   f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), callback_info);
193   return GetReturnValue<Object>(isolate);
194 }
195 
CallNamedDefiner(Handle<InterceptorInfo> interceptor,Handle<Name> name,const v8::PropertyDescriptor & desc)196 Handle<Object> PropertyCallbackArguments::CallNamedDefiner(
197     Handle<InterceptorInfo> interceptor, Handle<Name> name,
198     const v8::PropertyDescriptor& desc) {
199   DCHECK_NAME_COMPATIBLE(interceptor, name);
200   Isolate* isolate = this->isolate();
201   RuntimeCallTimerScope timer(isolate,
202                               RuntimeCallCounterId::kNamedDefinerCallback);
203   GenericNamedPropertyDefinerCallback f =
204       ToCData<GenericNamedPropertyDefinerCallback>(interceptor->definer());
205   Handle<Object> side_effect_check_not_supported;
206   PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, v8::Value,
207                         side_effect_check_not_supported);
208   LOG(isolate,
209       ApiNamedPropertyAccess("interceptor-named-define", holder(), *name));
210   f(v8::Utils::ToLocal(name), desc, callback_info);
211   return GetReturnValue<Object>(isolate);
212 }
213 
CallIndexedSetter(Handle<InterceptorInfo> interceptor,uint32_t index,Handle<Object> value)214 Handle<Object> PropertyCallbackArguments::CallIndexedSetter(
215     Handle<InterceptorInfo> interceptor, uint32_t index, Handle<Object> value) {
216   DCHECK(!interceptor->is_named());
217   Isolate* isolate = this->isolate();
218   RuntimeCallTimerScope timer(isolate,
219                               RuntimeCallCounterId::kIndexedSetterCallback);
220   IndexedPropertySetterCallback f =
221       ToCData<IndexedPropertySetterCallback>(interceptor->setter());
222   Handle<Object> side_effect_check_not_supported;
223   PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, v8::Value,
224                         side_effect_check_not_supported);
225   LOG(isolate,
226       ApiIndexedPropertyAccess("interceptor-indexed-set", holder(), index));
227   f(index, v8::Utils::ToLocal(value), callback_info);
228   return GetReturnValue<Object>(isolate);
229 }
230 
CallIndexedDefiner(Handle<InterceptorInfo> interceptor,uint32_t index,const v8::PropertyDescriptor & desc)231 Handle<Object> PropertyCallbackArguments::CallIndexedDefiner(
232     Handle<InterceptorInfo> interceptor, uint32_t index,
233     const v8::PropertyDescriptor& desc) {
234   DCHECK(!interceptor->is_named());
235   Isolate* isolate = this->isolate();
236   RuntimeCallTimerScope timer(isolate,
237                               RuntimeCallCounterId::kIndexedDefinerCallback);
238   IndexedPropertyDefinerCallback f =
239       ToCData<IndexedPropertyDefinerCallback>(interceptor->definer());
240   Handle<Object> side_effect_check_not_supported;
241   PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, v8::Value,
242                         side_effect_check_not_supported);
243   LOG(isolate,
244       ApiIndexedPropertyAccess("interceptor-indexed-define", holder(), index));
245   f(index, desc, callback_info);
246   return GetReturnValue<Object>(isolate);
247 }
248 
CallIndexedGetter(Handle<InterceptorInfo> interceptor,uint32_t index)249 Handle<Object> PropertyCallbackArguments::CallIndexedGetter(
250     Handle<InterceptorInfo> interceptor, uint32_t index) {
251   DCHECK(!interceptor->is_named());
252   Isolate* isolate = this->isolate();
253   RuntimeCallTimerScope timer(isolate,
254                               RuntimeCallCounterId::kNamedGetterCallback);
255   LOG(isolate,
256       ApiIndexedPropertyAccess("interceptor-indexed-getter", holder(), index));
257   IndexedPropertyGetterCallback f =
258       ToCData<IndexedPropertyGetterCallback>(interceptor->getter());
259   return BasicCallIndexedGetterCallback(f, index, interceptor);
260 }
261 
CallIndexedDescriptor(Handle<InterceptorInfo> interceptor,uint32_t index)262 Handle<Object> PropertyCallbackArguments::CallIndexedDescriptor(
263     Handle<InterceptorInfo> interceptor, uint32_t index) {
264   DCHECK(!interceptor->is_named());
265   Isolate* isolate = this->isolate();
266   RuntimeCallTimerScope timer(isolate,
267                               RuntimeCallCounterId::kIndexedDescriptorCallback);
268   LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-descriptor",
269                                         holder(), index));
270   IndexedPropertyDescriptorCallback f =
271       ToCData<IndexedPropertyDescriptorCallback>(interceptor->descriptor());
272   return BasicCallIndexedGetterCallback(f, index, interceptor);
273 }
274 
BasicCallIndexedGetterCallback(IndexedPropertyGetterCallback f,uint32_t index,Handle<Object> info)275 Handle<Object> PropertyCallbackArguments::BasicCallIndexedGetterCallback(
276     IndexedPropertyGetterCallback f, uint32_t index, Handle<Object> info) {
277   Isolate* isolate = this->isolate();
278   PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, v8::Value, info);
279   f(index, callback_info);
280   return GetReturnValue<Object>(isolate);
281 }
282 
CallPropertyEnumerator(Handle<InterceptorInfo> interceptor)283 Handle<JSObject> PropertyCallbackArguments::CallPropertyEnumerator(
284     Handle<InterceptorInfo> interceptor) {
285   // For now there is a single enumerator for indexed and named properties.
286   IndexedPropertyEnumeratorCallback f =
287       v8::ToCData<IndexedPropertyEnumeratorCallback>(interceptor->enumerator());
288   // TODO(cbruni): assert same type for indexed and named callback.
289   Isolate* isolate = this->isolate();
290   PREPARE_CALLBACK_INFO(isolate, f, Handle<JSObject>, v8::Array, interceptor);
291   f(callback_info);
292   return GetReturnValue<JSObject>(isolate);
293 }
294 
295 // -------------------------------------------------------------------------
296 // Accessors
297 
CallAccessorGetter(Handle<AccessorInfo> info,Handle<Name> name)298 Handle<Object> PropertyCallbackArguments::CallAccessorGetter(
299     Handle<AccessorInfo> info, Handle<Name> name) {
300   Isolate* isolate = this->isolate();
301   RuntimeCallTimerScope timer(isolate,
302                               RuntimeCallCounterId::kAccessorGetterCallback);
303   LOG(isolate, ApiNamedPropertyAccess("accessor-getter", holder(), *name));
304   AccessorNameGetterCallback f =
305       ToCData<AccessorNameGetterCallback>(info->getter());
306   return BasicCallNamedGetterCallback(f, name, info);
307 }
308 
CallAccessorSetter(Handle<AccessorInfo> accessor_info,Handle<Name> name,Handle<Object> value)309 Handle<Object> PropertyCallbackArguments::CallAccessorSetter(
310     Handle<AccessorInfo> accessor_info, Handle<Name> name,
311     Handle<Object> value) {
312   Isolate* isolate = this->isolate();
313   RuntimeCallTimerScope timer(isolate,
314                               RuntimeCallCounterId::kAccessorSetterCallback);
315   AccessorNameSetterCallback f =
316       ToCData<AccessorNameSetterCallback>(accessor_info->setter());
317   Handle<Object> side_effect_check_not_supported;
318   PREPARE_CALLBACK_INFO(isolate, f, Handle<Object>, void,
319                         side_effect_check_not_supported);
320   LOG(isolate, ApiNamedPropertyAccess("accessor-setter", holder(), *name));
321   f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), callback_info);
322   return GetReturnValue<Object>(isolate);
323 }
324 
325 #undef PREPARE_CALLBACK_INFO
326 
327 }  // namespace internal
328 }  // namespace v8
329 
330 #endif  // V8_API_ARGUMENTS_INL_H_
331