libv8-node 15.14.0.1-x86_64-linux → 16.10.0.0-x86_64-linux

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 +1 -1
  4. data/lib/libv8/node/version.rb +3 -3
  5. data/vendor/v8/include/cppgc/allocation.h +104 -45
  6. data/vendor/v8/include/cppgc/common.h +9 -6
  7. data/vendor/v8/include/cppgc/cross-thread-persistent.h +384 -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 +236 -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 +57 -1
  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 +353 -35
  26. data/vendor/v8/include/cppgc/liveness-broker.h +7 -1
  27. data/vendor/v8/include/cppgc/macros.h +2 -0
  28. data/vendor/v8/include/cppgc/member.h +85 -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 +33 -9
  32. data/vendor/v8/include/cppgc/platform.h +48 -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 +187 -23
  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 +562 -159
  45. data/vendor/v8/include/v8-inspector.h +23 -2
  46. data/vendor/v8/include/v8-internal.h +99 -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 +1192 -642
  54. data/vendor/v8/include/v8config.h +40 -9
  55. data/vendor/v8/{out.gn → x86_64-linux}/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,19 @@
141
222
  #include <stddef.h>
142
223
  #include <stdint.h>
143
224
 
225
+ #include <tuple>
226
+ #include <type_traits>
227
+
228
+ #include "v8.h" // NOLINT(build/include_directory)
144
229
  #include "v8config.h" // NOLINT(build/include_directory)
145
230
 
