v8 14.1.146 (node 25.0.0)
V8 is Google's open source JavaScript engine
Loading...
Searching...
No Matches
v8-local-handle.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_LOCAL_HANDLE_H_
6#define INCLUDE_V8_LOCAL_HANDLE_H_
7
8#include <stddef.h>
9
10#include <type_traits>
11#include <vector>
12
13#include "v8-handle-base.h" // NOLINT(build/include_directory)
14#include "v8-internal.h" // NOLINT(build/include_directory)
15
16namespace v8 {
17
18template <class T>
19class LocalBase;
20template <class T>
21class Local;
22template <class T>
23class LocalVector;
24template <class F>
25class MaybeLocal;
26
27template <class T>
28class Eternal;
29template <class T>
30class Global;
31
32template <class T>
33class NonCopyablePersistentTraits;
34template <class T>
35class PersistentBase;
36template <class T, class M = NonCopyablePersistentTraits<T>>
37class Persistent;
38
40template <class T>
42template <class F>
43class TracedReference;
44
45class ArrayBuffer;
46class Boolean;
47class Context;
49template <class F>
51class Isolate;
52class Object;
53template <class F1, class F2, class F3>
55class Primitive;
56class Private;
57template <class F>
59template <class F>
60class ReturnValue;
61class String;
62template <class F>
63class Traced;
65class Utils;
66class Uint32;
67class Value;
68
69namespace debug {
70class ConsoleCallArguments;
71}
72
73namespace internal {
74template <typename T>
76template <typename T>
77class LocalUnchecked;
78class SamplingHeapProfiler;
79} // namespace internal
80
81namespace api_internal {
82// Called when ToLocalChecked is called on an empty Local.
84
85#ifdef V8_ENABLE_CHECKS
86template <typename T, typename V = Value>
87void TypeCheckLocal(V* value) {
88 // If `T` does not provide a `Cast` method we cannot check anything.
89 if constexpr (requires { T::Cast(value); }) {
90 // TODO(419454582): Remove all these exceptions.
91 if (std::is_same_v<Array, T> && value->IsArgumentsObject()) return;
93 if (std::is_same_v<Object, T> && value->IsNull()) return;
94 if (std::is_same_v<Object, T> && value->IsString()) return;
95 if (std::is_same_v<Object, T> && value->IsUndefined()) return;
96 if (std::is_same_v<Uint32, T> && value->IsInt32()) return;
97 if (std::is_same_v<Object, T> && value->IsNumber()) return;
98 // Execute the actual check (part of the cast).
99 T::Cast(value);
100 }
101}
102#endif
103} // namespace api_internal
104
105/**
106 * A stack-allocated class that governs a number of local handles.
107 * After a handle scope has been created, all local handles will be
108 * allocated within that handle scope until either the handle scope is
109 * deleted or another handle scope is created. If there is already a
110 * handle scope and a new one is created, all allocations will take
111 * place in the new handle scope until it is deleted. After that,
112 * new handles will again be allocated in the original handle scope.
113 *
114 * After the handle scope of a local handle has been deleted the
115 * garbage collector will no longer track the object stored in the
116 * handle and may deallocate it. The behavior of accessing a handle
117 * for which the handle scope has been deleted is undefined.
118 */
120 public:
121 V8_INLINE explicit HandleScope(Isolate* isolate);
122
124
125 /**
126 * Counts the number of allocated handles.
127 */
128 static int NumberOfHandles(Isolate* isolate);
129
130 V8_INLINE Isolate* GetIsolate() const { return isolate_; }
131
132 HandleScope(const HandleScope&) = delete;
133 void operator=(const HandleScope&) = delete;
134
136 internal::Address value);
137
138 protected:
140
141 V8_INLINE void Initialize(Isolate* isolate);
142
143 V8_INLINE static internal::Address* CreateHandle(Isolate* i_isolate,
144 internal::Address value);
145
146 private:
147 // Extend the HandleScope making room for more handles. Not inlined.
148 static internal::Address* Extend(Isolate* isolate);
149 // Delete any extensions in HandleScope destructor. Not called unless there
150 // are extensions. Not inlined.
151 void DeleteExtensions(Isolate* isolate);
152
153#ifdef V8_ENABLE_CHECKS
154 // Non-inlined asserts on HandleScope constructor.
156 // Non-inlined assert for HandleScope destructor.
158 // Non-inlined asserts for HandleScope destructor. Also zaps the slots
159 // if this is enabled.
162#endif
163
164 // Declaring operator new and delete as deleted is not spec compliant.
165 // Therefore declare them private instead to disable dynamic alloc
166 void* operator new(size_t size);
167 void* operator new[](size_t size);
168 void operator delete(void*, size_t);
169 void operator delete[](void*, size_t);
170
171 Isolate* isolate_;
172 internal::Address* prev_next_;
173 internal::Address* prev_limit_;
174#ifdef V8_ENABLE_CHECKS
175 int scope_level_ = 0;
176#endif
177
178 // LocalBase<T>::New uses CreateHandle with an Isolate* parameter.
179 template <typename T>
180 friend class LocalBase;
181
182 // Object::GetInternalField and Context::GetEmbedderData use CreateHandle with
183 // a HeapObject in their shortcuts.
184 friend class Object;
185 friend class Context;
186};
187
188HandleScope::HandleScope(Isolate* v8_isolate) { Initialize(v8_isolate); }
189
190void HandleScope::Initialize(Isolate* v8_isolate) {
191 using I = internal::Internals;
192 internal::HandleScopeData* current = I::GetHandleScopeData(v8_isolate);
193 isolate_ = v8_isolate;
194 prev_next_ = current->next;
195 prev_limit_ = current->limit;
196 current->level++;
197#ifdef V8_ENABLE_CHECKS
198 DoInitializeAsserts(v8_isolate);
199 scope_level_ = current->level;
200#endif
201}
202
204 if (V8_UNLIKELY(isolate_ == nullptr)) return;
205#ifdef V8_ENABLE_CHECKS
206 AssertScopeLevelsMatch();
207 int handle_count_before = NumberOfHandles(isolate_);
208#endif
209
210 using I = internal::Internals;
211 internal::HandleScopeData* current = I::GetHandleScopeData(isolate_);
212 std::swap(current->next, prev_next_);
213 current->level--;
214 internal::Address* limit = prev_next_;
215 if (V8_UNLIKELY(current->limit != prev_limit_)) {
216 current->limit = prev_limit_;
217 limit = prev_limit_;
218 DeleteExtensions(isolate_);
219 }
220#ifdef V8_ENABLE_CHECKS
221 DoCloseScopeAsserts(handle_count_before, limit, current);
222#else
223 (void)limit; // Avoid unused variable warning.
224#endif
225}
226
228 internal::Address value) {
229 using I = internal::Internals;
230 internal::HandleScopeData* data = I::GetHandleScopeData(v8_isolate);
231 internal::Address* result = data->next;
232 if (V8_UNLIKELY(result == data->limit)) {
233 result = Extend(v8_isolate);
234 }
235 // Update the current next field, set the value in the created handle,
236 // and return the result.
237 data->next = reinterpret_cast<internal::Address*>(
238 reinterpret_cast<internal::Address>(result) + sizeof(internal::Address));
239 *result = value;
240 return result;
241}
242
243/**
244 * A base class for local handles.
245 * Its implementation depends on whether direct handle support is enabled.
246 * When it is, a local handle contains a direct pointer to the referenced
247 * object, otherwise it contains an indirect pointer.
248 */
249#ifdef V8_ENABLE_DIRECT_HANDLE
250
251template <typename T>
253 protected:
254 template <class F>
255 friend class Local;
256
257 V8_INLINE LocalBase() = default;
258
260#ifdef V8_ENABLE_CHECKS
262#endif
263 }
264
265 template <typename S>
267
269 return LocalBase<T>(value);
270 }
271
273 return LocalBase<T>::New(isolate,
275 }
276
278 if (slot == nullptr) return LocalBase<T>();
279 return LocalBase<T>(*slot);
280 }
281
284 return LocalBase<T>(repr);
285 }
286};
287
288#else // !V8_ENABLE_DIRECT_HANDLE
289
290template <typename T>
292 protected:
293 template <class F>
294 friend class Local;
295
296 V8_INLINE LocalBase() = default;
297
298 V8_INLINE explicit LocalBase(internal::Address* location)
299 : IndirectHandleBase(location) {
300#ifdef V8_ENABLE_CHECKS
301 if (!IsEmpty()) api_internal::TypeCheckLocal<T>(value<Value>());
302#endif
303 }
304
305 template <typename S>
306 V8_INLINE LocalBase(const LocalBase<S>& other) : IndirectHandleBase(other) {}
307
308 V8_INLINE static LocalBase<T> New(Isolate* isolate, internal::Address value) {
309 return LocalBase(HandleScope::CreateHandle(isolate, value));
310 }
311
312 V8_INLINE static LocalBase<T> New(Isolate* isolate, T* that) {
313 if (internal::ValueHelper::IsEmpty(that)) return LocalBase<T>();
314 return LocalBase<T>::New(isolate,
315 internal::ValueHelper::ValueAsAddress(that));
316 }
317
319 return LocalBase<T>(slot);
320 }
321
323 internal::ValueHelper::InternalRepresentationType repr) {
324 return LocalBase<T>(repr);
325 }
326};
327
328#endif // V8_ENABLE_DIRECT_HANDLE
329
330/**
331 * An object reference managed by the v8 garbage collector.
332 *
333 * All objects returned from v8 have to be tracked by the garbage collector so
334 * that it knows that the objects are still alive. Also, because the garbage
335 * collector may move objects, it is unsafe to point directly to an object.
336 * Instead, all objects are stored in handles which are known by the garbage
337 * collector and updated whenever an object moves. Handles should always be
338 * passed by value (except in cases like out-parameters) and they should never
339 * be allocated on the heap.
340 *
341 * There are two types of handles: local and persistent handles.
342 *
343 * Local handles are light-weight and transient and typically used in local
344 * operations. They are managed by HandleScopes. That means that a HandleScope
345 * must exist on the stack when they are created and that they are only valid
346 * inside of the HandleScope active during their creation. For passing a local
347 * handle to an outer HandleScope, an EscapableHandleScope and its Escape()
348 * method must be used.
349 *
350 * Persistent handles can be used when storing objects across several
351 * independent operations and have to be explicitly deallocated when they're no
352 * longer used.
353 *
354 * It is safe to extract the object stored in the handle by dereferencing the
355 * handle (for instance, to extract the Object* from a Local<Object>); the value
356 * will still be governed by a handle behind the scenes and the same rules apply
357 * to these values as to their handles.
358 */
359template <class T>
361#ifdef V8_ENABLE_LOCAL_OFF_STACK_CHECK
362 public api_internal::StackAllocated<true>
363#else
364 public api_internal::StackAllocated<false>
365#endif
366{
367 public:
368 /**
369 * Default constructor: Returns an empty handle.
370 */
371 V8_INLINE Local() = default;
372
373 /**
374 * Constructor for handling automatic up casting.
375 * Ex. Local<Object> can be passed when Local<Value> is expected but not
376 * the other way round.
377 */
378 template <class S>
381
382 V8_INLINE T* operator->() const { return this->template value<T>(); }
383
384 V8_INLINE T* operator*() const { return this->operator->(); }
385
386 /**
387 * Checks whether two handles are equal or different.
388 * They are equal iff they are both empty or they are both non-empty and the
389 * objects to which they refer are physically equal.
390 *
391 * If both handles refer to JS objects, this is the same as strict
392 * non-equality. For primitives, such as numbers or strings, a `true` return
393 * value does not indicate that the values aren't equal in the JavaScript
394 * sense. Use `Value::StrictEquals()` to check primitives for equality.
395 */
396
397 template <class S>
398 V8_INLINE bool operator==(const Local<S>& that) const {
399 return internal::HandleHelper::EqualHandles(*this, that);
400 }
401
402 template <class S>
403 V8_INLINE bool operator==(const PersistentBase<S>& that) const {
404 return internal::HandleHelper::EqualHandles(*this, that);
405 }
406
407 template <class S>
408 V8_INLINE bool operator!=(const Local<S>& that) const {
409 return !operator==(that);
410 }
411
412 template <class S>
413 V8_INLINE bool operator!=(const Persistent<S>& that) const {
414 return !operator==(that);
415 }
416
417 /**
418 * Cast a handle to a subclass, e.g. Local<Value> to Local<Object>.
419 * This is only valid if the handle actually refers to a value of the
420 * target type or if the handle is empty.
421 */
422 template <class S>
424#ifdef V8_ENABLE_CHECKS
425 // If we're going to perform the type check then we have to check
426 // that the handle isn't empty before doing the checked cast.
427 if (that.IsEmpty()) return Local<T>();
428 T::Cast(that.template value<S>());
429#endif
430 return Local<T>(LocalBase<T>(that));
431 }
432
433 /**
434 * Calling this is equivalent to Local<S>::Cast().
435 * In particular, this is only valid if the handle actually refers to a value
436 * of the target type or if the handle is empty.
437 */
438 template <class S>
439 V8_INLINE Local<S> As() const {
440 return Local<S>::Cast(*this);
441 }
442
443 /**
444 * Create a local handle for the content of another handle.
445 * The referee is kept alive by the local handle even when
446 * the original handle is destroyed/disposed.
447 */
449 return New(isolate, that.template value<T, true>());
450 }
451
453 const PersistentBase<T>& that) {
454 return New(isolate, that.template value<T, true>());
455 }
456
458 const BasicTracedReference<T>& that) {
459 return New(isolate, that.template value<T, true>());
460 }
461
462 private:
464 friend class Utils;
465 template <class F>
466 friend class Eternal;
467 template <class F>
468 friend class Global;
469 template <class F>
470 friend class Local;
471 template <class F>
472 friend class MaybeLocal;
473 template <class F, class M>
474 friend class Persistent;
475 template <class F>
477 template <class F>
479 friend class String;
480 friend class Object;
481 friend class Context;
482 friend class Isolate;
483 friend class Private;
484 template <class F>
486 friend Local<Primitive> Undefined(Isolate* isolate);
487 friend Local<Primitive> Null(Isolate* isolate);
488 friend Local<Boolean> True(Isolate* isolate);
489 friend Local<Boolean> False(Isolate* isolate);
490 friend class HandleScope;
492 friend class InternalEscapableScope;
493 template <class F1, class F2, class F3>
495 template <class F>
496 friend class ReturnValue;
497 template <class F>
498 friend class Traced;
499 friend class internal::SamplingHeapProfiler;
500 friend class internal::HandleHelper;
501 friend class debug::ConsoleCallArguments;
502 friend class internal::LocalUnchecked<T>;
503
504 explicit Local(no_checking_tag do_not_check)
505 : LocalBase<T>(), StackAllocated(do_not_check) {}
506 explicit Local(const Local<T>& other, no_checking_tag do_not_check)
507 : LocalBase<T>(other), StackAllocated(do_not_check) {}
508
509 V8_INLINE explicit Local(const LocalBase<T>& other) : LocalBase<T>(other) {}
510
511 V8_INLINE static Local<T> FromRepr(
512 internal::ValueHelper::InternalRepresentationType repr) {
513 return Local<T>(LocalBase<T>::FromRepr(repr));
514 }
515
516 V8_INLINE static Local<T> FromSlot(internal::Address* slot) {
517 return Local<T>(LocalBase<T>::FromSlot(slot));
518 }
519
520#ifdef V8_ENABLE_DIRECT_HANDLE
521 friend class TypecheckWitness;
522
524 return Local<T>(LocalBase<T>(ptr));
525 }
526#endif // V8_ENABLE_DIRECT_HANDLE
527
528 V8_INLINE static Local<T> New(Isolate* isolate, internal::Address value) {
529 return Local<T>(LocalBase<T>::New(isolate, value));
530 }
531
532 V8_INLINE static Local<T> New(Isolate* isolate, T* that) {
533 return Local<T>(LocalBase<T>::New(isolate, that));
534 }
535
536 // Unsafe cast, should be avoided.
537 template <class S>
538 V8_INLINE Local<S> UnsafeAs() const {
539 return Local<S>(LocalBase<S>(*this));
540 }
541};
542
543namespace internal {
544// A local variant that is suitable for off-stack allocation.
545// Used internally by LocalVector<T>. Not to be used directly!
546template <typename T>
547class V8_TRIVIAL_ABI LocalUnchecked : public Local<T> {
548 public:
549 LocalUnchecked() : Local<T>(Local<T>::do_not_check) {}
550
551#if defined(V8_ENABLE_LOCAL_OFF_STACK_CHECK) && V8_HAS_ATTRIBUTE_TRIVIAL_ABI
552 // In this case, the check is also enforced in the copy constructor and we
553 // need to suppress it.
554 LocalUnchecked(
555 const LocalUnchecked& other) noexcept // NOLINT(runtime/explicit)
556 : Local<T>(other, Local<T>::do_not_check) {}
557 LocalUnchecked& operator=(const LocalUnchecked&) noexcept = default;
558#endif
559
560 // Implicit conversion from Local.
561 LocalUnchecked(const Local<T>& other) noexcept // NOLINT(runtime/explicit)
562 : Local<T>(other, Local<T>::do_not_check) {}
563};
564
565#ifdef V8_ENABLE_DIRECT_HANDLE
566// Off-stack allocated direct locals must be registered as strong roots.
567// For off-stack indirect locals, this is not necessary.
568
569template <typename T>
571 public:
572 using value_type = LocalUnchecked<T>;
573 static_assert(std::is_standard_layout_v<value_type>);
574 static_assert(sizeof(value_type) == sizeof(Address));
575
576 template <typename HeapOrIsolateT>
579 template <typename U>
582
584 return reinterpret_cast<value_type*>(allocate_impl(n));
585 }
586 void deallocate(value_type* p, size_t n) noexcept {
587 return deallocate_impl(reinterpret_cast<Address*>(p), n);
588 }
589};
590#endif // V8_ENABLE_DIRECT_HANDLE
591} // namespace internal
592
593template <typename T>
594class LocalVector {
595 private:
596 using element_type = internal::LocalUnchecked<T>;
597
598#ifdef V8_ENABLE_DIRECT_HANDLE
599 using allocator_type = internal::StrongRootAllocator<element_type>;
600
601 static allocator_type make_allocator(Isolate* isolate) noexcept {
602 return allocator_type(isolate);
603 }
604#else
605 using allocator_type = std::allocator<element_type>;
606
607 static allocator_type make_allocator(Isolate* isolate) noexcept {
608 return allocator_type();
609 }
610#endif // V8_ENABLE_DIRECT_HANDLE
611
612 using vector_type = std::vector<element_type, allocator_type>;
613
614 public:
615 using value_type = Local<T>;
616 using reference = value_type&;
617 using const_reference = const value_type&;
618 using size_type = size_t;
619 using difference_type = ptrdiff_t;
620 using iterator =
621 internal::WrappedIterator<typename vector_type::iterator, Local<T>>;
622 using const_iterator =
623 internal::WrappedIterator<typename vector_type::const_iterator,
624 const Local<T>>;
625
626 explicit LocalVector(Isolate* isolate) : backing_(make_allocator(isolate)) {}
627 LocalVector(Isolate* isolate, size_t n)
628 : backing_(n, make_allocator(isolate)) {}
629 explicit LocalVector(Isolate* isolate, std::initializer_list<Local<T>> init)
630 : backing_(make_allocator(isolate)) {
631 if (init.size() == 0) return;
632 backing_.reserve(init.size());
633 backing_.insert(backing_.end(), init.begin(), init.end());
634 }
635
636 iterator begin() noexcept { return iterator(backing_.begin()); }
637 const_iterator begin() const noexcept {
638 return const_iterator(backing_.begin());
639 }
640 iterator end() noexcept { return iterator(backing_.end()); }
641 const_iterator end() const noexcept { return const_iterator(backing_.end()); }
642
643 size_t size() const noexcept { return backing_.size(); }
644 bool empty() const noexcept { return backing_.empty(); }
645 void reserve(size_t n) { backing_.reserve(n); }
646 void shrink_to_fit() { backing_.shrink_to_fit(); }
647
648 Local<T>& operator[](size_t n) { return backing_[n]; }
649 const Local<T>& operator[](size_t n) const { return backing_[n]; }
650
651 Local<T>& at(size_t n) { return backing_.at(n); }
652 const Local<T>& at(size_t n) const { return backing_.at(n); }
653
654 Local<T>& front() { return backing_.front(); }
655 const Local<T>& front() const { return backing_.front(); }
656 Local<T>& back() { return backing_.back(); }
657 const Local<T>& back() const { return backing_.back(); }
658
659 Local<T>* data() noexcept { return backing_.data(); }
660 const Local<T>* data() const noexcept { return backing_.data(); }
661
662 iterator insert(const_iterator pos, const Local<T>& value) {
663 return iterator(backing_.insert(pos.base(), value));
664 }
665
666 template <typename InputIt>
667 iterator insert(const_iterator pos, InputIt first, InputIt last) {
668 return iterator(backing_.insert(pos.base(), first, last));
669 }
670
671 iterator insert(const_iterator pos, std::initializer_list<Local<T>> init) {
672 return iterator(backing_.insert(pos.base(), init.begin(), init.end()));
673 }
674
675 LocalVector<T>& operator=(std::initializer_list<Local<T>> init) {
676 backing_.clear();
677 backing_.reserve(init.size());
678 backing_.insert(backing_.end(), init.begin(), init.end());
679 return *this;
680 }
681
682 void push_back(const Local<T>& x) { backing_.push_back(x); }
683 void pop_back() { backing_.pop_back(); }
684
685 template <typename... Args>
686 void emplace_back(Args&&... args) {
687 backing_.push_back(value_type{std::forward<Args>(args)...});
688 }
689
690 void clear() noexcept { backing_.clear(); }
691 void resize(size_t n) { backing_.resize(n); }
692 void swap(LocalVector<T>& other) { backing_.swap(other.backing_); }
693
694 friend bool operator==(const LocalVector<T>& x, const LocalVector<T>& y) {
695 return x.backing_ == y.backing_;
696 }
697 friend bool operator!=(const LocalVector<T>& x, const LocalVector<T>& y) {
698 return x.backing_ != y.backing_;
699 }
700 friend bool operator<(const LocalVector<T>& x, const LocalVector<T>& y) {
701 return x.backing_ < y.backing_;
702 }
703 friend bool operator>(const LocalVector<T>& x, const LocalVector<T>& y) {
704 return x.backing_ > y.backing_;
705 }
706 friend bool operator<=(const LocalVector<T>& x, const LocalVector<T>& y) {
707 return x.backing_ <= y.backing_;
708 }
709 friend bool operator>=(const LocalVector<T>& x, const LocalVector<T>& y) {
710 return x.backing_ >= y.backing_;
711 }
712
713 private:
714 vector_type backing_;
715};
716
717#if !defined(V8_IMMINENT_DEPRECATION_WARNINGS)
718// Handle is an alias for Local for historical reasons.
719template <class T>
720using Handle = Local<T>;
721#endif
722
723/**
724 * A MaybeLocal<> is a wrapper around Local<> that enforces a check whether
725 * the Local<> is empty before it can be used.
726 *
727 * If an API method returns a MaybeLocal<>, the API method can potentially fail
728 * either because an exception is thrown, or because an exception is pending,
729 * e.g. because a previous API call threw an exception that hasn't been caught
730 * yet, or because a TerminateExecution exception was thrown. In that case, an
731 * empty MaybeLocal is returned.
732 */
733template <class T>
735 public:
736 /**
737 * Default constructor: Returns an empty handle.
738 */
740 /**
741 * Implicitly construct MaybeLocal from Local.
742 */
743 template <class S>
746 /**
747 * Implicitly up-cast MaybeLocal<S> to MaybeLocal<T> if T is a base of S.
748 */
749 template <class S>
752
753 V8_INLINE bool IsEmpty() const { return local_.IsEmpty(); }
754
755 /**
756 * Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty,
757 * |false| is returned and |out| is assigned with nullptr.
758 */
759 template <class S>
761 *out = local_;
762 return !IsEmpty();
763 }
764
765 /**
766 * Converts this MaybeLocal<> to a Local<>. If this MaybeLocal<> is empty,
767 * V8 will crash the process.
768 */
771 return local_;
772 }
773
774 /**
775 * Converts this MaybeLocal<> to a Local<>, using a default value if this
776 * MaybeLocal<> is empty.
777 */
778 template <class S>
780 return IsEmpty() ? default_value : Local<S>(local_);
781 }
782
783 /**
784 * Cast a handle to a subclass, e.g. MaybeLocal<Value> to MaybeLocal<Object>.
785 * This is only valid if the handle actually refers to a value of the target
786 * type or if the handle is empty.
787 */
788 template <class S>
790 return MaybeLocal<T>{Local<T>::Cast(that.local_)};
791 }
792
793 /**
794 * Calling this is equivalent to MaybeLocal<S>::Cast().
795 * In particular, this is only valid if the handle actually refers to a value
796 * of the target type or if the handle is empty.
797 */
798 template <class S>
800 return MaybeLocal<S>::Cast(*this);
801 }
802
803 private:
804 Local<T> local_;
805
806 template <typename S>
807 friend class MaybeLocal;
808};
809
810/**
811 * A HandleScope which first allocates a handle in the current scope
812 * which will be later filled with the escape value.
813 */
815 public:
818
820 void operator=(const EscapableHandleScopeBase&) = delete;
821 void* operator new(size_t size) = delete;
822 void* operator new[](size_t size) = delete;
823 void operator delete(void*, size_t) = delete;
824 void operator delete[](void*, size_t) = delete;
825
826 protected:
827 /**
828 * Pushes the value into the previous scope and returns a handle to it.
829 * Cannot be called twice.
830 */
832
833 private:
834 internal::Address* escape_slot_;
835};
836
838 : public EscapableHandleScopeBase {
839 public:
840 explicit EscapableHandleScope(Isolate* isolate)
843 template <class T>
845#ifdef V8_ENABLE_DIRECT_HANDLE
846 return value;
847#else
848 if (value.IsEmpty()) return value;
849 return Local<T>::FromSlot(EscapeSlot(value.slot()));
850#endif
851 }
852
853 template <class T>
855 return Escape(value.FromMaybe(Local<T>()));
856 }
857};
858
859/**
860 * A SealHandleScope acts like a handle scope in which no handle allocations
861 * are allowed. It can be useful for debugging handle leaks.
862 * Handles can be allocated within inner normal HandleScopes.
863 */
865 public:
866 explicit SealHandleScope(Isolate* isolate);
868
870 void operator=(const SealHandleScope&) = delete;
871 void* operator new(size_t size) = delete;
872 void* operator new[](size_t size) = delete;
873 void operator delete(void*, size_t) = delete;
874 void operator delete[](void*, size_t) = delete;
875
876 private:
877 internal::Isolate* const i_isolate_;
878 internal::Address* prev_limit_;
879 int prev_sealed_level_;
880};
881
882} // namespace v8
883
884#endif // INCLUDE_V8_LOCAL_HANDLE_H_
EscapableHandleScopeBase(const EscapableHandleScopeBase &)=delete
internal::Address * EscapeSlot(internal::Address *escape_value)
EscapableHandleScopeBase(Isolate *isolate)
void * operator new(size_t size)=delete
void operator=(const EscapableHandleScopeBase &)=delete
void operator delete(void *, size_t)=delete
void operator delete[](void *, size_t)=delete
void * operator new[](size_t size)=delete
V8_INLINE ~EscapableHandleScopeBase()=default
V8_INLINE Local< T > Escape(Local< T > value)
EscapableHandleScope(Isolate *isolate)
V8_INLINE MaybeLocal< T > EscapeMaybe(MaybeLocal< T > value)
V8_INLINE ~EscapableHandleScope()=default
V8_INLINE void Initialize(Isolate *isolate)
V8_INLINE ~HandleScope()
V8_INLINE HandleScope()=default
static int NumberOfHandles(Isolate *isolate)
V8_INLINE Isolate * GetIsolate() const
static V8_INLINE internal::Address * CreateHandle(Isolate *i_isolate, internal::Address value)
HandleScope(const HandleScope &)=delete
static internal::Address * CreateHandleForCurrentIsolate(internal::Address value)
friend class LocalBase
V8_INLINE HandleScope(Isolate *isolate)
void operator=(const HandleScope &)=delete
V8_INLINE LocalBase(internal::Address *location)
V8_INLINE LocalBase(const LocalBase< S > &other)
V8_INLINE LocalBase()=default
static V8_INLINE LocalBase< T > FromRepr(internal::ValueHelper::InternalRepresentationType repr)
static V8_INLINE LocalBase< T > New(Isolate *isolate, T *that)
static V8_INLINE LocalBase< T > New(Isolate *isolate, internal::Address value)
static V8_INLINE LocalBase< T > FromSlot(internal::Address *slot)
friend class Local
friend Local< Primitive > Null(Isolate *isolate)
friend class internal::CustomArguments
friend Local< Boolean > False(Isolate *isolate)
friend Local< Primitive > Undefined(Isolate *isolate)
friend class Traced
friend class MaybeLocal
friend Local< Boolean > True(Isolate *isolate)
friend class Persistent
V8_INLINE Local()=default
friend class Global
friend class Eternal
void clear() noexcept
friend bool operator>=(const LocalVector< T > &x, const LocalVector< T > &y)
const_iterator begin() const noexcept
friend bool operator<(const LocalVector< T > &x, const LocalVector< T > &y)
size_t size() const noexcept
friend bool operator<=(const LocalVector< T > &x, const LocalVector< T > &y)
bool empty() const noexcept
LocalVector(Isolate *isolate, std::initializer_list< Local< T > > init)
const Local< T > * data() const noexcept
friend bool operator!=(const LocalVector< T > &x, const LocalVector< T > &y)
iterator insert(const_iterator pos, std::initializer_list< Local< T > > init)
void resize(size_t n)
const_iterator end() const noexcept
LocalVector(Isolate *isolate, size_t n)
const Local< T > & back() const
Local< T > * data() noexcept
void swap(LocalVector< T > &other)
Local< T > & front()
LocalVector(Isolate *isolate)
iterator begin() noexcept
iterator insert(const_iterator pos, const Local< T > &value)
LocalVector< T > & operator=(std::initializer_list< Local< T > > init)
Local< T > & operator[](size_t n)
const Local< T > & operator[](size_t n) const
iterator insert(const_iterator pos, InputIt first, InputIt last)
Local< T > & back()
void emplace_back(Args &&... args)
friend bool operator==(const LocalVector< T > &x, const LocalVector< T > &y)
const Local< T > & front() const
void push_back(const Local< T > &x)
const Local< T > & at(size_t n) const
Local< T > & at(size_t n)
void reserve(size_t n)
friend bool operator>(const LocalVector< T > &x, const LocalVector< T > &y)
iterator end() noexcept
V8_INLINE MaybeLocal()=default
friend class PersistentValueMapBase
friend class FunctionCallbackInfo
void operator=(const SealHandleScope &)=delete
void * operator new(size_t size)=delete
void operator delete(void *, size_t)=delete
void operator delete[](void *, size_t)=delete
void * operator new[](size_t size)=delete
SealHandleScope(Isolate *isolate)
SealHandleScope(const SealHandleScope &)=delete
static V8_INLINE HandleScopeData * GetHandleScopeData(v8::Isolate *isolate)
LocalUnchecked(const Local< T > &other) noexcept
V8_EXPORT void ToLocalEmpty()
uintptr_t Address
Definition v8-internal.h:52
#define V8_HAS_ATTRIBUTE_TRIVIAL_ABI
Definition v8config.h:814
#define V8_EXPORT
Definition v8config.h:860
#define V8_INLINE
Definition v8config.h:513
#define V8_WARN_UNUSED_RESULT
Definition v8config.h:684
#define V8_UNLIKELY(condition)
Definition v8config.h:673
#define V8_TRIVIAL_ABI
Definition v8config.h:813
#define V8_NODISCARD
Definition v8config.h:706