Loading...
Searching...
No Matches
v8-function-callback.h
Go to the documentation of this file.
1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef INCLUDE_V8_FUNCTION_CALLBACK_H_
6#define INCLUDE_V8_FUNCTION_CALLBACK_H_
7
8#include <cstdint>
9#include <limits>
10
11#include "v8-internal.h" // NOLINT(build/include_directory)
12#include "v8-local-handle.h" // NOLINT(build/include_directory)
13#include "v8-primitive.h" // NOLINT(build/include_directory)
14#include "v8config.h" // NOLINT(build/include_directory)
15
16namespace v8 {
17
18template <typename T>
19class BasicTracedReference;
20template <typename T>
21class Global;
22class Object;
23class Value;
24
25namespace internal {
26class FunctionCallbackArguments;
27class PropertyCallbackArguments;
28class Builtins;
29} // namespace internal
30
31namespace debug {
32class ConsoleCallArguments;
33} // namespace debug
34
35namespace api_internal {
37 v8::Isolate* isolate, v8::Local<v8::Data> raw_target);
38} // namespace api_internal
39
40template <typename T>
42 public:
43 template <class S>
44 V8_INLINE ReturnValue(const ReturnValue<S>& that) : value_(that.value_) {
45 static_assert(std::is_base_of_v<T, S>, "type check");
46 }
47 // Handle-based setters.
48 template <typename S>
49 V8_INLINE void Set(const Global<S>& handle);
50 template <typename S>
51 V8_INLINE void SetNonEmpty(const Global<S>& handle);
52 template <typename S>
53 V8_INLINE void Set(const BasicTracedReference<S>& handle);
54 template <typename S>
56 template <typename S>
57 V8_INLINE void Set(const Local<S> handle);
58 template <typename S>
59 V8_INLINE void SetNonEmpty(const Local<S> handle);
60
61 // Fast primitive number setters.
62 V8_INLINE void Set(bool value);
63 V8_INLINE void Set(double i);
64 V8_INLINE void Set(int16_t i);
65 V8_INLINE void Set(int32_t i);
66 V8_INLINE void Set(int64_t i);
67 V8_INLINE void Set(uint16_t i);
68 V8_INLINE void Set(uint32_t i);
69 V8_INLINE void Set(uint64_t i);
70
71 // Fast JS primitive setters.
72 V8_INLINE void SetNull();
74 V8_INLINE void SetFalse();
76
77 // Convenience getter for the Isolate.
79
80 // Pointer setter: Uncompilable to prevent inadvertent misuse.
81 template <typename S>
82 V8_INLINE void Set(S* whatever);
83
84 // Getter. Creates a new Local<> so it comes with a certain performance
85 // hit. If the ReturnValue was not yet set, this will return the undefined
86 // value.
88
89 private:
90 template <class F>
91 friend class ReturnValue;
92 template <class F>
94 template <class F>
96 template <class F, class G, class H>
98 V8_INLINE void SetInternal(internal::Address value);
99 // Default value depends on <T>:
100 // - <void> -> true_value,
101 // - <v8::Boolean> -> true_value,
102 // - <v8::Integer> -> 0,
103 // - <v8::Value> -> undefined_value,
104 // - <v8::Array> -> undefined_value.
105 V8_INLINE void SetDefaultValue();
107
108 // See FunctionCallbackInfo.
109 static constexpr int kIsolateValueIndex = -1;
110
111 internal::Address* value_;
112};
113
120template <typename T>
122 public:
124 V8_INLINE int Length() const;
129 V8_INLINE Local<Value> operator[](int i) const;
135 V8_INLINE bool IsConstructCall() const;
142
143 private:
148 using I = internal::Internals;
149
150 // Frame block, matches the layout of ApiCallbackExitFrame.
151 // See ApiCallbackExitFrameConstants.
152 enum {
153 //
154 // Optional frame arguments block (exists only for API_CONSTRUCT_EXIT
155 // frame).
156
157 // Frame arguments block.
158 kNewTargetIndex = -1,
159
160 //
161 // Mandatory part, exists for both API_CALLBACK_EXIT and API_CONSTRUCT_EXIT
162 // frames.
163 //
164
165 // Frame arguments block.
166 kArgcIndex,
167
168 // Regular ExitFrame structure.
169 kFrameSPIndex,
170 kFrameTypeIndex,
171 kFrameConstantPoolIndex, // Optional, see I::kFrameCPSlotCount.
172 kFrameFPIndex = kFrameConstantPoolIndex + I::kFrameCPSlotCount,
173 kFramePCIndex,
174
175 // Api arguments block, starts at kFirstArgumentIndex.
176 kFirstApiArgumentIndex,
177 kIsolateIndex = kFirstApiArgumentIndex,
178 kReturnValueIndex,
179 kContextIndex,
180 kTargetIndex,
181
182 // JS args block, starts at kFrameFirstImplicitArgsIndex.
183 kReceiverIndex,
184 kFirstJSArgumentIndex,
185
186 // Mandatory part includes receiver.
187 kArgsLength = kReceiverIndex + 1,
188 // Optional part size (exists only for API_CONSTRUCT_EXIT frame).
189 kOptionalArgsLength = 1,
190
191 // The length of just Api arguments part.
192 kApiArgsLength = kReceiverIndex - kFirstApiArgumentIndex,
193 };
194
195 static_assert(kArgcIndex == 0);
197 kIsolateIndex - kReturnValueIndex);
198
199 internal::Address* address_of_first_argument() const {
200 return &values_[kFirstJSArgumentIndex];
201 }
202
203 V8_INLINE FunctionCallbackInfo() = default;
204
205 // FunctionCallbackInfo object provides a view of the stack area where the
206 // data is stored and thus it's not supposed to be copyable/movable.
207 FunctionCallbackInfo(const FunctionCallbackInfo&) = delete;
208 FunctionCallbackInfo& operator=(const FunctionCallbackInfo&) = delete;
209 FunctionCallbackInfo(FunctionCallbackInfo&&) = delete;
210 FunctionCallbackInfo& operator=(FunctionCallbackInfo&&) = delete;
211
212 // Declare as mutable to let GC modify the contents of the slots even though
213 // it's not possible to change values via this class.
214 // Define the array size as 1 to make it clear that we are going to access
215 // it out-of-bounds from both sides anyway.
216 mutable internal::Address values_[1];
217};
218
223template <typename T>
225 public:
230
237
246
256
272
273 private:
274 template <typename U>
276 friend class MacroAssembler;
280 using I = internal::Internals;
281
282 // ShouldThrowOnError() can return true only for setter/definer/deleter
283 // callbacks which match [[Set]]/[[DefineOwnProperty]]/[[Delete]]
284 // operations. We detect these operations by return value type - they
285 // all return boolean value, even though setter/deleter callbacks are
286 // still using v8::PropertyCallbackInfo<void>.
287 // TODO(https://crbug.com/348660658): cleanup this, once the callbacks are
288 // migrated to a new return type.
289 static constexpr bool HasShouldThrowOnError() {
290 return std::is_same_v<T, v8::Boolean> || std::is_same_v<T, void>;
291 }
292
293 // Indicates whether this is a named accessor/interceptor callback call
294 // or an indexed one.
295 V8_INLINE bool IsNamed() const;
296
297 // Frame block, matches the layout of ApiAccessorExitFrame.
298 // See ApiAccessorExitFrameConstants.
299 enum {
300 // Frame arguments block.
301 kPropertyKeyIndex,
302
303 // Regular ExitFrame structure.
304 kFrameSPIndex,
305 kFrameTypeIndex,
306 kFrameConstantPoolIndex, // Optional, see I::kFrameCPSlotCount.
307 kFrameFPIndex = kFrameConstantPoolIndex + I::kFrameCPSlotCount,
308 kFramePCIndex,
309
310 // Other arguments block, starts at kFirstArgumentIndex.
311 kFirstApiArgumentIndex,
312 kIsolateIndex = kFirstApiArgumentIndex,
313 kReturnValueIndex,
314 kCallbackInfoIndex,
315 kHolderIndex,
316
317 //
318 // Optional part, used only by setter/definer/deleter callbacks.
319 //
320 kFirstOptionalArgument,
321 kShouldThrowOnErrorIndex = kFirstOptionalArgument,
322
323 // Used as value handle storage when called via CallApiSetter builtin.
324 kValueIndex,
325
326 kFullArgsLength,
327 kMandatoryArgsLength = kFirstOptionalArgument,
328 kOptionalArgsLength = kFullArgsLength - kFirstOptionalArgument,
329
330 // Various lengths of just Api arguments part.
331 kMandatoryApiArgsLength = kMandatoryArgsLength - kFirstApiArgumentIndex,
332 kFullApiArgsLength = kFullArgsLength - kFirstApiArgumentIndex,
333 };
334
335 // PropertyCallbackInfo object provides a view of the stack area where the
336 // data is stored and thus it's not supposed to be copyable/movable.
338 PropertyCallbackInfo& operator=(const PropertyCallbackInfo&) = delete;
340 PropertyCallbackInfo& operator=(PropertyCallbackInfo&&) = delete;
341
342 PropertyCallbackInfo() = default;
343
344 // Declare as mutable to let GC modify the contents of the slots even though
345 // it's not possible to change values via this class.
346 // Define the array size as 1 to make it clear that we are going to access
347 // it out-of-bounds anyway.
348 mutable internal::Address args_[1];
349};
350
351using FunctionCallback = void (*)(const FunctionCallbackInfo<Value>& info);
352
353// --- Implementation ---
354
355template <typename T>
356ReturnValue<T>::ReturnValue(internal::Address* slot) : value_(slot) {}
357
358template <typename T>
359void ReturnValue<T>::SetInternal(internal::Address value) {
360#if V8_STATIC_ROOTS_BOOL
361 using I = internal::Internals;
362 // Ensure that the upper 32-bits are not modified. Compiler should be
363 // able to optimize this to a store of a lower 32-bits of the value.
364 // This is fine since the callback can return only JavaScript values which
365 // are either Smis or heap objects allocated in the main cage.
366 *value_ = I::DecompressTaggedField(*value_, I::CompressTagged(value));
367#else
368 *value_ = value;
369#endif // V8_STATIC_ROOTS_BOOL
370}
371
372template <typename T>
373template <typename S>
374void ReturnValue<T>::Set(const Global<S>& handle) {
375 static_assert(std::is_base_of_v<T, S>, "type check");
376 if (V8_UNLIKELY(handle.IsEmpty())) {
377 SetDefaultValue();
378 } else {
379 SetInternal(handle.ptr());
380 }
381}
382
383template <typename T>
384template <typename S>
386 static_assert(std::is_base_of_v<T, S>, "type check");
387#ifdef V8_ENABLE_CHECKS
388 internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
389#endif // V8_ENABLE_CHECKS
390 SetInternal(handle.ptr());
391}
392
393template <typename T>
394template <typename S>
396 static_assert(std::is_base_of_v<T, S>, "type check");
397 if (V8_UNLIKELY(handle.IsEmpty())) {
398 SetDefaultValue();
399 } else {
400 SetInternal(handle.ptr());
401 }
402}
403
404template <typename T>
405template <typename S>
407 static_assert(std::is_base_of_v<T, S>, "type check");
408#ifdef V8_ENABLE_CHECKS
409 internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
410#endif // V8_ENABLE_CHECKS
411 SetInternal(handle.ptr());
412}
413
414template <typename T>
415template <typename S>
416void ReturnValue<T>::Set(const Local<S> handle) {
417 static_assert(std::is_base_of_v<T, S>, "type check");
418 if (V8_UNLIKELY(handle.IsEmpty())) {
419 SetDefaultValue();
420 } else {
421 SetInternal(handle.ptr());
422 }
423}
424
425template <typename T>
426template <typename S>
428 static_assert(std::is_base_of_v<T, S>, "type check");
429#ifdef V8_ENABLE_CHECKS
430 internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
431#endif // V8_ENABLE_CHECKS
432 SetInternal(handle.ptr());
433}
434
435template <typename T>
436void ReturnValue<T>::Set(double i) {
437 static_assert(std::is_base_of_v<T, Number>, "type check");
438 SetNonEmpty(Number::New(GetIsolate(), i));
439}
440
441template <typename T>
442void ReturnValue<T>::Set(int16_t i) {
443 static_assert(std::is_base_of_v<T, Integer>, "type check");
444 using I = internal::Internals;
445 static_assert(I::IsValidSmi(std::numeric_limits<int16_t>::min()));
446 static_assert(I::IsValidSmi(std::numeric_limits<int16_t>::max()));
447 SetInternal(I::IntegralToSmi(i));
448}
449
450template <typename T>
451void ReturnValue<T>::Set(int32_t i) {
452 static_assert(std::is_base_of_v<T, Integer>, "type check");
453 if (const auto result = internal::Internals::TryIntegralToSmi(i)) {
454 SetInternal(*result);
455 return;
456 }
457 SetNonEmpty(Integer::New(GetIsolate(), i));
458}
459
460template <typename T>
461void ReturnValue<T>::Set(int64_t i) {
462 static_assert(std::is_base_of_v<T, Integer>, "type check");
463 if (const auto result = internal::Internals::TryIntegralToSmi(i)) {
464 SetInternal(*result);
465 return;
466 }
467 SetNonEmpty(Number::New(GetIsolate(), static_cast<double>(i)));
468}
469
470template <typename T>
471void ReturnValue<T>::Set(uint16_t i) {
472 static_assert(std::is_base_of_v<T, Integer>, "type check");
473 using I = internal::Internals;
474 static_assert(I::IsValidSmi(std::numeric_limits<uint16_t>::min()));
475 static_assert(I::IsValidSmi(std::numeric_limits<uint16_t>::max()));
476 SetInternal(I::IntegralToSmi(i));
477}
478
479template <typename T>
480void ReturnValue<T>::Set(uint32_t i) {
481 static_assert(std::is_base_of_v<T, Integer>, "type check");
482 if (const auto result = internal::Internals::TryIntegralToSmi(i)) {
483 SetInternal(*result);
484 return;
485 }
486 SetNonEmpty(Integer::NewFromUnsigned(GetIsolate(), i));
487}
488
489template <typename T>
490void ReturnValue<T>::Set(uint64_t i) {
491 static_assert(std::is_base_of_v<T, Integer>, "type check");
492 if (const auto result = internal::Internals::TryIntegralToSmi(i)) {
493 SetInternal(*result);
494 return;
495 }
496 SetNonEmpty(Number::New(GetIsolate(), static_cast<double>(i)));
497}
498
499template <typename T>
500void ReturnValue<T>::Set(bool value) {
501 static_assert(std::is_void_v<T> || std::is_base_of_v<T, Boolean>,
502 "type check");
503 using I = internal::Internals;
504#if V8_STATIC_ROOTS_BOOL
505#ifdef V8_ENABLE_CHECKS
506 internal::PerformCastCheck(
507 internal::ValueHelper::SlotAsValue<Value, true>(value_));
508#endif // V8_ENABLE_CHECKS
509 SetInternal(value ? I::StaticReadOnlyRoot::kTrueValue
510 : I::StaticReadOnlyRoot::kFalseValue);
511#else
512 int root_index;
513 if (value) {
514 root_index = I::kTrueValueRootIndex;
515 } else {
516 root_index = I::kFalseValueRootIndex;
517 }
518 *value_ = I::GetRoot(GetIsolate(), root_index);
519#endif // V8_STATIC_ROOTS_BOOL
520}
521
522template <typename T>
524 using I = internal::Internals;
525 if constexpr (std::is_same_v<void, T> || std::is_same_v<v8::Boolean, T>) {
526 Set(true);
527 } else if constexpr (std::is_same_v<v8::Integer, T>) {
528 SetInternal(I::IntegralToSmi(0));
529 } else {
530 static_assert(std::is_same_v<v8::Value, T> || std::is_same_v<v8::Array, T>);
531#if V8_STATIC_ROOTS_BOOL
532 SetInternal(I::StaticReadOnlyRoot::kUndefinedValue);
533#else
534 *value_ = I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex);
535#endif // V8_STATIC_ROOTS_BOOL
536 }
537}
538
539template <typename T>
541 static_assert(std::is_base_of_v<T, Primitive>, "type check");
542 using I = internal::Internals;
543#if V8_STATIC_ROOTS_BOOL
544#ifdef V8_ENABLE_CHECKS
545 internal::PerformCastCheck(
546 internal::ValueHelper::SlotAsValue<Value, true>(value_));
547#endif // V8_ENABLE_CHECKS
548 SetInternal(I::StaticReadOnlyRoot::kNullValue);
549#else
550 *value_ = I::GetRoot(GetIsolate(), I::kNullValueRootIndex);
551#endif // V8_STATIC_ROOTS_BOOL
552}
553
554template <typename T>
556 static_assert(std::is_base_of_v<T, Primitive>, "type check");
557 using I = internal::Internals;
558#if V8_STATIC_ROOTS_BOOL
559#ifdef V8_ENABLE_CHECKS
560 internal::PerformCastCheck(
561 internal::ValueHelper::SlotAsValue<Value, true>(value_));
562#endif // V8_ENABLE_CHECKS
563 SetInternal(I::StaticReadOnlyRoot::kUndefinedValue);
564#else
565 *value_ = I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex);
566#endif // V8_STATIC_ROOTS_BOOL
567}
568
569template <typename T>
571 static_assert(std::is_void_v<T> || std::is_base_of_v<T, Boolean>,
572 "type check");
573 using I = internal::Internals;
574#if V8_STATIC_ROOTS_BOOL
575#ifdef V8_ENABLE_CHECKS
576 internal::PerformCastCheck(
577 internal::ValueHelper::SlotAsValue<Value, true>(value_));
578#endif // V8_ENABLE_CHECKS
579 SetInternal(I::StaticReadOnlyRoot::kFalseValue);
580#else
581 *value_ = I::GetRoot(GetIsolate(), I::kFalseValueRootIndex);
582#endif // V8_STATIC_ROOTS_BOOL
583}
584
585template <typename T>
587 static_assert(std::is_base_of_v<T, String>, "type check");
588 using I = internal::Internals;
589#if V8_STATIC_ROOTS_BOOL
590#ifdef V8_ENABLE_CHECKS
591 internal::PerformCastCheck(
592 internal::ValueHelper::SlotAsValue<Value, true>(value_));
593#endif // V8_ENABLE_CHECKS
594 SetInternal(I::StaticReadOnlyRoot::kEmptyString);
595#else
596 *value_ = I::GetRoot(GetIsolate(), I::kEmptyStringRootIndex);
597#endif // V8_STATIC_ROOTS_BOOL
598}
599
600template <typename T>
602 return *reinterpret_cast<Isolate**>(&value_[kIsolateValueIndex]);
603}
604
605template <typename T>
607 return Local<Value>::New(GetIsolate(),
608 internal::ValueHelper::SlotAsValue<Value>(value_));
609}
610
611template <typename T>
612template <typename S>
613void ReturnValue<T>::Set(S* whatever) {
614 static_assert(sizeof(S) < 0, "incompilable to prevent inadvertent misuse");
615}
616
617template <typename T>
619 if (i < 0 || Length() <= i) return Undefined(GetIsolate());
620 return Local<Value>::FromSlot(&values_[kFirstJSArgumentIndex + i]);
621}
622
623template <typename T>
625 return Local<Object>::FromSlot(&values_[kReceiverIndex]);
626}
627
628template <typename T>
630 if (IsConstructCall()) {
631 // Can't use &values_[kNewTargetIndex] because of "array index -1 is
632 // before the beginning of the array" error.
633 internal::Address* values = &values_[0];
634 return Local<Value>::FromSlot(values + kNewTargetIndex);
635 }
636 return Undefined(GetIsolate());
637}
638
639template <typename T>
641 auto target = Local<v8::Data>::FromSlot(&values_[kTargetIndex]);
642 return api_internal::GetFunctionTemplateData(GetIsolate(), target);
643}
644
645template <typename T>
647 return reinterpret_cast<Isolate*>(values_[kIsolateIndex]);
648}
649
650template <typename T>
652 return ReturnValue<T>(&values_[kReturnValueIndex]);
653}
654
655template <typename T>
657 return I::SmiValue(values_[kFrameTypeIndex]) == I::kFrameTypeApiConstructExit;
658}
659
660template <typename T>
662 return static_cast<int>(values_[kArgcIndex]);
663}
664
665template <typename T>
667 return I::SmiValue(args_[kFrameTypeIndex]) ==
668 I::kFrameTypeApiNamedAccessorExit;
669}
670
671template <typename T>
673 return *reinterpret_cast<Isolate**>(&args_[kIsolateIndex]);
674}
675
676template <typename T>
678 internal::Address callback_info = args_[kCallbackInfoIndex];
679 internal::Address data =
680 I::ReadTaggedPointerField(callback_info, I::kCallbackInfoDataOffset);
681 return Local<Value>::New(GetIsolate(), data);
682}
683
684template <typename T>
686 return Local<Object>::FromSlot(&args_[kHolderIndex]);
687}
688
689template <typename T>
691 return ReturnValue<T>(&args_[kReturnValueIndex]);
692}
693
694template <typename T>
696 if constexpr (!HasShouldThrowOnError()) return false;
697 if (args_[kShouldThrowOnErrorIndex] !=
698 I::IntegralToSmi(I::kInferShouldThrowMode)) {
699 return args_[kShouldThrowOnErrorIndex] != I::IntegralToSmi(I::kDontThrow);
700 }
702 reinterpret_cast<v8::internal::Isolate*>(GetIsolate()));
703}
704
705} // namespace v8
706
707#endif // INCLUDE_V8_FUNCTION_CALLBACK_H_
Definition: v8-traced-handle.h:124
Definition: v8-function-callback.h:121
ReturnValue< T > GetReturnValue() const
Definition: v8-function-callback.h:651
Local< Object > This() const
Definition: v8-function-callback.h:624
Local< Value > operator[](int i) const
Definition: v8-function-callback.h:618
Isolate * GetIsolate() const
Definition: v8-function-callback.h:646
Local< Value > NewTarget() const
Definition: v8-function-callback.h:629
friend class debug::ConsoleCallArguments
Definition: v8-function-callback.h:146
friend class internal::FunctionCallbackArguments
Definition: v8-function-callback.h:144
Local< Value > Data() const
Definition: v8-function-callback.h:640
bool IsConstructCall() const
Definition: v8-function-callback.h:656
int Length() const
Definition: v8-function-callback.h:661
Definition: v8-persistent-handle.h:353
Definition: v8-isolate.h:292
Definition: v8-local-handle.h:366
Definition: v8-util.h:166
Definition: v8-function-callback.h:224
Local< Value > Data() const
Definition: v8-function-callback.h:677
friend class internal::PropertyCallbackArguments
Definition: v8-function-callback.h:277
friend class PropertyCallbackInfo
Definition: v8-function-callback.h:275
Local< Object > Holder() const
Definition: v8-function-callback.h:685
bool ShouldThrowOnError() const
Definition: v8-function-callback.h:695
ReturnValue< T > GetReturnValue() const
Definition: v8-function-callback.h:690
friend class MacroAssembler
Definition: v8-function-callback.h:276
Isolate * GetIsolate() const
Definition: v8-function-callback.h:672
Definition: v8-function-callback.h:41
void SetFalse()
Definition: v8-function-callback.h:570
void SetEmptyString()
Definition: v8-function-callback.h:586
friend class ReturnValue
Definition: v8-function-callback.h:91
ReturnValue(const ReturnValue< S > &that)
Definition: v8-function-callback.h:44
void SetNonEmpty(const Global< S > &handle)
Definition: v8-function-callback.h:385
Local< Value > Get() const
Definition: v8-function-callback.h:606
void SetNull()
Definition: v8-function-callback.h:540
Isolate * GetIsolate() const
Definition: v8-function-callback.h:601
void SetUndefined()
Definition: v8-function-callback.h:555
Definition: v8-container.h:148
internal::Address ptr() const
Definition: v8-handle-base.h:80
bool IsEmpty() const
Definition: v8-handle-base.h:60
Definition: v8-local-handle.h:75
Definition: v8-internal.h:975
static constexpr int kFrameCPSlotCount
Definition: v8-internal.h:1119
v8::Local< v8::Value > GetFunctionTemplateData(v8::Isolate *isolate, v8::Local< v8::Data > raw_target)
void PrintPropertyCallbackInfo(void *property_callback_info)
bool ShouldThrowOnError(internal::Isolate *isolate)
uintptr_t Address
Definition: v8-internal.h:38
void PrintFunctionCallbackInfo(void *function_callback_info)
Definition: libplatform.h:15
Local< Primitive > Undefined(Isolate *isolate)
Definition: v8-primitive.h:1057
void(*)(const FunctionCallbackInfo< Value > &info) FunctionCallback
Definition: v8-function-callback.h:351
#define V8_EXPORT
Definition: v8config.h:867
#define V8_INLINE
Definition: v8config.h:511
#define V8_UNLIKELY(condition)
Definition: v8config.h:670