11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_UTIL_H_
61cb0ef41Sopenharmony_ci#define V8_UTIL_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <assert.h>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include <map>
111cb0ef41Sopenharmony_ci#include <vector>
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci#include "v8-function-callback.h"  // NOLINT(build/include_directory)
141cb0ef41Sopenharmony_ci#include "v8-persistent-handle.h"  // NOLINT(build/include_directory)
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci/**
171cb0ef41Sopenharmony_ci * Support for Persistent containers.
181cb0ef41Sopenharmony_ci *
191cb0ef41Sopenharmony_ci * C++11 embedders can use STL containers with Global values,
201cb0ef41Sopenharmony_ci * but pre-C++11 does not support the required move semantic and hence
211cb0ef41Sopenharmony_ci * may want these container classes.
221cb0ef41Sopenharmony_ci */
231cb0ef41Sopenharmony_cinamespace v8 {
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_citemplate <typename K, typename V, typename Traits>
261cb0ef41Sopenharmony_ciclass GlobalValueMap;
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_citypedef uintptr_t PersistentContainerValue;
291cb0ef41Sopenharmony_cistatic const uintptr_t kPersistentContainerNotFound = 0;
301cb0ef41Sopenharmony_cienum PersistentContainerCallbackType {
311cb0ef41Sopenharmony_ci  kNotWeak,
321cb0ef41Sopenharmony_ci  // These correspond to v8::WeakCallbackType
331cb0ef41Sopenharmony_ci  kWeakWithParameter,
341cb0ef41Sopenharmony_ci  kWeakWithInternalFields
351cb0ef41Sopenharmony_ci};
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci/**
381cb0ef41Sopenharmony_ci * A default trait implementation for PersistentValueMap which uses std::map
391cb0ef41Sopenharmony_ci * as a backing map.
401cb0ef41Sopenharmony_ci *
411cb0ef41Sopenharmony_ci * Users will have to implement their own weak callbacks & dispose traits.
421cb0ef41Sopenharmony_ci */
431cb0ef41Sopenharmony_citemplate<typename K, typename V>
441cb0ef41Sopenharmony_ciclass StdMapTraits {
451cb0ef41Sopenharmony_ci public:
461cb0ef41Sopenharmony_ci  // STL map & related:
471cb0ef41Sopenharmony_ci  typedef std::map<K, PersistentContainerValue> Impl;
481cb0ef41Sopenharmony_ci  typedef typename Impl::iterator Iterator;
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  static bool Empty(Impl* impl) { return impl->empty(); }
511cb0ef41Sopenharmony_ci  static size_t Size(Impl* impl) { return impl->size(); }
521cb0ef41Sopenharmony_ci  static void Swap(Impl& a, Impl& b) { std::swap(a, b); }
531cb0ef41Sopenharmony_ci  static Iterator Begin(Impl* impl) { return impl->begin(); }
541cb0ef41Sopenharmony_ci  static Iterator End(Impl* impl) { return impl->end(); }
551cb0ef41Sopenharmony_ci  static K Key(Iterator it) { return it->first; }
561cb0ef41Sopenharmony_ci  static PersistentContainerValue Value(Iterator it) { return it->second; }
571cb0ef41Sopenharmony_ci  static PersistentContainerValue Set(Impl* impl, K key,
581cb0ef41Sopenharmony_ci      PersistentContainerValue value) {
591cb0ef41Sopenharmony_ci    std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
601cb0ef41Sopenharmony_ci    PersistentContainerValue old_value = kPersistentContainerNotFound;
611cb0ef41Sopenharmony_ci    if (!res.second) {
621cb0ef41Sopenharmony_ci      old_value = res.first->second;
631cb0ef41Sopenharmony_ci      res.first->second = value;
641cb0ef41Sopenharmony_ci    }
651cb0ef41Sopenharmony_ci    return old_value;
661cb0ef41Sopenharmony_ci  }
671cb0ef41Sopenharmony_ci  static PersistentContainerValue Get(Impl* impl, K key) {
681cb0ef41Sopenharmony_ci    Iterator it = impl->find(key);
691cb0ef41Sopenharmony_ci    if (it == impl->end()) return kPersistentContainerNotFound;
701cb0ef41Sopenharmony_ci    return it->second;
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci  static PersistentContainerValue Remove(Impl* impl, K key) {
731cb0ef41Sopenharmony_ci    Iterator it = impl->find(key);
741cb0ef41Sopenharmony_ci    if (it == impl->end()) return kPersistentContainerNotFound;
751cb0ef41Sopenharmony_ci    PersistentContainerValue value = it->second;
761cb0ef41Sopenharmony_ci    impl->erase(it);
771cb0ef41Sopenharmony_ci    return value;
781cb0ef41Sopenharmony_ci  }
791cb0ef41Sopenharmony_ci};
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci/**
831cb0ef41Sopenharmony_ci * A default trait implementation for PersistentValueMap, which inherits
841cb0ef41Sopenharmony_ci * a std:map backing map from StdMapTraits and holds non-weak persistent
851cb0ef41Sopenharmony_ci * objects and has no special Dispose handling.
861cb0ef41Sopenharmony_ci *
871cb0ef41Sopenharmony_ci * You should not derive from this class, since MapType depends on the
881cb0ef41Sopenharmony_ci * surrounding class, and hence a subclass cannot simply inherit the methods.
891cb0ef41Sopenharmony_ci */
901cb0ef41Sopenharmony_citemplate<typename K, typename V>
911cb0ef41Sopenharmony_ciclass DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
921cb0ef41Sopenharmony_ci public:
931cb0ef41Sopenharmony_ci  // Weak callback & friends:
941cb0ef41Sopenharmony_ci  static const PersistentContainerCallbackType kCallbackType = kNotWeak;
951cb0ef41Sopenharmony_ci  typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
961cb0ef41Sopenharmony_ci      MapType;
971cb0ef41Sopenharmony_ci  typedef void WeakCallbackDataType;
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  static WeakCallbackDataType* WeakCallbackParameter(
1001cb0ef41Sopenharmony_ci      MapType* map, const K& key, Local<V> value) {
1011cb0ef41Sopenharmony_ci    return nullptr;
1021cb0ef41Sopenharmony_ci  }
1031cb0ef41Sopenharmony_ci  static MapType* MapFromWeakCallbackInfo(
1041cb0ef41Sopenharmony_ci      const WeakCallbackInfo<WeakCallbackDataType>& data) {
1051cb0ef41Sopenharmony_ci    return nullptr;
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci  static K KeyFromWeakCallbackInfo(
1081cb0ef41Sopenharmony_ci      const WeakCallbackInfo<WeakCallbackDataType>& data) {
1091cb0ef41Sopenharmony_ci    return K();
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci  static void DisposeCallbackData(WeakCallbackDataType* data) { }
1121cb0ef41Sopenharmony_ci  static void Dispose(Isolate* isolate, Global<V> value, K key) {}
1131cb0ef41Sopenharmony_ci};
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_citemplate <typename K, typename V>
1171cb0ef41Sopenharmony_ciclass DefaultGlobalMapTraits : public StdMapTraits<K, V> {
1181cb0ef41Sopenharmony_ci private:
1191cb0ef41Sopenharmony_ci  template <typename T>
1201cb0ef41Sopenharmony_ci  struct RemovePointer;
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci public:
1231cb0ef41Sopenharmony_ci  // Weak callback & friends:
1241cb0ef41Sopenharmony_ci  static const PersistentContainerCallbackType kCallbackType = kNotWeak;
1251cb0ef41Sopenharmony_ci  typedef GlobalValueMap<K, V, DefaultGlobalMapTraits<K, V> > MapType;
1261cb0ef41Sopenharmony_ci  typedef void WeakCallbackDataType;
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
1291cb0ef41Sopenharmony_ci                                                     Local<V> value) {
1301cb0ef41Sopenharmony_ci    return nullptr;
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci  static MapType* MapFromWeakCallbackInfo(
1331cb0ef41Sopenharmony_ci      const WeakCallbackInfo<WeakCallbackDataType>& data) {
1341cb0ef41Sopenharmony_ci    return nullptr;
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci  static K KeyFromWeakCallbackInfo(
1371cb0ef41Sopenharmony_ci      const WeakCallbackInfo<WeakCallbackDataType>& data) {
1381cb0ef41Sopenharmony_ci    return K();
1391cb0ef41Sopenharmony_ci  }
1401cb0ef41Sopenharmony_ci  static void DisposeCallbackData(WeakCallbackDataType* data) {}
1411cb0ef41Sopenharmony_ci  static void OnWeakCallback(
1421cb0ef41Sopenharmony_ci      const WeakCallbackInfo<WeakCallbackDataType>& data) {}
1431cb0ef41Sopenharmony_ci  static void Dispose(Isolate* isolate, Global<V> value, K key) {}
1441cb0ef41Sopenharmony_ci  // This is a second pass callback, so SetSecondPassCallback cannot be called.
1451cb0ef41Sopenharmony_ci  static void DisposeWeak(const WeakCallbackInfo<WeakCallbackDataType>& data) {}
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci private:
1481cb0ef41Sopenharmony_ci  template <typename T>
1491cb0ef41Sopenharmony_ci  struct RemovePointer<T*> {
1501cb0ef41Sopenharmony_ci    typedef T Type;
1511cb0ef41Sopenharmony_ci  };
1521cb0ef41Sopenharmony_ci};
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci/**
1561cb0ef41Sopenharmony_ci * A map wrapper that allows using Global as a mapped value.
1571cb0ef41Sopenharmony_ci * C++11 embedders don't need this class, as they can use Global
1581cb0ef41Sopenharmony_ci * directly in std containers.
1591cb0ef41Sopenharmony_ci *
1601cb0ef41Sopenharmony_ci * The map relies on a backing map, whose type and accessors are described
1611cb0ef41Sopenharmony_ci * by the Traits class. The backing map will handle values of type
1621cb0ef41Sopenharmony_ci * PersistentContainerValue, with all conversion into and out of V8
1631cb0ef41Sopenharmony_ci * handles being transparently handled by this class.
1641cb0ef41Sopenharmony_ci */
1651cb0ef41Sopenharmony_citemplate <typename K, typename V, typename Traits>
1661cb0ef41Sopenharmony_ciclass PersistentValueMapBase {
1671cb0ef41Sopenharmony_ci public:
1681cb0ef41Sopenharmony_ci  Isolate* GetIsolate() { return isolate_; }
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  /**
1711cb0ef41Sopenharmony_ci   * Return size of the map.
1721cb0ef41Sopenharmony_ci   */
1731cb0ef41Sopenharmony_ci  size_t Size() { return Traits::Size(&impl_); }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  /**
1761cb0ef41Sopenharmony_ci   * Return whether the map holds weak persistents.
1771cb0ef41Sopenharmony_ci   */
1781cb0ef41Sopenharmony_ci  bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  /**
1811cb0ef41Sopenharmony_ci   * Get value stored in map.
1821cb0ef41Sopenharmony_ci   */
1831cb0ef41Sopenharmony_ci  Local<V> Get(const K& key) {
1841cb0ef41Sopenharmony_ci    return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  /**
1881cb0ef41Sopenharmony_ci   * Check whether a value is contained in the map.
1891cb0ef41Sopenharmony_ci   */
1901cb0ef41Sopenharmony_ci  bool Contains(const K& key) {
1911cb0ef41Sopenharmony_ci    return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
1921cb0ef41Sopenharmony_ci  }
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  /**
1951cb0ef41Sopenharmony_ci   * Get value stored in map and set it in returnValue.
1961cb0ef41Sopenharmony_ci   * Return true if a value was found.
1971cb0ef41Sopenharmony_ci   */
1981cb0ef41Sopenharmony_ci  bool SetReturnValue(const K& key,
1991cb0ef41Sopenharmony_ci      ReturnValue<Value> returnValue) {
2001cb0ef41Sopenharmony_ci    return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
2011cb0ef41Sopenharmony_ci  }
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  /**
2041cb0ef41Sopenharmony_ci   * Return value for key and remove it from the map.
2051cb0ef41Sopenharmony_ci   */
2061cb0ef41Sopenharmony_ci  Global<V> Remove(const K& key) {
2071cb0ef41Sopenharmony_ci    return Release(Traits::Remove(&impl_, key)).Pass();
2081cb0ef41Sopenharmony_ci  }
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci  /**
2111cb0ef41Sopenharmony_ci  * Traverses the map repeatedly,
2121cb0ef41Sopenharmony_ci  * in case side effects of disposal cause insertions.
2131cb0ef41Sopenharmony_ci  **/
2141cb0ef41Sopenharmony_ci  void Clear() {
2151cb0ef41Sopenharmony_ci    typedef typename Traits::Iterator It;
2161cb0ef41Sopenharmony_ci    HandleScope handle_scope(isolate_);
2171cb0ef41Sopenharmony_ci    // TODO(dcarney): figure out if this swap and loop is necessary.
2181cb0ef41Sopenharmony_ci    while (!Traits::Empty(&impl_)) {
2191cb0ef41Sopenharmony_ci      typename Traits::Impl impl;
2201cb0ef41Sopenharmony_ci      Traits::Swap(impl_, impl);
2211cb0ef41Sopenharmony_ci      for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
2221cb0ef41Sopenharmony_ci        Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
2231cb0ef41Sopenharmony_ci                        Traits::Key(i));
2241cb0ef41Sopenharmony_ci      }
2251cb0ef41Sopenharmony_ci    }
2261cb0ef41Sopenharmony_ci  }
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  /**
2291cb0ef41Sopenharmony_ci   * Helper class for GetReference/SetWithReference. Do not use outside
2301cb0ef41Sopenharmony_ci   * that context.
2311cb0ef41Sopenharmony_ci   */
2321cb0ef41Sopenharmony_ci  class PersistentValueReference {
2331cb0ef41Sopenharmony_ci   public:
2341cb0ef41Sopenharmony_ci    PersistentValueReference() : value_(kPersistentContainerNotFound) { }
2351cb0ef41Sopenharmony_ci    PersistentValueReference(const PersistentValueReference& other)
2361cb0ef41Sopenharmony_ci        : value_(other.value_) { }
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci    Local<V> NewLocal(Isolate* isolate) const {
2391cb0ef41Sopenharmony_ci      return Local<V>::New(isolate, FromVal(value_));
2401cb0ef41Sopenharmony_ci    }
2411cb0ef41Sopenharmony_ci    bool IsEmpty() const {
2421cb0ef41Sopenharmony_ci      return value_ == kPersistentContainerNotFound;
2431cb0ef41Sopenharmony_ci    }
2441cb0ef41Sopenharmony_ci    template<typename T>
2451cb0ef41Sopenharmony_ci    bool SetReturnValue(ReturnValue<T> returnValue) {
2461cb0ef41Sopenharmony_ci      return SetReturnValueFromVal(&returnValue, value_);
2471cb0ef41Sopenharmony_ci    }
2481cb0ef41Sopenharmony_ci    void Reset() {
2491cb0ef41Sopenharmony_ci      value_ = kPersistentContainerNotFound;
2501cb0ef41Sopenharmony_ci    }
2511cb0ef41Sopenharmony_ci    void operator=(const PersistentValueReference& other) {
2521cb0ef41Sopenharmony_ci      value_ = other.value_;
2531cb0ef41Sopenharmony_ci    }
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci   private:
2561cb0ef41Sopenharmony_ci    friend class PersistentValueMapBase;
2571cb0ef41Sopenharmony_ci    friend class PersistentValueMap<K, V, Traits>;
2581cb0ef41Sopenharmony_ci    friend class GlobalValueMap<K, V, Traits>;
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci    explicit PersistentValueReference(PersistentContainerValue value)
2611cb0ef41Sopenharmony_ci        : value_(value) { }
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci    void operator=(PersistentContainerValue value) {
2641cb0ef41Sopenharmony_ci      value_ = value;
2651cb0ef41Sopenharmony_ci    }
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci    PersistentContainerValue value_;
2681cb0ef41Sopenharmony_ci  };
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  /**
2711cb0ef41Sopenharmony_ci   * Get a reference to a map value. This enables fast, repeated access
2721cb0ef41Sopenharmony_ci   * to a value stored in the map while the map remains unchanged.
2731cb0ef41Sopenharmony_ci   *
2741cb0ef41Sopenharmony_ci   * Careful: This is potentially unsafe, so please use with care.
2751cb0ef41Sopenharmony_ci   * The value will become invalid if the value for this key changes
2761cb0ef41Sopenharmony_ci   * in the underlying map, as a result of Set or Remove for the same
2771cb0ef41Sopenharmony_ci   * key; as a result of the weak callback for the same key; or as a
2781cb0ef41Sopenharmony_ci   * result of calling Clear() or destruction of the map.
2791cb0ef41Sopenharmony_ci   */
2801cb0ef41Sopenharmony_ci  PersistentValueReference GetReference(const K& key) {
2811cb0ef41Sopenharmony_ci    return PersistentValueReference(Traits::Get(&impl_, key));
2821cb0ef41Sopenharmony_ci  }
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci protected:
2851cb0ef41Sopenharmony_ci  explicit PersistentValueMapBase(Isolate* isolate)
2861cb0ef41Sopenharmony_ci      : isolate_(isolate), label_(nullptr) {}
2871cb0ef41Sopenharmony_ci  PersistentValueMapBase(Isolate* isolate, const char* label)
2881cb0ef41Sopenharmony_ci      : isolate_(isolate), label_(label) {}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  ~PersistentValueMapBase() { Clear(); }
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci  Isolate* isolate() { return isolate_; }
2931cb0ef41Sopenharmony_ci  typename Traits::Impl* impl() { return &impl_; }
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci  static V* FromVal(PersistentContainerValue v) {
2961cb0ef41Sopenharmony_ci    return reinterpret_cast<V*>(v);
2971cb0ef41Sopenharmony_ci  }
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci  static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
3001cb0ef41Sopenharmony_ci    V* v = persistent->val_;
3011cb0ef41Sopenharmony_ci    persistent->val_ = nullptr;
3021cb0ef41Sopenharmony_ci    return reinterpret_cast<PersistentContainerValue>(v);
3031cb0ef41Sopenharmony_ci  }
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci  static PersistentContainerValue Leak(Global<V>* persistent) {
3061cb0ef41Sopenharmony_ci    return reinterpret_cast<PersistentContainerValue>(persistent->val_);
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  /**
3101cb0ef41Sopenharmony_ci   * Return a container value as Global and make sure the weak
3111cb0ef41Sopenharmony_ci   * callback is properly disposed of. All remove functionality should go
3121cb0ef41Sopenharmony_ci   * through this.
3131cb0ef41Sopenharmony_ci   */
3141cb0ef41Sopenharmony_ci  static Global<V> Release(PersistentContainerValue v) {
3151cb0ef41Sopenharmony_ci    Global<V> p;
3161cb0ef41Sopenharmony_ci    p.val_ = FromVal(v);
3171cb0ef41Sopenharmony_ci    if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
3181cb0ef41Sopenharmony_ci      Traits::DisposeCallbackData(
3191cb0ef41Sopenharmony_ci          p.template ClearWeak<typename Traits::WeakCallbackDataType>());
3201cb0ef41Sopenharmony_ci    }
3211cb0ef41Sopenharmony_ci    return p.Pass();
3221cb0ef41Sopenharmony_ci  }
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci  void RemoveWeak(const K& key) {
3251cb0ef41Sopenharmony_ci    Global<V> p;
3261cb0ef41Sopenharmony_ci    p.val_ = FromVal(Traits::Remove(&impl_, key));
3271cb0ef41Sopenharmony_ci    p.Reset();
3281cb0ef41Sopenharmony_ci  }
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  void AnnotateStrongRetainer(Global<V>* persistent) {
3311cb0ef41Sopenharmony_ci    persistent->AnnotateStrongRetainer(label_);
3321cb0ef41Sopenharmony_ci  }
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci private:
3351cb0ef41Sopenharmony_ci  PersistentValueMapBase(PersistentValueMapBase&);
3361cb0ef41Sopenharmony_ci  void operator=(PersistentValueMapBase&);
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci  static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
3391cb0ef41Sopenharmony_ci                                    PersistentContainerValue value) {
3401cb0ef41Sopenharmony_ci    bool hasValue = value != kPersistentContainerNotFound;
3411cb0ef41Sopenharmony_ci    if (hasValue) {
3421cb0ef41Sopenharmony_ci      returnValue->SetInternal(
3431cb0ef41Sopenharmony_ci          *reinterpret_cast<internal::Address*>(FromVal(value)));
3441cb0ef41Sopenharmony_ci    }
3451cb0ef41Sopenharmony_ci    return hasValue;
3461cb0ef41Sopenharmony_ci  }
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci  Isolate* isolate_;
3491cb0ef41Sopenharmony_ci  typename Traits::Impl impl_;
3501cb0ef41Sopenharmony_ci  const char* label_;
3511cb0ef41Sopenharmony_ci};
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_citemplate <typename K, typename V, typename Traits>
3541cb0ef41Sopenharmony_ciclass PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
3551cb0ef41Sopenharmony_ci public:
3561cb0ef41Sopenharmony_ci  explicit PersistentValueMap(Isolate* isolate)
3571cb0ef41Sopenharmony_ci      : PersistentValueMapBase<K, V, Traits>(isolate) {}
3581cb0ef41Sopenharmony_ci  PersistentValueMap(Isolate* isolate, const char* label)
3591cb0ef41Sopenharmony_ci      : PersistentValueMapBase<K, V, Traits>(isolate, label) {}
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  typedef
3621cb0ef41Sopenharmony_ci      typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
3631cb0ef41Sopenharmony_ci          PersistentValueReference;
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci  /**
3661cb0ef41Sopenharmony_ci   * Put value into map. Depending on Traits::kIsWeak, the value will be held
3671cb0ef41Sopenharmony_ci   * by the map strongly or weakly.
3681cb0ef41Sopenharmony_ci   * Returns old value as Global.
3691cb0ef41Sopenharmony_ci   */
3701cb0ef41Sopenharmony_ci  Global<V> Set(const K& key, Local<V> value) {
3711cb0ef41Sopenharmony_ci    Global<V> persistent(this->isolate(), value);
3721cb0ef41Sopenharmony_ci    return SetUnique(key, &persistent);
3731cb0ef41Sopenharmony_ci  }
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ci  /**
3761cb0ef41Sopenharmony_ci   * Put value into map, like Set(const K&, Local<V>).
3771cb0ef41Sopenharmony_ci   */
3781cb0ef41Sopenharmony_ci  Global<V> Set(const K& key, Global<V> value) {
3791cb0ef41Sopenharmony_ci    return SetUnique(key, &value);
3801cb0ef41Sopenharmony_ci  }
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci  /**
3831cb0ef41Sopenharmony_ci   * Put the value into the map, and set the 'weak' callback when demanded
3841cb0ef41Sopenharmony_ci   * by the Traits class.
3851cb0ef41Sopenharmony_ci   */
3861cb0ef41Sopenharmony_ci  Global<V> SetUnique(const K& key, Global<V>* persistent) {
3871cb0ef41Sopenharmony_ci    if (Traits::kCallbackType == kNotWeak) {
3881cb0ef41Sopenharmony_ci      this->AnnotateStrongRetainer(persistent);
3891cb0ef41Sopenharmony_ci    } else {
3901cb0ef41Sopenharmony_ci      WeakCallbackType callback_type =
3911cb0ef41Sopenharmony_ci          Traits::kCallbackType == kWeakWithInternalFields
3921cb0ef41Sopenharmony_ci              ? WeakCallbackType::kInternalFields
3931cb0ef41Sopenharmony_ci              : WeakCallbackType::kParameter;
3941cb0ef41Sopenharmony_ci      Local<V> value(Local<V>::New(this->isolate(), *persistent));
3951cb0ef41Sopenharmony_ci      persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
3961cb0ef41Sopenharmony_ci          Traits::WeakCallbackParameter(this, key, value), WeakCallback,
3971cb0ef41Sopenharmony_ci          callback_type);
3981cb0ef41Sopenharmony_ci    }
3991cb0ef41Sopenharmony_ci    PersistentContainerValue old_value =
4001cb0ef41Sopenharmony_ci        Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
4011cb0ef41Sopenharmony_ci    return this->Release(old_value).Pass();
4021cb0ef41Sopenharmony_ci  }
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  /**
4051cb0ef41Sopenharmony_ci   * Put a value into the map and update the reference.
4061cb0ef41Sopenharmony_ci   * Restrictions of GetReference apply here as well.
4071cb0ef41Sopenharmony_ci   */
4081cb0ef41Sopenharmony_ci  Global<V> Set(const K& key, Global<V> value,
4091cb0ef41Sopenharmony_ci                PersistentValueReference* reference) {
4101cb0ef41Sopenharmony_ci    *reference = this->Leak(&value);
4111cb0ef41Sopenharmony_ci    return SetUnique(key, &value);
4121cb0ef41Sopenharmony_ci  }
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ci private:
4151cb0ef41Sopenharmony_ci  static void WeakCallback(
4161cb0ef41Sopenharmony_ci      const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
4171cb0ef41Sopenharmony_ci    if (Traits::kCallbackType != kNotWeak) {
4181cb0ef41Sopenharmony_ci      PersistentValueMap<K, V, Traits>* persistentValueMap =
4191cb0ef41Sopenharmony_ci          Traits::MapFromWeakCallbackInfo(data);
4201cb0ef41Sopenharmony_ci      K key = Traits::KeyFromWeakCallbackInfo(data);
4211cb0ef41Sopenharmony_ci      Traits::Dispose(data.GetIsolate(),
4221cb0ef41Sopenharmony_ci                      persistentValueMap->Remove(key).Pass(), key);
4231cb0ef41Sopenharmony_ci      Traits::DisposeCallbackData(data.GetParameter());
4241cb0ef41Sopenharmony_ci    }
4251cb0ef41Sopenharmony_ci  }
4261cb0ef41Sopenharmony_ci};
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_citemplate <typename K, typename V, typename Traits>
4301cb0ef41Sopenharmony_ciclass GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
4311cb0ef41Sopenharmony_ci public:
4321cb0ef41Sopenharmony_ci  explicit GlobalValueMap(Isolate* isolate)
4331cb0ef41Sopenharmony_ci      : PersistentValueMapBase<K, V, Traits>(isolate) {}
4341cb0ef41Sopenharmony_ci  GlobalValueMap(Isolate* isolate, const char* label)
4351cb0ef41Sopenharmony_ci      : PersistentValueMapBase<K, V, Traits>(isolate, label) {}
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci  typedef
4381cb0ef41Sopenharmony_ci      typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
4391cb0ef41Sopenharmony_ci          PersistentValueReference;
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci  /**
4421cb0ef41Sopenharmony_ci   * Put value into map. Depending on Traits::kIsWeak, the value will be held
4431cb0ef41Sopenharmony_ci   * by the map strongly or weakly.
4441cb0ef41Sopenharmony_ci   * Returns old value as Global.
4451cb0ef41Sopenharmony_ci   */
4461cb0ef41Sopenharmony_ci  Global<V> Set(const K& key, Local<V> value) {
4471cb0ef41Sopenharmony_ci    Global<V> persistent(this->isolate(), value);
4481cb0ef41Sopenharmony_ci    return SetUnique(key, &persistent);
4491cb0ef41Sopenharmony_ci  }
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci  /**
4521cb0ef41Sopenharmony_ci   * Put value into map, like Set(const K&, Local<V>).
4531cb0ef41Sopenharmony_ci   */
4541cb0ef41Sopenharmony_ci  Global<V> Set(const K& key, Global<V> value) {
4551cb0ef41Sopenharmony_ci    return SetUnique(key, &value);
4561cb0ef41Sopenharmony_ci  }
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci  /**
4591cb0ef41Sopenharmony_ci   * Put the value into the map, and set the 'weak' callback when demanded
4601cb0ef41Sopenharmony_ci   * by the Traits class.
4611cb0ef41Sopenharmony_ci   */
4621cb0ef41Sopenharmony_ci  Global<V> SetUnique(const K& key, Global<V>* persistent) {
4631cb0ef41Sopenharmony_ci    if (Traits::kCallbackType == kNotWeak) {
4641cb0ef41Sopenharmony_ci      this->AnnotateStrongRetainer(persistent);
4651cb0ef41Sopenharmony_ci    } else {
4661cb0ef41Sopenharmony_ci      WeakCallbackType callback_type =
4671cb0ef41Sopenharmony_ci          Traits::kCallbackType == kWeakWithInternalFields
4681cb0ef41Sopenharmony_ci              ? WeakCallbackType::kInternalFields
4691cb0ef41Sopenharmony_ci              : WeakCallbackType::kParameter;
4701cb0ef41Sopenharmony_ci      Local<V> value(Local<V>::New(this->isolate(), *persistent));
4711cb0ef41Sopenharmony_ci      persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
4721cb0ef41Sopenharmony_ci          Traits::WeakCallbackParameter(this, key, value), OnWeakCallback,
4731cb0ef41Sopenharmony_ci          callback_type);
4741cb0ef41Sopenharmony_ci    }
4751cb0ef41Sopenharmony_ci    PersistentContainerValue old_value =
4761cb0ef41Sopenharmony_ci        Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
4771cb0ef41Sopenharmony_ci    return this->Release(old_value).Pass();
4781cb0ef41Sopenharmony_ci  }
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci  /**
4811cb0ef41Sopenharmony_ci   * Put a value into the map and update the reference.
4821cb0ef41Sopenharmony_ci   * Restrictions of GetReference apply here as well.
4831cb0ef41Sopenharmony_ci   */
4841cb0ef41Sopenharmony_ci  Global<V> Set(const K& key, Global<V> value,
4851cb0ef41Sopenharmony_ci                PersistentValueReference* reference) {
4861cb0ef41Sopenharmony_ci    *reference = this->Leak(&value);
4871cb0ef41Sopenharmony_ci    return SetUnique(key, &value);
4881cb0ef41Sopenharmony_ci  }
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci private:
4911cb0ef41Sopenharmony_ci  static void OnWeakCallback(
4921cb0ef41Sopenharmony_ci      const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
4931cb0ef41Sopenharmony_ci    if (Traits::kCallbackType != kNotWeak) {
4941cb0ef41Sopenharmony_ci      auto map = Traits::MapFromWeakCallbackInfo(data);
4951cb0ef41Sopenharmony_ci      K key = Traits::KeyFromWeakCallbackInfo(data);
4961cb0ef41Sopenharmony_ci      map->RemoveWeak(key);
4971cb0ef41Sopenharmony_ci      Traits::OnWeakCallback(data);
4981cb0ef41Sopenharmony_ci      data.SetSecondPassCallback(SecondWeakCallback);
4991cb0ef41Sopenharmony_ci    }
5001cb0ef41Sopenharmony_ci  }
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci  static void SecondWeakCallback(
5031cb0ef41Sopenharmony_ci      const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
5041cb0ef41Sopenharmony_ci    Traits::DisposeWeak(data);
5051cb0ef41Sopenharmony_ci  }
5061cb0ef41Sopenharmony_ci};
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ci/**
5101cb0ef41Sopenharmony_ci * A map that uses Global as value and std::map as the backing
5111cb0ef41Sopenharmony_ci * implementation. Persistents are held non-weak.
5121cb0ef41Sopenharmony_ci *
5131cb0ef41Sopenharmony_ci * C++11 embedders don't need this class, as they can use
5141cb0ef41Sopenharmony_ci * Global directly in std containers.
5151cb0ef41Sopenharmony_ci */
5161cb0ef41Sopenharmony_citemplate<typename K, typename V,
5171cb0ef41Sopenharmony_ci    typename Traits = DefaultPersistentValueMapTraits<K, V> >
5181cb0ef41Sopenharmony_ciclass StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
5191cb0ef41Sopenharmony_ci public:
5201cb0ef41Sopenharmony_ci  explicit StdPersistentValueMap(Isolate* isolate)
5211cb0ef41Sopenharmony_ci      : PersistentValueMap<K, V, Traits>(isolate) {}
5221cb0ef41Sopenharmony_ci};
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci/**
5261cb0ef41Sopenharmony_ci * A map that uses Global as value and std::map as the backing
5271cb0ef41Sopenharmony_ci * implementation. Globals are held non-weak.
5281cb0ef41Sopenharmony_ci *
5291cb0ef41Sopenharmony_ci * C++11 embedders don't need this class, as they can use
5301cb0ef41Sopenharmony_ci * Global directly in std containers.
5311cb0ef41Sopenharmony_ci */
5321cb0ef41Sopenharmony_citemplate <typename K, typename V,
5331cb0ef41Sopenharmony_ci          typename Traits = DefaultGlobalMapTraits<K, V> >
5341cb0ef41Sopenharmony_ciclass StdGlobalValueMap : public GlobalValueMap<K, V, Traits> {
5351cb0ef41Sopenharmony_ci public:
5361cb0ef41Sopenharmony_ci  explicit StdGlobalValueMap(Isolate* isolate)
5371cb0ef41Sopenharmony_ci      : GlobalValueMap<K, V, Traits>(isolate) {}
5381cb0ef41Sopenharmony_ci};
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ciclass DefaultPersistentValueVectorTraits {
5421cb0ef41Sopenharmony_ci public:
5431cb0ef41Sopenharmony_ci  typedef std::vector<PersistentContainerValue> Impl;
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_ci  static void Append(Impl* impl, PersistentContainerValue value) {
5461cb0ef41Sopenharmony_ci    impl->push_back(value);
5471cb0ef41Sopenharmony_ci  }
5481cb0ef41Sopenharmony_ci  static bool IsEmpty(const Impl* impl) {
5491cb0ef41Sopenharmony_ci    return impl->empty();
5501cb0ef41Sopenharmony_ci  }
5511cb0ef41Sopenharmony_ci  static size_t Size(const Impl* impl) {
5521cb0ef41Sopenharmony_ci    return impl->size();
5531cb0ef41Sopenharmony_ci  }
5541cb0ef41Sopenharmony_ci  static PersistentContainerValue Get(const Impl* impl, size_t i) {
5551cb0ef41Sopenharmony_ci    return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
5561cb0ef41Sopenharmony_ci  }
5571cb0ef41Sopenharmony_ci  static void ReserveCapacity(Impl* impl, size_t capacity) {
5581cb0ef41Sopenharmony_ci    impl->reserve(capacity);
5591cb0ef41Sopenharmony_ci  }
5601cb0ef41Sopenharmony_ci  static void Clear(Impl* impl) {
5611cb0ef41Sopenharmony_ci    impl->clear();
5621cb0ef41Sopenharmony_ci  }
5631cb0ef41Sopenharmony_ci};
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci/**
5671cb0ef41Sopenharmony_ci * A vector wrapper that safely stores Global values.
5681cb0ef41Sopenharmony_ci * C++11 embedders don't need this class, as they can use Global
5691cb0ef41Sopenharmony_ci * directly in std containers.
5701cb0ef41Sopenharmony_ci *
5711cb0ef41Sopenharmony_ci * This class relies on a backing vector implementation, whose type and methods
5721cb0ef41Sopenharmony_ci * are described by the Traits class. The backing map will handle values of type
5731cb0ef41Sopenharmony_ci * PersistentContainerValue, with all conversion into and out of V8
5741cb0ef41Sopenharmony_ci * handles being transparently handled by this class.
5751cb0ef41Sopenharmony_ci */
5761cb0ef41Sopenharmony_citemplate<typename V, typename Traits = DefaultPersistentValueVectorTraits>
5771cb0ef41Sopenharmony_ciclass PersistentValueVector {
5781cb0ef41Sopenharmony_ci public:
5791cb0ef41Sopenharmony_ci  explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
5801cb0ef41Sopenharmony_ci
5811cb0ef41Sopenharmony_ci  ~PersistentValueVector() {
5821cb0ef41Sopenharmony_ci    Clear();
5831cb0ef41Sopenharmony_ci  }
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci  /**
5861cb0ef41Sopenharmony_ci   * Append a value to the vector.
5871cb0ef41Sopenharmony_ci   */
5881cb0ef41Sopenharmony_ci  void Append(Local<V> value) {
5891cb0ef41Sopenharmony_ci    Global<V> persistent(isolate_, value);
5901cb0ef41Sopenharmony_ci    Traits::Append(&impl_, ClearAndLeak(&persistent));
5911cb0ef41Sopenharmony_ci  }
5921cb0ef41Sopenharmony_ci
5931cb0ef41Sopenharmony_ci  /**
5941cb0ef41Sopenharmony_ci   * Append a persistent's value to the vector.
5951cb0ef41Sopenharmony_ci   */
5961cb0ef41Sopenharmony_ci  void Append(Global<V> persistent) {
5971cb0ef41Sopenharmony_ci    Traits::Append(&impl_, ClearAndLeak(&persistent));
5981cb0ef41Sopenharmony_ci  }
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci  /**
6011cb0ef41Sopenharmony_ci   * Are there any values in the vector?
6021cb0ef41Sopenharmony_ci   */
6031cb0ef41Sopenharmony_ci  bool IsEmpty() const {
6041cb0ef41Sopenharmony_ci    return Traits::IsEmpty(&impl_);
6051cb0ef41Sopenharmony_ci  }
6061cb0ef41Sopenharmony_ci
6071cb0ef41Sopenharmony_ci  /**
6081cb0ef41Sopenharmony_ci   * How many elements are in the vector?
6091cb0ef41Sopenharmony_ci   */
6101cb0ef41Sopenharmony_ci  size_t Size() const {
6111cb0ef41Sopenharmony_ci    return Traits::Size(&impl_);
6121cb0ef41Sopenharmony_ci  }
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  /**
6151cb0ef41Sopenharmony_ci   * Retrieve the i-th value in the vector.
6161cb0ef41Sopenharmony_ci   */
6171cb0ef41Sopenharmony_ci  Local<V> Get(size_t index) const {
6181cb0ef41Sopenharmony_ci    return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
6191cb0ef41Sopenharmony_ci  }
6201cb0ef41Sopenharmony_ci
6211cb0ef41Sopenharmony_ci  /**
6221cb0ef41Sopenharmony_ci   * Remove all elements from the vector.
6231cb0ef41Sopenharmony_ci   */
6241cb0ef41Sopenharmony_ci  void Clear() {
6251cb0ef41Sopenharmony_ci    size_t length = Traits::Size(&impl_);
6261cb0ef41Sopenharmony_ci    for (size_t i = 0; i < length; i++) {
6271cb0ef41Sopenharmony_ci      Global<V> p;
6281cb0ef41Sopenharmony_ci      p.val_ = FromVal(Traits::Get(&impl_, i));
6291cb0ef41Sopenharmony_ci    }
6301cb0ef41Sopenharmony_ci    Traits::Clear(&impl_);
6311cb0ef41Sopenharmony_ci  }
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ci  /**
6341cb0ef41Sopenharmony_ci   * Reserve capacity in the vector.
6351cb0ef41Sopenharmony_ci   * (Efficiency gains depend on the backing implementation.)
6361cb0ef41Sopenharmony_ci   */
6371cb0ef41Sopenharmony_ci  void ReserveCapacity(size_t capacity) {
6381cb0ef41Sopenharmony_ci    Traits::ReserveCapacity(&impl_, capacity);
6391cb0ef41Sopenharmony_ci  }
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci private:
6421cb0ef41Sopenharmony_ci  static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
6431cb0ef41Sopenharmony_ci    V* v = persistent->val_;
6441cb0ef41Sopenharmony_ci    persistent->val_ = nullptr;
6451cb0ef41Sopenharmony_ci    return reinterpret_cast<PersistentContainerValue>(v);
6461cb0ef41Sopenharmony_ci  }
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ci  static V* FromVal(PersistentContainerValue v) {
6491cb0ef41Sopenharmony_ci    return reinterpret_cast<V*>(v);
6501cb0ef41Sopenharmony_ci  }
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci  Isolate* isolate_;
6531cb0ef41Sopenharmony_ci  typename Traits::Impl impl_;
6541cb0ef41Sopenharmony_ci};
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci}  // namespace v8
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci#endif  // V8_UTIL_H
659