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-local-handle.h" // NOLINT(build/include_directory)
12#include "v8-primitive.h" // NOLINT(build/include_directory)
13#include "v8config.h" // NOLINT(build/include_directory)
14
15namespace v8 {
16
17template <typename T>
18class BasicTracedReference;
19template <typename T>
20class Global;
21class Object;
22class Value;
23
24namespace internal {
25class FunctionCallbackArguments;
26class PropertyCallbackArguments;
27class Builtins;
28} // namespace internal
29
30namespace debug {
31class ConsoleCallArguments;
32} // namespace debug
33
34template <typename T>
36 public:
37 template <class S>
38 V8_INLINE ReturnValue(const ReturnValue<S>& that) : value_(that.value_) {
39 static_assert(std::is_base_of<T, S>::value, "type check");
40 }
41 // Local setters
42 template <typename S>
43 V8_INLINE void Set(const Global<S>& handle);
44 template <typename S>
45 V8_INLINE void SetNonEmpty(const Global<S>& handle);
46 template <typename S>
47 V8_INLINE void Set(const BasicTracedReference<S>& handle);
48 template <typename S>
50 template <typename S>
51 V8_INLINE void Set(const Local<S> handle);
52 template <typename S>
53 V8_INLINE void SetNonEmpty(const Local<S> handle);
54 // Fast primitive setters
55 V8_INLINE void Set(bool value);
56 V8_INLINE void Set(double i);
57 V8_INLINE void Set(int32_t i);
58 V8_INLINE void Set(uint32_t i);
59 V8_INLINE void Set(uint16_t);
60 // Fast JS primitive setters
61 V8_INLINE void SetNull();
64 // Convenience getter for Isolate
66
67 // Pointer setter: Uncompilable to prevent inadvertent misuse.
68 template <typename S>
69 V8_INLINE void Set(S* whatever);
70
71 // Getter. Creates a new Local<> so it comes with a certain performance
72 // hit. If the ReturnValue was not yet set, this will return the undefined
73 // value.
75
76 private:
77 template <class F>
78 friend class ReturnValue;
79 template <class F>
81 template <class F>
83 template <class F, class G, class H>
85 V8_INLINE void SetInternal(internal::Address value);
86 // Setting the hole value has different meanings depending on the usage:
87 // - for function template callbacks it means that the callback returns
88 // the undefined value,
89 // - for property getter callbacks is means that the callback returns
90 // the undefined value (for property setter callbacks the value returned
91 // is ignored),
92 // - for interceptor callbacks it means that the request was not handled.
93 V8_INLINE void SetTheHole();
95
96 // See FunctionCallbackInfo.
97 static constexpr int kIsolateValueIndex = -2;
98
99 internal::Address* value_;
100};
101
108template <typename T>
110 public:
112 V8_INLINE int Length() const;
117 V8_INLINE Local<Value> operator[](int i) const;
131 "V8 will stop providing access to hidden prototype (i.e. "
132 "JSGlobalObject). Use This() instead. \n"
133 "DO NOT try to workaround this by accessing JSGlobalObject via "
134 "v8::Object::GetPrototype() - it'll be deprecated soon too. \n"
135 "See http://crbug.com/333672197. ")
140 V8_INLINE bool IsConstructCall() const;
147
148 // This is a temporary replacement for Holder() added just for the purpose
149 // of testing the deprecated Holder() machinery until it's removed for real.
150 // DO NOT use it.
152
153 private:
157
158 static constexpr int kHolderIndex = 0;
159 static constexpr int kIsolateIndex = 1;
160 static constexpr int kUnusedIndex = 2;
161 static constexpr int kReturnValueIndex = 3;
162 static constexpr int kDataIndex = 4;
163 static constexpr int kNewTargetIndex = 5;
164 static constexpr int kArgsLength = 6;
165
166 static constexpr int kArgsLengthWithReceiver = kArgsLength + 1;
167
168 // Codegen constants:
169 static constexpr int kSize = 3 * internal::kApiSystemPointerSize;
170 static constexpr int kImplicitArgsOffset = 0;
171 static constexpr int kValuesOffset =
172 kImplicitArgsOffset + internal::kApiSystemPointerSize;
173 static constexpr int kLengthOffset =
174 kValuesOffset + internal::kApiSystemPointerSize;
175
176 static constexpr int kThisValuesIndex = -1;
178 kIsolateIndex - kReturnValueIndex);
179
181 internal::Address* values, int length);
182 internal::Address* implicit_args_;
183 internal::Address* values_;
184 int length_;
185};
186
191template <typename T>
193 public:
198
205
248
259
269
278
280 "This is a temporary workaround to ease migration of Chromium bindings "
281 "code to the new interceptors Api")
282 explicit PropertyCallbackInfo(const PropertyCallbackInfo<void>& info)
283 : PropertyCallbackInfo(info.args_) {}
284
285 private:
286 template <typename U>
288 friend class MacroAssembler;
291 static constexpr int kShouldThrowOnErrorIndex = 0;
292 static constexpr int kHolderIndex = 1;
293 static constexpr int kIsolateIndex = 2;
294 static constexpr int kUnusedIndex = 3;
295 static constexpr int kReturnValueIndex = 4;
296 static constexpr int kDataIndex = 5;
297 static constexpr int kThisIndex = 6;
298 static constexpr int kArgsLength = 7;
299
300 static constexpr int kSize = 1 * internal::kApiSystemPointerSize;
301
303 : args_(args) {}
304
305 internal::Address* args_;
306};
307
308using FunctionCallback = void (*)(const FunctionCallbackInfo<Value>& info);
309
310// --- Implementation ---
311
312template <typename T>
313ReturnValue<T>::ReturnValue(internal::Address* slot) : value_(slot) {}
314
315template <typename T>
316void ReturnValue<T>::SetInternal(internal::Address value) {
317#if V8_STATIC_ROOTS_BOOL
318 using I = internal::Internals;
319 // Ensure that the upper 32-bits are not modified. Compiler should be
320 // able to optimize this to a store of a lower 32-bits of the value.
321 // This is fine since the callback can return only JavaScript values which
322 // are either Smis or heap objects allocated in the main cage.
323 *value_ = I::DecompressTaggedField(*value_, I::CompressTagged(value));
324#else
325 *value_ = value;
326#endif // V8_STATIC_ROOTS_BOOL
327}
328
329template <typename T>
330template <typename S>
331void ReturnValue<T>::Set(const Global<S>& handle) {
332 static_assert(std::is_base_of<T, S>::value, "type check");
333 if (V8_UNLIKELY(handle.IsEmpty())) {
334 SetTheHole();
335 } else {
336 SetInternal(handle.ptr());
337 }
338}
339
340template <typename T>
341template <typename S>
343 static_assert(std::is_base_of<T, S>::value, "type check");
344#ifdef V8_ENABLE_CHECKS
345 internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
346#endif // V8_ENABLE_CHECKS
347 SetInternal(handle.ptr());
348}
349
350template <typename T>
351template <typename S>
353 static_assert(std::is_base_of<T, S>::value, "type check");
354 if (V8_UNLIKELY(handle.IsEmpty())) {
355 SetTheHole();
356 } else {
357 SetInternal(handle.ptr());
358 }
359}
360
361template <typename T>
362template <typename S>
364 static_assert(std::is_base_of<T, S>::value, "type check");
365#ifdef V8_ENABLE_CHECKS
366 internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
367#endif // V8_ENABLE_CHECKS
368 SetInternal(handle.ptr());
369}
370
371template <typename T>
372template <typename S>
373void ReturnValue<T>::Set(const Local<S> handle) {
374 static_assert(std::is_void<T>::value || std::is_base_of<T, S>::value,
375 "type check");
376 if (V8_UNLIKELY(handle.IsEmpty())) {
377 SetTheHole();
378 } else {
379 SetInternal(handle.ptr());
380 }
381}
382
383template <typename T>
384template <typename S>
386 static_assert(std::is_void<T>::value || std::is_base_of<T, S>::value,
387 "type check");
388#ifdef V8_ENABLE_CHECKS
389 internal::VerifyHandleIsNonEmpty(handle.IsEmpty());
390#endif // V8_ENABLE_CHECKS
391 SetInternal(handle.ptr());
392}
393
394template <typename T>
395void ReturnValue<T>::Set(double i) {
396 static_assert(std::is_base_of<T, Number>::value, "type check");
397 SetNonEmpty(Number::New(GetIsolate(), i));
398}
399
400template <typename T>
401void ReturnValue<T>::Set(int32_t i) {
402 static_assert(std::is_base_of<T, Integer>::value, "type check");
403 using I = internal::Internals;
404 if (V8_LIKELY(I::IsValidSmi(i))) {
405 SetInternal(I::IntToSmi(i));
406 return;
407 }
408 SetNonEmpty(Integer::New(GetIsolate(), i));
409}
410
411template <typename T>
412void ReturnValue<T>::Set(uint32_t i) {
413 static_assert(std::is_base_of<T, Integer>::value, "type check");
414 // Can't simply use INT32_MAX here for whatever reason.
415 bool fits_into_int32_t = (i & (1U << 31)) == 0;
416 if (V8_LIKELY(fits_into_int32_t)) {
417 Set(static_cast<int32_t>(i));
418 return;
419 }
420 SetNonEmpty(Integer::NewFromUnsigned(GetIsolate(), i));
421}
422
423template <typename T>
424void ReturnValue<T>::Set(uint16_t i) {
425 static_assert(std::is_base_of<T, Integer>::value, "type check");
426 using I = internal::Internals;
427 static_assert(I::IsValidSmi(std::numeric_limits<uint16_t>::min()));
428 static_assert(I::IsValidSmi(std::numeric_limits<uint16_t>::max()));
429 SetInternal(I::IntToSmi(i));
430}
431
432template <typename T>
433void ReturnValue<T>::Set(bool value) {
434 static_assert(std::is_base_of<T, Boolean>::value, "type check");
435 using I = internal::Internals;
436#if V8_STATIC_ROOTS_BOOL
437#ifdef V8_ENABLE_CHECKS
438 internal::PerformCastCheck(
439 internal::ValueHelper::SlotAsValue<Value, true>(value_));
440#endif // V8_ENABLE_CHECKS
441 SetInternal(value ? I::StaticReadOnlyRoot::kTrueValue
442 : I::StaticReadOnlyRoot::kFalseValue);
443#else
444 int root_index;
445 if (value) {
446 root_index = I::kTrueValueRootIndex;
447 } else {
448 root_index = I::kFalseValueRootIndex;
449 }
450 *value_ = I::GetRoot(GetIsolate(), root_index);
451#endif // V8_STATIC_ROOTS_BOOL
452}
453
454template <typename T>
456 using I = internal::Internals;
457#if V8_STATIC_ROOTS_BOOL
458 SetInternal(I::StaticReadOnlyRoot::kTheHoleValue);
459#else
460 *value_ = I::GetRoot(GetIsolate(), I::kTheHoleValueRootIndex);
461#endif // V8_STATIC_ROOTS_BOOL
462}
463
464template <typename T>
466 static_assert(std::is_base_of<T, Primitive>::value, "type check");
467 using I = internal::Internals;
468#if V8_STATIC_ROOTS_BOOL
469#ifdef V8_ENABLE_CHECKS
470 internal::PerformCastCheck(
471 internal::ValueHelper::SlotAsValue<Value, true>(value_));
472#endif // V8_ENABLE_CHECKS
473 SetInternal(I::StaticReadOnlyRoot::kNullValue);
474#else
475 *value_ = I::GetRoot(GetIsolate(), I::kNullValueRootIndex);
476#endif // V8_STATIC_ROOTS_BOOL
477}
478
479template <typename T>
481 static_assert(std::is_base_of<T, Primitive>::value, "type check");
482 using I = internal::Internals;
483#if V8_STATIC_ROOTS_BOOL
484#ifdef V8_ENABLE_CHECKS
485 internal::PerformCastCheck(
486 internal::ValueHelper::SlotAsValue<Value, true>(value_));
487#endif // V8_ENABLE_CHECKS
488 SetInternal(I::StaticReadOnlyRoot::kUndefinedValue);
489#else
490 *value_ = I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex);
491#endif // V8_STATIC_ROOTS_BOOL
492}
493
494template <typename T>
496 static_assert(std::is_base_of<T, String>::value, "type check");
497 using I = internal::Internals;
498#if V8_STATIC_ROOTS_BOOL
499#ifdef V8_ENABLE_CHECKS
500 internal::PerformCastCheck(
501 internal::ValueHelper::SlotAsValue<Value, true>(value_));
502#endif // V8_ENABLE_CHECKS
503 SetInternal(I::StaticReadOnlyRoot::kEmptyString);
504#else
505 *value_ = I::GetRoot(GetIsolate(), I::kEmptyStringRootIndex);
506#endif // V8_STATIC_ROOTS_BOOL
507}
508
509template <typename T>
511 return *reinterpret_cast<Isolate**>(&value_[kIsolateValueIndex]);
512}
513
514template <typename T>
516 using I = internal::Internals;
517#if V8_STATIC_ROOTS_BOOL
518 if (I::is_identical(*value_, I::StaticReadOnlyRoot::kTheHoleValue)) {
519#else
520 if (*value_ == I::GetRoot(GetIsolate(), I::kTheHoleValueRootIndex)) {
521#endif // V8_STATIC_ROOTS_BOOL
522 return Undefined(GetIsolate());
523 }
524 return Local<Value>::New(GetIsolate(),
525 internal::ValueHelper::SlotAsValue<Value>(value_));
526}
527
528template <typename T>
529template <typename S>
530void ReturnValue<T>::Set(S* whatever) {
531 static_assert(sizeof(S) < 0, "incompilable to prevent inadvertent misuse");
532}
533
534template <typename T>
536 internal::Address* values,
537 int length)
538 : implicit_args_(implicit_args), values_(values), length_(length) {}
539
540template <typename T>
542 // values_ points to the first argument (not the receiver).
543 if (i < 0 || length_ <= i) return Undefined(GetIsolate());
544 return Local<Value>::FromSlot(values_ + i);
545}
546
547template <typename T>
549 // values_ points to the first argument (not the receiver).
550 return Local<Object>::FromSlot(values_ + kThisValuesIndex);
551}
552
553template <typename T>
555 return Local<Object>::FromSlot(&implicit_args_[kHolderIndex]);
556}
557
558template <typename T>
560 return HolderSoonToBeDeprecated();
561}
562
563template <typename T>
565 return Local<Value>::FromSlot(&implicit_args_[kNewTargetIndex]);
566}
567
568template <typename T>
570 return Local<Value>::FromSlot(&implicit_args_[kDataIndex]);
571}
572
573template <typename T>
575 return *reinterpret_cast<Isolate**>(&implicit_args_[kIsolateIndex]);
576}
577
578template <typename T>
580 return ReturnValue<T>(&implicit_args_[kReturnValueIndex]);
581}
582
583template <typename T>
585 return !NewTarget()->IsUndefined();
586}
587
588template <typename T>
590 return length_;
591}
592
593template <typename T>
595 return *reinterpret_cast<Isolate**>(&args_[kIsolateIndex]);
596}
597
598template <typename T>
600 return Local<Value>::FromSlot(&args_[kDataIndex]);
601}
602
603template <typename T>
605 return Local<Object>::FromSlot(&args_[kThisIndex]);
606}
607
608template <typename T>
610 return Local<Object>::FromSlot(&args_[kHolderIndex]);
611}
612
613template <typename T>
615 return ReturnValue<T>(&args_[kReturnValueIndex]);
616}
617
618template <typename T>
620 using I = internal::Internals;
621 if (args_[kShouldThrowOnErrorIndex] !=
622 I::IntToSmi(I::kInferShouldThrowMode)) {
623 return args_[kShouldThrowOnErrorIndex] != I::IntToSmi(I::kDontThrow);
624 }
626 reinterpret_cast<v8::internal::Isolate*>(GetIsolate()));
627}
628
629} // namespace v8
630
631#endif // INCLUDE_V8_FUNCTION_CALLBACK_H_
Definition: v8-traced-handle.h:125
Definition: v8-function-callback.h:109
Local< Object > HolderSoonToBeDeprecated() const
Definition: v8-function-callback.h:554
ReturnValue< T > GetReturnValue() const
Definition: v8-function-callback.h:579
Local< Object > This() const
Definition: v8-function-callback.h:548
Local< Object > Holder() const
Definition: v8-function-callback.h:559
Local< Value > operator[](int i) const
Definition: v8-function-callback.h:541
Isolate * GetIsolate() const
Definition: v8-function-callback.h:574
Local< Value > NewTarget() const
Definition: v8-function-callback.h:564
friend class debug::ConsoleCallArguments
Definition: v8-function-callback.h:156
friend class internal::FunctionCallbackArguments
Definition: v8-function-callback.h:154
Local< Value > Data() const
Definition: v8-function-callback.h:569
bool IsConstructCall() const
Definition: v8-function-callback.h:584
int Length() const
Definition: v8-function-callback.h:589
Definition: v8-persistent-handle.h:351
Definition: v8-isolate.h:210
Definition: v8-local-handle.h:258
Definition: v8-util.h:166
Definition: v8-function-callback.h:192
Local< Value > Data() const
Definition: v8-function-callback.h:599
friend class internal::PropertyCallbackArguments
Definition: v8-function-callback.h:289
friend class PropertyCallbackInfo
Definition: v8-function-callback.h:287
Local< Object > Holder() const
Definition: v8-function-callback.h:609
bool ShouldThrowOnError() const
Definition: v8-function-callback.h:619
ReturnValue< T > GetReturnValue() const
Definition: v8-function-callback.h:614
friend class MacroAssembler
Definition: v8-function-callback.h:288
Local< Object > This() const
Definition: v8-function-callback.h:604
Isolate * GetIsolate() const
Definition: v8-function-callback.h:594
Definition: v8-function-callback.h:35
void SetEmptyString()
Definition: v8-function-callback.h:495
friend class ReturnValue
Definition: v8-function-callback.h:78
ReturnValue(const ReturnValue< S > &that)
Definition: v8-function-callback.h:38
void SetNonEmpty(const Global< S > &handle)
Definition: v8-function-callback.h:342
Local< Value > Get() const
Definition: v8-function-callback.h:515
void SetNull()
Definition: v8-function-callback.h:465
Isolate * GetIsolate() const
Definition: v8-function-callback.h:510
void SetUndefined()
Definition: v8-function-callback.h:480
Definition: v8-container.h:148
internal::Address ptr() const
Definition: v8-handle-base.h:76
bool IsEmpty() const
Definition: v8-handle-base.h:56
Definition: v8-local-handle.h:74
Definition: v8-internal.h:729
const int kApiSystemPointerSize
Definition: v8-internal.h:44
bool ShouldThrowOnError(internal::Isolate *isolate)
uintptr_t Address
Definition: v8-internal.h:31
Definition: libplatform.h:15
Local< Primitive > Undefined(Isolate *isolate)
Definition: v8-primitive.h:839
void(*)(const FunctionCallbackInfo< Value > &info) FunctionCallback
Definition: v8-function-callback.h:308
#define V8_INLINE
Definition: v8config.h:477
#define V8_DEPRECATE_SOON(message)
Definition: v8config.h:580
#define V8_LIKELY(condition)
Definition: v8config.h:627
#define V8_UNLIKELY(condition)
Definition: v8config.h:626