summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2023-07-13 05:54:23 +0000
committerMoonchild <moonchild@palemoon.org>2023-07-13 05:54:23 +0000
commit8e0e86face0bf8d19e7b23277078bf1e65779187 (patch)
tree3723b5eaa1273c3a335ae6eb69751e5dcae94d59
parent377625e5391178db4fba7e24288a813c5abd43e9 (diff)
parent0980b1e93685bc6505189073869818392e81e56b (diff)
downloaduxp-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-xdom/performance/Performance.cpp30
-rw-r--r--dom/performance/Performance.h6
-rw-r--r--mfbt/Maybe.h87
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;
}