libv8-node 16.10.0.0-arm64-darwin

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/ext/libv8-node/.location.yml +1 -0
  3. data/ext/libv8-node/location.rb +76 -0
  4. data/ext/libv8-node/paths.rb +34 -0
  5. data/lib/libv8/node/version.rb +7 -0
  6. data/lib/libv8/node.rb +11 -0
  7. data/lib/libv8-node.rb +1 -0
  8. data/vendor/v8/arm64-darwin/libv8/obj/libv8_monolith.a +0 -0
  9. data/vendor/v8/include/cppgc/allocation.h +232 -0
  10. data/vendor/v8/include/cppgc/common.h +29 -0
  11. data/vendor/v8/include/cppgc/cross-thread-persistent.h +384 -0
  12. data/vendor/v8/include/cppgc/custom-space.h +97 -0
  13. data/vendor/v8/include/cppgc/default-platform.h +75 -0
  14. data/vendor/v8/include/cppgc/ephemeron-pair.h +30 -0
  15. data/vendor/v8/include/cppgc/explicit-management.h +82 -0
  16. data/vendor/v8/include/cppgc/garbage-collected.h +117 -0
  17. data/vendor/v8/include/cppgc/heap-consistency.h +236 -0
  18. data/vendor/v8/include/cppgc/heap-state.h +70 -0
  19. data/vendor/v8/include/cppgc/heap-statistics.h +120 -0
  20. data/vendor/v8/include/cppgc/heap.h +201 -0
  21. data/vendor/v8/include/cppgc/internal/api-constants.h +47 -0
  22. data/vendor/v8/include/cppgc/internal/atomic-entry-flag.h +48 -0
  23. data/vendor/v8/include/cppgc/internal/caged-heap-local-data.h +68 -0
  24. data/vendor/v8/include/cppgc/internal/compiler-specific.h +38 -0
  25. data/vendor/v8/include/cppgc/internal/finalizer-trait.h +90 -0
  26. data/vendor/v8/include/cppgc/internal/gc-info.h +76 -0
  27. data/vendor/v8/include/cppgc/internal/logging.h +50 -0
  28. data/vendor/v8/include/cppgc/internal/name-trait.h +111 -0
  29. data/vendor/v8/include/cppgc/internal/persistent-node.h +172 -0
  30. data/vendor/v8/include/cppgc/internal/pointer-policies.h +175 -0
  31. data/vendor/v8/include/cppgc/internal/prefinalizer-handler.h +30 -0
  32. data/vendor/v8/include/cppgc/internal/write-barrier.h +396 -0
  33. data/vendor/v8/include/cppgc/liveness-broker.h +74 -0
  34. data/vendor/v8/include/cppgc/macros.h +26 -0
  35. data/vendor/v8/include/cppgc/member.h +286 -0
  36. data/vendor/v8/include/cppgc/name-provider.h +65 -0
  37. data/vendor/v8/include/cppgc/object-size-trait.h +58 -0
  38. data/vendor/v8/include/cppgc/persistent.h +365 -0
  39. data/vendor/v8/include/cppgc/platform.h +153 -0
  40. data/vendor/v8/include/cppgc/prefinalizer.h +52 -0
  41. data/vendor/v8/include/cppgc/process-heap-statistics.h +36 -0
  42. data/vendor/v8/include/cppgc/sentinel-pointer.h +32 -0
  43. data/vendor/v8/include/cppgc/source-location.h +92 -0
  44. data/vendor/v8/include/cppgc/testing.h +99 -0
  45. data/vendor/v8/include/cppgc/trace-trait.h +116 -0
  46. data/vendor/v8/include/cppgc/type-traits.h +247 -0
  47. data/vendor/v8/include/cppgc/visitor.h +377 -0
  48. data/vendor/v8/include/libplatform/libplatform-export.h +29 -0
  49. data/vendor/v8/include/libplatform/libplatform.h +117 -0
  50. data/vendor/v8/include/libplatform/v8-tracing.h +334 -0
  51. data/vendor/v8/include/v8-cppgc.h +325 -0
  52. data/vendor/v8/include/v8-fast-api-calls.h +791 -0
  53. data/vendor/v8/include/v8-inspector-protocol.h +13 -0
  54. data/vendor/v8/include/v8-inspector.h +348 -0
  55. data/vendor/v8/include/v8-internal.h +499 -0
  56. data/vendor/v8/include/v8-metrics.h +202 -0
  57. data/vendor/v8/include/v8-platform.h +709 -0
  58. data/vendor/v8/include/v8-profiler.h +1123 -0
  59. data/vendor/v8/include/v8-unwinder-state.h +30 -0
  60. data/vendor/v8/include/v8-util.h +652 -0
  61. data/vendor/v8/include/v8-value-serializer-version.h +24 -0
  62. data/vendor/v8/include/v8-version-string.h +38 -0
  63. data/vendor/v8/include/v8-version.h +20 -0
  64. data/vendor/v8/include/v8-wasm-trap-handler-posix.h +31 -0
  65. data/vendor/v8/include/v8-wasm-trap-handler-win.h +28 -0
  66. data/vendor/v8/include/v8.h +12648 -0
  67. data/vendor/v8/include/v8config.h +515 -0
  68. metadata +138 -0