146
231
  namespace v8 {
147
232
 
233
+ class Isolate;
234
+
148
235
  class CTypeInfo {
149
236
  public:
150
- enum class Type : char {
237
+ enum class Type : uint8_t {
151
238
  kVoid,
152
239
  kBool,
153
240
  kInt32,
@@ -157,232 +244,548 @@ class CTypeInfo {
157
244
  kFloat32,
158
245
  kFloat64,
159
246
  kV8Value,
247
+ kApiObject, // This will be deprecated once all users have
248
+ // migrated from v8::ApiObject to v8::Local<v8::Value>.
160
249
  };
161
250
 
162
- enum class ArgFlags : uint8_t {
163
- kNone = 0,
164
- kIsArrayBit = 1 << 0, // This argument is first in an array of values.
251
+ // kCallbackOptionsType is not part of the Type enum
252
+ // because it is only used internally. Use value 255 that is larger
253
+ // than any valid Type enum.
254
+ static constexpr Type kCallbackOptionsType = Type(255);
255
+
256
+ enum class SequenceType : uint8_t {
257
+ kScalar,
258
+ kIsSequence, // sequence<T>
259
+ kIsTypedArray, // TypedArray of T or any ArrayBufferView if T
260
+ // is void
261
+ kIsArrayBuffer // ArrayBuffer
165
262
  };
166
263
 
167
- static CTypeInfo FromWrapperType(ArgFlags flags = ArgFlags::kNone) {
168
- return CTypeInfo(static_cast<int>(flags) | kIsWrapperTypeBit);
169
- }
264
+ enum class Flags : uint8_t {
265
+ kNone = 0,
266
+ kAllowSharedBit = 1 << 0, // Must be an ArrayBuffer or TypedArray
267
+ kEnforceRangeBit = 1 << 1, // T must be integral
268
+ kClampBit = 1 << 2, // T must be integral
269
+ kIsRestrictedBit = 1 << 3, // T must be float or double
270
+ };
170
271
 
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
- }
272
+ explicit constexpr CTypeInfo(
273
+ Type type, SequenceType sequence_type = SequenceType::kScalar,
274
+ Flags flags = Flags::kNone)
275
+ : type_(type), sequence_type_(sequence_type), flags_(flags) {}
180
276
 
181
- const void* GetWrapperInfo() const;
277
+ constexpr Type GetType() const { return type_; }
278
+ constexpr SequenceType GetSequenceType() const { return sequence_type_; }
279
+ constexpr Flags GetFlags() const { return flags_; }
182
280
 
183
- constexpr Type GetType() const {
184
- if (payload_ & kIsWrapperTypeBit) {
185
- return Type::kV8Value;
186
- }
187
- return static_cast<Type>((payload_ & kTypeMask) >> kTypeOffset);
281
+ static constexpr bool IsIntegralType(Type type) {
282
+ return type == Type::kInt32 || type == Type::kUint32 ||
283
+ type == Type::kInt64 || type == Type::kUint64;
188
284
  }
189
285
 
190
- constexpr bool IsArray() const {
191
- return payload_ & static_cast<int>(ArgFlags::kIsArrayBit);
286
+ static constexpr bool IsFloatingPointType(Type type) {
287
+ return type == Type::kFloat32 || type == Type::kFloat64;
192
288
  }
193
289
 
194
- static const CTypeInfo& Invalid() {
195
- static CTypeInfo invalid = CTypeInfo(0);
196
- return invalid;
290
+ static constexpr bool IsPrimitive(Type type) {
291
+ return IsIntegralType(type) || IsFloatingPointType(type) ||
292
+ type == Type::kBool;
197
293
  }
198
294
 
199
295
  private:
200
- explicit constexpr CTypeInfo(uintptr_t payload) : payload_(payload) {}
296
+ Type type_;
297
+ SequenceType sequence_type_;
298
+ Flags flags_;
299
+ };
300
+
301
+ template <typename T>
302
+ struct FastApiTypedArray {
303
+ T* data; // should include the typed array offset applied
304
+ size_t length; // length in number of elements
305
+ };
306
+
307
+ // Any TypedArray. It uses kTypedArrayBit with base type void
308
+ // Overloaded args of ArrayBufferView and TypedArray are not supported
309
+ // (for now) because the generic “any” ArrayBufferView doesn’t have its
310
+ // own instance type. It could be supported if we specify that
311
+ // TypedArray<T> always has precedence over the generic ArrayBufferView,
312
+ // but this complicates overload resolution.
313
+ struct FastApiArrayBufferView {
314
+ void* data;
315
+ size_t byte_length;
316
+ };
317
+
318
+ struct FastApiArrayBuffer {
319
+ void* data;
320
+ size_t byte_length;
321
+ };
322
+
323
+ class V8_EXPORT CFunctionInfo {
324
+ public:
325
+ // Construct a struct to hold a CFunction's type information.
326
+ // |return_info| describes the function's return type.
327
+ // |arg_info| is an array of |arg_count| CTypeInfos describing the
328
+ // arguments. Only the last argument may be of the special type
329
+ // CTypeInfo::kCallbackOptionsType.
330
+ CFunctionInfo(const CTypeInfo& return_info, unsigned int arg_count,
331
+ const CTypeInfo* arg_info);
332
+
333
+ const CTypeInfo& ReturnInfo() const { return return_info_; }
334
+
335
+ // The argument count, not including the v8::FastApiCallbackOptions
336
+ // if present.
337
+ unsigned int ArgumentCount() const {
338
+ return HasOptions() ? arg_count_ - 1 : arg_count_;
339
+ }
201
340
 
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;
341
+ // |index| must be less than ArgumentCount().
342
+ // Note: if the last argument passed on construction of CFunctionInfo
343
+ // has type CTypeInfo::kCallbackOptionsType, it is not included in
344
+ // ArgumentCount().
345
+ const CTypeInfo& ArgumentInfo(unsigned int index) const;
206
346
 
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;
347
+ bool HasOptions() const {
348
+ // The options arg is always the last one.
349
+ return arg_count_ > 0 && arg_info_[arg_count_ - 1].GetType() ==
350
+ CTypeInfo::kCallbackOptionsType;
351
+ }
211
352
 
212
- const uintptr_t payload_;
353
+ private:
354
+ const CTypeInfo return_info_;
355
+ const unsigned int arg_count_;
356
+ const CTypeInfo* arg_info_;
213
357
  };
214
358
 
215
- class CFunctionInfo {
359
+ class V8_EXPORT CFunction {
216
360
  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;
361
+ constexpr CFunction() : address_(nullptr), type_info_(nullptr) {}
362
+
363
+ const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); }
364
+
365
+ const CTypeInfo& ArgumentInfo(unsigned int index) const {
366
+ return type_info_->ArgumentInfo(index);
367
+ }
368
+
369
+ unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); }
370
+
371
+ const void* GetAddress() const { return address_; }
372
+ const CFunctionInfo* GetTypeInfo() const { return type_info_; }
373
+
374
+ enum class OverloadResolution { kImpossible, kAtRuntime, kAtCompileTime };
375
+
376
+ // Returns whether an overload between this and the given CFunction can
377
+ // be resolved at runtime by the RTTI available for the arguments or at
378
+ // compile time for functions with different number of arguments.
379
+ OverloadResolution GetOverloadResolution(const CFunction* other) {
380
+ // Runtime overload resolution can only deal with functions with the
381
+ // same number of arguments. Functions with different arity are handled
382
+ // by compile time overload resolution though.
383
+ if (ArgumentCount() != other->ArgumentCount()) {
384
+ return OverloadResolution::kAtCompileTime;
385
+ }
386
+
387
+ // The functions can only differ by a single argument position.
388
+ int diff_index = -1;
389
+ for (unsigned int i = 0; i < ArgumentCount(); ++i) {
390
+ if (ArgumentInfo(i).GetSequenceType() !=
391
+ other->ArgumentInfo(i).GetSequenceType()) {
392
+ if (diff_index >= 0) {
393
+ return OverloadResolution::kImpossible;
394
+ }
395
+ diff_index = i;
396
+
397
+ // We only support overload resolution between sequence types.
398
+ if (ArgumentInfo(i).GetSequenceType() ==
399
+ CTypeInfo::SequenceType::kScalar ||
400
+ other->ArgumentInfo(i).GetSequenceType() ==
401
+ CTypeInfo::SequenceType::kScalar) {
402
+ return OverloadResolution::kImpossible;
403
+ }
404
+ }
405
+ }
406
+
407
+ return OverloadResolution::kAtRuntime;
408
+ }
409
+
410
+ template <typename F>
411
+ static CFunction Make(F* func) {
412
+ return ArgUnwrap<F*>::Make(func);
413
+ }
414
+
415
+ template <typename F>
416
+ V8_DEPRECATED("Use CFunctionBuilder instead.")
417
+ static CFunction MakeWithFallbackSupport(F* func) {
418
+ return ArgUnwrap<F*>::Make(func);
419
+ }
420
+
421
+ CFunction(const void* address, const CFunctionInfo* type_info);
422
+
423
+ private:
424
+ const void* address_;
425
+ const CFunctionInfo* type_info_;
426
+
427
+ template <typename F>
428
+ class ArgUnwrap {
429
+ static_assert(sizeof(F) != sizeof(F),
430
+ "CFunction must be created from a function pointer.");
431
+ };
432
+
433
+ template <typename R, typename... Args>
434
+ class ArgUnwrap<R (*)(Args...)> {
435
+ public:
436
+ static CFunction Make(R (*func)(Args...));
437
+ };
220
438
  };
221
439
 
222
440
  struct ApiObject {
223
441
  uintptr_t address;
224
442
  };
225
443
 
444
+ /**
445
+ * A struct which may be passed to a fast call callback, like so:
446
+ * \code
447
+ * void FastMethodWithOptions(int param, FastApiCallbackOptions& options);
448
+ * \endcode
449
+ */
450
+ struct FastApiCallbackOptions {
451
+ /**
452
+ * Creates a new instance of FastApiCallbackOptions for testing purpose. The
453
+ * returned instance may be filled with mock data.
454
+ */
455
+ static FastApiCallbackOptions CreateForTesting(Isolate* isolate) {
456
+ return {false, {0}};
457
+ }
458
+
459
+ /**
460
+ * If the callback wants to signal an error condition or to perform an
461
+ * allocation, it must set options.fallback to true and do an early return
462
+ * from the fast method. Then V8 checks the value of options.fallback and if
463
+ * it's true, falls back to executing the SlowCallback, which is capable of
464
+ * reporting the error (either by throwing a JS exception or logging to the
465
+ * console) or doing the allocation. It's the embedder's responsibility to
466
+ * ensure that the fast callback is idempotent up to the point where error and
467
+ * fallback conditions are checked, because otherwise executing the slow
468
+ * callback might produce visible side-effects twice.
469
+ */
470
+ bool fallback;
471
+
472
+ /**
473
+ * The `data` passed to the FunctionTemplate constructor, or `undefined`.
474
+ * `data_ptr` allows for default constructing FastApiCallbackOptions.
475
+ */
476
+ union {
477
+ uintptr_t data_ptr;
478
+ v8::Value data;
479
+ };
480
+ };
481
+
226
482
  namespace internal {
227
483
 
228
- template <typename T>
229
- struct GetCType {
230
- static constexpr CTypeInfo Get() {
231
- return CTypeInfo::FromCType(CTypeInfo::Type::kV8Value);
484
+ // Helper to count the number of occurances of `T` in `List`
485
+ template <typename T, typename... List>
486
+ struct count : std::integral_constant<int, 0> {};
487
+ template <typename T, typename... Args>
488
+ struct count<T, T, Args...>
489
+ : std::integral_constant<std::size_t, 1 + count<T, Args...>::value> {};
490
+ template <typename T, typename U, typename... Args>
491
+ struct count<T, U, Args...> : count<T, Args...> {};
492
+
493
+ template <typename RetBuilder, typename... ArgBuilders>
494
+ class CFunctionInfoImpl : public CFunctionInfo {
495
+ static constexpr int kOptionsArgCount =
496
+ count<FastApiCallbackOptions&, ArgBuilders...>();
497
+ static constexpr int kReceiverCount = 1;
498
+
499
+ static_assert(kOptionsArgCount == 0 || kOptionsArgCount == 1,
500
+ "Only one options parameter is supported.");
501
+
502
+ static_assert(sizeof...(ArgBuilders) >= kOptionsArgCount + kReceiverCount,
503
+ "The receiver or the options argument is missing.");
504
+
505
+ public:
506
+ constexpr CFunctionInfoImpl()
507
+ : CFunctionInfo(RetBuilder::Build(), sizeof...(ArgBuilders),
508
+ arg_info_storage_),
509
+ arg_info_storage_{ArgBuilders::Build()...} {
510
+ constexpr CTypeInfo::Type kReturnType = RetBuilder::Build().GetType();
511
+ static_assert(kReturnType == CTypeInfo::Type::kVoid ||
512
+ kReturnType == CTypeInfo::Type::kBool ||
513
+ kReturnType == CTypeInfo::Type::kInt32 ||
514
+ kReturnType == CTypeInfo::Type::kUint32 ||
515
+ kReturnType == CTypeInfo::Type::kFloat32 ||
516
+ kReturnType == CTypeInfo::Type::kFloat64,
517
+ "64-bit int and api object values are not currently "
518
+ "supported return types.");
232
519
  }
520
+
521
+ private:
522
+ const CTypeInfo arg_info_storage_[sizeof...(ArgBuilders)];
233
523
  };
234
524
 
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
- } \
525
+ template <typename T>
526
+ struct TypeInfoHelper {
527
+ static_assert(sizeof(T) != sizeof(T), "This type is not supported");
528
+ };
529
+
530
+ #define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR(T, Enum) \
531
+ template <> \
532
+ struct TypeInfoHelper<T> { \
533
+ static constexpr CTypeInfo::Flags Flags() { \
534
+ return CTypeInfo::Flags::kNone; \
535
+ } \
536
+ \
537
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \
538
+ static constexpr CTypeInfo::SequenceType SequenceType() { \
539
+ return CTypeInfo::SequenceType::kScalar; \
540
+ } \
241
541
  };
242
542
 
243
- #define SUPPORTED_C_TYPES(V) \
244
- V(void, kVoid) \
543
+ template <CTypeInfo::Type type>
544
+ struct CTypeInfoTraits {};
545
+
546
+ #define DEFINE_TYPE_INFO_TRAITS(CType, Enum) \
547
+ template <> \
548
+ struct CTypeInfoTraits<CTypeInfo::Type::Enum> { \
549
+ using ctype = CType; \
550
+ };
551
+
552
+ #define PRIMITIVE_C_TYPES(V) \
245
553
  V(bool, kBool) \
246
554
  V(int32_t, kInt32) \
247
555
  V(uint32_t, kUint32) \
248
556
  V(int64_t, kInt64) \
249
557
  V(uint64_t, kUint64) \
250
558
  V(float, kFloat32) \
251
- V(double, kFloat64) \
252
- V(ApiObject, kV8Value)
559
+ V(double, kFloat64)
560
+
561
+ // Same as above, but includes deprecated types for compatibility.
562
+ #define ALL_C_TYPES(V) \
563
+ PRIMITIVE_C_TYPES(V) \
564
+ V(void, kVoid) \
565
+ V(v8::Local<v8::Value>, kV8Value) \
566
+ V(v8::Local<v8::Object>, kV8Value) \
567
+ V(ApiObject, kApiObject)
568
+
569
+ // ApiObject was a temporary solution to wrap the pointer to the v8::Value.
570
+ // Please use v8::Local<v8::Value> in new code for the arguments and
571
+ // v8::Local<v8::Object> for the receiver, as ApiObject will be deprecated.
572
+
573
+ ALL_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR)
574
+ PRIMITIVE_C_TYPES(DEFINE_TYPE_INFO_TRAITS)
575
+
576
+ #undef PRIMITIVE_C_TYPES
577
+ #undef ALL_C_TYPES
578
+
579
+ #define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA(T, Enum) \
580
+ template <> \
581
+ struct TypeInfoHelper<FastApiTypedArray<T>> { \
582
+ static constexpr CTypeInfo::Flags Flags() { \
583
+ return CTypeInfo::Flags::kNone; \
584
+ } \
585
+ \
586
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \
587
+ static constexpr CTypeInfo::SequenceType SequenceType() { \
588
+ return CTypeInfo::SequenceType::kIsTypedArray; \
589
+ } \
590
+ };
253
591
 
254
- SUPPORTED_C_TYPES(SPECIALIZE_GET_C_TYPE_FOR)
592
+ #define TYPED_ARRAY_C_TYPES(V) \
593
+ V(int32_t, kInt32) \
594
+ V(uint32_t, kUint32) \
595
+ V(int64_t, kInt64) \
596
+ V(uint64_t, kUint64) \
597
+ V(float, kFloat32) \
598
+ V(double, kFloat64)
255
599
 
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);
262
- }
263
- };
600
+ TYPED_ARRAY_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA)
264
601
 
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(); }
269
- };
602
+ #undef TYPED_ARRAY_C_TYPES
270
603
 
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");
275
- };
604
+ template <>
605
+ struct TypeInfoHelper<v8::Local<v8::Array>> {
606
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
276
607
 
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);
608
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kVoid; }
609
+ static constexpr CTypeInfo::SequenceType SequenceType() {
610
+ return CTypeInfo::SequenceType::kIsSequence;
282
611
  }
