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