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