283
612
  };
284
613
 
285
- template <typename T>
286
- struct GetCType<T**> : public GetCTypePointerPointerImpl<T> {};
287
-
288
- template <typename T>
289
- struct GetCType<T*> : public GetCTypePointerImpl<T> {};
614
+ template <>
615
+ struct TypeInfoHelper<v8::Local<v8::Uint32Array>> {
616
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
290
617
 
291
- template <typename R, bool RaisesException, typename... Args>
292
- class CFunctionInfoImpl : public CFunctionInfo {
293
- 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.");
618
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kUint32; }
619
+ static constexpr CTypeInfo::SequenceType SequenceType() {
620
+ return CTypeInfo::SequenceType::kIsTypedArray;
305
621
  }
622
+ };
306
623
 
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];
314
- }
624
+ template <>
625
+ struct TypeInfoHelper<FastApiCallbackOptions&> {
626
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
315
627
 
316
- private:
317
- const CTypeInfo return_info_;
318
- const unsigned int arg_count_;
319
- const CTypeInfo arg_info_[sizeof...(Args)];
628
+ static constexpr CTypeInfo::Type Type() {
629
+ return CTypeInfo::kCallbackOptionsType;
630
+ }
631
+ static constexpr CTypeInfo::SequenceType SequenceType() {
632
+ return CTypeInfo::SequenceType::kScalar;
633
+ }
320
634
  };
