Bug 1640839 - Provide helpers for converting a string to a WebIDL enum value. r=mccr8,media-playback-reviewers,padenot

Differential Revision: https://phabricator.services.mozilla.com/D201338
This commit is contained in:
Peter Van der Beken 2024-03-01 14:31:12 +00:00
parent a1122e9bfc
commit e0ed150b44
10 changed files with 53 additions and 68 deletions

View File

@ -1343,6 +1343,8 @@ inline bool EnumValueNotFound<true>(BindingCallContext& cx,
deflated.get(), type);
}
namespace binding_detail {
template <typename CharT>
inline int FindEnumStringIndexImpl(const CharT* chars, size_t length,
const Span<const nsLiteralCString>& values) {
@ -1405,6 +1407,16 @@ inline bool FindEnumStringIndex(BindingCallContext& cx, JS::Handle<JS::Value> v,
return EnumValueNotFound<InvalidValueFatal>(cx, str, type, sourceDescription);
}
} // namespace binding_detail
template <typename Enum, class StringT>
inline Maybe<Enum> StringToEnum(const StringT& aString) {
int index = binding_detail::FindEnumStringIndexImpl(
aString.BeginReading(), aString.Length(),
binding_detail::EnumStrings<Enum>::Values);
return index >= 0 ? Some(static_cast<Enum>(index)) : Nothing();
}
template <typename Enum>
inline const nsCString& GetEnumString(Enum stringId) {
if (stringId == Enum::EndGuard_) {

View File

@ -7045,10 +7045,10 @@ def getJSToNativeConversionInfo(
"""
{
int index;
if (!FindEnumStringIndex<${invalidEnumValueFatal}>(cx, $${val},
binding_detail::EnumStrings<${enumtype}>::Values,
"${enumtype}", "${sourceDescription}",
&index)) {
if (!binding_detail::FindEnumStringIndex<${invalidEnumValueFatal}>(cx, $${val},
binding_detail::EnumStrings<${enumtype}>::Values,
"${enumtype}", "${sourceDescription}",
&index)) {
$*{exceptionCode}
}
$*{handleInvalidEnumValueCode}

View File

@ -106,10 +106,8 @@ ConsoleLogLevel PrefToValue(const nsACString& aPref,
return aLevel;
}
int index = FindEnumStringIndexImpl(
value.get(), value.Length(),
binding_detail::EnumStrings<ConsoleLogLevel>::Values);
if (NS_WARN_IF(index < 0)) {
Maybe<ConsoleLogLevel> level = StringToEnum<ConsoleLogLevel>(value);
if (NS_WARN_IF(level.isNothing())) {
nsString message;
message.AssignLiteral("Invalid Console.maxLogLevelPref value: ");
message.Append(NS_ConvertUTF8toUTF16(value));
@ -119,8 +117,7 @@ ConsoleLogLevel PrefToValue(const nsACString& aPref,
return aLevel;
}
MOZ_ASSERT(index < (int)ConsoleLogLevelValues::Count);
return static_cast<ConsoleLogLevel>(index);
return level.value();
}
void ConsoleInstance::SetLogLevel() {

View File

@ -929,6 +929,15 @@ and exported to `mozilla/dom/BindingUtils.h` that can be used to convert an enum
value to its corresponding string value. It returns a `const nsCString&`
containing the string value.
`mozilla::dom::StringToEnum` is a templated helper function in
[`BindingUtils.h`](https://searchfox.org/mozilla-central/source/dom/bindings/BindingUtils.h)
and exported to `mozilla/dom/BindingUtils.h` that can be used to convert a
string to the corresponding enum value. It needs to be supplied with the enum
class as a template argument, and returns a `mozilla::Maybe<Enum>`. If the string
value passed to it as an argument is not one of the string values for the enum
then it returns `mozilla::Nothing()`, else it returns the right enum value in
the `mozilla::Maybe`.
#### Callback function types
Callback functions are represented as an object, inheriting from

View File

@ -2746,9 +2746,8 @@ RefPtr<MediaManager::StreamPromise> MediaManager::GetUserMedia(
vc.mMediaSource.Construct().AssignASCII(
dom::GetEnumString(MediaSourceEnum::Camera));
}
videoType = StringToEnum(
dom::binding_detail::EnumStrings<dom::MediaSourceEnum>::Values,
vc.mMediaSource.Value(), MediaSourceEnum::Other);
videoType = dom::StringToEnum<MediaSourceEnum>(vc.mMediaSource.Value())
.valueOr(MediaSourceEnum::Other);
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE,
(uint32_t)videoType);
switch (videoType) {
@ -2839,9 +2838,8 @@ RefPtr<MediaManager::StreamPromise> MediaManager::GetUserMedia(
ac.mMediaSource.Construct(NS_ConvertASCIItoUTF16(
dom::GetEnumString(MediaSourceEnum::Microphone)));
}
audioType = StringToEnum(
dom::binding_detail::EnumStrings<dom::MediaSourceEnum>::Values,
ac.mMediaSource.Value(), MediaSourceEnum::Other);
audioType = dom::StringToEnum<MediaSourceEnum>(ac.mMediaSource.Value())
.valueOr(MediaSourceEnum::Other);
Telemetry::Accumulate(Telemetry::WEBRTC_GET_USER_MEDIA_TYPE,
(uint32_t)audioType);

View File

@ -352,15 +352,13 @@ static bool SupportsEncryptionScheme(
static bool ToSessionType(const nsAString& aSessionType,
MediaKeySessionType& aOutType) {
if (aSessionType.Equals(ToString(MediaKeySessionType::Temporary))) {
aOutType = MediaKeySessionType::Temporary;
return true;
Maybe<MediaKeySessionType> type =
StringToEnum<MediaKeySessionType>(aSessionType);
if (type.isNothing()) {
return false;
}
if (aSessionType.Equals(ToString(MediaKeySessionType::Persistent_license))) {
aOutType = MediaKeySessionType::Persistent_license;
return true;
}
return false;
aOutType = type.value();
return true;
}
// 5.1.1 Is persistent session type?

View File

@ -20,17 +20,6 @@ namespace mozilla {
class LocalMediaDevice;
class MediaDevice;
template <class EnumValuesStrings, class Enum>
static Enum StringToEnum(const EnumValuesStrings& aStrings,
const nsAString& aValue, Enum aDefaultValue) {
for (size_t i = 0; i < ArrayLength(aStrings); i++) {
if (aValue.EqualsASCII(aStrings[i].get())) {
return Enum(i);
}
}
return aDefaultValue;
}
// Helper classes for orthogonal constraints without interdependencies.
// Instead of constraining values, constrain the constraints themselves.
class NormalizedConstraintSet {

View File

@ -131,19 +131,9 @@ ReferrerPolicy ReferrerPolicyFromToken(const nsAString& aContent,
}
}
// Supported tokes - ReferrerPolicyValues, are generated from
// ReferrerPolicy.webidl
for (size_t i = 0;
i < ArrayLength(binding_detail::EnumStrings<ReferrerPolicy>::Values);
i++) {
if (lowerContent.EqualsASCII(
binding_detail::EnumStrings<ReferrerPolicy>::Values[i].get())) {
return static_cast<enum ReferrerPolicy>(i);
}
}
// Return no referrer policy (empty string) if none of the previous match
return ReferrerPolicy::_empty;
// Return no referrer policy (empty string) if it's not a valid enum value.
return StringToEnum<ReferrerPolicy>(lowerContent)
.valueOr(ReferrerPolicy::_empty);
}
// static

View File

@ -168,27 +168,23 @@ already_AddRefed<Promise> XRSystem::RequestSession(
if (aOptions.mRequiredFeatures.WasPassed()) {
for (const nsString& val : aOptions.mRequiredFeatures.Value()) {
int index = FindEnumStringIndexImpl(
val.BeginReading(), val.Length(),
binding_detail::EnumStrings<XRReferenceSpaceType>::Values);
if (index < 0) {
Maybe<XRReferenceSpaceType> type =
StringToEnum<XRReferenceSpaceType>(val);
if (type.isNothing()) {
promise->MaybeRejectWithNotSupportedError(
"A required feature for the XRSession is not available.");
return promise.forget();
}
requiredReferenceSpaceTypes.AppendElement(
static_cast<XRReferenceSpaceType>(index));
requiredReferenceSpaceTypes.AppendElement(type.value());
}
}
if (aOptions.mOptionalFeatures.WasPassed()) {
for (const nsString& val : aOptions.mOptionalFeatures.Value()) {
int index = FindEnumStringIndexImpl(
val.BeginReading(), val.Length(),
binding_detail::EnumStrings<XRReferenceSpaceType>::Values);
if (index >= 0) {
optionalReferenceSpaceTypes.AppendElement(
static_cast<XRReferenceSpaceType>(index));
Maybe<XRReferenceSpaceType> type =
StringToEnum<XRReferenceSpaceType>(val);
if (type.isSome()) {
optionalReferenceSpaceTypes.AppendElement(type.value());
}
}
}

View File

@ -7,6 +7,7 @@
#if defined(ENABLE_TESTS)
# include "mozilla/ipc/UtilityProcessManager.h"
# include "mozilla/ipc/UtilityProcessTest.h"
# include "mozilla/dom/ChromeUtilsBinding.h"
# include "mozilla/dom/Promise.h"
# include "mozilla/ProcInfo.h"
# include "mozilla/IntentionalCrash.h"
@ -26,14 +27,9 @@ namespace mozilla::ipc {
static UtilityActorName UtilityActorNameFromString(
const nsACString& aStringName) {
using namespace mozilla::dom;
// We use WebIDLUtilityActorNames because UtilityActorNames is not designed
// for iteration.
for (size_t i = 0; i < WebIDLUtilityActorNameValues::Count; ++i) {
auto idlName = static_cast<UtilityActorName>(i);
if (GetEnumString(idlName).Equals(aStringName)) {
return idlName;
}
auto idlName = StringToEnum<UtilityActorName>(aStringName);
if (idlName.isSome()) {
return idlName.value();
}
MOZ_CRASH("Unknown utility actor name");
}