150 V8_INLINE void SetWeak(P* parameter,
151 typename WeakCallbackInfo::Callback callback,
152 WeakCallbackType type);
153
154 /**
155 * Turns this handle into a weak phantom handle without finalization callback.
156 * The handle will be reset automatically when the garbage collector detects
157 * that the object is no longer reachable.
158 */
159 V8_INLINE void SetWeak();
160
161 template
162 V8_INLINE P* ClearWeak();
163
164 // TODO(dcarney): remove this.
165 V8_INLINE void ClearWeak() { ClearWeak(); }
166
167 /**
168 * Annotates the strong handle with the given label, which is then used by the
169 * heap snapshot generator as a name of the edge from the root to the handle.
170 * The function does not take ownership of the label and assumes that the
171 * label is valid as long as the handle is valid.
172 */
173 V8_INLINE void AnnotateStrongRetainer(const char* label);
174
175 /** Returns true if the handle's reference is weak. */
176 V8_INLINE bool IsWeak() const;
177
178 /**
179 * Assigns a wrapper class ID to the handle.
180 */
181 V8_INLINE void SetWrapperClassId(uint16_t class_id);
182
183 /**
184 * Returns the class ID previously assigned to this handle or 0 if no class ID
185 * was previously assigned.
186 */
187 V8_INLINE uint16_t WrapperClassId() const;
188
189 PersistentBase(const PersistentBase& other) = delete;
190 void operator=(const PersistentBase&) = delete;
191
192 private:
193 friend class Isolate;
194 friend class Utils;
195 template
196 friend class Local;
197 template
198 friend class Persistent;
199 template
200 friend class Global;
201 template
202 friend class PersistentBase;
203 template
204 friend class ReturnValue;
205 template
206 friend class PersistentValueMapBase;
207 template
208 friend class PersistentValueVector;
209 friend class Object;
210 friend class internal::ValueHelper;
211
212 V8_INLINE PersistentBase() = default;
213
214 V8_INLINE explicit PersistentBase(internal::Address* location)
215 : IndirectHandleBase(location) {}
216
217 V8_INLINE static internal::Address* New(Isolate* isolate, T* that);
218 };
219
220 /**
221 * Default traits for Persistent. This class does not allow
222 * use of the copy constructor or assignment operator.
223 * At present kResetInDestructor is not set, but that will change in a future
224 * version.
225 */
226 template
227 class NonCopyablePersistentTraits {
228 public:
229 using NonCopyablePersistent = Persistent>;
230 static const bool kResetInDestructor = false;
231 template
232 V8_INLINE static void Copy(const Persistent& source,
233 NonCopyablePersistent* dest) {
234 static_assert(sizeof(S) < 0,
235 "NonCopyablePersistentTraits::Copy is not instantiable");
236 }
237 };
238
239 /**
240 * Helper class traits to allow copying and assignment of Persistent.
241 * This will clone the contents of storage cell, but not any of the flags, etc.
242 */
243 template
244 struct CopyablePersistentTraits {
245 using CopyablePersistent = Persistent>;
246 static const bool kResetInDestructor = true;
247 template
248 static V8_INLINE void Copy(const Persistent& source,
249 CopyablePersistent* dest) {
250 // do nothing, just allow copy
251 }
252 };
253
254 /**
255 * A PersistentBase which allows copy and assignment.
256 *
257 * Copy, assignment and destructor behavior is controlled by the traits
258 * class M.
259 *
260 * CAVEAT: Persistent objects do not have proper destruction behavior by default
261 * and as such will leak the object without explicit clear. Consider using
262 * `v8::Global` instead which has proper destruction and move semantics.
263 */
264 template
265 class Persistent : public PersistentBase {
266 public:
267 /**
268 * A Persistent with no storage cell.
269 */
270 V8_INLINE Persistent() = default;
271
272 /**
273 * Construct a Persistent from a Local.
274 * When the Local is non-empty, a new storage cell is created
275 * pointing to the same object, and no flags are set.
276 */
277 template
278 V8_INLINE Persistent(Isolate* isolate, Local that)
279 : PersistentBase(
280 PersistentBase::New(isolate, that.template value())) {
281 static_assert(std::is_base_of::value, "type check");
282 }
283
284 /**
285 * Construct a Persistent from a Persistent.
286 * When the Persistent is non-empty, a new storage cell is created
287 * pointing to the same object, and no flags are set.
288 */
289 template
290 V8_INLINE Persistent(Isolate* isolate, const Persistent& that)
291 : PersistentBase(
292 PersistentBase::New(isolate, that.template value())) {
293 static_assert(std::is_base_of::value, "type check");
294 }
295
296 /**
297 * The copy constructors and assignment operator create a Persistent
298 * exactly as the Persistent constructor, but the Copy function from the
299 * traits class is called, allowing the setting of flags based on the
300 * copied Persistent.
301 */
302 V8_INLINE Persistent(const Persistent& that) : PersistentBase() {
303 Copy(that);
304 }
305 template
306 V8_INLINE Persistent(const Persistent& that) : PersistentBase() {
307 Copy(that);
308 }
309 V8_INLINE Persistent& operator=(const Persistent& that) {
310 Copy(that);
311 return *this;
312 }
313 template
314 V8_INLINE Persistent& operator=(const Persistent& that) {
315 Copy(that);
316 return *this;
317 }
318
319 /**
320 * The destructor will dispose the Persistent based on the
321 * kResetInDestructor flags in the traits class. Since not calling dispose
322 * can result in a memory leak, it is recommended to always set this flag.
323 */
324 V8_INLINE ~Persistent() {
325 if (M::kResetInDestructor) this->Reset();
326 }
327
328 // TODO(dcarney): this is pretty useless, fix or remove
329 template
330 V8_INLINE static Persistent& Cast(const Persistent& that) {
331 #ifdef V8_ENABLE_CHECKS
332 // If we're going to perform the type check then we have to check
333 // that the handle isn't empty before doing the checked cast.
334 if (!that.IsEmpty()) T::Cast(that.template value());
335 #endif
336 return reinterpret_cast&>(
337 const_cast&>(that));
338 }
339
340 // TODO(dcarney): this is pretty useless, fix or remove
341 template
342 V8_INLINE Persistent& As() const {
343 return Persistent::Cast(*this);
344 }
345
346 private:
347 friend class Isolate;
348 friend class Utils;
349 template
350 friend class Local;
351 template
352 friend class Persistent;
353 template
354 friend class ReturnValue;
355
356 template
357 V8_INLINE void Copy(const Persistent& that);
358 };
359
360 /**
361 * A PersistentBase which has move semantics.
362 *
363 * Note: Persistent class hierarchy is subject to future changes.
364 */
365 template
366 class Global : public PersistentBase {
367 public:
368 /**
369 * A Global with no storage cell.
370 */
371 V8_INLINE Global() = default;
372
373 /**
374 * Construct a Global from a Local.
375 * When the Local is non-empty, a new storage cell is created
376 * pointing to the same object, and no flags are set.
377 */
378 template
379 V8_INLINE Global(Isolate* isolate, Local that)
380 : PersistentBase(
381 PersistentBase::New(isolate, that.template value())) {
382 static_assert(std::is_base_of::value, "type check");
383 }
384
385 /**
386 * Construct a Global from a PersistentBase.
387 * When the Persistent is non-empty, a new storage cell is created
388 * pointing to the same object, and no flags are set.
389 */
390 template
391 V8_INLINE Global(Isolate* isolate, const PersistentBase& that)
392 : PersistentBase(
393 PersistentBase::New(isolate, that.template value())) {
394 static_assert(std::is_base_of::value, "type check");
395 }
396
397 /**
398 * Move constructor.
399 */
400 V8_INLINE Global(Global&& other);
401
402 V8_INLINE ~Global() { this->Reset(); }
403
404 /**
405 * Move via assignment.
406 */
407 template
408 V8_INLINE Global& operator=(Global&& rhs);
409
410 /**
411 * Pass allows returning uniques from functions, etc.
412 */
413 Global Pass() { return static_cast(*this); }
414
415 /*
416 * For compatibility with Chromium's base::Bind (base::Passed).
417 */
418 using MoveOnlyTypeForCPP03 = void;
419
420 Global(const Global&) = delete;
421 void operator=(const Global&) = delete;
422
423 private:
424 template
425 friend class ReturnValue;
426 };
427
428 // UniquePersistent is an alias for Global for historical reason.
429 template
430 using UniquePersistent = Global;
431
432 /**
433 * Interface for iterating through all the persistent handles in the heap.
434 */
435 class V8_EXPORT PersistentHandleVisitor {
436 public:
437 virtual ~PersistentHandleVisitor() = default;
438 virtual void VisitPersistentHandle(Persistent* value,
439 uint16_t class_id) {}
440 };
441
442 template
443 internal::Address* PersistentBase::New(Isolate* isolate, T* that) {
444 if (internal::ValueHelper::IsEmpty(that)) return nullptr;
445 return api_internal::GlobalizeReference(
446 reinterpret_cast(isolate),
447 internal::ValueHelper::ValueAsAddress(that));
448 }
449
450 template
451 template
452 void Persistent::Copy(const Persistent& that) {
453 static_assert(std::is_base_of::value, "type check");
454 this->Reset();
455 if (that.IsEmpty()) return;
456 this->slot() = api_internal::CopyGlobalReference(that.slot());
457 M::Copy(that, this);
458 }
459
460 template
461 bool PersistentBase::IsWeak() const {
462 using I = internal::Internals;
463 if (this->IsEmpty()) return false;
464 return I::GetNodeState(this->slot()) == I::kNodeStateIsWeakValue;
465 }
466
467 template
468 void PersistentBase::Reset() {
469 if (this->IsEmpty()) return;
470 api_internal::DisposeGlobal(this->slot());
471 this->Clear();
472 }
473
474 /**
475 * If non-empty, destroy the underlying storage cell
476 * and create a new one with the contents of other if other is non empty
477 */
478 template
479 template
480 void PersistentBase::Reset(Isolate* isolate, const Local& other) {
481 static_assert(std::is_base_of::value, "type check");
482 Reset();
483 if (other.IsEmpty()) return;
484 this->slot() = New(isolate, *other);
485 }
486
487 /**
488 * If non-empty, destroy the underlying storage cell
489 * and create a new one with the contents of other if other is non empty
490 */
491 template
492 template
493 void PersistentBase::Reset(Isolate* isolate,
494 const PersistentBase& other) {
495 static_assert(std::is_base_of::value, "type check");
496 Reset();
497 if (other.IsEmpty()) return;
498 this->slot() = New(isolate, other.template value());
499 }
500
501 template
502 template
503 V8_INLINE void PersistentBase::SetWeak(
504 P* parameter, typename WeakCallbackInfo::Callback callback,
505 WeakCallbackType type) {
506 using Callback = WeakCallbackInfo::Callback;
507 #if (__GNUC__ >= 8) && !defined(__clang__)
508 #pragma GCC diagnostic push
509 #pragma GCC diagnostic ignored "-Wcast-function-type"
510 #endif
511 api_internal::MakeWeak(this->slot(), parameter,
512 reinterpret_cast(callback), type);
513 #if (__GNUC__ >= 8) && !defined(__clang__)
514 #pragma GCC diagnostic pop
515 #endif
516 }
517
518 template
519 void PersistentBase::SetWeak() {
520 api_internal::MakeWeak(&this->slot());
521 }
522
523 template
524 template
525 P* PersistentBase::ClearWeak() {
526 return reinterpret_cast(api_internal::ClearWeak(this->slot()));
527 }
528
529 template
530 void PersistentBase::AnnotateStrongRetainer(const char* label) {
531 api_internal::AnnotateStrongRetainer(this->slot(), label);
532 }
533
534 template
535 void PersistentBase::SetWrapperClassId(uint16_t class_id) {
536 using I = internal::Internals;
537 if (this->IsEmpty()) return;
538 uint8_t* addr = reinterpret_cast(slot()) + I::kNodeClassIdOffset;
539 *reinterpret_cast(addr) = class_id;
540 }
541
542 template
543 uint16_t PersistentBase::WrapperClassId() const {
544 using I = internal::Internals;
545 if (this->IsEmpty()) return 0;
546 uint8_t* addr = reinterpret_cast(slot()) + I::kNodeClassIdOffset;
547 return *reinterpret_cast(addr);
548 }
549
550 template
551 Global::Global(Global&& other) : PersistentBase(other.slot()) {
552 if (!other.IsEmpty()) {
553 api_internal::MoveGlobalReference(&other.slot(), &this->slot());
554 other.Clear();
555 }
556 }
557
558 template
559 template
560 Global& Global::operator=(Global&& rhs) {
561 static_assert(std::is_base_of::value, "type check");
562 if (this != &rhs) {
563 this->Reset();
564 if (!rhs.IsEmpty()) {
565 this->slot() = rhs.slot();
566 api_internal::MoveGlobalReference(&rhs.slot(), &this->slot());
567 rhs.Clear();
568 }
569 }
570 return *this;
571 }
572
573 } // namespace v8
574
575 #endif // INCLUDE_V8_PERSISTENT_HANDLE_H_