321
635
 
322
- } // namespace internal
636
+ #define STATIC_ASSERT_IMPLIES(COND, ASSERTION, MSG) \
637
+ static_assert(((COND) == 0) || (ASSERTION), MSG)
323
638
 
324
- class V8_EXPORT CFunction {
639
+ template <typename T, CTypeInfo::Flags... Flags>
640
+ class CTypeInfoBuilder {
325
641
  public:
326
- constexpr CFunction() : address_(nullptr), type_info_(nullptr) {}
327
-
328
- const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); }
329
-
330
- const CTypeInfo& ArgumentInfo(unsigned int index) const {
331
- return type_info_->ArgumentInfo(index);
642
+ using BaseType = T;
643
+
644
+ static constexpr CTypeInfo Build() {
645
+ constexpr CTypeInfo::Flags kFlags =
646
+ MergeFlags(TypeInfoHelper<T>::Flags(), Flags...);
647
+ constexpr CTypeInfo::Type kType = TypeInfoHelper<T>::Type();
648
+ constexpr CTypeInfo::SequenceType kSequenceType =
649
+ TypeInfoHelper<T>::SequenceType();
650
+
651
+ STATIC_ASSERT_IMPLIES(
652
+ uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kAllowSharedBit),
653
+ (kSequenceType == CTypeInfo::SequenceType::kIsTypedArray ||
654
+ kSequenceType == CTypeInfo::SequenceType::kIsArrayBuffer),
655
+ "kAllowSharedBit is only allowed for TypedArrays and ArrayBuffers.");
656
+ STATIC_ASSERT_IMPLIES(
657
+ uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kEnforceRangeBit),
658
+ CTypeInfo::IsIntegralType(kType),
659
+ "kEnforceRangeBit is only allowed for integral types.");
660
+ STATIC_ASSERT_IMPLIES(
661
+ uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kClampBit),
662
+ CTypeInfo::IsIntegralType(kType),
663
+ "kClampBit is only allowed for integral types.");
664
+ STATIC_ASSERT_IMPLIES(
665
+ uint8_t(kFlags) & uint8_t(CTypeInfo::Flags::kIsRestrictedBit),
666
+ CTypeInfo::IsFloatingPointType(kType),
667
+ "kIsRestrictedBit is only allowed for floating point types.");
668
+ STATIC_ASSERT_IMPLIES(kSequenceType == CTypeInfo::SequenceType::kIsSequence,
669
+ kType == CTypeInfo::Type::kVoid,
670
+ "Sequences are only supported from void type.");
671
+ STATIC_ASSERT_IMPLIES(
672
+ kSequenceType == CTypeInfo::SequenceType::kIsTypedArray,
673
+ CTypeInfo::IsPrimitive(kType) || kType == CTypeInfo::Type::kVoid,
674
+ "TypedArrays are only supported from primitive types or void.");
675
+
676
+ // Return the same type with the merged flags.
677
+ return CTypeInfo(TypeInfoHelper<T>::Type(),
678
+ TypeInfoHelper<T>::SequenceType(), kFlags);
332
679
  }