@@ -0,0 +1,791 @@
1
+ // Copyright 2020 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
+ /**
6
+ * This file provides additional API on top of the default one for making
7
+ * API calls, which come from embedder C++ functions. The functions are being
8
+ * called directly from optimized code, doing all the necessary typechecks
9
+ * in the compiler itself, instead of on the embedder side. Hence the "fast"
10
+ * in the name. Example usage might look like:
11
+ *
12
+ * \code
13
+ * void FastMethod(int param, bool another_param);
14
+ *
15
+ * v8::FunctionTemplate::New(isolate, SlowCallback, data,
16
+ * signature, length, constructor_behavior
17
+ * side_effect_type,
18
+ * &v8::CFunction::Make(FastMethod));
19
+ * \endcode
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
+ *
53
+ * An example for custom embedder type support might employ a way to wrap/
54
+ * unwrap various C++ types in JSObject instances, e.g:
55
+ *
56
+ * \code
57
+ *
58
+ * // Helper method with a check for field count.
59
+ * template <typename T, int offset>
60
+ * inline T* GetInternalField(v8::Local<v8::Object> wrapper) {
61
+ * assert(offset < wrapper->InternalFieldCount());
62
+ * return reinterpret_cast<T*>(
63
+ * wrapper->GetAlignedPointerFromInternalField(offset));
64
+ * }
65
+ *
66
+ * class CustomEmbedderType {
67
+ * public:
68
+ * // Returns the raw C object from a wrapper JS object.
69
+ * static CustomEmbedderType* Unwrap(v8::Local<v8::Object> wrapper) {
70
+ * return GetInternalField<CustomEmbedderType,
71
+ * kV8EmbedderWrapperObjectIndex>(wrapper);
72
+ * }
73
+ * static void FastMethod(v8::Local<v8::Object> receiver_obj, int param) {
74
+ * CustomEmbedderType* receiver = static_cast<CustomEmbedderType*>(
75
+ * receiver_obj->GetAlignedPointerFromInternalField(
76
+ * kV8EmbedderWrapperObjectIndex));
77
+ *
78
+ * // Type checks are already done by the optimized code.
79
+ * // Then call some performance-critical method like:
80
+ * // receiver->Method(param);
81
+ * }
82
+ *
83
+ * static void SlowMethod(
84
+ * const v8::FunctionCallbackInfo<v8::Value>& info) {
85
+ * v8::Local<v8::Object> instance =
86
+ * v8::Local<v8::Object>::Cast(info.Holder());
87
+ * CustomEmbedderType* receiver = Unwrap(instance);
88
+ * // TODO: Do type checks and extract {param}.
89
+ * receiver->Method(param);
90
+ * }
91
+ * };
92
+ *
93
+ * // TODO(mslekova): Clean-up these constants
94
+ * // The constants kV8EmbedderWrapperTypeIndex and
95
+ * // kV8EmbedderWrapperObjectIndex describe the offsets for the type info
96
+ * // struct and the native object, when expressed as internal field indices
97
+ * // within a JSObject. The existance of this helper function assumes that
98
+ * // all embedder objects have their JSObject-side type info at the same
99
+ * // offset, but this is not a limitation of the API itself. For a detailed
100
+ * // use case, see the third example.
101
+ * static constexpr int kV8EmbedderWrapperTypeIndex = 0;
102
+ * static constexpr int kV8EmbedderWrapperObjectIndex = 1;
103
+ *
104
+ * // The following setup function can be templatized based on
105
+ * // the {embedder_object} argument.
106
+ * void SetupCustomEmbedderObject(v8::Isolate* isolate,
107
+ * v8::Local<v8::Context> context,
108
+ * CustomEmbedderType* embedder_object) {
109
+ * isolate->set_embedder_wrapper_type_index(
110
+ * kV8EmbedderWrapperTypeIndex);
111
+ * isolate->set_embedder_wrapper_object_index(
112
+ * kV8EmbedderWrapperObjectIndex);
113
+ *
114
+ * v8::CFunction c_func =
115
+ * MakeV8CFunction(CustomEmbedderType::FastMethod);
116
+ *
117
+ * Local<v8::FunctionTemplate> method_template =
118
+ * v8::FunctionTemplate::New(
119
+ * isolate, CustomEmbedderType::SlowMethod, v8::Local<v8::Value>(),
120
+ * v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kAllow,
121
+ * v8::SideEffectType::kHasSideEffect, &c_func);
122
+ *
123
+ * v8::Local<v8::ObjectTemplate> object_template =
124
+ * v8::ObjectTemplate::New(isolate);
125
+ * object_template->SetInternalFieldCount(
126
+ * kV8EmbedderWrapperObjectIndex + 1);
127
+ * object_template->Set(isolate, "method", method_template);
128
+ *
129
+ * // Instantiate the wrapper JS object.
130
+ * v8::Local<v8::Object> object =
131
+ * object_template->NewInstance(context).ToLocalChecked();
132
+ * object->SetAlignedPointerInInternalField(
133
+ * kV8EmbedderWrapperObjectIndex,
134
+ * reinterpret_cast<void*>(embedder_object));
135
+ *
136
+ * // TODO: Expose {object} where it's necessary.
137
+ * }
138
+ * \endcode
139
+ *
140
+ * For instance if {object} is exposed via a global "obj" variable,
141
+ * one could write in JS:
142
+ * function hot_func() {
143
+ * obj.method(42);
144
+ * }
145
+ * and once {hot_func} gets optimized, CustomEmbedderType::FastMethod
146
+ * will be called instead of the slow version, with the following arguments:
147
+ * receiver := the {embedder_object} from above
148
+ * param := 42
149
+ *
150
+ * Currently supported return types:
151
+ * - void
152
+ * - bool
153
+ * - int32_t
154
+ * - uint32_t
155
+ * - float32_t
156
+ * - float64_t
157
+ * Currently supported argument types:
158
+ * - pointer to an embedder type
159
+ * - JavaScript array of primitive types
160
+ * - bool
161
+ * - int32_t
162
+ * - uint32_t
163
+ * - int64_t
164
+ * - uint64_t
165
+ * - float32_t
166
+ * - float64_t
167
+ *
168
+ * The 64-bit integer types currently have the IDL (unsigned) long long
169
+ * semantics: https://heycam.github.io/webidl/#abstract-opdef-converttoint
170
+ * In the future we'll extend the API to also provide conversions from/to
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
+ *
179
+ * To be supported types:
180
+ * - TypedArrays and ArrayBuffers
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.
217
+ */
218
+
219
+ #ifndef INCLUDE_V8_FAST_API_CALLS_H_
220
+ #define INCLUDE_V8_FAST_API_CALLS_H_
221
+
222
+ #include <stddef.h>
223
+ #include <stdint.h>
224
+
225
+ #include <tuple>
226
+ #include <type_traits>
227
+
228
+ #include "v8.h" // NOLINT(build/include_directory)
229
+ #include "v8config.h" // NOLINT(build/include_directory)
230
+
231
+ namespace v8 {
232
+
233
+ class Isolate;
234
+
235
+ class CTypeInfo {
236
+ public:
237
+ enum class Type : uint8_t {
238
+ kVoid,
239
+ kBool,
240
+ kInt32,
241
+ kUint32,
242
+ kInt64,
243
+ kUint64,
244
+ kFloat32,
245
+ kFloat64,
246
+ kV8Value,
247
+ kApiObject, // This will be deprecated once all users have
248
+ // migrated from v8::ApiObject to v8::Local<v8::Value>.
249
+ };
250
+
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
262
+ };
263
+
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
+ };
271
+
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) {}
276
+
277
+ constexpr Type GetType() const { return type_; }
278
+ constexpr SequenceType GetSequenceType() const { return sequence_type_; }
279
+ constexpr Flags GetFlags() const { return flags_; }
280
+
281
+ static constexpr bool IsIntegralType(Type type) {
282
+ return type == Type::kInt32 || type == Type::kUint32 ||
283
+ type == Type::kInt64 || type == Type::kUint64;
284
+ }
285
+
286
+ static constexpr bool IsFloatingPointType(Type type) {
287
+ return type == Type::kFloat32 || type == Type::kFloat64;
288
+ }
289
+
290
+ static constexpr bool IsPrimitive(Type type) {
291
+ return IsIntegralType(type) || IsFloatingPointType(type) ||
292
+ type == Type::kBool;
293
+ }
294
+
295
+ private:
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
+ }
340
+
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;
346
+
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
+ }
352
+
353
+ private:
354
+ const CTypeInfo return_info_;
355
+ const unsigned int arg_count_;
356
+ const CTypeInfo* arg_info_;
357
+ };
358
+
359
+ class V8_EXPORT CFunction {
360
+ public:
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
+ };
438
+ };
439
+
440
+ struct ApiObject {
441
+ uintptr_t address;
442
+ };
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
+
482
+ namespace internal {
483
+
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.");
519
+ }
520
+
521
+ private:
522
+ const CTypeInfo arg_info_storage_[sizeof...(ArgBuilders)];
523
+ };
524
+
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
+ } \
541
+ };
542
+
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) \
553
+ V(bool, kBool) \
554
+ V(int32_t, kInt32) \
555
+ V(uint32_t, kUint32) \
556
+ V(int64_t, kInt64) \
557
+ V(uint64_t, kUint64) \
558
+ V(float, kFloat32) \
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
+ };
591
+
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)
599
+
600
+ TYPED_ARRAY_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR_TA)
601
+
602
+ #undef TYPED_ARRAY_C_TYPES
603
+
604
+ template <>
605
+ struct TypeInfoHelper<v8::Local<v8::Array>> {
606
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
607
+
608
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kVoid; }
609
+ static constexpr CTypeInfo::SequenceType SequenceType() {
610
+ return CTypeInfo::SequenceType::kIsSequence;
611
+ }
612
+ };
613
+
614
+ template <>
615
+ struct TypeInfoHelper<v8::Local<v8::Uint32Array>> {
616
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
617
+
618
+ static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::kUint32; }
619
+ static constexpr CTypeInfo::SequenceType SequenceType() {
620
+ return CTypeInfo::SequenceType::kIsTypedArray;
621
+ }
622
+ };
623
+
624
+ template <>
625
+ struct TypeInfoHelper<FastApiCallbackOptions&> {
626
+ static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
627
+
628
+ static constexpr CTypeInfo::Type Type() {
629
+ return CTypeInfo::kCallbackOptionsType;
630
+ }
631
+ static constexpr CTypeInfo::SequenceType SequenceType() {
632
+ return CTypeInfo::SequenceType::kScalar;
633
+ }
634
+ };
635
+
636
+ #define STATIC_ASSERT_IMPLIES(COND, ASSERTION, MSG) \
637
+ static_assert(((COND) == 0) || (ASSERTION), MSG)
638
+
639
+ template <typename T, CTypeInfo::Flags... Flags>
640
+ class CTypeInfoBuilder {
641
+ public:
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);
679
+ }
680
+
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
+ };
689
+
690
+ template <typename RetBuilder, typename... ArgBuilders>
691
+ class CFunctionBuilderWithFunction {
692
+ public:
693
+ explicit constexpr CFunctionBuilderWithFunction(const void* fn) : fn_(fn) {}
694
+
695
+ template <CTypeInfo::Flags... Flags>
696
+ constexpr auto Ret() {
697
+ return CFunctionBuilderWithFunction<
698
+ CTypeInfoBuilder<typename RetBuilder::BaseType, Flags...>,
699
+ ArgBuilders...>(fn_);
700
+ }
701
+
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)>());
708
+ }
709
+
710
+ auto Build() {
711
+ static CFunctionInfoImpl<RetBuilder, ArgBuilders...> instance;
712
+ return CFunction(fn_, &instance);
713
+ }
714
+
715
+ private:
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
+ };
726
+
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
+ };
738
+
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_);
746
+ }
747
+
748
+ const void* fn_;
749
+ };
750
+
751
+ class CFunctionBuilder {
752
+ public:
753
+ constexpr CFunctionBuilder() {}
754
+
755
+ template <typename R, typename... Args>
756
+ constexpr auto Fn(R (*fn)(Args...)) {
757
+ return CFunctionBuilderWithFunction<CTypeInfoBuilder<R>,
758
+ CTypeInfoBuilder<Args>...>(
759
+ reinterpret_cast<const void*>(fn));
760
+ }
761
+ };
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
+
789
+ } // namespace v8
790
+
791
+ #endif // INCLUDE_V8_FAST_API_CALLS_H_