v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
api-arguments.h
Go to the documentation of this file.
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_API_ARGUMENTS_H_
6#define V8_API_API_ARGUMENTS_H_
7
11#include "src/objects/slots.h"
13
14namespace v8 {
15namespace internal {
16
17// Custom arguments replicate a small segment of stack that can be
18// accessed through an Arguments object the same way the actual stack
19// can.
21 protected:
22 explicit inline CustomArgumentsBase(Isolate* isolate);
23};
24
25template <typename T>
27 public:
28 static constexpr int kReturnValueIndex = T::kReturnValueIndex;
29 static_assert(T::kSize == sizeof(T));
30
31 ~CustomArguments() override;
32
33 inline void IterateInstance(RootVisitor* v) override {
34 v->VisitRootPointers(Root::kRelocatable, nullptr, slot_at(0),
35 slot_at(T::kArgsLength));
36 }
37
38 protected:
39 explicit inline CustomArguments(Isolate* isolate)
40 : CustomArgumentsBase(isolate) {}
41
42 template <typename V>
43 Handle<V> GetReturnValue(Isolate* isolate) const;
44
45 inline Isolate* isolate() const {
46 return reinterpret_cast<Isolate*>((*slot_at(T::kIsolateIndex)).ptr());
47 }
48
49 inline FullObjectSlot slot_at(int index) const {
50 // This allows index == T::kArgsLength so "one past the end" slots
51 // can be retrieved for iterating purposes.
52 DCHECK_LE(static_cast<unsigned>(index),
53 static_cast<unsigned>(T::kArgsLength));
54 return FullObjectSlot(values_ + index);
55 }
56
57 Address values_[T::kArgsLength];
58};
59
60// Note: Calling args.Call() sets the return value on args. For multiple
61// Call()'s, a new args should be used every time.
62// This class also serves as a side effects detection scope (JavaScript code
63// execution). It is used for ensuring correctness of the interceptor callback
64// implementations. The idea is that the interceptor callback that does not
65// intercept an operation must not produce side effects. If the callback
66// signals that it has handled the operation (by either returning a respective
67// result or by throwing an exception) then the AcceptSideEffects() method
68// must be called to "accept" the side effects that have happened during the
69// lifetime of the PropertyCallbackArguments object.
71 : public CustomArguments<PropertyCallbackInfo<Value> > {
72 public:
75 static constexpr int kArgsLength = T::kArgsLength;
76 static constexpr int kThisIndex = T::kThisIndex;
77 static constexpr int kDataIndex = T::kDataIndex;
78 static constexpr int kHolderV2Index = T::kHolderV2Index;
79 static constexpr int kHolderIndex = T::kHolderIndex;
80 static constexpr int kIsolateIndex = T::kIsolateIndex;
83
84 // This constructor leaves kPropertyKeyIndex and kReturnValueIndex slots
85 // uninitialized in order to let them be initialized by the subsequent
86 // CallXXX(..) and avoid double initialization. As a consequence, there
87 // must be no GC call between this constructor and CallXXX(..).
88 // In debug mode these slots are zapped, so GC should be able to detect
89 // the misuse of this object.
92 Maybe<ShouldThrow> should_throw);
94
95 // Don't copy PropertyCallbackArguments, because they would both have the
96 // same prev_ pointer.
99 delete;
100
101 // -------------------------------------------------------------------------
102 // Accessor Callbacks
103
104 // Returns the result of [[Get]] operation or throws an exception.
105 // In case of exception empty handle is returned.
106 // TODO(ishell, 328490288): stop returning empty handles.
108 DirectHandle<Name> name);
109 // Returns the result of [[Set]] operation or throws an exception.
114
115 // -------------------------------------------------------------------------
116 // Named Interceptor Callbacks
117
118 // Empty handle means that the request was not intercepted.
119 // Pending exception handling should be done by the caller.
124
125 // Calls Setter/Definer/Deleter callback and returns whether the request
126 // was intercepted.
127 // Pending exception handling and interpretation of the result should be
128 // done by the caller using GetBooleanReturnValue(..).
134 const v8::PropertyDescriptor& desc);
137
138 // Empty handle means that the request was not intercepted.
139 // Pending exception handling should be done by the caller.
142 // Returns JSArray-like object with property names or undefined.
145
146 // -------------------------------------------------------------------------
147 // Indexed Interceptor Callbacks
148
149 // Empty handle means that the request was not intercepted.
150 // Pending exception handling should be done by the caller.
152 DirectHandle<InterceptorInfo> interceptor, uint32_t index);
154 DirectHandle<InterceptorInfo> interceptor, uint32_t index);
155
156 // Calls Setter/Definer/Deleter callback and returns whether the request
157 // was intercepted.
158 // Pending exception handling and interpretation of the result should be
159 // done by the caller using GetBooleanReturnValue(..).
161 DirectHandle<InterceptorInfo> interceptor, uint32_t index,
164 DirectHandle<InterceptorInfo> interceptor, uint32_t index,
165 const v8::PropertyDescriptor& desc);
167 DirectHandle<InterceptorInfo> interceptor, uint32_t index);
168
169 // Empty handle means that the request was not intercepted.
170 // Pending exception handling should be done by the caller.
172 DirectHandle<InterceptorInfo> interceptor, uint32_t index);
173 // Returns JSArray-like object with property names or undefined.
176
177 // Accept potential JavaScript side effects that might occur during life
178 // time of this object.
179 inline void AcceptSideEffects() {
180#ifdef DEBUG
181 javascript_execution_counter_ = 0;
182#endif // DEBUG
183 }
184
185 // Converts the result of Setter/Definer/Deleter interceptor callback to
186 // Maybe<InterceptorResult>.
187 // Currently, in certain scenarios the actual boolean result returned by
188 // the Setter/Definer operation is ignored and thus we don't need to process
189 // the actual return value.
191 v8::Intercepted intercepted, const char* callback_kind_for_error_message,
192 bool ignore_return_value = false);
193
194 // TODO(ishell): cleanup this hack by embedding the PropertyCallbackInfo
195 // into PropertyCallbackArguments object.
196 template <typename T>
198 return *(reinterpret_cast<PropertyCallbackInfo<T>*>(&values_[0]));
199 }
200
201 // Forwards ShouldThrowOnError() request to the underlying
202 // v8::PropertyCallbackInfo<> object.
204 return GetPropertyCallbackInfo<Value>().ShouldThrowOnError();
205 }
206
207 // Unofficial way of getting property key from v8::PropertyCallbackInfo<T>.
208 template <typename T>
210 return Tagged<Object>(info.args_[kPropertyKeyIndex]);
211 }
212 template <typename T>
214 const PropertyCallbackInfo<T>& info) {
215 return Handle<Object>(&info.args_[kPropertyKeyIndex]);
216 }
217
218 // Returns index value passed to CallIndexedXXX(). This works as long as
219 // all the calls to indexed interceptor callbacks are done via
220 // PropertyCallbackArguments.
221 template <typename T>
222 static uint32_t GetPropertyIndex(const PropertyCallbackInfo<T>& info) {
223 // Currently all indexed interceptor callbacks are called via
224 // PropertyCallbackArguments, so it's guaranteed that
225 // v8::PropertyCallbackInfo<T>::args_ array IS the
226 // PropertyCallbackArguments::values_ array. As a result we can restore
227 // pointer to PropertyCallbackArguments object from the former.
228 Address ptr = reinterpret_cast<Address>(&info.args_) -
230 auto pca = reinterpret_cast<const PropertyCallbackArguments*>(ptr);
231 return pca->index_;
232 }
233
234 private:
235 // Returns JSArray-like object with property names or undefined.
238
239 inline Tagged<JSObject> holder() const;
240 inline Tagged<Object> receiver() const;
241
242 // This field is used for propagating index value from CallIndexedXXX()
243 // to ExceptionPropagationCallback.
244 uint32_t index_ = kMaxUInt32;
245
246#ifdef DEBUG
247 // This stores current value of Isolate::javascript_execution_counter().
248 // It's used for detecting whether JavaScript code was executed between
249 // PropertyCallbackArguments's constructor and destructor.
250 uint32_t javascript_execution_counter_;
251#endif // DEBUG
252};
253
255 : public CustomArguments<FunctionCallbackInfo<Value> > {
256 public:
259 static constexpr int kArgsLength = T::kArgsLength;
261
262 static constexpr int kUnusedIndex = T::kUnusedIndex;
263 static constexpr int kIsolateIndex = T::kIsolateIndex;
264 static constexpr int kContextIndex = T::kContextIndex;
265 static constexpr int kTargetIndex = T::kTargetIndex;
266 static constexpr int kNewTargetIndex = T::kNewTargetIndex;
267
269
270 static constexpr int kSize = T::kSize;
272 static constexpr int kValuesOffset = T::kValuesOffset;
273 static constexpr int kLengthOffset = T::kLengthOffset;
274
275 // Make sure all FunctionCallbackInfo constants are in sync.
276 static_assert(T::kSize == sizeof(T));
277 static_assert(T::kImplicitArgsOffset == offsetof(T, implicit_args_));
278 static_assert(T::kValuesOffset == offsetof(T, values_));
279 static_assert(T::kLengthOffset == offsetof(T, length_));
280
284 int argc);
285
286 /*
287 * The following Call function wraps the calling of all callbacks to handle
288 * calling either the old or the new style callbacks depending on which one
289 * has been registered.
290 * For old callbacks which return an empty handle, the ReturnValue is checked
291 * and used if it's been set to anything inside the callback.
292 * New style callbacks always use the return value.
293 */
296
297 // Unofficial way of getting target FunctionTemplateInfo from
298 // v8::FunctionCallbackInfo<T>.
299 template <typename T>
301 return Tagged<Object>(info.implicit_args_[kTargetIndex]);
302 }
303
304 private:
306 int const argc_;
307};
308
309static_assert(BuiltinArguments::kNumExtraArgs ==
313
314} // namespace internal
315} // namespace v8
316
317#endif // V8_API_API_ARGUMENTS_H_
#define T
static constexpr int kArgsLength
static constexpr int kContextIndex
static constexpr int kTargetIndex
static constexpr int kUnusedIndex
static constexpr int kIsolateIndex
static constexpr int kThisValuesIndex
static constexpr int kLengthOffset
static constexpr int kValuesOffset
static constexpr int kNewTargetIndex
static constexpr int kArgsLengthWithReceiver
static constexpr int kImplicitArgsOffset
static constexpr int kIsolateIndex
static constexpr int kDataIndex
static constexpr int kArgsLength
static constexpr int kShouldThrowOnErrorIndex
static constexpr int kHolderV2Index
static constexpr int kThisIndex
static constexpr int kHolderIndex
static constexpr int kPropertyKeyIndex
static constexpr int kNumExtraArgsWithReceiver
static constexpr int kReceiverArgsIndex
static constexpr int kNumExtraArgs
Handle< V > GetReturnValue(Isolate *isolate) const
Address values_[T::kArgsLength]
CustomArguments(Isolate *isolate)
static constexpr int kReturnValueIndex
FullObjectSlot slot_at(int index) const
void IterateInstance(RootVisitor *v) override
static Tagged< Object > GetTarget(const FunctionCallbackInfo< T > &info)
FunctionCallbackArguments(Isolate *isolate, Tagged< FunctionTemplateInfo > target, Tagged< HeapObject > new_target, Address *argv, int argc)
FunctionCallbackInfo< Value > T
DirectHandle< Object > CallOrConstruct(Tagged< FunctionTemplateInfo > function, bool is_construct)
DirectHandle< JSAny > CallNamedGetter(DirectHandle< InterceptorInfo > interceptor, DirectHandle< Name > name)
DirectHandle< JSObjectOrUndefined > CallIndexedEnumerator(DirectHandle< InterceptorInfo > interceptor)
const v8::PropertyCallbackInfo< T > & GetPropertyCallbackInfo()
Handle< JSAny > CallIndexedDescriptor(DirectHandle< InterceptorInfo > interceptor, uint32_t index)
static uint32_t GetPropertyIndex(const PropertyCallbackInfo< T > &info)
static Tagged< Object > GetPropertyKey(const PropertyCallbackInfo< T > &info)
DirectHandle< JSAny > CallAccessorGetter(DirectHandle< AccessorInfo > info, DirectHandle< Name > name)
PropertyCallbackArguments & operator=(const PropertyCallbackArguments &)=delete
v8::Intercepted CallNamedDeleter(DirectHandle< InterceptorInfo > interceptor, DirectHandle< Name > name)
PropertyCallbackArguments(Isolate *isolate, Tagged< Object > data, Tagged< Object > self, Tagged< JSObject > holder, Maybe< ShouldThrow > should_throw)
Maybe< InterceptorResult > GetBooleanReturnValue(v8::Intercepted intercepted, const char *callback_kind_for_error_message, bool ignore_return_value=false)
DirectHandle< JSObjectOrUndefined > CallNamedEnumerator(DirectHandle< InterceptorInfo > interceptor)
DirectHandle< Object > CallNamedQuery(DirectHandle< InterceptorInfo > interceptor, DirectHandle< Name > name)
static Handle< Object > GetPropertyKeyHandle(const PropertyCallbackInfo< T > &info)
v8::Intercepted CallNamedSetter(DirectHandle< InterceptorInfo > interceptor, DirectHandle< Name > name, DirectHandle< Object > value)
v8::Intercepted CallNamedDefiner(DirectHandle< InterceptorInfo > interceptor, DirectHandle< Name > name, const v8::PropertyDescriptor &desc)
DirectHandle< JSAny > CallIndexedGetter(DirectHandle< InterceptorInfo > interceptor, uint32_t index)
DirectHandle< JSObjectOrUndefined > CallPropertyEnumerator(DirectHandle< InterceptorInfo > interceptor)
v8::Intercepted CallIndexedDefiner(DirectHandle< InterceptorInfo > interceptor, uint32_t index, const v8::PropertyDescriptor &desc)
PropertyCallbackArguments(const PropertyCallbackArguments &)=delete
DirectHandle< Object > CallIndexedQuery(DirectHandle< InterceptorInfo > interceptor, uint32_t index)
static constexpr int kShouldThrowOnErrorIndex
v8::Intercepted CallIndexedDeleter(DirectHandle< InterceptorInfo > interceptor, uint32_t index)
V8_WARN_UNUSED_RESULT bool CallAccessorSetter(DirectHandle< AccessorInfo > info, DirectHandle< Name > name, DirectHandle< Object > value)
v8::Intercepted CallIndexedSetter(DirectHandle< InterceptorInfo > interceptor, uint32_t index, DirectHandle< Object > value)
Handle< JSAny > CallNamedDescriptor(DirectHandle< InterceptorInfo > interceptor, DirectHandle< Name > name)
virtual void VisitRootPointers(Root root, const char *description, FullObjectSlot start, FullObjectSlot end)=0
DirectHandle< Object > new_target
Definition execution.cc:75
bool is_construct
Definition execution.cc:82
const int length_
Definition mul-fft.cc:473
constexpr uint32_t kMaxUInt32
Definition globals.h:387
Intercepted
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:671