333
680
 
334
- unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); }
681
+ private:
682
+ template <typename... Rest>
683
+ static constexpr CTypeInfo::Flags MergeFlags(CTypeInfo::Flags flags,
684
+ Rest... rest) {
685
+ return CTypeInfo::Flags(uint8_t(flags) | uint8_t(MergeFlags(rest...)));
686
+ }
687
+ static constexpr CTypeInfo::Flags MergeFlags() { return CTypeInfo::Flags(0); }
688
+ };
335
689
 
336
- const void* GetAddress() const { return address_; }
337
- const CFunctionInfo* GetTypeInfo() const { return type_info_; }
690
+ template <typename RetBuilder, typename... ArgBuilders>
691
+ class CFunctionBuilderWithFunction {
692
+ public:
693
+ explicit constexpr CFunctionBuilderWithFunction(const void* fn) : fn_(fn) {}
338
694
 
339
- template <typename F>
340
- static CFunction Make(F* func) {
341
- return ArgUnwrap<F*>::Make(func);
695
+ template <CTypeInfo::Flags... Flags>
696
+ constexpr auto Ret() {
697
+ return CFunctionBuilderWithFunction<
698
+ CTypeInfoBuilder<typename RetBuilder::BaseType, Flags...>,
699
+ ArgBuilders...>(fn_);
342
700
  }
343
701
 
344
- template <typename F>
345
- static CFunction MakeWithErrorSupport(F* func) {
346
- return ArgUnwrap<F*>::MakeWithErrorSupport(func);
702
+ template <unsigned int N, CTypeInfo::Flags... Flags>
703
+ constexpr auto Arg() {
704
+ // Return a copy of the builder with the Nth arg builder merged with
705
+ // template parameter pack Flags.
706
+ return ArgImpl<N, Flags...>(
707
+ std::make_index_sequence<sizeof...(ArgBuilders)>());
347
708
  }
348
709
 
349
- template <typename F>
350
- static CFunction Make(F* func, const CFunctionInfo* type_info) {
351
- return CFunction(reinterpret_cast<const void*>(func), type_info);
710
+ auto Build() {
711
+ static CFunctionInfoImpl<RetBuilder, ArgBuilders...> instance;
712
+ return CFunction(fn_, &instance);
352
713
  }
353
714
 
354
715
  private:
355
- const void* address_;
356
- const CFunctionInfo* type_info_;
716
+ template <bool Merge, unsigned int N, CTypeInfo::Flags... Flags>
717
+ struct GetArgBuilder;
718
+
719
+ // Returns the same ArgBuilder as the one at index N, including its flags.
720
+ // Flags in the template parameter pack are ignored.
721
+ template <unsigned int N, CTypeInfo::Flags... Flags>
722
+ struct GetArgBuilder<false, N, Flags...> {
723
+ using type =
724
+ typename std::tuple_element<N, std::tuple<ArgBuilders...>>::type;
725
+ };
357
726
 
358
- CFunction(const void* address, const CFunctionInfo* type_info);
727
+ // Returns an ArgBuilder with the same base type as the one at index N,
728
+ // but merges the flags with the flags in the template parameter pack.
729
+ template <unsigned int N, CTypeInfo::Flags... Flags>
730
+ struct GetArgBuilder<true, N, Flags...> {
731
+ using type = CTypeInfoBuilder<
732
+ typename std::tuple_element<N,
733
+ std::tuple<ArgBuilders...>>::type::BaseType,
734
+ std::tuple_element<N, std::tuple<ArgBuilders...>>::type::Build()
735
+ .GetFlags(),
736
+ Flags...>;
737
+ };
359
738
 
360
- template <typename R, bool RaisesException, typename... Args>
361
- static CFunctionInfo* GetCFunctionInfo() {
362
- static internal::CFunctionInfoImpl<R, RaisesException, Args...> instance;
363
- return &instance;
739
+ // Return a copy of the CFunctionBuilder, but merges the Flags on
740
+ // ArgBuilder index N with the new Flags passed in the template parameter
741
+ // pack.
742
+ template <unsigned int N, CTypeInfo::Flags... Flags, size_t... I>
743
+ constexpr auto ArgImpl(std::index_sequence<I...>) {
744
+ return CFunctionBuilderWithFunction<
745
+ RetBuilder, typename GetArgBuilder<N == I, I, Flags...>::type...>(fn_);
364
746
  }
365
747
 
366
- template <typename F>
367
- class ArgUnwrap {
368
- static_assert(sizeof(F) != sizeof(F),
369
- "CFunction must be created from a function pointer.");
370
- };
748
+ const void* fn_;
749
+ };
750
+
751
+ class CFunctionBuilder {
752
+ public:
753
+ constexpr CFunctionBuilder() {}
371
754
 
372
755
  template <typename R, typename... Args>
373
- class ArgUnwrap<R (*)(Args...)> {
374
- 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
- }
383
- };
756
+ constexpr auto Fn(R (*fn)(Args...)) {
757
+ return CFunctionBuilderWithFunction<CTypeInfoBuilder<R>,
758
+ CTypeInfoBuilder<Args>...>(
759
+ reinterpret_cast<const void*>(fn));
760
+ }
384
761
  };
385
762
 
763
+ } // namespace internal
764
+
765
+ // static
766
+ template <typename R, typename... Args>
767
+ CFunction CFunction::ArgUnwrap<R (*)(Args...)>::Make(R (*func)(Args...)) {
768
+ return internal::CFunctionBuilder().Fn(func).Build();
769
+ }
770
+
771
+ using CFunctionBuilder = internal::CFunctionBuilder;
772
+
773
+ /**
774
+ * Copies the contents of this JavaScript array to a C++ buffer with
775
+ * a given max_length. A CTypeInfo is passed as an argument,
776
+ * instructing different rules for conversion (e.g. restricted float/double).
777
+ * The element type T of the destination array must match the C type
778
+ * corresponding to the CTypeInfo (specified by CTypeInfoTraits).
779
+ * If the array length is larger than max_length or the array is of
780
+ * unsupported type, the operation will fail, returning false. Generally, an
781
+ * array which contains objects, undefined, null or anything not convertible
782
+ * to the requested destination type, is considered unsupported. The operation
783
+ * returns true on success. `type_info` will be used for conversions.
784
+ */
785
+ template <const CTypeInfo* type_info, typename T>
786
+ bool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
787
+ uint32_t max_length);
788
+
386
789
  } // namespace v8
387
790
 
388
791
  #endif // INCLUDE_V8_FAST_API_CALLS_H_