diff options
author | Moonchild <moonchild@palemoon.org> | 2023-07-13 05:54:23 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2023-07-13 05:54:23 +0000 |
commit | 8e0e86face0bf8d19e7b23277078bf1e65779187 (patch) | |
tree | 3723b5eaa1273c3a335ae6eb69751e5dcae94d59 | |
parent | 377625e5391178db4fba7e24288a813c5abd43e9 (diff) | |
parent | 0980b1e93685bc6505189073869818392e81e56b (diff) | |
download | uxp-8e0e86face0bf8d19e7b23277078bf1e65779187.tar.gz |
Merge pull request 'Further enhance Maybe<> and use it in the Performance API' (#2272) from dbsoft/UXP:maybe-2255-deux into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/2272
-rwxr-xr-x | dom/performance/Performance.cpp | 30 | ||||
-rw-r--r-- | dom/performance/Performance.h | 6 | ||||
-rw-r--r-- | mfbt/Maybe.h | 87 |
3 files changed, 105 insertions, 18 deletions
diff --git a/dom/performance/Performance.cpp b/dom/performance/Performance.cpp index 109f767557..217faa5afe 100755 --- a/dom/performance/Performance.cpp +++ b/dom/performance/Performance.cpp @@ -414,16 +414,16 @@ DOMHighResTimeStamp Performance::ConvertNameToTimestamp(const nsAString& aName, DOMHighResTimeStamp Performance::ResolveEndTimeForMeasure( const Optional<nsAString>& aEndMark, - const PerformanceMeasureOptions* aOptions, + const Maybe<const PerformanceMeasureOptions&>& aOptions, ErrorResult& aRv) { DOMHighResTimeStamp endTime; if (aEndMark.WasPassed()) { endTime = ConvertMarkToTimestampWithString(aEndMark.Value(), aRv); - } else if (aOptions != nullptr && aOptions->mEnd.WasPassed()) { + } else if (aOptions && aOptions->mEnd.WasPassed()) { endTime = ConvertMarkToTimestamp(ResolveTimestampAttribute::End, aOptions->mEnd.Value(), aRv); - } else if (aOptions != nullptr && aOptions->mStart.WasPassed() && + } else if (aOptions && aOptions->mStart.WasPassed() && aOptions->mDuration.WasPassed()) { const DOMHighResTimeStamp start = ConvertMarkToTimestamp( ResolveTimestampAttribute::Start, aOptions->mStart.Value(), aRv); @@ -448,16 +448,16 @@ Performance::ResolveEndTimeForMeasure( DOMHighResTimeStamp Performance::ResolveStartTimeForMeasure( - const nsAString* aStartMark, - const PerformanceMeasureOptions* aOptions, + const Maybe<const nsAString&>& aStartMark, + const Maybe<const PerformanceMeasureOptions&>& aOptions, ErrorResult& aRv) { DOMHighResTimeStamp startTime; - if (aOptions != nullptr && aOptions->mStart.WasPassed()) { + if (aOptions && aOptions->mStart.WasPassed()) { startTime = ConvertMarkToTimestamp(ResolveTimestampAttribute::Start, aOptions->mStart.Value(), aRv); - } else if (aOptions != nullptr && aOptions->mDuration.WasPassed() && + } else if (aOptions && aOptions->mDuration.WasPassed() && aOptions->mEnd.WasPassed()) { const DOMHighResTimeStamp duration = ConvertMarkToTimestampWithDOMHighResTimeStamp( @@ -475,7 +475,7 @@ Performance::ResolveStartTimeForMeasure( } startTime = end - duration; - } else if (aStartMark != nullptr) { + } else if (aStartMark) { startTime = ConvertMarkToTimestampWithString(*aStartMark, aRv); } else { startTime = 0; @@ -497,13 +497,14 @@ Performance::Measure(JSContext* aCx, mUserEntries.Clear(); } - const PerformanceMeasureOptions* options = nullptr; + // Maybe is more readable than using the union type directly. + Maybe<const PerformanceMeasureOptions&> options; if (aStartOrMeasureOptions.IsPerformanceMeasureOptions()) { - options = &aStartOrMeasureOptions.GetAsPerformanceMeasureOptions(); + options.emplace(aStartOrMeasureOptions.GetAsPerformanceMeasureOptions()); } const bool isOptionsNotEmpty = - (options != nullptr) && + options.isSome() && (!options->mDetail.isUndefined() || options->mStart.WasPassed() || options->mEnd.WasPassed() || options->mDuration.WasPassed()); if (isOptionsNotEmpty) { @@ -530,9 +531,10 @@ Performance::Measure(JSContext* aCx, return nullptr; } - const nsAString* startMark = nullptr; + // Convert to Maybe for consistency with options. + Maybe<const nsAString&> startMark; if (aStartOrMeasureOptions.IsString()) { - startMark = &aStartOrMeasureOptions.GetAsString(); + startMark.emplace(aStartOrMeasureOptions.GetAsString()); } const DOMHighResTimeStamp startTime = ResolveStartTimeForMeasure(startMark, options, aRv); @@ -541,7 +543,7 @@ Performance::Measure(JSContext* aCx, } JS::Rooted<JS::Value> detail(aCx); - if (options != nullptr && !options->mDetail.isNullOrUndefined()) { + if (options && !options->mDetail.isNullOrUndefined()) { StructuredSerializeOptions serializeOptions; JS::Rooted<JS::Value> valueToClone(aCx, options->mDetail); nsContentUtils::StructuredClone(aCx, GetParentObject(), valueToClone, diff --git a/dom/performance/Performance.h b/dom/performance/Performance.h index dc58322416..7a60eb85a9 100644 --- a/dom/performance/Performance.h +++ b/dom/performance/Performance.h @@ -195,11 +195,11 @@ private: DOMHighResTimeStamp ResolveEndTimeForMeasure( const Optional<nsAString>& aEndMark, - const PerformanceMeasureOptions* aOptions, + const Maybe<const PerformanceMeasureOptions&>& aOptions, ErrorResult& aRv); DOMHighResTimeStamp ResolveStartTimeForMeasure( - const nsAString* aStartMark, - const PerformanceMeasureOptions* aOptions, + const Maybe<const nsAString&>& aStartMark, + const Maybe<const PerformanceMeasureOptions&>& aOptions, ErrorResult& aRv); }; diff --git a/mfbt/Maybe.h b/mfbt/Maybe.h index bc123b047f..cc02528f92 100644 --- a/mfbt/Maybe.h +++ b/mfbt/Maybe.h @@ -16,6 +16,7 @@ #include <new> // for placement new #include <type_traits> +#include <utility> namespace mozilla { @@ -83,7 +84,15 @@ template<class T> class Maybe { bool mIsSome; - AlignedStorage2<T> mStorage; + + // To support |Maybe<const Type>| we give |mStorage| the type |T| with any + // const-ness removed. That allows us to |emplace()| an object into + // |mStorage|. Since we treat the contained object as having type |T| + // everywhere else (both internally, and when exposed via public methods) the + // contained object is still treated as const once stored since |const| is + // part of |T|'s type signature. + typedef typename RemoveCV<T>::Type StorageType; + AlignedStorage2<StorageType> mStorage; public: typedef T ValueType; @@ -453,6 +462,72 @@ public: } }; +template <typename T> +class Maybe<T&> { + public: + constexpr Maybe() = default; + constexpr MOZ_IMPLICIT Maybe(Nothing) {} + + void emplace(T& aRef) { mValue = &aRef; } + + /* Methods that check whether this Maybe contains a value */ + explicit operator bool() const { return isSome(); } + bool isSome() const { return mValue; } + bool isNothing() const { return !mValue; } + + T& ref() const { + MOZ_DIAGNOSTIC_ASSERT(isSome()); + return *mValue; + } + + T* operator->() const { return &ref(); } + T& operator*() const { return ref(); } + + // Deliberately not defining value and ptr accessors, as these may be + // confusing on a reference-typed Maybe. + + // XXX Should we define refOr? + + void reset() { mValue = nullptr; } + + template <typename Func> + Maybe& apply(Func&& aFunc) { + if (isSome()) { + std::forward<Func>(aFunc)(ref()); + } + return *this; + } + + template <typename Func> + const Maybe& apply(Func&& aFunc) const { + if (isSome()) { + std::forward<Func>(aFunc)(ref()); + } + return *this; + } + + template <typename Func> + auto map(Func&& aFunc) { + Maybe<decltype(std::forward<Func>(aFunc)(ref()))> val; + if (isSome()) { + val.emplace(std::forward<Func>(aFunc)(ref())); + } + return val; + } + + template <typename Func> + auto map(Func&& aFunc) const { + Maybe<decltype(std::forward<Func>(aFunc)(ref()))> val; + if (isSome()) { + val.emplace(std::forward<Func>(aFunc)(ref())); + } + return val; + } + + private: + T* mValue = nullptr; +}; + /* * Some() creates a Maybe<T> value containing the provided T value. If T has a * move constructor, it's used to make this as efficient as possible. @@ -474,6 +549,13 @@ Some(T&& aValue) return value; } +template <typename T> +Maybe<T&> SomeRef(T& aValue) { + Maybe<T&> value; + value.emplace(aValue); + return value; +} + template<typename T> Maybe<typename RemoveCV<typename RemoveReference<T>::Type>::Type> ToMaybe(T* aPtr) @@ -492,6 +574,9 @@ ToMaybe(T* aPtr) template<typename T> bool operator==(const Maybe<T>& aLHS, const Maybe<T>& aRHS) { + static_assert(!std::is_reference<T>::value, + "operator== is not defined for Maybe<T&>, compare values or " + "addresses explicitly instead"); if (aLHS.isNothing() != aRHS.isNothing()) { return false; } |