| 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());
|
| + }
|
| + }
|
| };
|
|
|
|
|
|
|