Index: include/v8-util.h |
diff --git a/include/v8-util.h b/include/v8-util.h |
index 1eaf1ab68f6be618a6690c25b7e10a297e88ee6e..ca36b6c58bcf0cdc762f2aa01a259cc67334a986 100644 |
--- a/include/v8-util.h |
+++ b/include/v8-util.h |
@@ -105,6 +105,43 @@ class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> { |
}; |
+template <typename K, typename V> |
+class DefaultPhantomPersistentValueMapTraits : public StdMapTraits<K, V> { |
+ private: |
+ template <typename T> |
+ struct RemovePointer; |
+ |
+ public: |
+ // Weak callback & friends: |
+ static const PersistentContainerCallbackType kCallbackType = kNotWeak; |
+ typedef PersistentValueMap< |
+ K, V, DefaultPhantomPersistentValueMapTraits<K, V> > MapType; |
+ typedef void PhantomCallbackDataType; |
+ |
+ static PhantomCallbackDataType* PhantomCallbackParameter(MapType* map, |
+ const K& key, |
+ Local<V> value) { |
+ return NULL; |
+ } |
+ static MapType* MapFromPhantomCallbackData( |
+ const PhantomCallbackData<PhantomCallbackDataType>& data) { |
+ return NULL; |
+ } |
+ static K KeyFromPhantomCallbackData( |
+ const PhantomCallbackData<PhantomCallbackDataType>& data) { |
+ return K(); |
+ } |
+ static void DisposeCallbackData(PhantomCallbackDataType* data) {} |
+ static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) {} |
+ |
+ private: |
+ template <typename T> |
+ struct RemovePointer<T*> { |
+ typedef T Type; |
+ }; |
+}; |
+ |
+ |
/** |
* A map wrapper that allows using UniquePersistent as a mapped value. |
* C++11 embedders don't need this class, as they can use UniquePersistent |
@@ -115,13 +152,9 @@ class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> { |
* PersistentContainerValue, with all conversion into and out of V8 |
* handles being transparently handled by this class. |
*/ |
-template<typename K, typename V, typename Traits> |
-class PersistentValueMap { |
+template <typename K, typename V, typename Traits> |
+class PersistentValueMapBase { |
public: |
- explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {} |
- |
- ~PersistentValueMap() { Clear(); } |
- |
Isolate* GetIsolate() { return isolate_; } |
/** |
@@ -168,23 +201,6 @@ class PersistentValueMap { |
} |
/** |
- * Put value into map. Depending on Traits::kIsWeak, the value will be held |
- * by the map strongly or weakly. |
- * Returns old value as UniquePersistent. |
- */ |
- UniquePersistent<V> Set(const K& key, Local<V> value) { |
- UniquePersistent<V> persistent(isolate_, value); |
- return SetUnique(key, &persistent); |
- } |
- |
- /** |
- * Put value into map, like Set(const K&, Local<V>). |
- */ |
- UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) { |
- return SetUnique(key, &value); |
- } |
- |
- /** |
* Return value for key and remove it from the map. |
*/ |
UniquePersistent<V> Remove(const K& key) { |
@@ -237,7 +253,9 @@ class PersistentValueMap { |
} |
private: |
- friend class PersistentValueMap; |
+ friend class PersistentValueMapBase; |
+ friend class PersistentValueMap<K, V, Traits>; |
+ friend class PhantomPersistentValueMap<K, V, Traits>; |
explicit PersistentValueReference(PersistentContainerValue value) |
: value_(value) { } |
@@ -263,19 +281,89 @@ class PersistentValueMap { |
return PersistentValueReference(Traits::Get(&impl_, key)); |
} |
+ protected: |
+ explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {} |
+ |
+ ~PersistentValueMapBase() { Clear(); } |
+ |
+ Isolate* isolate() { return isolate_; } |
+ typename Traits::Impl* impl() { return &impl_; } |
+ |
+ static V* FromVal(PersistentContainerValue v) { |
+ return reinterpret_cast<V*>(v); |
+ } |
+ |
+ static PersistentContainerValue ClearAndLeak( |
+ UniquePersistent<V>* persistent) { |
+ V* v = persistent->val_; |
+ persistent->val_ = 0; |
+ return reinterpret_cast<PersistentContainerValue>(v); |
+ } |
+ |
+ static PersistentContainerValue Leak(UniquePersistent<V>* persistent) { |
+ return reinterpret_cast<PersistentContainerValue>(persistent->val_); |
+ } |
+ |
/** |
- * Put a value into the map and update the reference. |
- * Restrictions of GetReference apply here as well. |
+ * Return a container value as UniquePersistent and make sure the weak |
+ * callback is properly disposed of. All remove functionality should go |
+ * through this. |
*/ |
- UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, |
- PersistentValueReference* reference) { |
- *reference = Leak(&value); |
- return SetUnique(key, &value); |
+ static UniquePersistent<V> Release(PersistentContainerValue v) { |
+ UniquePersistent<V> p; |
+ p.val_ = FromVal(v); |
+ if (Traits::kCallbackType != kNotWeak && p.IsWeak()) { |
+ Traits::DisposeCallbackData( |
+ p.template ClearWeak<typename Traits::WeakCallbackDataType>()); |
+ } |
+ return p.Pass(); |
} |
private: |
- PersistentValueMap(PersistentValueMap&); |
- void operator=(PersistentValueMap&); |
+ PersistentValueMapBase(PersistentValueMapBase&); |
+ void operator=(PersistentValueMapBase&); |
+ |
+ static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue, |
+ PersistentContainerValue value) { |
+ bool hasValue = value != kPersistentContainerNotFound; |
+ if (hasValue) { |
+ returnValue->SetInternal( |
+ *reinterpret_cast<internal::Object**>(FromVal(value))); |
+ } |
+ return hasValue; |
+ } |
+ |
+ Isolate* isolate_; |
+ typename Traits::Impl impl_; |
+}; |
+ |
+ |
+template <typename K, typename V, typename Traits> |
+class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> { |
+ public: |
+ explicit PersistentValueMap(Isolate* isolate) |
+ : PersistentValueMapBase<K, V, Traits>(isolate) {} |
+ |
+ typedef |
+ typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference |
+ PersistentValueReference; |
+ |
+ /** |
+ * Put value into map. Depending on Traits::kIsWeak, the value will be held |
+ * by the map strongly or weakly. |
+ * Returns old value as UniquePersistent. |
+ */ |
+ UniquePersistent<V> Set(const K& key, Local<V> value) { |
+ UniquePersistent<V> persistent(this->isolate(), value); |
+ return SetUnique(key, &persistent); |
+ } |
+ |
+ /** |
+ * Put value into map, like Set(const K&, Local<V>). |
+ */ |
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) { |
+ return SetUnique(key, &value); |
+ } |
/** |
* Put the value into the map, and set the 'weak' callback when demanded |
@@ -283,15 +371,26 @@ class PersistentValueMap { |
*/ |
UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { |
if (Traits::kCallbackType != kNotWeak) { |
- Local<V> value(Local<V>::New(isolate_, *persistent)); |
+ Local<V> value(Local<V>::New(this->isolate(), *persistent)); |
persistent->template SetWeak<typename Traits::WeakCallbackDataType>( |
Traits::WeakCallbackParameter(this, key, value), WeakCallback); |
} |
PersistentContainerValue old_value = |
- Traits::Set(&impl_, key, ClearAndLeak(persistent)); |
- return Release(old_value).Pass(); |
+ Traits::Set(this->impl(), key, this->ClearAndLeak(persistent)); |
+ return this->Release(old_value).Pass(); |
+ } |
+ |
+ /** |
+ * Put a value into the map and update the reference. |
+ * Restrictions of GetReference apply here as well. |
+ */ |
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, |
+ PersistentValueReference* reference) { |
+ *reference = this->Leak(&value); |
+ return SetUnique(key, &value); |
} |
+ private: |
static void WeakCallback( |
const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { |
if (Traits::kCallbackType != kNotWeak) { |
@@ -303,50 +402,73 @@ class PersistentValueMap { |
Traits::DisposeCallbackData(data.GetParameter()); |
} |
} |
+}; |
- static V* FromVal(PersistentContainerValue v) { |
- return reinterpret_cast<V*>(v); |
- } |
- static bool SetReturnValueFromVal( |
- ReturnValue<Value>* returnValue, PersistentContainerValue value) { |
- bool hasValue = value != kPersistentContainerNotFound; |
- if (hasValue) { |
- returnValue->SetInternal( |
- *reinterpret_cast<internal::Object**>(FromVal(value))); |
- } |
- return hasValue; |
- } |
+template <typename K, typename V, typename Traits> |
+class PhantomPersistentValueMap : public PersistentValueMapBase<K, V, Traits> { |
+ public: |
+ explicit PhantomPersistentValueMap(Isolate* isolate) |
+ : PersistentValueMapBase<K, V, Traits>(isolate) {} |
- static PersistentContainerValue ClearAndLeak( |
- UniquePersistent<V>* persistent) { |
- V* v = persistent->val_; |
- persistent->val_ = 0; |
- return reinterpret_cast<PersistentContainerValue>(v); |
+ typedef |
+ typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference |
+ PersistentValueReference; |
+ |
+ /** |
+ * Put value into map. Depending on Traits::kIsWeak, the value will be held |
+ * by the map strongly or weakly. |
+ * Returns old value as UniquePersistent. |
+ */ |
+ UniquePersistent<V> Set(const K& key, Local<V> value) { |
+ UniquePersistent<V> persistent(this->isolate(), value); |
+ return SetUnique(key, &persistent); |
} |
- static PersistentContainerValue Leak( |
- UniquePersistent<V>* persistent) { |
- return reinterpret_cast<PersistentContainerValue>(persistent->val_); |
+ /** |
+ * Put value into map, like Set(const K&, Local<V>). |
+ */ |
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) { |
+ return SetUnique(key, &value); |
} |
/** |
- * Return a container value as UniquePersistent and make sure the weak |
- * callback is properly disposed of. All remove functionality should go |
- * through this. |
+ * Put the value into the map, and set the 'weak' callback when demanded |
+ * by the Traits class. |
*/ |
- static UniquePersistent<V> Release(PersistentContainerValue v) { |
- UniquePersistent<V> p; |
- p.val_ = FromVal(v); |
- if (Traits::kCallbackType != kNotWeak && p.IsWeak()) { |
- Traits::DisposeCallbackData( |
- p.template ClearWeak<typename Traits::WeakCallbackDataType>()); |
+ UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { |
+ if (Traits::kCallbackType != kNotWeak) { |
+ Local<V> value(Local<V>::New(this->isolate(), *persistent)); |
+ persistent->template SetPhantom<typename Traits::WeakCallbackDataType>( |
+ Traits::WeakCallbackParameter(this, key, value), WeakCallback, 0, 1); |
} |
- return p.Pass(); |
+ PersistentContainerValue old_value = |
+ Traits::Set(this->impl(), key, this->ClearAndLeak(persistent)); |
+ return this->Release(old_value).Pass(); |
} |
- Isolate* isolate_; |
- typename Traits::Impl impl_; |
+ /** |
+ * Put a value into the map and update the reference. |
+ * Restrictions of GetReference apply here as well. |
+ */ |
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, |
+ PersistentValueReference* reference) { |
+ *reference = this->Leak(&value); |
+ return SetUnique(key, &value); |
+ } |
+ |
+ private: |
+ static void WeakCallback( |
+ const PhantomCallbackData<typename Traits::WeakCallbackDataType>& data) { |
+ if (Traits::kCallbackType != kNotWeak) { |
+ PhantomPersistentValueMap<K, V, Traits>* persistentValueMap = |
+ Traits::MapFromPhantomCallbackData(data); |
+ K key = Traits::KeyFromPhantomCallbackData(data); |
+ Traits::Dispose(data.GetIsolate(), persistentValueMap->Remove(key).Pass(), |
+ key); |
+ Traits::DisposeCallbackData(data.GetParameter()); |
+ } |
+ } |
}; |