diff options
author | Moonchild <moonchild@palemoon.org> | 2022-05-24 06:51:11 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2022-05-24 06:51:46 +0000 |
commit | dc5a60fb62a0f43fe77517bd0e46fe40358b44b0 (patch) | |
tree | cb5dcd22fb22fc292adaff89626c35e18e09a6be /js/public | |
parent | 1588077e629baa1c27e03149e39f06c265419e0b (diff) | |
download | uxp-dc5a60fb62a0f43fe77517bd0e46fe40358b44b0.tar.gz |
Issue #1742 - Part 1: Refactor rooting base class templates
Based on Bug 1325406
Diffstat (limited to 'js/public')
-rw-r--r-- | js/public/GCHashTable.h | 76 | ||||
-rw-r--r-- | js/public/GCVariant.h | 36 | ||||
-rw-r--r-- | js/public/GCVector.h | 36 | ||||
-rw-r--r-- | js/public/RootingAPI.h | 83 | ||||
-rw-r--r-- | js/public/SweepingAPI.h | 7 | ||||
-rw-r--r-- | js/public/Value.h | 52 |
6 files changed, 83 insertions, 207 deletions
diff --git a/js/public/GCHashTable.h b/js/public/GCHashTable.h index 4de1c39a81..3e647ed100 100644 --- a/js/public/GCHashTable.h +++ b/js/public/GCHashTable.h @@ -133,13 +133,13 @@ class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy, AllocPol } }; -template <typename Outer, typename... Args> -class GCHashMapOperations +template <typename Wrapper, typename... Args> +class WrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper> { using Map = JS::GCHashMap<Args...>; using Lookup = typename Map::Lookup; - const Map& map() const { return static_cast<const Outer*>(this)->get(); } + const Map& map() const { return static_cast<const Wrapper*>(this)->get(); } public: using AddPtr = typename Map::AddPtr; @@ -162,18 +162,18 @@ class GCHashMapOperations } }; -template <typename Outer, typename... Args> -class MutableGCHashMapOperations - : public GCHashMapOperations<Outer, Args...> +template <typename Wrapper, typename... Args> +class MutableWrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper> + : public WrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper> { using Map = JS::GCHashMap<Args...>; using Lookup = typename Map::Lookup; - Map& map() { return static_cast<Outer*>(this)->get(); } + Map& map() { return static_cast<Wrapper*>(this)->get(); } public: using AddPtr = typename Map::AddPtr; - struct Enum : public Map::Enum { explicit Enum(Outer& o) : Map::Enum(o.map()) {} }; + struct Enum : public Map::Enum { explicit Enum(Wrapper& o) : Map::Enum(o.map()) {} }; using Ptr = typename Map::Ptr; using Range = typename Map::Range; @@ -210,26 +210,6 @@ class MutableGCHashMapOperations } }; -template <typename A, typename B, typename C, typename D, typename E> -class RootedBase<JS::GCHashMap<A,B,C,D,E>> - : public MutableGCHashMapOperations<JS::Rooted<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E> -{}; - -template <typename A, typename B, typename C, typename D, typename E> -class MutableHandleBase<JS::GCHashMap<A,B,C,D,E>> - : public MutableGCHashMapOperations<JS::MutableHandle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E> -{}; - -template <typename A, typename B, typename C, typename D, typename E> -class HandleBase<JS::GCHashMap<A,B,C,D,E>> - : public GCHashMapOperations<JS::Handle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E> -{}; - -template <typename A, typename B, typename C, typename D, typename E> -class WeakCacheBase<JS::GCHashMap<A,B,C,D,E>> - : public MutableGCHashMapOperations<JS::WeakCache<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E> -{}; - } // namespace js namespace JS { @@ -291,13 +271,13 @@ class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy> namespace js { -template <typename Outer, typename... Args> -class GCHashSetOperations +template <typename Wrapper, typename... Args> +class WrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper> { using Set = JS::GCHashSet<Args...>; using Lookup = typename Set::Lookup; - const Set& set() const { return static_cast<const Outer*>(this)->get(); } + const Set& set() const { return static_cast<const Wrapper*>(this)->get(); } public: using AddPtr = typename Set::AddPtr; @@ -321,19 +301,19 @@ class GCHashSetOperations } }; -template <typename Outer, typename... Args> -class MutableGCHashSetOperations - : public GCHashSetOperations<Outer, Args...> +template <typename Wrapper, typename... Args> +class MutableWrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper> + : public WrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper> { using Set = JS::GCHashSet<Args...>; using Lookup = typename Set::Lookup; - Set& set() { return static_cast<Outer*>(this)->get(); } + Set& set() { return static_cast<Wrapper*>(this)->get(); } public: using AddPtr = typename Set::AddPtr; using Entry = typename Set::Entry; - struct Enum : public Set::Enum { explicit Enum(Outer& o) : Set::Enum(o.set()) {} }; + struct Enum : public Set::Enum { explicit Enum(Wrapper& o) : Set::Enum(o.set()) {} }; using Ptr = typename Set::Ptr; using Range = typename Set::Range; @@ -369,30 +349,6 @@ class MutableGCHashSetOperations } }; -template <typename T, typename HP, typename AP> -class RootedBase<JS::GCHashSet<T, HP, AP>> - : public MutableGCHashSetOperations<JS::Rooted<JS::GCHashSet<T, HP, AP>>, T, HP, AP> -{ -}; - -template <typename T, typename HP, typename AP> -class MutableHandleBase<JS::GCHashSet<T, HP, AP>> - : public MutableGCHashSetOperations<JS::MutableHandle<JS::GCHashSet<T, HP, AP>>, T, HP, AP> -{ -}; - -template <typename T, typename HP, typename AP> -class HandleBase<JS::GCHashSet<T, HP, AP>> - : public GCHashSetOperations<JS::Handle<JS::GCHashSet<T, HP, AP>>, T, HP, AP> -{ -}; - -template <typename T, typename HP, typename AP> -class WeakCacheBase<JS::GCHashSet<T, HP, AP>> - : public MutableGCHashSetOperations<JS::WeakCache<JS::GCHashSet<T, HP, AP>>, T, HP, AP> -{ -}; - } /* namespace js */ #endif /* GCHashTable_h */ diff --git a/js/public/GCVariant.h b/js/public/GCVariant.h index 43f2957fee..3ec40df5ca 100644 --- a/js/public/GCVariant.h +++ b/js/public/GCVariant.h @@ -123,13 +123,13 @@ struct GCPolicy<mozilla::Variant<Ts...>> namespace js { -template <typename Outer, typename... Ts> -class GCVariantOperations +template <typename Wrapper, typename... Ts> +class WrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper> { using Impl = JS::detail::GCVariantImplementation<Ts...>; using Variant = mozilla::Variant<Ts...>; - const Variant& variant() const { return static_cast<const Outer*>(this)->get(); } + const Variant& variant() const { return static_cast<const Wrapper*>(this)->get(); } public: template <typename T> @@ -149,15 +149,15 @@ class GCVariantOperations } }; -template <typename Outer, typename... Ts> -class MutableGCVariantOperations - : public GCVariantOperations<Outer, Ts...> +template <typename Wrapper, typename... Ts> +class MutableWrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper> + : public WrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper> { using Impl = JS::detail::GCVariantImplementation<Ts...>; using Variant = mozilla::Variant<Ts...>; - const Variant& variant() const { return static_cast<const Outer*>(this)->get(); } - Variant& variant() { return static_cast<Outer*>(this)->get(); } + const Variant& variant() const { return static_cast<const Wrapper*>(this)->get(); } + Variant& variant() { return static_cast<Wrapper*>(this)->get(); } public: template <typename T> @@ -172,26 +172,6 @@ class MutableGCVariantOperations } }; -template <typename... Ts> -class RootedBase<mozilla::Variant<Ts...>> - : public MutableGCVariantOperations<JS::Rooted<mozilla::Variant<Ts...>>, Ts...> -{ }; - -template <typename... Ts> -class MutableHandleBase<mozilla::Variant<Ts...>> - : public MutableGCVariantOperations<JS::MutableHandle<mozilla::Variant<Ts...>>, Ts...> -{ }; - -template <typename... Ts> -class HandleBase<mozilla::Variant<Ts...>> - : public GCVariantOperations<JS::Handle<mozilla::Variant<Ts...>>, Ts...> -{ }; - -template <typename... Ts> -class PersistentRootedBase<mozilla::Variant<Ts...>> - : public MutableGCVariantOperations<JS::PersistentRooted<mozilla::Variant<Ts...>>, Ts...> -{ }; - } // namespace js #endif // js_GCVariant_h diff --git a/js/public/GCVector.h b/js/public/GCVector.h index 1c99252617..4acf0d1fc5 100644 --- a/js/public/GCVector.h +++ b/js/public/GCVector.h @@ -134,11 +134,11 @@ class GCVector namespace js { -template <typename Outer, typename T, size_t Capacity, typename AllocPolicy> -class GCVectorOperations +template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy> +class WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper> { using Vec = JS::GCVector<T, Capacity, AllocPolicy>; - const Vec& vec() const { return static_cast<const Outer*>(this)->get(); } + const Vec& vec() const { return static_cast<const Wrapper*>(this)->get(); } public: const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); } @@ -154,13 +154,13 @@ class GCVectorOperations } }; -template <typename Outer, typename T, size_t Capacity, typename AllocPolicy> -class MutableGCVectorOperations - : public GCVectorOperations<Outer, T, Capacity, AllocPolicy> +template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy> +class MutableWrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper> + : public WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper> { using Vec = JS::GCVector<T, Capacity, AllocPolicy>; - const Vec& vec() const { return static_cast<const Outer*>(this)->get(); } - Vec& vec() { return static_cast<Outer*>(this)->get(); } + const Vec& vec() const { return static_cast<const Wrapper*>(this)->get(); } + Vec& vec() { return static_cast<Wrapper*>(this)->get(); } public: const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); } @@ -223,26 +223,6 @@ class MutableGCVectorOperations void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); } }; -template <typename T, size_t N, typename AP> -class RootedBase<JS::GCVector<T,N,AP>> - : public MutableGCVectorOperations<JS::Rooted<JS::GCVector<T,N,AP>>, T,N,AP> -{}; - -template <typename T, size_t N, typename AP> -class MutableHandleBase<JS::GCVector<T,N,AP>> - : public MutableGCVectorOperations<JS::MutableHandle<JS::GCVector<T,N,AP>>, T,N,AP> -{}; - -template <typename T, size_t N, typename AP> -class HandleBase<JS::GCVector<T,N,AP>> - : public GCVectorOperations<JS::Handle<JS::GCVector<T,N,AP>>, T,N,AP> -{}; - -template <typename T, size_t N, typename AP> -class PersistentRootedBase<JS::GCVector<T,N,AP>> - : public MutableGCVectorOperations<JS::PersistentRooted<JS::GCVector<T,N,AP>>, T,N,AP> -{}; - } // namespace js #endif // js_GCVector_h diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 5f0740d53a..120e1fcde0 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -112,17 +112,23 @@ template <typename T> struct BarrierMethods { }; -template <typename T> -class RootedBase {}; +template <typename Element, typename Wrapper> +class WrappedPtrOperations {}; -template <typename T> -class HandleBase {}; +template <typename Element, typename Wrapper> +class MutableWrappedPtrOperations : public WrappedPtrOperations<Element, Wrapper> {}; -template <typename T> -class MutableHandleBase {}; +template <typename T, typename Wrapper> +class RootedBase : public MutableWrappedPtrOperations<T, Wrapper> {}; -template <typename T> -class HeapBase {}; +template <typename T, typename Wrapper> +class HandleBase : public WrappedPtrOperations<T, Wrapper> {}; + +template <typename T, typename Wrapper> +class MutableHandleBase : public MutableWrappedPtrOperations<T, Wrapper> {}; + +template <typename T, typename Wrapper> +class HeapBase : public MutableWrappedPtrOperations<T, Wrapper> {}; // Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many macros into scope template <typename T> struct IsHeapConstructibleType { static constexpr bool value = false; }; @@ -132,8 +138,8 @@ FOR_EACH_PUBLIC_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE) FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE) #undef DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE -template <typename T> -class PersistentRootedBase {}; +template <typename T, typename Wrapper> +class PersistentRootedBase : public MutableWrappedPtrOperations<T, Wrapper> {}; static void* const ConstNullValue = nullptr; @@ -230,7 +236,7 @@ AssertGCThingIsNotAnObjectSubclass(js::gc::Cell* cell) {} * Type T must be a public GC pointer type. */ template <typename T> -class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T> +class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T, Heap<T>> { // Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for legacy reasons. static_assert(js::IsHeapConstructibleType<T>::value, @@ -367,7 +373,7 @@ ScriptIsMarkedGray(const Heap<JSScript*>& script) * - It is not possible to store flag bits in a Heap<T>. */ template <typename T> -class TenuredHeap : public js::HeapBase<T> +class TenuredHeap : public js::HeapBase<T, TenuredHeap<T>> { public: TenuredHeap() : bits(0) { @@ -451,7 +457,7 @@ class TenuredHeap : public js::HeapBase<T> * specialization, define a HandleBase<T> specialization containing them. */ template <typename T> -class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T> +class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T, Handle<T>> { friend class JS::MutableHandle<T>; @@ -540,7 +546,7 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T> * them. */ template <typename T> -class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T> +class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T, MutableHandle<T>> { public: inline MOZ_IMPLICIT MutableHandle(Rooted<T>* root); @@ -753,7 +759,7 @@ namespace JS { * specialization, define a RootedBase<T> specialization containing them. */ template <typename T> -class MOZ_RAII Rooted : public js::RootedBase<T> +class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> { inline void registerWithRootLists(js::RootedListHeads& roots) { this->stack = &roots[JS::MapTypeToRootKind<T>::kind]; @@ -853,8 +859,8 @@ namespace js { * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>()); * Handle<StringObject*> h = rooted; */ -template <> -class RootedBase<JSObject*> +template <typename Container> +class RootedBase<JSObject*, Container> : public MutableWrappedPtrOperations<JSObject*, Container> { public: template <class U> @@ -871,8 +877,8 @@ class RootedBase<JSObject*> * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>()); * Handle<StringObject*> h = rooted; */ -template <> -class HandleBase<JSObject*> +template <typename Container> +class HandleBase<JSObject*, Container> : public WrappedPtrOperations<JSObject*, Container> { public: template <class U> @@ -881,7 +887,7 @@ class HandleBase<JSObject*> /** Interface substitute for Rooted<T> which does not root the variable's memory. */ template <typename T> -class MOZ_RAII FakeRooted : public RootedBase<T> +class MOZ_RAII FakeRooted : public RootedBase<T, FakeRooted<T>> { public: template <typename CX> @@ -908,7 +914,7 @@ class MOZ_RAII FakeRooted : public RootedBase<T> /** Interface substitute for MutableHandle<T> which is not required to point to rooted memory. */ template <typename T> -class FakeMutableHandle : public js::MutableHandleBase<T> +class FakeMutableHandle : public js::MutableHandleBase<T, FakeMutableHandle<T>> { public: MOZ_IMPLICIT FakeMutableHandle(T* t) { @@ -1075,7 +1081,7 @@ MutableHandle<T>::MutableHandle(PersistentRooted<T>* root) * marked when the object itself is marked. */ template<typename T> -class PersistentRooted : public js::PersistentRootedBase<T>, +class PersistentRooted : public js::RootedBase<T, PersistentRooted<T>>, private mozilla::LinkedListElement<PersistentRooted<T>> { using ListBase = mozilla::LinkedListElement<PersistentRooted<T>>; @@ -1240,10 +1246,10 @@ class JS_PUBLIC_API(ObjectPtr) namespace js { -template <typename Outer, typename T, typename D> -class UniquePtrOperations +template <typename T, typename D, typename Container> +class WrappedPtrOperations<UniquePtr<T, D>, Container> { - const UniquePtr<T, D>& uniquePtr() const { return static_cast<const Outer*>(this)->get(); } + const UniquePtr<T, D>& uniquePtr() const { return static_cast<const Container*>(this)->get(); } public: explicit operator bool() const { return !!uniquePtr(); } @@ -1252,36 +1258,17 @@ class UniquePtrOperations T& operator*() const { return *uniquePtr(); } }; -template <typename Outer, typename T, typename D> -class MutableUniquePtrOperations : public UniquePtrOperations<Outer, T, D> +template <typename T, typename D, typename Container> +class MutableWrappedPtrOperations<UniquePtr<T, D>, Container> + : public WrappedPtrOperations<UniquePtr<T, D>, Container> { - UniquePtr<T, D>& uniquePtr() { return static_cast<Outer*>(this)->get(); } + UniquePtr<T, D>& uniquePtr() { return static_cast<Container*>(this)->get(); } public: MOZ_MUST_USE typename UniquePtr<T, D>::Pointer release() { return uniquePtr().release(); } void reset(T* ptr = T()) { uniquePtr().reset(ptr); } }; -template <typename T, typename D> -class RootedBase<UniquePtr<T, D>> - : public MutableUniquePtrOperations<JS::Rooted<UniquePtr<T, D>>, T, D> -{ }; - -template <typename T, typename D> -class MutableHandleBase<UniquePtr<T, D>> - : public MutableUniquePtrOperations<JS::MutableHandle<UniquePtr<T, D>>, T, D> -{ }; - -template <typename T, typename D> -class HandleBase<UniquePtr<T, D>> - : public UniquePtrOperations<JS::Handle<UniquePtr<T, D>>, T, D> -{ }; - -template <typename T, typename D> -class PersistentRootedBase<UniquePtr<T, D>> - : public MutableUniquePtrOperations<JS::PersistentRooted<UniquePtr<T, D>>, T, D> -{ }; - namespace gc { template <typename T, typename TraceCallbacks> diff --git a/js/public/SweepingAPI.h b/js/public/SweepingAPI.h index 39abb0fc0e..bbc1ec279b 100644 --- a/js/public/SweepingAPI.h +++ b/js/public/SweepingAPI.h @@ -8,11 +8,6 @@ #include "js/HeapAPI.h" -namespace js { -template <typename T> -class WeakCacheBase {}; -} // namespace js - namespace JS { template <typename T> class WeakCache; @@ -24,7 +19,7 @@ RegisterWeakCache(JS::Zone* zone, JS::WeakCache<void*>* cachep); // A WeakCache stores the given Sweepable container and links itself into a // list of such caches that are swept during each GC. template <typename T> -class WeakCache : public js::WeakCacheBase<T>, +class WeakCache : public js::MutableWrappedPtrOperations<T, WeakCache<T>>, private mozilla::LinkedListElement<WeakCache<T>> { friend class mozilla::LinkedListElement<WeakCache<T>>; diff --git a/js/public/Value.h b/js/public/Value.h index 087d178efd..c645f07733 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -1340,20 +1340,18 @@ struct BarrierMethods<JS::Value> } }; -template <class Outer> class MutableValueOperations; +template <class Wrapper> class MutableValueOperations; /** * A class designed for CRTP use in implementing the non-mutating parts of the - * Value interface in Value-like classes. Outer must be a class inheriting - * ValueOperations<Outer> with a visible get() method returning a const - * reference to the Value abstracted by Outer. + * Value interface in Value-like classes. Wrapper must be a class inheriting + * ValueOperations<Wrapper> with a visible get() method returning a const + * reference to the Value abstracted by Wrapper. */ -template <class Outer> -class ValueOperations +template <class Wrapper> +class WrappedPtrOperations<JS::Value, Wrapper> { - friend class MutableValueOperations<Outer>; - - const JS::Value& value() const { return static_cast<const Outer*>(this)->get(); } + const JS::Value& value() const { return static_cast<const Wrapper*>(this)->get(); } public: bool isUndefined() const { return value().isUndefined(); } @@ -1398,17 +1396,17 @@ class ValueOperations /** * A class designed for CRTP use in implementing all the mutating parts of the - * Value interface in Value-like classes. Outer must be a class inheriting - * MutableValueOperations<Outer> with visible get() methods returning const and - * non-const references to the Value abstracted by Outer. + * Value interface in Value-like classes. Wrapper must be a class inheriting + * MutableWrappedPtrOperations<Wrapper> with visible get() methods returning const and + * non-const references to the Value abstracted by Wrapper. */ -template <class Outer> -class MutableValueOperations : public ValueOperations<Outer> +template <class Wrapper> +class MutableWrappedPtrOperations<JS::Value, Wrapper> : public WrappedPtrOperations<JS::Value, Wrapper> { protected: void set(const JS::Value& v) { // Call Outer::set to trigger any barriers. - static_cast<Outer*>(this)->set(v); + static_cast<Wrapper*>(this)->set(v); } public: @@ -1434,13 +1432,9 @@ class MutableValueOperations : public ValueOperations<Outer> * Augment the generic Heap<T> interface when T = Value with * type-querying, value-extracting, and mutating operations. */ -template <> -class HeapBase<JS::Value> : public MutableValueOperations<JS::Heap<JS::Value> > +template <typename Wrapper> +class HeapBase<JS::Value, Wrapper> : public MutableWrappedPtrOperations<JS::Value, Wrapper> { - typedef JS::Heap<JS::Value> Outer; - - friend class ValueOperations<Outer>; - public: void setNumber(uint32_t ui) { if (ui > JSVAL_INT_MAX) { @@ -1460,22 +1454,6 @@ class HeapBase<JS::Value> : public MutableValueOperations<JS::Heap<JS::Value> > } }; -template <> -class HandleBase<JS::Value> : public ValueOperations<JS::Handle<JS::Value> > -{}; - -template <> -class MutableHandleBase<JS::Value> : public MutableValueOperations<JS::MutableHandle<JS::Value> > -{}; - -template <> -class RootedBase<JS::Value> : public MutableValueOperations<JS::Rooted<JS::Value> > -{}; - -template <> -class PersistentRootedBase<JS::Value> : public MutableValueOperations<JS::PersistentRooted<JS::Value>> -{}; - /* * If the Value is a GC pointer type, convert to that type and call |f| with * the pointer. If the Value is not a GC type, calls F::defaultValue. |