From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- js/public/GCVariant.h | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 js/public/GCVariant.h (limited to 'js/public/GCVariant.h') diff --git a/js/public/GCVariant.h b/js/public/GCVariant.h new file mode 100644 index 0000000000..43610b898b --- /dev/null +++ b/js/public/GCVariant.h @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_GCVariant_h +#define js_GCVariant_h + +#include "mozilla/Variant.h" + +#include + +#include "js/GCPolicyAPI.h" +#include "js/RootingAPI.h" +#include "js/TracingAPI.h" + +namespace JS { + +// These template specializations allow Variant to be used inside GC wrappers. +// +// When matching on GC wrappers around Variants, matching should be done on +// the wrapper itself. The matcher class's methods should take Handles or +// MutableHandles. For example, +// +// struct MyMatcher +// { +// using ReturnType = const char*; +// ReturnType match(HandleObject o) { return "object"; } +// ReturnType match(HandleScript s) { return "script"; } +// }; +// +// Rooted> v(cx, someScript); +// MyMatcher mm; +// v.match(mm); +// +// If you get compile errors about inability to upcast subclasses (e.g., from +// NativeObject* to JSObject*) and are inside js/src, be sure to also include +// "gc/Policy.h". + +namespace detail { + +template +struct GCVariantImplementation; + +// The base case. +template +struct GCVariantImplementation { + template + static void trace(JSTracer* trc, ConcreteVariant* v, const char* name) { + T& thing = v->template as(); + GCPolicy::trace(trc, &thing, name); + } + + template + static typename Matcher::ReturnType match(Matcher& matcher, + Handle v) { + const T& thing = v.get().template as(); + return matcher.match(Handle::fromMarkedLocation(&thing)); + } + + template + static typename Matcher::ReturnType match(Matcher& matcher, + MutableHandle v) { + T& thing = v.get().template as(); + return matcher.match(MutableHandle::fromMarkedLocation(&thing)); + } +}; + +// The inductive case. +template +struct GCVariantImplementation { + using Next = GCVariantImplementation; + + template + static void trace(JSTracer* trc, ConcreteVariant* v, const char* name) { + if (v->template is()) { + T& thing = v->template as(); + GCPolicy::trace(trc, &thing, name); + } else { + Next::trace(trc, v, name); + } + } + + template + static typename Matcher::ReturnType match(Matcher& matcher, + Handle v) { + if (v.get().template is()) { + const T& thing = v.get().template as(); + return matcher.match(Handle::fromMarkedLocation(&thing)); + } + return Next::match(matcher, v); + } + + template + static typename Matcher::ReturnType match(Matcher& matcher, + MutableHandle v) { + if (v.get().template is()) { + T& thing = v.get().template as(); + return matcher.match(MutableHandle::fromMarkedLocation(&thing)); + } + return Next::match(matcher, v); + } +}; + +} // namespace detail + +template +struct GCPolicy> { + using Impl = detail::GCVariantImplementation; + + static void trace(JSTracer* trc, mozilla::Variant* v, + const char* name) { + Impl::trace(trc, v, name); + } + + static bool isValid(const mozilla::Variant& v) { + return v.match([](auto& v) { + return GCPolicy>::isValid(v); + }); + } +}; + +} // namespace JS + +namespace js { + +template +class WrappedPtrOperations, Wrapper> { + using Impl = JS::detail::GCVariantImplementation; + using Variant = mozilla::Variant; + + const Variant& variant() const { + return static_cast(this)->get(); + } + + public: + template + bool is() const { + return variant().template is(); + } + + template + JS::Handle as() const { + return JS::Handle::fromMarkedLocation(&variant().template as()); + } + + template + typename Matcher::ReturnType match(Matcher& matcher) const { + return Impl::match(matcher, + JS::Handle::fromMarkedLocation(&variant())); + } +}; + +template +class MutableWrappedPtrOperations, Wrapper> + : public WrappedPtrOperations, Wrapper> { + using Impl = JS::detail::GCVariantImplementation; + using Variant = mozilla::Variant; + + const Variant& variant() const { + return static_cast(this)->get(); + } + Variant& variant() { return static_cast(this)->get(); } + + public: + template + JS::MutableHandle as() { + return JS::MutableHandle::fromMarkedLocation( + &variant().template as()); + } + + template + typename Matcher::ReturnType match(Matcher& matcher) { + return Impl::match( + matcher, JS::MutableHandle::fromMarkedLocation(&variant())); + } +}; + +} // namespace js + +#endif // js_GCVariant_h -- cgit v1.2.3