Coverage Report

Created: 2025-10-31 09:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/deps/v8/include/v8-function-callback.h
Line
Count
Source
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 <cstdint>
9
#include <limits>
10
11
#include "v8-internal.h"      // NOLINT(build/include_directory)
12
#include "v8-local-handle.h"  // NOLINT(build/include_directory)
13
#include "v8-primitive.h"     // NOLINT(build/include_directory)
14
#include "v8config.h"         // NOLINT(build/include_directory)
15
16
namespace v8 {
17
18
template <typename T>
19
class BasicTracedReference;
20
template <typename T>
21
class Global;
22
class Object;
23
class Value;
24
25
namespace internal {
26
class FunctionCallbackArguments;
27
class PropertyCallbackArguments;
28
class Builtins;
29
}  // namespace internal
30
31
namespace debug {
32
class ConsoleCallArguments;
33
}  // namespace debug
34
35
namespace api_internal {
36
V8_EXPORT v8::Local<v8::Value> GetFunctionTemplateData(
37
    v8::Isolate* isolate, v8::Local<v8::Data> raw_target);
38
}  // namespace api_internal
39
40
template <typename T>
41
class ReturnValue {
42
 public:
43
  template <class S>
44
  V8_INLINE ReturnValue(const ReturnValue<S>& that) : value_(that.value_) {
45
    static_assert(std::is_base_of_v<T, S>, "type check");
46
  }
47
  // Handle-based setters.
48
  template <typename S>
49
  V8_INLINE void Set(const Global<S>& handle);
50
  template <typename S>
51
  V8_INLINE void SetNonEmpty(const Global<S>& handle);
52
  template <typename S>
53
  V8_INLINE void Set(const BasicTracedReference<S>& handle);
54
  template <typename S>
55
  V8_INLINE void SetNonEmpty(const BasicTracedReference<S>& handle);
56
  template <typename S>
57
  V8_INLINE void Set(const Local<S> handle);
58
  template <typename S>
59
  V8_INLINE void SetNonEmpty(const Local<S> handle);
60
  // Fast primitive number setters.
61
  V8_INLINE void Set(bool value);
62
  V8_INLINE void Set(double i);
63
  V8_INLINE void Set(int16_t i);
64
  V8_INLINE void Set(int32_t i);
65
  V8_INLINE void Set(int64_t i);
66
  V8_INLINE void Set(uint16_t i);
67
  V8_INLINE void Set(uint32_t i);
68
  V8_INLINE void Set(uint64_t i);
69
  // Fast JS primitive setters.
70
  V8_INLINE void SetNull();
71
  V8_INLINE void SetUndefined();
72
  V8_INLINE void SetFalse();
73
  V8_INLINE void SetEmptyString();
74
  // Convenience getter for the Isolate.
75
  V8_INLINE Isolate* GetIsolate() const;
76
77
  // Pointer setter: Uncompilable to prevent inadvertent misuse.
78
  template <typename S>
79
  V8_INLINE void Set(S* whatever);
80
81
  // Getter. Creates a new Local<> so it comes with a certain performance
82
  // hit. If the ReturnValue was not yet set, this will return the undefined
83
  // value.
84
  V8_INLINE Local<Value> Get() const;
85
86
 private:
87
  template <class F>
88
  friend class ReturnValue;
89
  template <class F>
90
  friend class FunctionCallbackInfo;
91
  template <class F>
92
  friend class PropertyCallbackInfo;
93
  template <class F, class G, class H>
94
  friend class PersistentValueMapBase;
95
  V8_INLINE void SetInternal(internal::Address value);
96
  // Default value depends on <T>:
97
  //  - <void> -> true_value,
98
  //  - <v8::Boolean> -> true_value,
99
  //  - <v8::Integer> -> 0,
100
  //  - <v8::Value> -> undefined_value,
101
  //  - <v8::Array> -> undefined_value.
102
  V8_INLINE void SetDefaultValue();
103
  V8_INLINE explicit ReturnValue(internal::Address* slot);
104
105
  // See FunctionCallbackInfo.
106
  static constexpr int kIsolateValueIndex = -2;
107
108
  internal::Address* value_;
109
};
110
111
/**
112
 * The argument information given to function call callbacks.  This
113
 * class provides access to information about the context of the call,
114
 * including the receiver, the number and values of arguments, and
115
 * the holder of the function.
116
 */
117
template <typename T>
118
class FunctionCallbackInfo {
119
 public:
120
  /** The number of available arguments. */
121
  V8_INLINE int Length() const;
122
  /**
123
   * Accessor for the available arguments. Returns `undefined` if the index
124
   * is out of bounds.
125
   */
126
  V8_INLINE Local<Value> operator[](int i) const;
127
  /** Returns the receiver. This corresponds to the "this" value. */
128
  V8_INLINE Local<Object> This() const;
129
  /** For construct calls, this returns the "new.target" value. */
130
  V8_INLINE Local<Value> NewTarget() const;
131
  /** Indicates whether this is a regular call or a construct call. */
132
  V8_INLINE bool IsConstructCall() const;
133
  /** The data argument specified when creating the callback. */
134
  V8_INLINE Local<Value> Data() const;
135
  /** The current Isolate. */
136
  V8_INLINE Isolate* GetIsolate() const;
137
  /** The ReturnValue for the call. */
138
  V8_INLINE ReturnValue<T> GetReturnValue() const;
139
140
 private:
141
  friend class internal::FunctionCallbackArguments;
142
  friend class internal::CustomArguments<FunctionCallbackInfo>;
143
  friend class debug::ConsoleCallArguments;
144
  friend void internal::PrintFunctionCallbackInfo(void*);
145
146
  // TODO(ishell, http://crbug.com/326505377): in case of non-constructor
147
  // call, don't pass kNewTarget and kUnused. Add IsConstructCall flag to
148
  // kIsolate field.
149
  static constexpr int kUnusedIndex = 0;
150
  static constexpr int kIsolateIndex = 1;
151
  static constexpr int kContextIndex = 2;
152
  static constexpr int kReturnValueIndex = 3;
153
  static constexpr int kTargetIndex = 4;
154
  static constexpr int kNewTargetIndex = 5;
155
  static constexpr int kArgsLength = 6;
156
157
  static constexpr int kArgsLengthWithReceiver = kArgsLength + 1;
158
159
  // Codegen constants:
160
  static constexpr int kSize = 3 * internal::kApiSystemPointerSize;
161
  static constexpr int kImplicitArgsOffset = 0;
162
  static constexpr int kValuesOffset =
163
      kImplicitArgsOffset + internal::kApiSystemPointerSize;
164
  static constexpr int kLengthOffset =
165
      kValuesOffset + internal::kApiSystemPointerSize;
166
167
  static constexpr int kThisValuesIndex = -1;
168
  static_assert(ReturnValue<Value>::kIsolateValueIndex ==
169
                kIsolateIndex - kReturnValueIndex);
170
171
  V8_INLINE FunctionCallbackInfo(internal::Address* implicit_args,
172
                                 internal::Address* values, int length);
173
174
  // TODO(https://crbug.com/326505377): flatten the v8::FunctionCallbackInfo
175
  // object to avoid indirect loads through values_ and implicit_args_ and
176
  // reduce the number of instructions in the CallApiCallback builtin.
177
  internal::Address* implicit_args_;
178
  internal::Address* values_;
179
  internal::Address length_;
180
};
181
182
/**
183
 * The information passed to a property callback about the context
184
 * of the property access.
185
 */
186
template <typename T>
187
class PropertyCallbackInfo {
188
 public:
189
  /**
190
   * \return The isolate of the property access.
191
   */
192
  V8_INLINE Isolate* GetIsolate() const;
193
194
  /**
195
   * \return The data set in the configuration, i.e., in
196
   * `NamedPropertyHandlerConfiguration` or
197
   * `IndexedPropertyHandlerConfiguration.`
198
   */
199
  V8_INLINE Local<Value> Data() const;
200
201
  /**
202
   * \return The receiver. In many cases, this is the object on which the
203
   * property access was intercepted. When using
204
   * `Reflect.get`, `Function.prototype.call`, or similar functions, it is the
205
   * object passed in as receiver or thisArg.
206
   *
207
   * \code
208
   *  void GetterCallback(Local<Name> name,
209
   *                      const v8::PropertyCallbackInfo<v8::Value>& info) {
210
   *     auto context = info.GetIsolate()->GetCurrentContext();
211
   *
212
   *     v8::Local<v8::Value> a_this =
213
   *         info.This()
214
   *             ->GetRealNamedProperty(context, v8_str("a"))
215
   *             .ToLocalChecked();
216
   *     v8::Local<v8::Value> a_holder =
217
   *         info.Holder()
218
   *             ->GetRealNamedProperty(context, v8_str("a"))
219
   *             .ToLocalChecked();
220
   *
221
   *    CHECK(v8_str("r")->Equals(context, a_this).FromJust());
222
   *    CHECK(v8_str("obj")->Equals(context, a_holder).FromJust());
223
   *
224
   *    info.GetReturnValue().Set(name);
225
   *  }
226
   *
227
   *  v8::Local<v8::FunctionTemplate> templ =
228
   *  v8::FunctionTemplate::New(isolate);
229
   *  templ->InstanceTemplate()->SetHandler(
230
   *      v8::NamedPropertyHandlerConfiguration(GetterCallback));
231
   *  LocalContext env;
232
   *  env->Global()
233
   *      ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
234
   *                                           .ToLocalChecked()
235
   *                                           ->NewInstance(env.local())
236
   *                                           .ToLocalChecked())
237
   *      .FromJust();
238
   *
239
   *  CompileRun("obj.a = 'obj'; var r = {a: 'r'}; Reflect.get(obj, 'x', r)");
240
   * \endcode
241
   */
242
  V8_INLINE Local<Object> This() const;
243
244
  /**
245
   * \return The object in the prototype chain of the receiver that has the
246
   * interceptor. Suppose you have `x` and its prototype is `y`, and `y`
247
   * has an interceptor. Then `info.This()` is `x` and `info.Holder()` is `y`.
248
   * The Holder() could be a hidden object (the global object, rather
249
   * than the global proxy).
250
   *
251
   * \note For security reasons, do not pass the object back into the runtime.
252
   */
253
  V8_DEPRECATED(
254
      "V8 will stop providing access to hidden prototype (i.e. "
255
      "JSGlobalObject). Use HolderV2() instead. \n"
256
      "DO NOT try to workaround this by accessing JSGlobalObject via "
257
      "v8::Object::GetPrototype() - it'll be deprecated soon too. \n"
258
      "See http://crbug.com/333672197. ")
259
  V8_INLINE Local<Object> Holder() const;
260
261
  /**
262
   * \return The object in the prototype chain of the receiver that has the
263
   * interceptor. Suppose you have `x` and its prototype is `y`, and `y`
264
   * has an interceptor. Then `info.This()` is `x` and `info.Holder()` is `y`.
265
   * In case the property is installed on the global object the Holder()
266
   * would return the global proxy.
267
   */
268
  V8_INLINE Local<Object> HolderV2() const;
269
270
  /**
271
   * \return The return value of the callback.
272
   * Can be changed by calling Set().
273
   * \code
274
   * info.GetReturnValue().Set(...)
275
   * \endcode
276
   *
277
   */
278
  V8_INLINE ReturnValue<T> GetReturnValue() const;
279
280
  /**
281
   * \return True if the intercepted function should throw if an error occurs.
282
   * Usually, `true` corresponds to `'use strict'`.
283
   *
284
   * \note Always `false` when intercepting `Reflect.set()`
285
   * independent of the language mode.
286
   */
287
  V8_INLINE bool ShouldThrowOnError() const;
288
289
 private:
290
  template <typename U>
291
  friend class PropertyCallbackInfo;
292
  friend class MacroAssembler;
293
  friend class internal::PropertyCallbackArguments;
294
  friend class internal::CustomArguments<PropertyCallbackInfo>;
295
  friend void internal::PrintPropertyCallbackInfo(void*);
296
297
  static constexpr int kPropertyKeyIndex = 0;
298
  static constexpr int kShouldThrowOnErrorIndex = 1;
299
  static constexpr int kHolderIndex = 2;
300
  static constexpr int kIsolateIndex = 3;
301
  static constexpr int kHolderV2Index = 4;
302
  static constexpr int kReturnValueIndex = 5;
303
  static constexpr int kDataIndex = 6;
304
  static constexpr int kThisIndex = 7;
305
  static constexpr int kArgsLength = 8;
306
307
  static constexpr int kSize = kArgsLength * internal::kApiSystemPointerSize;
308
309
  PropertyCallbackInfo() = default;
310
311
  mutable internal::Address args_[kArgsLength];
312
};
313
314
using FunctionCallback = void (*)(const FunctionCallbackInfo<Value>& info);
315
316
// --- Implementation ---
317
318
template <typename T>
319
3.74k
ReturnValue<T>::ReturnValue(internal::Address* slot) : value_(slot) {}
v8::ReturnValue<v8::Value>::ReturnValue(unsigned long*)
Line
Count
Source
319
3.74k
ReturnValue<T>::ReturnValue(internal::Address* slot) : value_(slot) {}
Unexecuted instantiation: v8::ReturnValue<v8::Integer>::ReturnValue(unsigned long*)
Unexecuted instantiation: v8::ReturnValue<v8::Boolean>::ReturnValue(unsigned long*)
Unexecuted instantiation: v8::ReturnValue<v8::Array>::ReturnValue(unsigned long*)
Unexecuted instantiation: v8::ReturnValue<void>::ReturnValue(unsigned long*)
320
321
template <typename T>
322
3.67k
void ReturnValue<T>::SetInternal(internal::Address value) {
323
#if V8_STATIC_ROOTS_BOOL
324
  using I = internal::Internals;
325
  // Ensure that the upper 32-bits are not modified. Compiler should be
326
  // able to optimize this to a store of a lower 32-bits of the value.
327
  // This is fine since the callback can return only JavaScript values which
328
  // are either Smis or heap objects allocated in the main cage.
329
  *value_ = I::DecompressTaggedField(*value_, I::CompressTagged(value));
330
#else
331
3.67k
  *value_ = value;
332
3.67k
#endif  // V8_STATIC_ROOTS_BOOL
333
3.67k
}
v8::ReturnValue<v8::Value>::SetInternal(unsigned long)
Line
Count
Source
322
3.67k
void ReturnValue<T>::SetInternal(internal::Address value) {
323
#if V8_STATIC_ROOTS_BOOL
324
  using I = internal::Internals;
325
  // Ensure that the upper 32-bits are not modified. Compiler should be
326
  // able to optimize this to a store of a lower 32-bits of the value.
327
  // This is fine since the callback can return only JavaScript values which
328
  // are either Smis or heap objects allocated in the main cage.
329
  *value_ = I::DecompressTaggedField(*value_, I::CompressTagged(value));
330
#else
331
3.67k
  *value_ = value;
332
3.67k
#endif  // V8_STATIC_ROOTS_BOOL
333
3.67k
}
Unexecuted instantiation: v8::ReturnValue<v8::Integer>::SetInternal(unsigned long)
Unexecuted instantiation: v8::ReturnValue<v8::Array>::SetInternal(unsigned long)
334
335
template <typename T>
336
template <typename S>
337
void ReturnValue<T>::Set(const Global<S>& handle) {
338
  static_assert(std::is_base_of_v<T, S>, "type check");
339
  if (V8_UNLIKELY(handle.IsEmpty())) {
340
    SetDefaultValue();
341
  } else {
342
    SetInternal(handle.ptr());
343
  }
344
}
345
346
template <typename T>
347
template <typename S>
348
void ReturnValue<T>::SetNonEmpty(const Global<S>& handle) {
349
  static_assert(std::is_base_of_v<T, S>, "type check");
350
#ifdef V8_ENABLE_CHECKS
351
  internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
352
#endif  // V8_ENABLE_CHECKS
353
  SetInternal(handle.ptr());
354
}
355
356
template <typename T>
357
template <typename S>
358
void ReturnValue<T>::Set(const BasicTracedReference<S>& handle) {
359
  static_assert(std::is_base_of_v<T, S>, "type check");
360
  if (V8_UNLIKELY(handle.IsEmpty())) {
361
    SetDefaultValue();
362
  } else {
363
    SetInternal(handle.ptr());
364
  }
365
}
366
367
template <typename T>
368
template <typename S>
369
void ReturnValue<T>::SetNonEmpty(const BasicTracedReference<S>& handle) {
370
  static_assert(std::is_base_of_v<T, S>, "type check");
371
#ifdef V8_ENABLE_CHECKS
372
  internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
373
#endif  // V8_ENABLE_CHECKS
374
  SetInternal(handle.ptr());
375
}
376
377
template <typename T>
378
template <typename S>
379
3.64k
void ReturnValue<T>::Set(const Local<S> handle) {
380
  // "V8_DEPRECATE_SOON" this method if |T| is |void|.
381
#ifdef V8_IMMINENT_DEPRECATION_WARNINGS
382
  static constexpr bool is_allowed_void = false;
383
  static_assert(!std::is_void_v<T>,
384
                "ReturnValue<void>::Set(const Local<S>) is deprecated. "
385
                "Do nothing to indicate that the operation succeeded or use "
386
                "SetFalse() to indicate that the operation failed (don't "
387
                "forget to handle info.ShouldThrowOnError()). "
388
                "See http://crbug.com/348660658 for details.");
389
#else
390
3.64k
  static constexpr bool is_allowed_void = std::is_void_v<T>;
391
3.64k
#endif  // V8_IMMINENT_DEPRECATION_WARNINGS
392
3.64k
  static_assert(is_allowed_void || std::is_base_of_v<T, S>, "type check");
393
3.64k
  if (V8_UNLIKELY(handle.IsEmpty())) {
394
0
    SetDefaultValue();
395
0
  } else if constexpr (is_allowed_void) {
396
    // Simulate old behaviour for "v8::AccessorSetterCallback" for which
397
    // it was possible to set the return value even for ReturnValue<void>.
398
    Set(handle->BooleanValue(GetIsolate()));
399
3.64k
  } else {
400
3.64k
    SetInternal(handle.ptr());
401
3.64k
  }
402
3.64k
}
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Array>(v8::Local<v8::Array>)
void v8::ReturnValue<v8::Value>::Set<v8::Object>(v8::Local<v8::Object>)
Line
Count
Source
379
1.29k
void ReturnValue<T>::Set(const Local<S> handle) {
380
  // "V8_DEPRECATE_SOON" this method if |T| is |void|.
381
#ifdef V8_IMMINENT_DEPRECATION_WARNINGS
382
  static constexpr bool is_allowed_void = false;
383
  static_assert(!std::is_void_v<T>,
384
                "ReturnValue<void>::Set(const Local<S>) is deprecated. "
385
                "Do nothing to indicate that the operation succeeded or use "
386
                "SetFalse() to indicate that the operation failed (don't "
387
                "forget to handle info.ShouldThrowOnError()). "
388
                "See http://crbug.com/348660658 for details.");
389
#else
390
1.29k
  static constexpr bool is_allowed_void = std::is_void_v<T>;
391
1.29k
#endif  // V8_IMMINENT_DEPRECATION_WARNINGS
392
1.29k
  static_assert(is_allowed_void || std::is_base_of_v<T, S>, "type check");
393
1.29k
  if (V8_UNLIKELY(handle.IsEmpty())) {
394
0
    SetDefaultValue();
395
0
  } else if constexpr (is_allowed_void) {
396
    // Simulate old behaviour for "v8::AccessorSetterCallback" for which
397
    // it was possible to set the return value even for ReturnValue<void>.
398
    Set(handle->BooleanValue(GetIsolate()));
399
1.29k
  } else {
400
1.29k
    SetInternal(handle.ptr());
401
1.29k
  }
402
1.29k
}
void v8::ReturnValue<v8::Value>::Set<v8::Value>(v8::Local<v8::Value>)
Line
Count
Source
379
71
void ReturnValue<T>::Set(const Local<S> handle) {
380
  // "V8_DEPRECATE_SOON" this method if |T| is |void|.
381
#ifdef V8_IMMINENT_DEPRECATION_WARNINGS
382
  static constexpr bool is_allowed_void = false;
383
  static_assert(!std::is_void_v<T>,
384
                "ReturnValue<void>::Set(const Local<S>) is deprecated. "
385
                "Do nothing to indicate that the operation succeeded or use "
386
                "SetFalse() to indicate that the operation failed (don't "
387
                "forget to handle info.ShouldThrowOnError()). "
388
                "See http://crbug.com/348660658 for details.");
389
#else
390
71
  static constexpr bool is_allowed_void = std::is_void_v<T>;
391
71
#endif  // V8_IMMINENT_DEPRECATION_WARNINGS
392
71
  static_assert(is_allowed_void || std::is_base_of_v<T, S>, "type check");
393
71
  if (V8_UNLIKELY(handle.IsEmpty())) {
394
0
    SetDefaultValue();
395
0
  } else if constexpr (is_allowed_void) {
396
    // Simulate old behaviour for "v8::AccessorSetterCallback" for which
397
    // it was possible to set the return value even for ReturnValue<void>.
398
    Set(handle->BooleanValue(GetIsolate()));
399
71
  } else {
400
71
    SetInternal(handle.ptr());
401
71
  }
402
71
}
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::ArrayBuffer>(v8::Local<v8::ArrayBuffer>)
void v8::ReturnValue<v8::Value>::Set<v8::Uint32Array>(v8::Local<v8::Uint32Array>)
Line
Count
Source
379
35
void ReturnValue<T>::Set(const Local<S> handle) {
380
  // "V8_DEPRECATE_SOON" this method if |T| is |void|.
381
#ifdef V8_IMMINENT_DEPRECATION_WARNINGS
382
  static constexpr bool is_allowed_void = false;
383
  static_assert(!std::is_void_v<T>,
384
                "ReturnValue<void>::Set(const Local<S>) is deprecated. "
385
                "Do nothing to indicate that the operation succeeded or use "
386
                "SetFalse() to indicate that the operation failed (don't "
387
                "forget to handle info.ShouldThrowOnError()). "
388
                "See http://crbug.com/348660658 for details.");
389
#else
390
35
  static constexpr bool is_allowed_void = std::is_void_v<T>;
391
35
#endif  // V8_IMMINENT_DEPRECATION_WARNINGS
392
35
  static_assert(is_allowed_void || std::is_base_of_v<T, S>, "type check");
393
35
  if (V8_UNLIKELY(handle.IsEmpty())) {
394
0
    SetDefaultValue();
395
0
  } else if constexpr (is_allowed_void) {
396
    // Simulate old behaviour for "v8::AccessorSetterCallback" for which
397
    // it was possible to set the return value even for ReturnValue<void>.
398
    Set(handle->BooleanValue(GetIsolate()));
399
35
  } else {
400
35
    SetInternal(handle.ptr());
401
35
  }
402
35
}
void v8::ReturnValue<v8::Value>::Set<v8::String>(v8::Local<v8::String>)
Line
Count
Source
379
35
void ReturnValue<T>::Set(const Local<S> handle) {
380
  // "V8_DEPRECATE_SOON" this method if |T| is |void|.
381
#ifdef V8_IMMINENT_DEPRECATION_WARNINGS
382
  static constexpr bool is_allowed_void = false;
383
  static_assert(!std::is_void_v<T>,
384
                "ReturnValue<void>::Set(const Local<S>) is deprecated. "
385
                "Do nothing to indicate that the operation succeeded or use "
386
                "SetFalse() to indicate that the operation failed (don't "
387
                "forget to handle info.ShouldThrowOnError()). "
388
                "See http://crbug.com/348660658 for details.");
389
#else
390
35
  static constexpr bool is_allowed_void = std::is_void_v<T>;
391
35
#endif  // V8_IMMINENT_DEPRECATION_WARNINGS
392
35
  static_assert(is_allowed_void || std::is_base_of_v<T, S>, "type check");
393
35
  if (V8_UNLIKELY(handle.IsEmpty())) {
394
0
    SetDefaultValue();
395
0
  } else if constexpr (is_allowed_void) {
396
    // Simulate old behaviour for "v8::AccessorSetterCallback" for which
397
    // it was possible to set the return value even for ReturnValue<void>.
398
    Set(handle->BooleanValue(GetIsolate()));
399
35
  } else {
400
35
    SetInternal(handle.ptr());
401
35
  }
402
35
}
void v8::ReturnValue<v8::Value>::Set<v8::Function>(v8::Local<v8::Function>)
Line
Count
Source
379
2.20k
void ReturnValue<T>::Set(const Local<S> handle) {
380
  // "V8_DEPRECATE_SOON" this method if |T| is |void|.
381
#ifdef V8_IMMINENT_DEPRECATION_WARNINGS
382
  static constexpr bool is_allowed_void = false;
383
  static_assert(!std::is_void_v<T>,
384
                "ReturnValue<void>::Set(const Local<S>) is deprecated. "
385
                "Do nothing to indicate that the operation succeeded or use "
386
                "SetFalse() to indicate that the operation failed (don't "
387
                "forget to handle info.ShouldThrowOnError()). "
388
                "See http://crbug.com/348660658 for details.");
389
#else
390
2.20k
  static constexpr bool is_allowed_void = std::is_void_v<T>;
391
2.20k
#endif  // V8_IMMINENT_DEPRECATION_WARNINGS
392
2.20k
  static_assert(is_allowed_void || std::is_base_of_v<T, S>, "type check");
393
2.20k
  if (V8_UNLIKELY(handle.IsEmpty())) {
394
0
    SetDefaultValue();
395
0
  } else if constexpr (is_allowed_void) {
396
    // Simulate old behaviour for "v8::AccessorSetterCallback" for which
397
    // it was possible to set the return value even for ReturnValue<void>.
398
    Set(handle->BooleanValue(GetIsolate()));
399
2.20k
  } else {
400
2.20k
    SetInternal(handle.ptr());
401
2.20k
  }
402
2.20k
}
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Boolean>(v8::Local<v8::Boolean>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Promise>(v8::Local<v8::Promise>)
Unexecuted instantiation: void v8::ReturnValue<v8::Array>::Set<v8::Array>(v8::Local<v8::Array>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Symbol>(v8::Local<v8::Symbol>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Map>(v8::Local<v8::Map>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Number>(v8::Local<v8::Number>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Uint8Array>(v8::Local<v8::Uint8Array>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::BigInt>(v8::Local<v8::BigInt>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Integer>(v8::Local<v8::Integer>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Float64Array>(v8::Local<v8::Float64Array>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::External>(v8::Local<v8::External>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::Set<v8::Primitive>(v8::Local<v8::Primitive>)
403
404
template <typename T>
405
template <typename S>
406
0
void ReturnValue<T>::SetNonEmpty(const Local<S> handle) {
407
  // "V8_DEPRECATE_SOON" this method if |T| is |void|.
408
#ifdef V8_IMMINENT_DEPRECATION_WARNINGS
409
  static constexpr bool is_allowed_void = false;
410
  static_assert(!std::is_void_v<T>,
411
                "ReturnValue<void>::SetNonEmpty(const Local<S>) is deprecated. "
412
                "Do nothing to indicate that the operation succeeded or use "
413
                "SetFalse() to indicate that the operation failed (don't "
414
                "forget to handle info.ShouldThrowOnError()). "
415
                "See http://crbug.com/348660658 for details.");
416
#else
417
0
  static constexpr bool is_allowed_void = std::is_void_v<T>;
418
0
#endif  // V8_IMMINENT_DEPRECATION_WARNINGS
419
0
  static_assert(is_allowed_void || std::is_base_of_v<T, S>, "type check");
420
#ifdef V8_ENABLE_CHECKS
421
  internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
422
#endif  // V8_ENABLE_CHECKS
423
  if constexpr (is_allowed_void) {
424
    // Simulate old behaviour for "v8::AccessorSetterCallback" for which
425
    // it was possible to set the return value even for ReturnValue<void>.
426
    Set(handle->BooleanValue(GetIsolate()));
427
0
  } else {
428
0
    SetInternal(handle.ptr());
429
0
  }
430
0
}
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::SetNonEmpty<v8::Number>(v8::Local<v8::Number>)
Unexecuted instantiation: void v8::ReturnValue<v8::Value>::SetNonEmpty<v8::Integer>(v8::Local<v8::Integer>)
Unexecuted instantiation: void v8::ReturnValue<v8::Integer>::SetNonEmpty<v8::Integer>(v8::Local<v8::Integer>)
431
432
template <typename T>
433
0
void ReturnValue<T>::Set(double i) {
434
0
  static_assert(std::is_base_of_v<T, Number>, "type check");
435
0
  SetNonEmpty(Number::New(GetIsolate(), i));
436
0
}
437
438
template <typename T>
439
void ReturnValue<T>::Set(int16_t i) {
440
  static_assert(std::is_base_of_v<T, Integer>, "type check");
441
  using I = internal::Internals;
442
  static_assert(I::IsValidSmi(std::numeric_limits<int16_t>::min()));
443
  static_assert(I::IsValidSmi(std::numeric_limits<int16_t>::max()));
444
  SetInternal(I::IntegralToSmi(i));
445
}
446
447
template <typename T>
448
0
void ReturnValue<T>::Set(int32_t i) {
449
0
  static_assert(std::is_base_of_v<T, Integer>, "type check");
450
0
  if (const auto result = internal::Internals::TryIntegralToSmi(i)) {
451
0
    SetInternal(*result);
452
0
    return;
453
0
  }
454
0
  SetNonEmpty(Integer::New(GetIsolate(), i));
455
0
}
Unexecuted instantiation: v8::ReturnValue<v8::Value>::Set(int)
Unexecuted instantiation: v8::ReturnValue<v8::Integer>::Set(int)
456
457
template <typename T>
458
void ReturnValue<T>::Set(int64_t i) {
459
  static_assert(std::is_base_of_v<T, Integer>, "type check");
460
  if (const auto result = internal::Internals::TryIntegralToSmi(i)) {
461
    SetInternal(*result);
462
    return;
463
  }
464
  SetNonEmpty(Number::New(GetIsolate(), static_cast<double>(i)));
465
}
466
467
template <typename T>
468
void ReturnValue<T>::Set(uint16_t i) {
469
  static_assert(std::is_base_of_v<T, Integer>, "type check");
470
  using I = internal::Internals;
471
  static_assert(I::IsValidSmi(std::numeric_limits<uint16_t>::min()));
472
  static_assert(I::IsValidSmi(std::numeric_limits<uint16_t>::max()));
473
  SetInternal(I::IntegralToSmi(i));
474
}
475
476
template <typename T>
477
35
void ReturnValue<T>::Set(uint32_t i) {
478
35
  static_assert(std::is_base_of_v<T, Integer>, "type check");
479
35
  if (const auto result = internal::Internals::TryIntegralToSmi(i)) {
480
35
    SetInternal(*result);
481
35
    return;
482
35
  }
483
0
  SetNonEmpty(Integer::NewFromUnsigned(GetIsolate(), i));
484
0
}
485
486
template <typename T>
487
0
void ReturnValue<T>::Set(uint64_t i) {
488
0
  static_assert(std::is_base_of_v<T, Integer>, "type check");
489
0
  if (const auto result = internal::Internals::TryIntegralToSmi(i)) {
490
0
    SetInternal(*result);
491
0
    return;
492
0
  }
493
0
  SetNonEmpty(Number::New(GetIsolate(), static_cast<double>(i)));
494
0
}
495
496
template <typename T>
497
70
void ReturnValue<T>::Set(bool value) {
498
70
  static_assert(std::is_void_v<T> || std::is_base_of_v<T, Boolean>,
499
70
                "type check");
500
70
  using I = internal::Internals;
501
#if V8_STATIC_ROOTS_BOOL
502
#ifdef V8_ENABLE_CHECKS
503
  internal::PerformCastCheck(
504
      internal::ValueHelper::SlotAsValue<Value, true>(value_));
505
#endif  // V8_ENABLE_CHECKS
506
  SetInternal(value ? I::StaticReadOnlyRoot::kTrueValue
507
                    : I::StaticReadOnlyRoot::kFalseValue);
508
#else
509
70
  int root_index;
510
70
  if (value) {
511
0
    root_index = I::kTrueValueRootIndex;
512
70
  } else {
513
70
    root_index = I::kFalseValueRootIndex;
514
70
  }
515
70
  *value_ = I::GetRoot(GetIsolate(), root_index);
516
70
#endif  // V8_STATIC_ROOTS_BOOL
517
70
}
v8::ReturnValue<v8::Value>::Set(bool)
Line
Count
Source
497
70
void ReturnValue<T>::Set(bool value) {
498
70
  static_assert(std::is_void_v<T> || std::is_base_of_v<T, Boolean>,
499
70
                "type check");
500
70
  using I = internal::Internals;
501
#if V8_STATIC_ROOTS_BOOL
502
#ifdef V8_ENABLE_CHECKS
503
  internal::PerformCastCheck(
504
      internal::ValueHelper::SlotAsValue<Value, true>(value_));
505
#endif  // V8_ENABLE_CHECKS
506
  SetInternal(value ? I::StaticReadOnlyRoot::kTrueValue
507
                    : I::StaticReadOnlyRoot::kFalseValue);
508
#else
509
70
  int root_index;
510
70
  if (value) {
511
0
    root_index = I::kTrueValueRootIndex;
512
70
  } else {
513
70
    root_index = I::kFalseValueRootIndex;
514
70
  }
515
70
  *value_ = I::GetRoot(GetIsolate(), root_index);
516
70
#endif  // V8_STATIC_ROOTS_BOOL
517
70
}
Unexecuted instantiation: v8::ReturnValue<v8::Boolean>::Set(bool)
518
519
template <typename T>
520
0
void ReturnValue<T>::SetDefaultValue() {
521
0
  using I = internal::Internals;
522
  if constexpr (std::is_same_v<void, T> || std::is_same_v<v8::Boolean, T>) {
523
    Set(true);
524
  } else if constexpr (std::is_same_v<v8::Integer, T>) {
525
    SetInternal(I::IntegralToSmi(0));
526
0
  } else {
527
0
    static_assert(std::is_same_v<v8::Value, T> || std::is_same_v<v8::Array, T>);
528
#if V8_STATIC_ROOTS_BOOL
529
    SetInternal(I::StaticReadOnlyRoot::kUndefinedValue);
530
#else
531
0
    *value_ = I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex);
532
0
#endif  // V8_STATIC_ROOTS_BOOL
533
0
  }
534
0
}
Unexecuted instantiation: v8::ReturnValue<v8::Value>::SetDefaultValue()
Unexecuted instantiation: v8::ReturnValue<v8::Array>::SetDefaultValue()
535
536
template <typename T>
537
0
void ReturnValue<T>::SetNull() {
538
0
  static_assert(std::is_base_of_v<T, Primitive>, "type check");
539
0
  using I = internal::Internals;
540
#if V8_STATIC_ROOTS_BOOL
541
#ifdef V8_ENABLE_CHECKS
542
  internal::PerformCastCheck(
543
      internal::ValueHelper::SlotAsValue<Value, true>(value_));
544
#endif  // V8_ENABLE_CHECKS
545
  SetInternal(I::StaticReadOnlyRoot::kNullValue);
546
#else
547
0
  *value_ = I::GetRoot(GetIsolate(), I::kNullValueRootIndex);
548
0
#endif  // V8_STATIC_ROOTS_BOOL
549
0
}
550
551
template <typename T>
552
0
void ReturnValue<T>::SetUndefined() {
553
0
  static_assert(std::is_base_of_v<T, Primitive>, "type check");
554
0
  using I = internal::Internals;
555
#if V8_STATIC_ROOTS_BOOL
556
#ifdef V8_ENABLE_CHECKS
557
  internal::PerformCastCheck(
558
      internal::ValueHelper::SlotAsValue<Value, true>(value_));
559
#endif  // V8_ENABLE_CHECKS
560
  SetInternal(I::StaticReadOnlyRoot::kUndefinedValue);
561
#else
562
0
  *value_ = I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex);
563
0
#endif  // V8_STATIC_ROOTS_BOOL
564
0
}
565
566
template <typename T>
567
0
void ReturnValue<T>::SetFalse() {
568
0
  static_assert(std::is_void_v<T> || std::is_base_of_v<T, Boolean>,
569
0
                "type check");
570
0
  using I = internal::Internals;
571
#if V8_STATIC_ROOTS_BOOL
572
#ifdef V8_ENABLE_CHECKS
573
  internal::PerformCastCheck(
574
      internal::ValueHelper::SlotAsValue<Value, true>(value_));
575
#endif  // V8_ENABLE_CHECKS
576
  SetInternal(I::StaticReadOnlyRoot::kFalseValue);
577
#else
578
0
  *value_ = I::GetRoot(GetIsolate(), I::kFalseValueRootIndex);
579
0
#endif  // V8_STATIC_ROOTS_BOOL
580
0
}
581
582
template <typename T>
583
0
void ReturnValue<T>::SetEmptyString() {
584
0
  static_assert(std::is_base_of_v<T, String>, "type check");
585
0
  using I = internal::Internals;
586
#if V8_STATIC_ROOTS_BOOL
587
#ifdef V8_ENABLE_CHECKS
588
  internal::PerformCastCheck(
589
      internal::ValueHelper::SlotAsValue<Value, true>(value_));
590
#endif  // V8_ENABLE_CHECKS
591
  SetInternal(I::StaticReadOnlyRoot::kEmptyString);
592
#else
593
0
  *value_ = I::GetRoot(GetIsolate(), I::kEmptyStringRootIndex);
594
0
#endif  // V8_STATIC_ROOTS_BOOL
595
0
}
596
597
template <typename T>
598
70
Isolate* ReturnValue<T>::GetIsolate() const {
599
70
  return *reinterpret_cast<Isolate**>(&value_[kIsolateValueIndex]);
600
70
}
v8::ReturnValue<v8::Value>::GetIsolate() const
Line
Count
Source
598
70
Isolate* ReturnValue<T>::GetIsolate() const {
599
70
  return *reinterpret_cast<Isolate**>(&value_[kIsolateValueIndex]);
600
70
}
Unexecuted instantiation: v8::ReturnValue<v8::Integer>::GetIsolate() const
Unexecuted instantiation: v8::ReturnValue<v8::Boolean>::GetIsolate() const
Unexecuted instantiation: v8::ReturnValue<v8::Array>::GetIsolate() const
Unexecuted instantiation: v8::ReturnValue<void>::GetIsolate() const
601
602
template <typename T>
603
Local<Value> ReturnValue<T>::Get() const {
604
  return Local<Value>::New(GetIsolate(),
605
                           internal::ValueHelper::SlotAsValue<Value>(value_));
606
}
607
608
template <typename T>
609
template <typename S>
610
void ReturnValue<T>::Set(S* whatever) {
611
  static_assert(sizeof(S) < 0, "incompilable to prevent inadvertent misuse");
612
}
613
614
template <typename T>
615
FunctionCallbackInfo<T>::FunctionCallbackInfo(internal::Address* implicit_args,
616
                                              internal::Address* values,
617
                                              int length)
618
    : implicit_args_(implicit_args), values_(values), length_(length) {}
619
620
template <typename T>
621
16.5k
Local<Value> FunctionCallbackInfo<T>::operator[](int i) const {
622
  // values_ points to the first argument (not the receiver).
623
16.5k
  if (i < 0 || Length() <= i) return Undefined(GetIsolate());
624
16.5k
  return Local<Value>::FromSlot(values_ + i);
625
16.5k
}
626
627
template <typename T>
628
0
Local<Object> FunctionCallbackInfo<T>::This() const {
629
  // values_ points to the first argument (not the receiver).
630
0
  return Local<Object>::FromSlot(values_ + kThisValuesIndex);
631
0
}
632
633
template <typename T>
634
0
Local<Value> FunctionCallbackInfo<T>::NewTarget() const {
635
0
  return Local<Value>::FromSlot(&implicit_args_[kNewTargetIndex]);
636
0
}
637
638
template <typename T>
639
0
Local<Value> FunctionCallbackInfo<T>::Data() const {
640
0
  auto target = Local<v8::Data>::FromSlot(&implicit_args_[kTargetIndex]);
641
0
  return api_internal::GetFunctionTemplateData(GetIsolate(), target);
642
0
}
643
644
template <typename T>
645
5.42k
Isolate* FunctionCallbackInfo<T>::GetIsolate() const {
646
5.42k
  return *reinterpret_cast<Isolate**>(&implicit_args_[kIsolateIndex]);
647
5.42k
}
648
649
template <typename T>
650
3.67k
ReturnValue<T> FunctionCallbackInfo<T>::GetReturnValue() const {
651
3.67k
  return ReturnValue<T>(&implicit_args_[kReturnValueIndex]);
652
3.67k
}
653
654
template <typename T>
655
0
bool FunctionCallbackInfo<T>::IsConstructCall() const {
656
0
  return !NewTarget()->IsUndefined();
657
0
}
658
659
template <typename T>
660
19.7k
int FunctionCallbackInfo<T>::Length() const {
661
19.7k
  return static_cast<int>(length_);
662
19.7k
}
663
664
template <typename T>
665
246
Isolate* PropertyCallbackInfo<T>::GetIsolate() const {
666
246
  return *reinterpret_cast<Isolate**>(&args_[kIsolateIndex]);
667
246
}
v8::PropertyCallbackInfo<v8::Value>::GetIsolate() const
Line
Count
Source
665
246
Isolate* PropertyCallbackInfo<T>::GetIsolate() const {
666
246
  return *reinterpret_cast<Isolate**>(&args_[kIsolateIndex]);
667
246
}
Unexecuted instantiation: v8::PropertyCallbackInfo<void>::GetIsolate() const
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Array>::GetIsolate() const
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Integer>::GetIsolate() const
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Boolean>::GetIsolate() const
668
669
template <typename T>
670
1
Local<Value> PropertyCallbackInfo<T>::Data() const {
671
1
  return Local<Value>::FromSlot(&args_[kDataIndex]);
672
1
}
673
674
template <typename T>
675
1
Local<Object> PropertyCallbackInfo<T>::This() const {
676
1
  return Local<Object>::FromSlot(&args_[kThisIndex]);
677
1
}
v8::PropertyCallbackInfo<v8::Value>::This() const
Line
Count
Source
675
1
Local<Object> PropertyCallbackInfo<T>::This() const {
676
1
  return Local<Object>::FromSlot(&args_[kThisIndex]);
677
1
}
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Integer>::This() const
Unexecuted instantiation: v8::PropertyCallbackInfo<void>::This() const
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Boolean>::This() const
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Array>::This() const
678
679
template <typename T>
680
Local<Object> PropertyCallbackInfo<T>::Holder() const {
681
  return Local<Object>::FromSlot(&args_[kHolderIndex]);
682
}
683
684
namespace api_internal {
685
// Returns JSGlobalProxy if holder is JSGlobalObject or unmodified holder
686
// otherwise.
687
V8_EXPORT internal::Address ConvertToJSGlobalProxyIfNecessary(
688
    internal::Address holder);
689
}  // namespace api_internal
690
691
template <typename T>
692
Local<Object> PropertyCallbackInfo<T>::HolderV2() const {
693
  using I = internal::Internals;
694
  if (!I::HasHeapObjectTag(args_[kHolderV2Index])) {
695
    args_[kHolderV2Index] =
696
        api_internal::ConvertToJSGlobalProxyIfNecessary(args_[kHolderIndex]);
697
  }
698
  return Local<Object>::FromSlot(&args_[kHolderV2Index]);
699
}
700
701
template <typename T>
702
71
ReturnValue<T> PropertyCallbackInfo<T>::GetReturnValue() const {
703
71
  return ReturnValue<T>(&args_[kReturnValueIndex]);
704
71
}
v8::PropertyCallbackInfo<v8::Value>::GetReturnValue() const
Line
Count
Source
702
71
ReturnValue<T> PropertyCallbackInfo<T>::GetReturnValue() const {
703
71
  return ReturnValue<T>(&args_[kReturnValueIndex]);
704
71
}
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Integer>::GetReturnValue() const
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Boolean>::GetReturnValue() const
Unexecuted instantiation: v8::PropertyCallbackInfo<v8::Array>::GetReturnValue() const
Unexecuted instantiation: v8::PropertyCallbackInfo<void>::GetReturnValue() const
705
706
template <typename T>
707
0
bool PropertyCallbackInfo<T>::ShouldThrowOnError() const {
708
0
  using I = internal::Internals;
709
0
  if (args_[kShouldThrowOnErrorIndex] !=
710
0
      I::IntegralToSmi(I::kInferShouldThrowMode)) {
711
0
    return args_[kShouldThrowOnErrorIndex] != I::IntegralToSmi(I::kDontThrow);
712
0
  }
713
0
  return v8::internal::ShouldThrowOnError(
714
0
      reinterpret_cast<v8::internal::Isolate*>(GetIsolate()));
715
0
}
716
717
}  // namespace v8
718
719
#endif  // INCLUDE_V8_FUNCTION_CALLBACK_H_