v8  10.1.124 (node 18.2.0)
V8 is Google's open source JavaScript engine
v8-function-callback.h
Go to the documentation of this file.
1 // Copyright 2021 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 INCLUDE_V8_FUNCTION_CALLBACK_H_
6 #define INCLUDE_V8_FUNCTION_CALLBACK_H_
7 
8 #include "v8-local-handle.h" // NOLINT(build/include_directory)
9 #include "v8-primitive.h" // NOLINT(build/include_directory)
10 #include "v8config.h" // NOLINT(build/include_directory)
11 
12 namespace v8 {
13 
14 template <typename T>
16 template <typename T>
17 class Global;
18 class Object;
19 class Value;
20 
21 namespace internal {
22 class FunctionCallbackArguments;
23 class PropertyCallbackArguments;
24 } // namespace internal
25 
26 namespace debug {
27 class ConsoleCallArguments;
28 } // namespace debug
29 
30 template <typename T>
31 class ReturnValue {
32  public:
33  template <class S>
34  V8_INLINE ReturnValue(const ReturnValue<S>& that) : value_(that.value_) {
35  static_assert(std::is_base_of<T, S>::value, "type check");
36  }
37  // Local setters
38  template <typename S>
39  V8_INLINE void Set(const Global<S>& handle);
40  template <typename S>
41  V8_INLINE void Set(const BasicTracedReference<S>& handle);
42  template <typename S>
43  V8_INLINE void Set(const Local<S> handle);
44  // Fast primitive setters
45  V8_INLINE void Set(bool value);
46  V8_INLINE void Set(double i);
47  V8_INLINE void Set(int32_t i);
48  V8_INLINE void Set(uint32_t i);
49  // Fast JS primitive setters
50  V8_INLINE void SetNull();
51  V8_INLINE void SetUndefined();
53  // Convenience getter for Isolate
54  V8_INLINE Isolate* GetIsolate() const;
55 
56  // Pointer setter: Uncompilable to prevent inadvertent misuse.
57  template <typename S>
58  V8_INLINE void Set(S* whatever);
59 
60  // Getter. Creates a new Local<> so it comes with a certain performance
61  // hit. If the ReturnValue was not yet set, this will return the undefined
62  // value.
63  V8_INLINE Local<Value> Get() const;
64 
65  private:
66  template <class F>
67  friend class ReturnValue;
68  template <class F>
69  friend class FunctionCallbackInfo;
70  template <class F>
71  friend class PropertyCallbackInfo;
72  template <class F, class G, class H>
73  friend class PersistentValueMapBase;
74  V8_INLINE void SetInternal(internal::Address value) { *value_ = value; }
75  V8_INLINE internal::Address GetDefaultValue();
76  V8_INLINE explicit ReturnValue(internal::Address* slot);
77  internal::Address* value_;
78 };
79 
80 /**
81  * The argument information given to function call callbacks. This
82  * class provides access to information about the context of the call,
83  * including the receiver, the number and values of arguments, and
84  * the holder of the function.
85  */
86 template <typename T>
88  public:
89  /** The number of available arguments. */
90  V8_INLINE int Length() const;
91  /**
92  * Accessor for the available arguments. Returns `undefined` if the index
93  * is out of bounds.
94  */
95  V8_INLINE Local<Value> operator[](int i) const;
96  /** Returns the receiver. This corresponds to the "this" value. */
97  V8_INLINE Local<Object> This() const;
98  /**
99  * If the callback was created without a Signature, this is the same
100  * value as This(). If there is a signature, and the signature didn't match
101  * This() but one of its hidden prototypes, this will be the respective
102  * hidden prototype.
103  *
104  * Note that this is not the prototype of This() on which the accessor
105  * referencing this callback was found (which in V8 internally is often
106  * referred to as holder [sic]).
107  */
108  V8_INLINE Local<Object> Holder() const;
109  /** For construct calls, this returns the "new.target" value. */
110  V8_INLINE Local<Value> NewTarget() const;
111  /** Indicates whether this is a regular call or a construct call. */
112  V8_INLINE bool IsConstructCall() const;
113  /** The data argument specified when creating the callback. */
114  V8_INLINE Local<Value> Data() const;
115  /** The current Isolate. */
116  V8_INLINE Isolate* GetIsolate() const;
117  /** The ReturnValue for the call. */
119  // This shouldn't be public, but the arm compiler needs it.
120  static const int kArgsLength = 6;
121 
122  protected:
123  friend class internal::FunctionCallbackArguments;
125  friend class debug::ConsoleCallArguments;
126  static const int kHolderIndex = 0;
127  static const int kIsolateIndex = 1;
128  static const int kReturnValueDefaultValueIndex = 2;
129  static const int kReturnValueIndex = 3;
130  static const int kDataIndex = 4;
131  static const int kNewTargetIndex = 5;
132 
134  internal::Address* values, int length);
137  int length_;
138 };
139 
140 /**
141  * The information passed to a property callback about the context
142  * of the property access.
143  */
144 template <typename T>
146  public:
147  /**
148  * \return The isolate of the property access.
149  */
151 
152  /**
153  * \return The data set in the configuration, i.e., in
154  * `NamedPropertyHandlerConfiguration` or
155  * `IndexedPropertyHandlerConfiguration.`
156  */
158 
159  /**
160  * \return The receiver. In many cases, this is the object on which the
161  * property access was intercepted. When using
162  * `Reflect.get`, `Function.prototype.call`, or similar functions, it is the
163  * object passed in as receiver or thisArg.
164  *
165  * \code
166  * void GetterCallback(Local<Name> name,
167  * const v8::PropertyCallbackInfo<v8::Value>& info) {
168  * auto context = info.GetIsolate()->GetCurrentContext();
169  *
170  * v8::Local<v8::Value> a_this =
171  * info.This()
172  * ->GetRealNamedProperty(context, v8_str("a"))
173  * .ToLocalChecked();
174  * v8::Local<v8::Value> a_holder =
175  * info.Holder()
176  * ->GetRealNamedProperty(context, v8_str("a"))
177  * .ToLocalChecked();
178  *
179  * CHECK(v8_str("r")->Equals(context, a_this).FromJust());
180  * CHECK(v8_str("obj")->Equals(context, a_holder).FromJust());
181  *
182  * info.GetReturnValue().Set(name);
183  * }
184  *
185  * v8::Local<v8::FunctionTemplate> templ =
186  * v8::FunctionTemplate::New(isolate);
187  * templ->InstanceTemplate()->SetHandler(
188  * v8::NamedPropertyHandlerConfiguration(GetterCallback));
189  * LocalContext env;
190  * env->Global()
191  * ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
192  * .ToLocalChecked()
193  * ->NewInstance(env.local())
194  * .ToLocalChecked())
195  * .FromJust();
196  *
197  * CompileRun("obj.a = 'obj'; var r = {a: 'r'}; Reflect.get(obj, 'x', r)");
198  * \endcode
199  */
201 
202  /**
203  * \return The object in the prototype chain of the receiver that has the
204  * interceptor. Suppose you have `x` and its prototype is `y`, and `y`
205  * has an interceptor. Then `info.This()` is `x` and `info.Holder()` is `y`.
206  * The Holder() could be a hidden object (the global object, rather
207  * than the global proxy).
208  *
209  * \note For security reasons, do not pass the object back into the runtime.
210  */
212 
213  /**
214  * \return The return value of the callback.
215  * Can be changed by calling Set().
216  * \code
217  * info.GetReturnValue().Set(...)
218  * \endcode
219  *
220  */
222 
223  /**
224  * \return True if the intercepted function should throw if an error occurs.
225  * Usually, `true` corresponds to `'use strict'`.
226  *
227  * \note Always `false` when intercepting `Reflect.set()`
228  * independent of the language mode.
229  */
231 
232  // This shouldn't be public, but the arm compiler needs it.
233  static const int kArgsLength = 7;
234 
235  protected:
236  friend class MacroAssembler;
237  friend class internal::PropertyCallbackArguments;
239  static const int kShouldThrowOnErrorIndex = 0;
240  static const int kHolderIndex = 1;
241  static const int kIsolateIndex = 2;
242  static const int kReturnValueDefaultValueIndex = 3;
243  static const int kReturnValueIndex = 4;
244  static const int kDataIndex = 5;
245  static const int kThisIndex = 6;
246 
249 };
250 
251 using FunctionCallback = void (*)(const FunctionCallbackInfo<Value>& info);
252 
253 // --- Implementation ---
254 
255 template <typename T>
256 ReturnValue<T>::ReturnValue(internal::Address* slot) : value_(slot) {}
257 
258 template <typename T>
259 template <typename S>
260 void ReturnValue<T>::Set(const Global<S>& handle) {
261  static_assert(std::is_base_of<T, S>::value, "type check");
262  if (V8_UNLIKELY(handle.IsEmpty())) {
263  *value_ = GetDefaultValue();
264  } else {
265  *value_ = *reinterpret_cast<internal::Address*>(*handle);
266  }
267 }
268 
269 template <typename T>
270 template <typename S>
271 void ReturnValue<T>::Set(const BasicTracedReference<S>& handle) {
272  static_assert(std::is_base_of<T, S>::value, "type check");
273  if (V8_UNLIKELY(handle.IsEmpty())) {
274  *value_ = GetDefaultValue();
275  } else {
276  *value_ = *reinterpret_cast<internal::Address*>(handle.val_);
277  }
278 }
279 
280 template <typename T>
281 template <typename S>
282 void ReturnValue<T>::Set(const Local<S> handle) {
283  static_assert(std::is_void<T>::value || std::is_base_of<T, S>::value,
284  "type check");
285  if (V8_UNLIKELY(handle.IsEmpty())) {
286  *value_ = GetDefaultValue();
287  } else {
288  *value_ = *reinterpret_cast<internal::Address*>(*handle);
289  }
290 }
291 
292 template <typename T>
293 void ReturnValue<T>::Set(double i) {
294  static_assert(std::is_base_of<T, Number>::value, "type check");
296 }
297 
298 template <typename T>
299 void ReturnValue<T>::Set(int32_t i) {
300  static_assert(std::is_base_of<T, Integer>::value, "type check");
301  using I = internal::Internals;
302  if (V8_LIKELY(I::IsValidSmi(i))) {
303  *value_ = I::IntToSmi(i);
304  return;
305  }
307 }
308 
309 template <typename T>
310 void ReturnValue<T>::Set(uint32_t i) {
311  static_assert(std::is_base_of<T, Integer>::value, "type check");
312  // Can't simply use INT32_MAX here for whatever reason.
313  bool fits_into_int32_t = (i & (1U << 31)) == 0;
314  if (V8_LIKELY(fits_into_int32_t)) {
315  Set(static_cast<int32_t>(i));
316  return;
317  }
319 }
320 
321 template <typename T>
322 void ReturnValue<T>::Set(bool value) {
323  static_assert(std::is_base_of<T, Boolean>::value, "type check");
324  using I = internal::Internals;
325  int root_index;
326  if (value) {
327  root_index = I::kTrueValueRootIndex;
328  } else {
329  root_index = I::kFalseValueRootIndex;
330  }
331  *value_ = *I::GetRoot(GetIsolate(), root_index);
332 }
333 
334 template <typename T>
335 void ReturnValue<T>::SetNull() {
336  static_assert(std::is_base_of<T, Primitive>::value, "type check");
337  using I = internal::Internals;
339 }
340 
341 template <typename T>
343  static_assert(std::is_base_of<T, Primitive>::value, "type check");
344  using I = internal::Internals;
346 }
347 
348 template <typename T>
350  static_assert(std::is_base_of<T, String>::value, "type check");
351  using I = internal::Internals;
353 }
354 
355 template <typename T>
357  // Isolate is always the pointer below the default value on the stack.
358  return *reinterpret_cast<Isolate**>(&value_[-2]);
359 }
360 
361 template <typename T>
362 Local<Value> ReturnValue<T>::Get() const {
363  using I = internal::Internals;
365  return Local<Value>(*Undefined(GetIsolate()));
366  return Local<Value>::New(GetIsolate(), reinterpret_cast<Value*>(value_));
367 }
368 
369 template <typename T>
370 template <typename S>
371 void ReturnValue<T>::Set(S* whatever) {
372  static_assert(sizeof(S) < 0, "incompilable to prevent inadvertent misuse");
373 }
374 
375 template <typename T>
376 internal::Address ReturnValue<T>::GetDefaultValue() {
377  // Default value is always the pointer below value_ on the stack.
378  return value_[-1];
379 }
380 
381 template <typename T>
383  internal::Address* values,
384  int length)
385  : implicit_args_(implicit_args), values_(values), length_(length) {}
386 
387 template <typename T>
389  // values_ points to the first argument (not the receiver).
390  if (i < 0 || length_ <= i) return Local<Value>(*Undefined(GetIsolate()));
391  return Local<Value>(reinterpret_cast<Value*>(values_ + i));
392 }
393 
394 template <typename T>
396  // values_ points to the first argument (not the receiver).
397  return Local<Object>(reinterpret_cast<Object*>(values_ - 1));
398 }
399 
400 template <typename T>
402  return Local<Object>(
403  reinterpret_cast<Object*>(&implicit_args_[kHolderIndex]));
404 }
405 
406 template <typename T>
408  return Local<Value>(
409  reinterpret_cast<Value*>(&implicit_args_[kNewTargetIndex]));
410 }
411 
412 template <typename T>
414  return Local<Value>(reinterpret_cast<Value*>(&implicit_args_[kDataIndex]));
415 }
416 
417 template <typename T>
419  return *reinterpret_cast<Isolate**>(&implicit_args_[kIsolateIndex]);
420 }
421 
422 template <typename T>
425 }
426 
427 template <typename T>
429  return !NewTarget()->IsUndefined();
430 }
431 
432 template <typename T>
433 int FunctionCallbackInfo<T>::Length() const {
434  return length_;
435 }
436 
437 template <typename T>
439  return *reinterpret_cast<Isolate**>(&args_[kIsolateIndex]);
440 }
441 
442 template <typename T>
444  return Local<Value>(reinterpret_cast<Value*>(&args_[kDataIndex]));
445 }
446 
447 template <typename T>
449  return Local<Object>(reinterpret_cast<Object*>(&args_[kThisIndex]));
450 }
451 
452 template <typename T>
454  return Local<Object>(reinterpret_cast<Object*>(&args_[kHolderIndex]));
455 }
456 
457 template <typename T>
459  return ReturnValue<T>(&args_[kReturnValueIndex]);
460 }
461 
462 template <typename T>
464  using I = internal::Internals;
468  }
470  reinterpret_cast<v8::internal::Isolate*>(GetIsolate()));
471 }
472 
473 } // namespace v8
474 
475 #endif // INCLUDE_V8_FUNCTION_CALLBACK_H_