Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-15 09:13:52

0001 // Copyright 2021 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
0004 
0005 #ifndef INCLUDE_V8_MAYBE_H_
0006 #define INCLUDE_V8_MAYBE_H_
0007 
0008 #include <type_traits>
0009 #include <utility>
0010 
0011 #include "cppgc/internal/conditional-stack-allocated.h"  // NOLINT(build/include_directory)
0012 #include "v8-internal.h"  // NOLINT(build/include_directory)
0013 #include "v8config.h"     // NOLINT(build/include_directory)
0014 
0015 namespace v8 {
0016 
0017 namespace internal {
0018 struct NullMaybeType {};
0019 
0020 constexpr NullMaybeType kNullMaybe;
0021 }  // namespace internal
0022 
0023 namespace api_internal {
0024 // Called when ToChecked is called on an empty Maybe.
0025 V8_EXPORT void FromJustIsNothing();
0026 }  // namespace api_internal
0027 
0028 /**
0029  * A simple Maybe type, representing an object which may or may not have a
0030  * value, see https://hackage.haskell.org/package/base/docs/Data-Maybe.html.
0031  *
0032  * If an API method returns a Maybe<>, the API method can potentially fail
0033  * either because an exception is thrown, or because an exception is pending,
0034  * e.g. because a previous API call threw an exception that hasn't been caught
0035  * yet, or because a TerminateExecution exception was thrown. In that case, a
0036  * "Nothing" value is returned.
0037  */
0038 template <class T>
0039 class Maybe : public cppgc::internal::ConditionalStackAllocatedBase<T> {
0040  public:
0041   constexpr Maybe() = default;
0042 
0043   V8_INLINE Maybe(internal::NullMaybeType) {}
0044 
0045   V8_INLINE bool IsNothing() const { return !has_value_; }
0046   V8_INLINE bool IsJust() const { return has_value_; }
0047 
0048   /**
0049    * Same as IsNothing(). It's useful for unified handling of empty states
0050    * with v8::MaybeLocal<T>.
0051    */
0052   V8_INLINE bool IsEmpty() const { return IsNothing(); }
0053 
0054   /**
0055    * An alias for |FromJust|. Will crash if the Maybe<> is nothing.
0056    */
0057   V8_INLINE T ToChecked() const { return FromJust(); }
0058 
0059   /**
0060    * Short-hand for ToChecked(), which doesn't return a value. To be used, where
0061    * the actual value of the Maybe is not needed like Object::Set.
0062    */
0063   V8_INLINE void Check() const {
0064     if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
0065   }
0066 
0067   /**
0068    * Converts this Maybe<> to a value of type T. If this Maybe<> is
0069    * nothing (empty), |false| is returned and |out| is left untouched.
0070    */
0071   V8_WARN_UNUSED_RESULT V8_INLINE bool To(T* out) const {
0072     if (V8_LIKELY(IsJust())) *out = value_;
0073     return IsJust();
0074   }
0075 
0076   /**
0077    * Converts this Maybe<> to a value of type T, moving out of it. If this
0078    * Maybe<> is nothing (empty), |false| is returned and |out| is left
0079    * untouched.
0080    */
0081   V8_WARN_UNUSED_RESULT V8_INLINE bool MoveTo(T* out) && {
0082     if (V8_LIKELY(IsJust())) *out = std::move(value_);
0083     return IsJust();
0084   }
0085 
0086   /**
0087    * Converts this Maybe<> to a value of type T. If this Maybe<> is
0088    * nothing (empty), V8 will crash the process.
0089    */
0090   V8_INLINE T FromJust() const& {
0091     if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
0092     return value_;
0093   }
0094 
0095   /**
0096    * Converts this Maybe<> to a value of type T. If this Maybe<> is
0097    * nothing (empty), V8 will crash the process.
0098    */
0099   V8_INLINE T FromJust() && {
0100     if (V8_UNLIKELY(!IsJust())) api_internal::FromJustIsNothing();
0101     return std::move(value_);
0102   }
0103 
0104   /**
0105    * Converts this Maybe<> to a value of type T, using a default value if this
0106    * Maybe<> is nothing (empty).
0107    */
0108   V8_INLINE T FromMaybe(const T& default_value) const {
0109     return has_value_ ? value_ : default_value;
0110   }
0111 
0112   V8_INLINE bool operator==(const Maybe& other) const {
0113     return (IsJust() == other.IsJust()) &&
0114            (!IsJust() || FromJust() == other.FromJust());
0115   }
0116 
0117   V8_INLINE bool operator!=(const Maybe& other) const {
0118     return !operator==(other);
0119   }
0120 
0121  private:
0122   explicit Maybe(const T& t) : has_value_(true), value_(t) {}
0123   explicit Maybe(T&& t) : has_value_(true), value_(std::move(t)) {}
0124 
0125   bool has_value_ = false;
0126   T value_;
0127 
0128   template <class U>
0129   friend Maybe<U> Just(const U& u);
0130   template <class U, std::enable_if_t<!std::is_lvalue_reference_v<U>>*>
0131   friend Maybe<U> Just(U&& u);
0132 };
0133 
0134 template <class T>
0135 inline constexpr Maybe<T> Nothing() {
0136   return {};
0137 }
0138 
0139 template <class T>
0140 inline Maybe<T> Just(const T& t) {
0141   return Maybe<T>(t);
0142 }
0143 
0144 // Don't use forwarding references here but instead use two overloads.
0145 // Forwarding references only work when type deduction takes place, which is not
0146 // the case for callsites such as Just<Type>(t).
0147 template <class T, std::enable_if_t<!std::is_lvalue_reference_v<T>>* = nullptr>
0148 inline Maybe<T> Just(T&& t) {
0149   return Maybe<T>(std::move(t));
0150 }
0151 
0152 // A template specialization of Maybe<T> for the case of T = void.
0153 template <>
0154 class Maybe<void> {
0155  public:
0156   constexpr Maybe() = default;
0157   constexpr Maybe(internal::NullMaybeType) {}
0158 
0159   V8_INLINE bool IsNothing() const { return !is_valid_; }
0160   V8_INLINE bool IsEmpty() const { return IsNothing(); }
0161   V8_INLINE bool IsJust() const { return is_valid_; }
0162 
0163   V8_INLINE bool operator==(const Maybe& other) const {
0164     return IsJust() == other.IsJust();
0165   }
0166 
0167   V8_INLINE bool operator!=(const Maybe& other) const {
0168     return !operator==(other);
0169   }
0170 
0171  private:
0172   struct JustTag {};
0173 
0174   explicit Maybe(JustTag) : is_valid_(true) {}
0175 
0176   bool is_valid_ = false;
0177 
0178   friend Maybe<void> JustVoid();
0179 };
0180 
0181 inline Maybe<void> JustVoid() { return Maybe<void>(Maybe<void>::JustTag()); }
0182 
0183 }  // namespace v8
0184 
0185 #endif  // INCLUDE_V8_MAYBE_H_