libv8-node 15.14.0.0-x86_64-linux-musl → 16.17.0.0-x86_64-linux-musl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libv8-node/location.rb +1 -1
  3. data/ext/libv8-node/paths.rb +5 -1
  4. data/lib/libv8/node/version.rb +3 -3
  5. data/vendor/v8/include/cppgc/allocation.h +105 -45
  6. data/vendor/v8/include/cppgc/common.h +9 -6
  7. data/vendor/v8/include/cppgc/cross-thread-persistent.h +413 -0
  8. data/vendor/v8/include/cppgc/custom-space.h +37 -2
  9. data/vendor/v8/include/cppgc/default-platform.h +47 -48
  10. data/vendor/v8/include/cppgc/ephemeron-pair.h +30 -0
  11. data/vendor/v8/include/cppgc/explicit-management.h +82 -0
  12. data/vendor/v8/include/cppgc/garbage-collected.h +4 -3
  13. data/vendor/v8/include/cppgc/heap-consistency.h +253 -0
  14. data/vendor/v8/include/cppgc/heap-state.h +70 -0
  15. data/vendor/v8/include/cppgc/heap-statistics.h +120 -0
  16. data/vendor/v8/include/cppgc/heap.h +68 -6
  17. data/vendor/v8/include/cppgc/internal/api-constants.h +3 -3
  18. data/vendor/v8/include/cppgc/internal/caged-heap-local-data.h +2 -1
  19. data/vendor/v8/include/cppgc/internal/compiler-specific.h +2 -2
  20. data/vendor/v8/include/cppgc/internal/gc-info.h +44 -13
  21. data/vendor/v8/include/cppgc/internal/name-trait.h +111 -0
  22. data/vendor/v8/include/cppgc/internal/persistent-node.h +58 -2
  23. data/vendor/v8/include/cppgc/internal/pointer-policies.h +69 -28
  24. data/vendor/v8/include/cppgc/internal/prefinalizer-handler.h +1 -1
  25. data/vendor/v8/include/cppgc/internal/write-barrier.h +390 -35
  26. data/vendor/v8/include/cppgc/liveness-broker.h +11 -2
  27. data/vendor/v8/include/cppgc/macros.h +2 -0
  28. data/vendor/v8/include/cppgc/member.h +87 -25
  29. data/vendor/v8/include/cppgc/name-provider.h +65 -0
  30. data/vendor/v8/include/cppgc/object-size-trait.h +58 -0
  31. data/vendor/v8/include/cppgc/persistent.h +40 -10
  32. data/vendor/v8/include/cppgc/platform.h +49 -25
  33. data/vendor/v8/include/cppgc/prefinalizer.h +1 -1
  34. data/vendor/v8/include/cppgc/process-heap-statistics.h +36 -0
  35. data/vendor/v8/include/cppgc/sentinel-pointer.h +32 -0
  36. data/vendor/v8/include/cppgc/source-location.h +2 -1
  37. data/vendor/v8/include/cppgc/testing.h +99 -0
  38. data/vendor/v8/include/cppgc/trace-trait.h +8 -3
  39. data/vendor/v8/include/cppgc/type-traits.h +157 -19
  40. data/vendor/v8/include/cppgc/visitor.h +194 -28
  41. data/vendor/v8/include/libplatform/libplatform.h +11 -0
  42. data/vendor/v8/include/libplatform/v8-tracing.h +2 -0
  43. data/vendor/v8/include/v8-cppgc.h +258 -159
  44. data/vendor/v8/include/v8-fast-api-calls.h +603 -155
  45. data/vendor/v8/include/v8-inspector.h +22 -4
  46. data/vendor/v8/include/v8-internal.h +111 -27
  47. data/vendor/v8/include/v8-metrics.h +77 -8
  48. data/vendor/v8/include/v8-platform.h +47 -22
  49. data/vendor/v8/include/v8-profiler.h +75 -11
  50. data/vendor/v8/include/v8-unwinder-state.h +30 -0
  51. data/vendor/v8/include/v8-util.h +1 -1
  52. data/vendor/v8/include/v8-version.h +4 -4
  53. data/vendor/v8/include/v8.h +1196 -642
  54. data/vendor/v8/include/v8config.h +87 -11
  55. data/vendor/v8/{out.gn → x86_64-linux-musl}/libv8/obj/libv8_monolith.a +0 -0
  56. metadata +17 -5
  57. data/vendor/v8/include/cppgc/internal/process-heap.h +0 -34
@@ -18,6 +18,38 @@
18
18
  * &v8::CFunction::Make(FastMethod));
19
19
  * \endcode
20
20
  *
21
+ * By design, fast calls are limited by the following requirements, which
22
+ * the embedder should enforce themselves:
23
+ * - they should not allocate on the JS heap;
24
+ * - they should not trigger JS execution.
25
+ * To enforce them, the embedder could use the existing
26
+ * v8::Isolate::DisallowJavascriptExecutionScope and a utility similar to
27
+ * Blink's NoAllocationScope:
28
+ * https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/heap/thread_state_scopes.h;l=16
29
+ *
30
+ * Due to these limitations, it's not directly possible to report errors by
31
+ * throwing a JS exception or to otherwise do an allocation. There is an
32
+ * alternative way of creating fast calls that supports falling back to the
33
+ * slow call and then performing the necessary allocation. When one creates
34
+ * the fast method by using CFunction::MakeWithFallbackSupport instead of
35
+ * CFunction::Make, the fast callback gets as last parameter an output variable,
36
+ * through which it can request falling back to the slow call. So one might
37
+ * declare their method like:
38
+ *
39
+ * \code
40
+ * void FastMethodWithFallback(int param, FastApiCallbackOptions& options);
41
+ * \endcode
42
+ *
43
+ * If the callback wants to signal an error condition or to perform an
44
+ * allocation, it must set options.fallback to true and do an early return from
45
+ * the fast method. Then V8 checks the value of options.fallback and if it's
46
+ * true, falls back to executing the SlowCallback, which is capable of reporting
47
+ * the error (either by throwing a JS exception or logging to the console) or
48
+ * doing the allocation. It's the embedder's responsibility to ensure that the
49
+ * fast callback is idempotent up to the point where error and fallback
50
+ * conditions are checked, because otherwise executing the slow callback might
51
+ * produce visible side-effects twice.
52
+ *
21
53
  * An example for custom embedder type support might employ a way to wrap/
22
54
  * unwrap various C++ types in JSObject instances, e.g:
23
55
  *
@@ -38,8 +70,7 @@
38
70
  * return GetInternalField<CustomEmbedderType,
39
71
  * kV8EmbedderWrapperObjectIndex>(wrapper);
40
72
  * }
41
- * static void FastMethod(v8::ApiObject receiver_obj, int param) {
42
- * v8::Object* v8_object = reinterpret_cast<v8::Object*>(&api_object);
73
+ * static void FastMethod(v8::Local<v8::Object> receiver_obj, int param) {
43
74
  * CustomEmbedderType* receiver = static_cast<CustomEmbedderType*>(
44
75
  * receiver_obj->GetAlignedPointerFromInternalField(
45
76
  * kV8EmbedderWrapperObjectIndex));
@@ -116,23 +147,73 @@
116
147
  * receiver := the {embedder_object} from above
117
148
  * param := 42
118
149
  *
119
- * Currently only void return types are supported.
150
+ * Currently supported return types:
151
+ * - void
152
+ * - bool
153
+ * - int32_t
154
+ * - uint32_t
155
+ * - float32_t
156
+ * - float64_t
120
157
  * Currently supported argument types:
121
158
  * - pointer to an embedder type
159
+ * - JavaScript array of primitive types
122
160
  * - bool
123
161
  * - int32_t
124
162
  * - uint32_t
125
163
  * - int64_t
126
164
  * - uint64_t
165
+ * - float32_t
166
+ * - float64_t
167
+ *
127
168
  * The 64-bit integer types currently have the IDL (unsigned) long long
128
169
  * semantics: https://heycam.github.io/webidl/#abstract-opdef-converttoint
129
170
  * In the future we'll extend the API to also provide conversions from/to
130
171
  * BigInt to preserve full precision.
172
+ * The floating point types currently have the IDL (unrestricted) semantics,
173
+ * which is the only one used by WebGL. We plan to add support also for
174
+ * restricted floats/doubles, similarly to the BigInt conversion policies.
175
+ * We also differ from the specific NaN bit pattern that WebIDL prescribes
176
+ * (https://heycam.github.io/webidl/#es-unrestricted-float) in that Blink
177
+ * passes NaN values as-is, i.e. doesn't normalize them.
178
+ *
131
179
  * To be supported types:
132
- * - float32_t
133
- * - float64_t
134
- * - arrays of C types
180
+ * - TypedArrays and ArrayBuffers
135
181
  * - arrays of embedder types
182
+ *
183
+ *
184
+ * The API offers a limited support for function overloads:
185
+ *
186
+ * \code
187
+ * void FastMethod_2Args(int param, bool another_param);
188
+ * void FastMethod_3Args(int param, bool another_param, int third_param);
189
+ *
190
+ * v8::CFunction fast_method_2args_c_func =
191
+ * MakeV8CFunction(FastMethod_2Args);
192
+ * v8::CFunction fast_method_3args_c_func =
193
+ * MakeV8CFunction(FastMethod_3Args);
194
+ * const v8::CFunction fast_method_overloads[] = {fast_method_2args_c_func,
195
+ * fast_method_3args_c_func};
196
+ * Local<v8::FunctionTemplate> method_template =
197
+ * v8::FunctionTemplate::NewWithCFunctionOverloads(
198
+ * isolate, SlowCallback, data, signature, length,
199
+ * constructor_behavior, side_effect_type,
200
+ * {fast_method_overloads, 2});
201
+ * \endcode
202
+ *
203
+ * In this example a single FunctionTemplate is associated to multiple C++
204
+ * functions. The overload resolution is currently only based on the number of
205
+ * arguments passed in a call. For example, if this method_template is
206
+ * registered with a wrapper JS object as described above, a call with two
207
+ * arguments:
208
+ * obj.method(42, true);
209
+ * will result in a fast call to FastMethod_2Args, while a call with three or
210
+ * more arguments:
211
+ * obj.method(42, true, 11);
212
+ * will result in a fast call to FastMethod_3Args. Instead a call with less than
213
+ * two arguments, like:
214
+ * obj.method(42);
215
+ * would not result in a fast call but would fall back to executing the
216
+ * associated SlowCallback.
136
217
  */
137
218
 
138
219
  #ifndef INCLUDE_V8_FAST_API_CALLS_H_
@@ -141,13 +222,20 @@
141
222
  #include <stddef.h>
142
223
  #include <stdint.h>
143
224
 
144
- #include "v8config.h" // NOLINT(build/include_directory)
225
+ #include <tuple>
226
+ #include <type_traits>
227
+
228
+ #include "v8-internal.h" // NOLINT(build/include_directory)
229
+ #include "v8.h" // NOLINT(build/include_directory)
230
+ #include "v8config.h" // NOLINT(build/include_directory)
145
231
 
146
232
  namespace v8 {
147
233
 
234
+ class Isolate;
235
+
148
236
  class CTypeInfo {
149
237
  public:
150
- enum class Type : char {
238
+ enum class Type : uint8_t {
151
239
  kVoid,
152
240
  kBool,
153
241
  kInt32,
@@ -157,170 +245,144 @@ class CTypeInfo {
157
245
  kFloat32,
158
246
  kFloat64,
159
247
  kV8Value,
248
+ kApiObject, // This will be deprecated once all users have
249
+ // migrated from v8::ApiObject to v8::Local<v8::Value>.
160
250
  };
161
251
 
162
- enum class ArgFlags : uint8_t {
163
- kNone = 0,
164
- kIsArrayBit = 1 << 0, // This argument is first in an array of values.
252
+ // kCallbackOptionsType is not part of the Type enum
253
+ // because it is only used internally. Use value 255 that is larger
254
+ // than any valid Type enum.
255
+ static constexpr Type kCallbackOptionsType = Type(255);
256
+
257
+ enum class SequenceType : uint8_t {
258
+ kScalar,
259
+ kIsSequence, // sequence<T>
260
+ kIsTypedArray, // TypedArray of T or any ArrayBufferView if T
261
+ // is void
262
+ kIsArrayBuffer // ArrayBuffer
165
263
  };
166
264
 
167
- static CTypeInfo FromWrapperType(ArgFlags flags = ArgFlags::kNone) {
168
- return CTypeInfo(static_cast<int>(flags) | kIsWrapperTypeBit);
169
- }
265
+ enum class Flags : uint8_t {
266
+ kNone = 0,
267
+ kAllowSharedBit = 1 << 0, // Must be an ArrayBuffer or TypedArray
268
+ kEnforceRangeBit = 1 << 1, // T must be integral
269
+ kClampBit = 1 << 2, // T must be integral
270
+ kIsRestrictedBit = 1 << 3, // T must be float or double
271
+ };
170
272
 
171
- static constexpr CTypeInfo FromCType(Type ctype,
172
- ArgFlags flags = ArgFlags::kNone) {
173
- // TODO(mslekova): Refactor the manual bit manipulations to use
174
- // PointerWithPayload instead.
175
- // ctype cannot be Type::kV8Value.
176
- return CTypeInfo(
177
- ((static_cast<uintptr_t>(ctype) << kTypeOffset) & kTypeMask) |
178
- static_cast<int>(flags));
179
- }
273
+ explicit constexpr CTypeInfo(
274
+ Type type, SequenceType sequence_type = SequenceType::kScalar,
275
+ Flags flags = Flags::kNone)
276
+ : type_(type), sequence_type_(sequence_type), flags_(flags) {}
180
277
 
181
- const void* GetWrapperInfo() const;
278
+ constexpr Type GetType() const { return type_; }
279
+ constexpr SequenceType GetSequenceType() const { return sequence_type_; }
280
+ constexpr Flags GetFlags() const { return flags_; }
182
281
 
183
- constexpr Type GetType() const {
184
- if (payload_ & kIsWrapperTypeBit) {
185
- return Type::kV8Value;
186
- }
187
- return static_cast<Type>((payload_ & kTypeMask) >> kTypeOffset);
282
+ static constexpr bool IsIntegralType(Type type) {
283
+ return type == Type::kInt32 || type == Type::kUint32 ||
284
+ type == Type::kInt64 || type == Type::kUint64;
188
285
  }
189
286
 
190
- constexpr bool IsArray() const {
191
- return payload_ & static_cast<int>(ArgFlags::kIsArrayBit);
287
+ static constexpr bool IsFloatingPointType(Type type) {
288
+ return type == Type::kFloat32 || type == Type::kFloat64;
192
289
  }
193
290
 
194
- static const CTypeInfo& Invalid() {
195
- static CTypeInfo invalid = CTypeInfo(0);
196
- return invalid;
291
+ static constexpr bool IsPrimitive(Type type) {
292
+ return IsIntegralType(type) || IsFloatingPointType(type) ||
293
+ type == Type::kBool;
197
294
  }
198
295
 
199
296
  private:
200
- explicit constexpr CTypeInfo(uintptr_t payload) : payload_(payload) {}
201
-
202
- // That must be the last bit after ArgFlags.
203
- static constexpr uintptr_t kIsWrapperTypeBit = 1 << 1;
204
- static constexpr uintptr_t kWrapperTypeInfoMask = static_cast<uintptr_t>(~0)
205
- << 2;
206
-
207
- static constexpr unsigned int kTypeOffset = kIsWrapperTypeBit;
208
- static constexpr unsigned int kTypeSize = 8 - kTypeOffset;
209
- static constexpr uintptr_t kTypeMask =
210
- (~(static_cast<uintptr_t>(~0) << kTypeSize)) << kTypeOffset;
211
-
212
- const uintptr_t payload_;
297
+ Type type_;
298
+ SequenceType sequence_type_;
299
+ Flags flags_;
213
300
  };
214
301
 
215
- class CFunctionInfo {
302
+ struct FastApiTypedArrayBase {
216
303
  public:
217
- virtual const CTypeInfo& ReturnInfo() const = 0;
218
- virtual unsigned int ArgumentCount() const = 0;
219
- virtual const CTypeInfo& ArgumentInfo(unsigned int index) const = 0;
220
- };
304
+ // Returns the length in number of elements.
305
+ size_t V8_EXPORT length() const { return length_; }
306
+ // Checks whether the given index is within the bounds of the collection.
307
+ void V8_EXPORT ValidateIndex(size_t index) const;
221
308
 
222
- struct ApiObject {
223
- uintptr_t address;
309
+ protected:
310
+ size_t length_ = 0;
224
311
  };
225
312
 
226
- namespace internal {
227
-
228
313
  template <typename T>
229
- struct GetCType {
230
- static constexpr CTypeInfo Get() {
231
- return CTypeInfo::FromCType(CTypeInfo::Type::kV8Value);
232
- }
233
- };
234
-
235
- #define SPECIALIZE_GET_C_TYPE_FOR(ctype, ctypeinfo) \
236
- template <> \
237
- struct GetCType<ctype> { \
238
- static constexpr CTypeInfo Get() { \
239
- return CTypeInfo::FromCType(CTypeInfo::Type::ctypeinfo); \
240
- } \
241
- };
242
-
243
- #define SUPPORTED_C_TYPES(V) \
244
- V(void, kVoid) \
245
- V(bool, kBool) \
246
- V(int32_t, kInt32) \
247
- V(uint32_t, kUint32) \
248
- V(int64_t, kInt64) \
249
- V(uint64_t, kUint64) \
250
- V(float, kFloat32) \
251
- V(double, kFloat64) \
252
- V(ApiObject, kV8Value)
253
-
254
- SUPPORTED_C_TYPES(SPECIALIZE_GET_C_TYPE_FOR)
255
-
256
- // T* where T is a primitive (array of primitives).
257
- template <typename T, typename = void>
258
- struct GetCTypePointerImpl {
259
- static constexpr CTypeInfo Get() {
260
- return CTypeInfo::FromCType(GetCType<T>::Get().GetType(),
261
- CTypeInfo::ArgFlags::kIsArrayBit);
314
+ struct FastApiTypedArray : public FastApiTypedArrayBase {
315
+ public:
316
+ V8_INLINE T get(size_t index) const {
317
+ #ifdef DEBUG
318
+ ValidateIndex(index);
319
+ #endif // DEBUG
320
+ T tmp;
321
+ memcpy(&tmp, reinterpret_cast<T*>(data_) + index, sizeof(T));
322
+ return tmp;
262
323
  }
263
- };
264
324
 
265
- // T* where T is an API object.
266
- template <typename T>
267
- struct GetCTypePointerImpl<T, void> {
268
- static constexpr CTypeInfo Get() { return CTypeInfo::FromWrapperType(); }
325
+ private:
326
+ // This pointer should include the typed array offset applied.
327
+ // It's not guaranteed that it's aligned to sizeof(T), it's only
328
+ // guaranteed that it's 4-byte aligned, so for 8-byte types we need to
329
+ // provide a special implementation for reading from it, which hides
330
+ // the possibly unaligned read in the `get` method.
331
+ void* data_;
269
332
  };
270
333
 
271
- // T** where T is a primitive. Not allowed.
272
- template <typename T, typename = void>
273
- struct GetCTypePointerPointerImpl {
274
- static_assert(sizeof(T**) != sizeof(T**), "Unsupported type");
334
+ // Any TypedArray. It uses kTypedArrayBit with base type void
335
+ // Overloaded args of ArrayBufferView and TypedArray are not supported
336
+ // (for now) because the generic “any” ArrayBufferView doesn’t have its
337
+ // own instance type. It could be supported if we specify that
338
+ // TypedArray<T> always has precedence over the generic ArrayBufferView,
339
+ // but this complicates overload resolution.
340
+ struct FastApiArrayBufferView {
341
+ void* data;
342
+ size_t byte_length;
275
343
  };
276
344
 
277
- // T** where T is an API object (array of API objects).
278
- template <typename T>
279
- struct GetCTypePointerPointerImpl<T, void> {
280
- static constexpr CTypeInfo Get() {
281
- return CTypeInfo::FromWrapperType(CTypeInfo::ArgFlags::kIsArrayBit);
282
- }
345
+ struct FastApiArrayBuffer {
346
+ void* data;
347
+ size_t byte_length;
283
348
  };
284
349
 
285
- template <typename T>
286
- struct GetCType<T**> : public GetCTypePointerPointerImpl<T> {};
287
-
288
- template <typename T>
289
- struct GetCType<T*> : public GetCTypePointerImpl<T> {};
290
-
291
- template <typename R, bool RaisesException, typename... Args>
292
- class CFunctionInfoImpl : public CFunctionInfo {
350
+ class V8_EXPORT CFunctionInfo {
293
351
  public:
294
- static constexpr int kHasErrorArgCount = (RaisesException ? 1 : 0);
295
- static constexpr int kReceiverCount = 1;
296
- CFunctionInfoImpl()
297
- : return_info_(internal::GetCType<R>::Get()),
298
- arg_count_(sizeof...(Args) - kHasErrorArgCount),
299
- arg_info_{internal::GetCType<Args>::Get()...} {
300
- static_assert(sizeof...(Args) >= kHasErrorArgCount + kReceiverCount,
301
- "The receiver or the has_error argument is missing.");
302
- static_assert(
303
- internal::GetCType<R>::Get().GetType() == CTypeInfo::Type::kVoid,
304
- "Only void return types are currently supported.");
352
+ // Construct a struct to hold a CFunction's type information.
353
+ // |return_info| describes the function's return type.
354
+ // |arg_info| is an array of |arg_count| CTypeInfos describing the
355
+ // arguments. Only the last argument may be of the special type
356
+ // CTypeInfo::kCallbackOptionsType.
357
+ CFunctionInfo(const CTypeInfo& return_info, unsigned int arg_count,
358
+ const CTypeInfo* arg_info);
359
+
360
+ const CTypeInfo& ReturnInfo() const { return return_info_; }
361
+
362
+ // The argument count, not including the v8::FastApiCallbackOptions
363
+ // if present.
364
+ unsigned int ArgumentCount() const {
365
+ return HasOptions() ? arg_count_ - 1 : arg_count_;
305
366
  }
306
367
 
307
- const CTypeInfo& ReturnInfo() const override { return return_info_; }
308
- unsigned int ArgumentCount() const override { return arg_count_; }
309
- const CTypeInfo& ArgumentInfo(unsigned int index) const override {
310
- if (index >= ArgumentCount()) {
311
- return CTypeInfo::Invalid();
312
- }
313
- return arg_info_[index];
368
+ // |index| must be less than ArgumentCount().
369
+ // Note: if the last argument passed on construction of CFunctionInfo
370
+ // has type CTypeInfo::kCallbackOptionsType, it is not included in
371
+ // ArgumentCount().
372
+ const CTypeInfo& ArgumentInfo(unsigned int index) const;
373
+
374
+ bool HasOptions() const {
375
+ // The options arg is always the last one.
376
+ return arg_count_ > 0 && arg_info_[arg_count_ - 1].GetType() ==
377
+ CTypeInfo::kCallbackOptionsType;
314
378
  }
315
379
 
316
380
  private:
317
381
  const CTypeInfo return_info_;
318
382
  const unsigned int arg_count_;
319
- const CTypeInfo arg_info_[sizeof...(Args)];
383
+ const CTypeInfo* arg_info_;
320
384
  };
321
385
 
322
- } // namespace internal
323
-
324
386
  class V8_EXPORT CFunction {
325
387
  public:
326
388
  constexpr CFunction() : address_(nullptr), type_info_(nullptr) {}
@@ -336,33 +398,59 @@ class V8_EXPORT CFunction {
336
398
  const void* GetAddress() const { return address_; }
337
399
  const CFunctionInfo* GetTypeInfo() const { return type_info_; }
338
400
 
401
+ enum class OverloadResolution { kImpossible, kAtRuntime, kAtCompileTime };
402
+
403
+ // Returns whether an overload between this and the given CFunction can
404
+ // be resolved at runtime by the RTTI available for the arguments or at
405
+ // compile time for functions with different number of arguments.
406
+ OverloadResolution GetOverloadResolution(const CFunction* other) {
407
+ // Runtime overload resolution can only deal with functions with the
408
+ // same number of arguments. Functions with different arity are handled
409
+ // by compile time overload resolution though.
410
+ if (ArgumentCount() != other->ArgumentCount()) {
411
+ return OverloadResolution::kAtCompileTime;
412
+ }
413
+
414
+ // The functions can only differ by a single argument position.
415
+ int diff_index = -1;
416
+ for (unsigned int i = 0; i < ArgumentCount(); ++i) {
417
+ if (ArgumentInfo(i).GetSequenceType() !=
418
+ other->ArgumentInfo(i).GetSequenceType()) {
419
+ if (diff_index >= 0) {
420
+ return OverloadResolution::kImpossible;
421
+ }
422
+ diff_index = i;
423
+
424
+ // We only support overload resolution between sequence types.
425
+ if (ArgumentInfo(i).GetSequenceType() ==
426
+ CTypeInfo::SequenceType::kScalar ||
427
+ other->ArgumentInfo(i).GetSequenceType() ==
428
+ CTypeInfo::SequenceType::kScalar) {
429
+ return OverloadResolution::kImpossible;
430
+ }
431
+ }
432
+ }
433
+
434
+ return OverloadResolution::kAtRuntime;
435
+ }
436
+
339
437
  template <typename F>
340
438
  static CFunction Make(F* func) {
341
439
  return ArgUnwrap<F*>::Make(func);
342
440
  }
343
441
 
344
442
  template <typename F>
345
- static CFunction MakeWithErrorSupport(F* func) {
346
- return ArgUnwrap<F*>::MakeWithErrorSupport(func);
443
+ V8_DEPRECATED("Use CFunctionBuilder instead.")
444
+ static CFunction MakeWithFallbackSupport(F* func) {
445
+ return ArgUnwrap<F*>::Make(func);
347
446
  }
348
447
 
349
- template <typename F>
350
- static CFunction Make(F* func, const CFunctionInfo* type_info) {
351
- return CFunction(reinterpret_cast<const void*>(func), type_info);
352
- }
448
+ CFunction(const void* address, const CFunctionInfo* type_info);
353
449
 
354
450
  private:
355
451
  const void* address_;
356
452
  const CFunctionInfo* type_info_;
357
453
 
358
- CFunction(const void* address, const CFunctionInfo* type_info);
359
-
360
- template <typename R, bool RaisesException, typename... Args>
361
- static CFunctionInfo* GetCFunctionInfo() {
362
- static internal::CFunctionInfoImpl<R, RaisesException, Args...> instance;
363
- return &instance;
364
- }
365
-
366
454
  template <typename F>
367
455
  class ArgUnwrap {
368
456
  static_assert(sizeof(F) != sizeof(F),
@@ -372,17 +460,377 @@ class V8_EXPORT CFunction {
372
460
  template <typename R, typename... Args>
373
461
  class ArgUnwrap<R (*)(Args...)> {
374
462
  public:
375
- static CFunction Make(R (*func)(Args...)) {
376
- return CFunction(reinterpret_cast<const void*>(func),
377
- GetCFunctionInfo<R, false, Args...>());
378
- }
379
- static CFunction MakeWithErrorSupport(R (*func)(Args...)) {
380
- return CFunction(reinterpret_cast<const void*>(func),
381
- GetCFunctionInfo<R, true, Args...>());
382
- }
463
+ static CFunction Make(R (*func)(Args...));
464
+ };
465
+ };
466
+
467
+ struct ApiObject {
468
+ uintptr_t address;
469
+ };
470
+
471
+ /**
472
+ * A struct which may be passed to a fast call callback, like so:
473
+ * \code
474
+ * void FastMethodWithOptions(int param, FastApiCallbackOptions& options);
475
+ * \endcode
476
+ */
477
+ struct FastApiCallbackOptions {
478
+ /**
479
+ * Creates a new instance of FastApiCallbackOptions for testing purpose. The
480
+ * returned instance may be filled with mock data.
481
+ */
482
+ static FastApiCallbackOptions CreateForTesting(Isolate* isolate) {
483
+ return {false, {0}};
484
+ }
485
+
486
+ /**
487
+ * If the callback wants to signal an error condition or to perform an
488
+ * allocation, it must set options.fallback to true and do an early return
489
+ * from the fast method. Then V8 checks the value of options.fallback and if
490
+ * it's true, falls back to executing the SlowCallback, which is capable of
491
+ * reporting the error (either by throwing a JS exception or logging to the
492
+ * console) or doing the allocation. It's the embedder's responsibility to
493
+ * ensure that the fast callback is idempotent up to the point where error and
494
+ * fallback conditions are checked, because otherwise executing the slow
495
+ * callback might produce visible side-effects twice.
496
+ */
497
+ bool fallback;
498
+
499
+ /**
500
+ * The `data` passed to the FunctionTemplate constructor, or `undefined`.
501
+ * `data_ptr` allows for default constructing FastApiCallbackOptions.
502
+ */
503
+ union {
504
+ uintptr_t data_ptr;
505
+ v8::Value data;
383
506
  };
384
507
  };
385
508
 
509
+ namespace internal {
510
+
511
+ // Helper to count the number of occurances of `T` in `List`
512
+ template <typename T, typename... List>
513
+ struct count : std::integral_constant<int, 0> {};
514
+ template <typename T, typename... Args>
515
+ struct count<T, T, Args...>
516
+ : std::integral_constant<std::size_t, 1 + count<T, Args...>::value> {};
517
+ template <typename T, typename U, typename... Args>
518
+ struct count<T, U, Args...> : count<T, Args...> {};
519
+
520
+ template <typename RetBuilder, typename... ArgBuilders>
521
+ class CFunctionInfoImpl : public CFunctionInfo {
522
+ static constexpr int kOptionsArgCount =
523
+ count<FastApiCallbackOptions&, ArgBuilders...>();
524
+ static constexpr int kReceiverCount = 1;
525
+
526
+ static_assert(kOptionsArgCount == 0 || kOptionsArgCount == 1,
527
+ "Only one options parameter is supported.");
528
+
529
+ static_assert(sizeof...(ArgBuilders) >= kOptionsArgCount + kReceiverCount,
530
+ "The receiver or the options argument is missing.");
531
+
532
+ public:
533
+ constexpr CFunctionInfoImpl()
534
+ : CFunctionInfo(RetBuilder::Build(), sizeof...(ArgBuilders),
535
+ arg_info_storage_),
536
+ arg_info_storage_{ArgBuilders::Build()...} {
537
+ constexpr CTypeInfo::Type kReturnType = RetBuilder::Build().GetType();
538
+ static_assert(kReturnType == CTypeInfo::Type::kVoid ||
539
+ kReturnType == CTypeInfo::Type::kBool ||
540
+ kReturnType == CTypeInfo::Type::kInt32 ||
541
+ kReturnType == CTypeInfo::Type::kUint32 ||
542
+ kReturnType == CTypeInfo::Type::kFloat32 ||
543
+ kReturnType == CTypeInfo::Type::kFloat64,
544
+ "64-bit int and api object values are not currently "
545
+ "supported return types.");
546
+ }
547
+
548
+ private:
549
+ const CTypeInfo arg_info_storage_[sizeof...(ArgBuilders)];
550
+ };
551
+
552
+ template <typename T>
553
+ struct TypeInfoHelper {
554
+ static_assert(sizeof(T) != sizeof(T), "This type is not supported");
555
+ };
556
+
557
+ #define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR(T, Enum) \
558
+ template <> \
559
+ struct TypeInfoHelper<T> { \
560
+ static constexpr CTypeInfo::Flags Flags() { \
561
+ return CTypeInfo::Flags::kNone; \
562
+ } \
563
+ \
564
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \
565
+ static constexpr CTypeInfo::SequenceType SequenceType() { \
566
+ return CTypeInfo::SequenceType::kScalar; \
567
+ } \
568
+ };
569
+
570
+ template <CTypeInfo::Type type>
571
+ struct CTypeInfoTraits {};
572
+
573
+ #define DEFINE_TYPE_INFO_TRAITS(CType, Enum) \
574
+ template <> \
575
+ struct CTypeInfoTraits<CTypeInfo::Type::Enum> { \
576
+ using ctype = CType; \
577
+ };
578
+
579
+ #define PRIMITIVE_C_TYPES(V) \
580
+ V(bool, kBool) \
581
+ V(int32_t, kInt32) \
582
+ V(uint32_t, kUint32) \
583
+ V(int64_t, kInt64) \
584
+ V(uint64_t, kUint64) \
585
+ V(float, kFloat32) \
586
+ V(double, kFloat64)
587
+
588
+ // Same as above, but includes deprecated types for compatibility.
589
+ #define ALL_C_TYPES(V) \
590
+ PRIMITIVE_C_TYPES(V) \
591
+ V(void, kVoid) \
592
+ V(v8::Local<v8::Value>, kV8Value) \
593
+ V(v8::Local<v8::Object>, kV8Value) \
594
+ V(ApiObject, kApiObject)
595
+
596
+ // ApiObject was a temporary solution to wrap the pointer to the v8::Value.
597
+ // Please use v8::Local<v8::Value> in new code for the arguments and
598
+ // v8::Local<v8::Object> for the receiver, as ApiObject will be deprecated.
599
+
600
+ ALL_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR)
601
+ PRIMITIVE_C_TYPES(DEFINE_TYPE_INFO_TRAITS)
602
+
603
+ #undef PRIMITIVE_C_TYPES
604
+ #undef ALL_C_TYPES
605
+
606
+ #define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA(T, Enum) \
607
+ template <> \
608
+ struct TypeInfoHelper<const FastApiTypedArray<T>&> { \
609
+ static constexpr CTypeInfo::Flags Flags() { \
610
+ return CTypeInfo::Flags::kNone; \
611
+ } \
612
+ \
613
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \
614
+ static constexpr CTypeInfo::SequenceType SequenceType() { \
615
+ return CTypeInfo::SequenceType::kIsTypedArray; \
616
+ } \
617
+ };
618
+
619
+ #define TYPED_ARRAY_C_TYPES(V) \
620
+ V(int32_t, kInt32) \
621
+ V(uint32_t, kUint32) \
622
+ V(int64_t, kInt64) \
623
+ V(uint64_t, kUint64) \
624
+ V(float, kFloat32) \
625
+ V(double, kFloat64)
626
+
627
+ TYPED_ARRAY_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA)
628
+
629
+ #undef TYPED_ARRAY_C_TYPES
630
+
631
+ template <>
632
+ struct TypeInfoHelper<v8::Local<v8::Array>> {
633
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
634
+
635
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kVoid; }
636
+ static constexpr CTypeInfo::SequenceType SequenceType() {
637
+ return CTypeInfo::SequenceType::kIsSequence;
638
+ }
639
+ };
640
+
641
+ template <>
642
+ struct TypeInfoHelper<v8::Local<v8::Uint32Array>> {
643
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
644
+
645
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kUint32; }
646
+ static constexpr CTypeInfo::SequenceType SequenceType() {
647
+ return CTypeInfo::SequenceType::kIsTypedArray;
648
+ }
649
+ };
650
+
651
+ template <>
652
+ struct TypeInfoHelper<FastApiCallbackOptions&> {
653
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
654
+
655
+ static constexpr CTypeInfo::Type Type() {
656
+ return CTypeInfo::kCallbackOptionsType;
657
+ }
658
+ static constexpr CTypeInfo::SequenceType SequenceType() {
659
+ return CTypeInfo::SequenceType::kScalar;
660
+ }
661
+ };
662
+
663
+ #define STATIC_ASSERT_IMPLIES(COND, ASSERTION, MSG) \
664
+ static_assert(((COND) == 0) || (ASSERTION), MSG)
665
+
666
+ template <typename T, CTypeInfo::Flags... Flags>
667
+ class CTypeInfoBuilder {
668
+ public:
669
+ using BaseType = T;
670
+
671
+ static constexpr CTypeInfo Build() {
672
+ constexpr CTypeInfo::Flags kFlags =
673
+ MergeFlags(TypeInfoHelper<T>::Flags(), Flags...);
674
+ constexpr CTypeInfo::Type kType = TypeInfoHelper<T>::Type();
675
+ constexpr CTypeInfo::SequenceType kSequenceType =
676
+ TypeInfoHelper<T>::SequenceType();
677
+
678
+ STATIC_ASSERT_IMPLIES(
679
+ uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kAllowSharedBit),
680
+ (kSequenceType == CTypeInfo::SequenceType::kIsTypedArray ||
681
+ kSequenceType == CTypeInfo::SequenceType::kIsArrayBuffer),
682
+ "kAllowSharedBit is only allowed for TypedArrays and ArrayBuffers.");
683
+ STATIC_ASSERT_IMPLIES(
684
+ uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kEnforceRangeBit),
685
+ CTypeInfo::IsIntegralType(kType),
686
+ "kEnforceRangeBit is only allowed for integral types.");
687
+ STATIC_ASSERT_IMPLIES(
688
+ uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kClampBit),
689
+ CTypeInfo::IsIntegralType(kType),
690
+ "kClampBit is only allowed for integral types.");
691
+ STATIC_ASSERT_IMPLIES(
692
+ uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kIsRestrictedBit),
693
+ CTypeInfo::IsFloatingPointType(kType),
694
+ "kIsRestrictedBit is only allowed for floating point types.");
695
+ STATIC_ASSERT_IMPLIES(kSequenceType == CTypeInfo::SequenceType::kIsSequence,
696
+ kType == CTypeInfo::Type::kVoid,
697
+ "Sequences are only supported from void type.");
698
+ STATIC_ASSERT_IMPLIES(
699
+ kSequenceType == CTypeInfo::SequenceType::kIsTypedArray,
700
+ CTypeInfo::IsPrimitive(kType) || kType == CTypeInfo::Type::kVoid,
701
+ "TypedArrays are only supported from primitive types or void.");
702
+
703
+ // Return the same type with the merged flags.
704
+ return CTypeInfo(TypeInfoHelper<T>::Type(),
705
+ TypeInfoHelper<T>::SequenceType(), kFlags);
706
+ }
707
+
708
+ private:
709
+ template <typename... Rest>
710
+ static constexpr CTypeInfo::Flags MergeFlags(CTypeInfo::Flags flags,
711
+ Rest... rest) {
712
+ return CTypeInfo::Flags(uint8_t(flags) | uint8_t(MergeFlags(rest...)));
713
+ }
714
+ static constexpr CTypeInfo::Flags MergeFlags() { return CTypeInfo::Flags(0); }
715
+ };
716
+
717
+ template <typename RetBuilder, typename... ArgBuilders>
718
+ class CFunctionBuilderWithFunction {
719
+ public:
720
+ explicit constexpr CFunctionBuilderWithFunction(const void* fn) : fn_(fn) {}
721
+
722
+ template <CTypeInfo::Flags... Flags>
723
+ constexpr auto Ret() {
724
+ return CFunctionBuilderWithFunction<
725
+ CTypeInfoBuilder<typename RetBuilder::BaseType, Flags...>,
726
+ ArgBuilders...>(fn_);
727
+ }
728
+
729
+ template <unsigned int N, CTypeInfo::Flags... Flags>
730
+ constexpr auto Arg() {
731
+ // Return a copy of the builder with the Nth arg builder merged with
732
+ // template parameter pack Flags.
733
+ return ArgImpl<N, Flags...>(
734
+ std::make_index_sequence<sizeof...(ArgBuilders)>());
735
+ }
736
+
737
+ auto Build() {
738
+ static CFunctionInfoImpl<RetBuilder, ArgBuilders...> instance;
739
+ return CFunction(fn_, &instance);
740
+ }
741
+
742
+ private:
743
+ template <bool Merge, unsigned int N, CTypeInfo::Flags... Flags>
744
+ struct GetArgBuilder;
745
+
746
+ // Returns the same ArgBuilder as the one at index N, including its flags.
747
+ // Flags in the template parameter pack are ignored.
748
+ template <unsigned int N, CTypeInfo::Flags... Flags>
749
+ struct GetArgBuilder<false, N, Flags...> {
750
+ using type =
751
+ typename std::tuple_element<N, std::tuple<ArgBuilders...>>::type;
752
+ };
753
+
754
+ // Returns an ArgBuilder with the same base type as the one at index N,
755
+ // but merges the flags with the flags in the template parameter pack.
756
+ template <unsigned int N, CTypeInfo::Flags... Flags>
757
+ struct GetArgBuilder<true, N, Flags...> {
758
+ using type = CTypeInfoBuilder<
759
+ typename std::tuple_element<N,
760
+ std::tuple<ArgBuilders...>>::type::BaseType,
761
+ std::tuple_element<N, std::tuple<ArgBuilders...>>::type::Build()
762
+ .GetFlags(),
763
+ Flags...>;
764
+ };
765
+
766
+ // Return a copy of the CFunctionBuilder, but merges the Flags on
767
+ // ArgBuilder index N with the new Flags passed in the template parameter
768
+ // pack.
769
+ template <unsigned int N, CTypeInfo::Flags... Flags, size_t... I>
770
+ constexpr auto ArgImpl(std::index_sequence<I...>) {
771
+ return CFunctionBuilderWithFunction<
772
+ RetBuilder, typename GetArgBuilder<N == I, I, Flags...>::type...>(fn_);
773
+ }
774
+
775
+ const void* fn_;
776
+ };
777
+
778
+ class CFunctionBuilder {
779
+ public:
780
+ constexpr CFunctionBuilder() {}
781
+
782
+ template <typename R, typename... Args>
783
+ constexpr auto Fn(R (*fn)(Args...)) {
784
+ return CFunctionBuilderWithFunction<CTypeInfoBuilder<R>,
785
+ CTypeInfoBuilder<Args>...>(
786
+ reinterpret_cast<const void*>(fn));
787
+ }
788
+ };
789
+
790
+ } // namespace internal
791
+
792
+ // static
793
+ template <typename R, typename... Args>
794
+ CFunction CFunction::ArgUnwrap<R (*)(Args...)>::Make(R (*func)(Args...)) {
795
+ return internal::CFunctionBuilder().Fn(func).Build();
796
+ }
797
+
798
+ using CFunctionBuilder = internal::CFunctionBuilder;
799
+
800
+ static constexpr CTypeInfo kTypeInfoInt32 = CTypeInfo(CTypeInfo::Type::kInt32);
801
+ static constexpr CTypeInfo kTypeInfoFloat64 =
802
+ CTypeInfo(CTypeInfo::Type::kFloat64);
803
+
804
+ /**
805
+ * Copies the contents of this JavaScript array to a C++ buffer with
806
+ * a given max_length. A CTypeInfo is passed as an argument,
807
+ * instructing different rules for conversion (e.g. restricted float/double).
808
+ * The element type T of the destination array must match the C type
809
+ * corresponding to the CTypeInfo (specified by CTypeInfoTraits).
810
+ * If the array length is larger than max_length or the array is of
811
+ * unsupported type, the operation will fail, returning false. Generally, an
812
+ * array which contains objects, undefined, null or anything not convertible
813
+ * to the requested destination type, is considered unsupported. The operation
814
+ * returns true on success. `type_info` will be used for conversions.
815
+ */
816
+ template <const CTypeInfo* type_info, typename T>
817
+ bool V8_EXPORT V8_WARN_UNUSED_RESULT TryCopyAndConvertArrayToCppBuffer(
818
+ Local<Array> src, T* dst, uint32_t max_length);
819
+
820
+ template <>
821
+ inline bool V8_WARN_UNUSED_RESULT
822
+ TryCopyAndConvertArrayToCppBuffer<&kTypeInfoInt32, int32_t>(
823
+ Local<Array> src, int32_t* dst, uint32_t max_length) {
824
+ return CopyAndConvertArrayToCppBufferInt32(src, dst, max_length);
825
+ }
826
+
827
+ template <>
828
+ inline bool V8_WARN_UNUSED_RESULT
829
+ TryCopyAndConvertArrayToCppBuffer<&kTypeInfoFloat64, double>(
830
+ Local<Array> src, double* dst, uint32_t max_length) {
831
+ return CopyAndConvertArrayToCppBufferFloat64(src, dst, max_length);
832
+ }
833
+
386
834
  } // namespace v8
387
835
 
388
836
  #endif // INCLUDE_V8_FAST_API_CALLS_H_