a058070
commit 940af9f2c87b436559b97c53763aa9eaaf1254eb
a058070
Author: Jeremy Roman <jbroman@chromium.org>
a058070
Date:   Wed Nov 15 16:24:54 2023 +0000
a058070
a058070
    Use C++20 features to simplify blink::NativeValueTraitsBase.
a058070
    
a058070
    These allow some of the metaprogramming bits to be simplified a little.
a058070
    
a058070
    Change-Id: I052b4397586d21348401616e1792afdb9662f975
a058070
    Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5030335
a058070
    Reviewed-by: Yuki Shiino <yukishiino@chromium.org>
a058070
    Commit-Queue: Jeremy Roman <jbroman@chromium.org>
a058070
    Cr-Commit-Position: refs/heads/main@{#1224978}
a058070
a058070
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits.h
a058070
index 7fc91d14acc71..1e5a0790df6da 100644
a058070
--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits.h
a058070
+++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits.h
a058070
@@ -5,6 +5,7 @@
a058070
 #ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_NATIVE_VALUE_TRAITS_H_
a058070
 #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_NATIVE_VALUE_TRAITS_H_
a058070
 
a058070
+#include <concepts>
a058070
 #include <type_traits>
a058070
 
a058070
 #include "third_party/blink/renderer/bindings/core/v8/idl_types_base.h"
a058070
@@ -30,7 +31,7 @@ class ExceptionState;
a058070
 //     return toInt32(isolate, value, exceptionState, NormalConversion);
a058070
 //   }
a058070
 // }
a058070
-template <typename T, typename SFINAEHelper = void>
a058070
+template <typename T>
a058070
 struct NativeValueTraits;
a058070
 
a058070
 // This declaration serves only as a blueprint for specializations: the
a058070
@@ -45,22 +46,15 @@ struct NativeValueTraits;
a058070
 
a058070
 namespace bindings {
a058070
 
a058070
-template <typename T, typename = void>
a058070
-struct NativeValueTraitsHasIsNull : std::false_type {};
a058070
-
a058070
 template <typename T>
a058070
-struct NativeValueTraitsHasIsNull<
a058070
-    T,
a058070
-    std::void_t<decltype(std::declval<T>().IsNull())>> : std::true_type {};
a058070
+struct ImplTypeFor {
a058070
+  using type = T;
a058070
+};
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraitsHasNullValue {
a058070
-  // true if |T| supports IDL null value.
a058070
-  static constexpr bool value =
a058070
-      // ScriptValue, String, and union types have IsNull member function.
a058070
-      bindings::NativeValueTraitsHasIsNull<T>::value ||
a058070
-      // Pointer types have nullptr as IDL null value.
a058070
-      std::is_pointer<T>::value;
a058070
+  requires std::derived_from<T, IDLBase>
a058070
+struct ImplTypeFor<T> {
a058070
+  using type = typename T::ImplType;
a058070
 };
a058070
 
a058070
 }  // namespace bindings
a058070
@@ -78,37 +72,17 @@ struct NativeValueTraitsHasNullValue {
a058070
 // If present, |NullValue()| will be used when converting from the nullable type
a058070
 // T?, and should be used if the impl type has an existing "null" state. If not
a058070
 // present, WTF::Optional will be used to wrap the type.
a058070
-template <typename T, typename SFINAEHelper = void>
a058070
-struct NativeValueTraitsBase {
a058070
-  STATIC_ONLY(NativeValueTraitsBase);
a058070
-
a058070
-  using ImplType = T;
a058070
-
a058070
-  static constexpr bool has_null_value =
a058070
-      bindings::NativeValueTraitsHasNullValue<ImplType>::value;
a058070
-
a058070
-  template <typename... ExtraArgs>
a058070
-  static decltype(auto) ArgumentValue(v8::Isolate* isolate,
a058070
-                                      int argument_index,
a058070
-                                      v8::Local<v8::Value> value,
a058070
-                                      ExceptionState& exception_state,
a058070
-                                      ExtraArgs... extra_args) {
a058070
-    return NativeValueTraits<std::remove_pointer_t<T>>::NativeValue(
a058070
-        isolate, value, exception_state,
a058070
-        std::forward<ExtraArgs>(extra_args)...);
a058070
-  }
a058070
-};
a058070
-
a058070
 template <typename T>
a058070
-struct NativeValueTraitsBase<
a058070
-    T,
a058070
-    std::enable_if_t<std::is_base_of<IDLBase, T>::value>> {
a058070
+struct NativeValueTraitsBase {
a058070
   STATIC_ONLY(NativeValueTraitsBase);
a058070
 
a058070
-  using ImplType = typename T::ImplType;
a058070
+  using ImplType = bindings::ImplTypeFor<T>::type;
a058070
 
a058070
+  // Pointer types have nullptr as IDL null value.
a058070
+  // ScriptValue, String, and union types have IsNull member function.
a058070
   static constexpr bool has_null_value =
a058070
-      bindings::NativeValueTraitsHasNullValue<ImplType>::value;
a058070
+      std::is_pointer_v<ImplType> ||
a058070
+      requires(ImplType value) { value.IsNull(); };
a058070
 
a058070
   template <typename... ExtraArgs>
a058070
   static decltype(auto) ArgumentValue(v8::Isolate* isolate,
a058070
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc b/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
a058070
index 508ea6d8eea48..18de71d84023f 100644
a058070
--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
a058070
+++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_buffer_sources.cc
a058070
@@ -7,6 +7,7 @@
a058070
 #include "third_party/blink/renderer/core/core_export.h"
a058070
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
a058070
 #include "third_party/blink/renderer/core/frame/web_feature.h"
a058070
+#include "third_party/blink/renderer/core/typed_arrays/flexible_array_buffer_view.h"
a058070
 #include "third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h"
a058070
 
a058070
 namespace blink {
a058070
@@ -698,12 +699,11 @@ DOMArrayBufferBase* NativeValueTraits<
a058070
 // ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-NotShared<T> NativeValueTraits<
a058070
-    NotShared<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    NativeValue(v8::Isolate* isolate,
a058070
-                v8::Local<v8::Value> value,
a058070
-                ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+NotShared<T> NativeValueTraits<NotShared<T>>::NativeValue(
a058070
+    v8::Isolate* isolate,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return NativeValueImpl<
a058070
       RecipeTrait<NotShared<T>>, ToDOMViewType<T, kNotShared>,
a058070
       Nullablity::kIsNotNullable, BufferSizeCheck::kCheck,
a058070
@@ -712,13 +712,12 @@ NotShared<T> NativeValueTraits<
a058070
 }
a058070
 
a058070
 template <typename T>
a058070
-NotShared<T> NativeValueTraits<
a058070
-    NotShared<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    ArgumentValue(v8::Isolate* isolate,
a058070
-                  int argument_index,
a058070
-                  v8::Local<v8::Value> value,
a058070
-                  ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+NotShared<T> NativeValueTraits<NotShared<T>>::ArgumentValue(
a058070
+    v8::Isolate* isolate,
a058070
+    int argument_index,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return ArgumentValueImpl<
a058070
       RecipeTrait<NotShared<T>>, ToDOMViewType<T, kNotShared>,
a058070
       Nullablity::kIsNotNullable, BufferSizeCheck::kCheck,
a058070
@@ -729,12 +728,11 @@ NotShared<T> NativeValueTraits<
a058070
 // [AllowShared] ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-MaybeShared<T> NativeValueTraits<
a058070
-    MaybeShared<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    NativeValue(v8::Isolate* isolate,
a058070
-                v8::Local<v8::Value> value,
a058070
-                ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+MaybeShared<T> NativeValueTraits<MaybeShared<T>>::NativeValue(
a058070
+    v8::Isolate* isolate,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return NativeValueImpl<RecipeTrait<MaybeShared<T>>,
a058070
                          ToDOMViewType<T, kMaybeShared>,
a058070
                          Nullablity::kIsNotNullable, BufferSizeCheck::kCheck,
a058070
@@ -743,13 +741,12 @@ MaybeShared<T> NativeValueTraits<
a058070
 }
a058070
 
a058070
 template <typename T>
a058070
-MaybeShared<T> NativeValueTraits<
a058070
-    MaybeShared<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    ArgumentValue(v8::Isolate* isolate,
a058070
-                  int argument_index,
a058070
-                  v8::Local<v8::Value> value,
a058070
-                  ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+MaybeShared<T> NativeValueTraits<MaybeShared<T>>::ArgumentValue(
a058070
+    v8::Isolate* isolate,
a058070
+    int argument_index,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return ArgumentValueImpl<RecipeTrait<MaybeShared<T>>,
a058070
                            ToDOMViewType<T, kMaybeShared>,
a058070
                            Nullablity::kIsNotNullable, BufferSizeCheck::kCheck,
a058070
@@ -760,12 +757,12 @@ MaybeShared<T> NativeValueTraits<
a058070
 // [AllowShared, BufferSourceTypeNoSizeLimit] ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-MaybeShared<T> NativeValueTraits<
a058070
-    IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    NativeValue(v8::Isolate* isolate,
a058070
-                v8::Local<v8::Value> value,
a058070
-                ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+MaybeShared<T>
a058070
+NativeValueTraits<IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>>::NativeValue(
a058070
+    v8::Isolate* isolate,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return NativeValueImpl<
a058070
       RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>,
a058070
       Nullablity::kIsNotNullable, BufferSizeCheck::kDoNotCheck,
a058070
@@ -774,13 +771,12 @@ MaybeShared<T> NativeValueTraits<
a058070
 }
a058070
 
a058070
 template <typename T>
a058070
-MaybeShared<T> NativeValueTraits<
a058070
-    IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    ArgumentValue(v8::Isolate* isolate,
a058070
-                  int argument_index,
a058070
-                  v8::Local<v8::Value> value,
a058070
-                  ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+MaybeShared<T> NativeValueTraits
a058070
+    MaybeShared<T>>>::ArgumentValue(v8::Isolate* isolate,
a058070
+                                    int argument_index,
a058070
+                                    v8::Local<v8::Value> value,
a058070
+                                    ExceptionState& exception_state) {
a058070
   return ArgumentValueImpl<
a058070
       RecipeTrait<MaybeShared<T>>, ToDOMViewType<T, kMaybeShared>,
a058070
       Nullablity::kIsNotNullable, BufferSizeCheck::kDoNotCheck,
a058070
@@ -791,12 +787,11 @@ MaybeShared<T> NativeValueTraits<
a058070
 // Nullable ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-NotShared<T> NativeValueTraits<
a058070
-    IDLNullable<NotShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    NativeValue(v8::Isolate* isolate,
a058070
-                v8::Local<v8::Value> value,
a058070
-                ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+NotShared<T> NativeValueTraits<IDLNullable<NotShared<T>>>::NativeValue(
a058070
+    v8::Isolate* isolate,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return NativeValueImpl<
a058070
       RecipeTrait<NotShared<T>>, ToDOMViewType<T, kNotShared>,
a058070
       Nullablity::kIsNullable, BufferSizeCheck::kCheck,
a058070
@@ -805,13 +800,12 @@ NotShared<T> NativeValueTraits<
a058070
 }
a058070
 
a058070
 template <typename T>
a058070
-NotShared<T> NativeValueTraits<
a058070
-    IDLNullable<NotShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    ArgumentValue(v8::Isolate* isolate,
a058070
-                  int argument_index,
a058070
-                  v8::Local<v8::Value> value,
a058070
-                  ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+NotShared<T> NativeValueTraits<IDLNullable<NotShared<T>>>::ArgumentValue(
a058070
+    v8::Isolate* isolate,
a058070
+    int argument_index,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return ArgumentValueImpl<
a058070
       RecipeTrait<NotShared<T>>, ToDOMViewType<T, kNotShared>,
a058070
       Nullablity::kIsNullable, BufferSizeCheck::kCheck,
a058070
@@ -822,12 +816,11 @@ NotShared<T> NativeValueTraits<
a058070
 // Nullable [AllowShared] ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-MaybeShared<T> NativeValueTraits<
a058070
-    IDLNullable<MaybeShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    NativeValue(v8::Isolate* isolate,
a058070
-                v8::Local<v8::Value> value,
a058070
-                ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+MaybeShared<T> NativeValueTraits<IDLNullable<MaybeShared<T>>>::NativeValue(
a058070
+    v8::Isolate* isolate,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return NativeValueImpl<RecipeTrait<MaybeShared<T>>,
a058070
                          ToDOMViewType<T, kMaybeShared>,
a058070
                          Nullablity::kIsNullable, BufferSizeCheck::kCheck,
a058070
@@ -836,13 +829,12 @@ MaybeShared<T> NativeValueTraits<
a058070
 }
a058070
 
a058070
 template <typename T>
a058070
-MaybeShared<T> NativeValueTraits<
a058070
-    IDLNullable<MaybeShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
-    ArgumentValue(v8::Isolate* isolate,
a058070
-                  int argument_index,
a058070
-                  v8::Local<v8::Value> value,
a058070
-                  ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+MaybeShared<T> NativeValueTraits<IDLNullable<MaybeShared<T>>>::ArgumentValue(
a058070
+    v8::Isolate* isolate,
a058070
+    int argument_index,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return ArgumentValueImpl<RecipeTrait<MaybeShared<T>>,
a058070
                            ToDOMViewType<T, kMaybeShared>,
a058070
                            Nullablity::kIsNullable, BufferSizeCheck::kCheck,
a058070
@@ -853,9 +845,9 @@ MaybeShared<T> NativeValueTraits<
a058070
 // Nullable [AllowShared, BufferSourceTypeNoSizeLimit] ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-MaybeShared<T> NativeValueTraits<
a058070
-    IDLNullable<IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>::
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+MaybeShared<T>
a058070
+NativeValueTraits<IDLNullable<IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>>>::
a058070
     ArgumentValue(v8::Isolate* isolate,
a058070
                   int argument_index,
a058070
                   v8::Local<v8::Value> value,
a058070
@@ -870,13 +862,11 @@ MaybeShared<T> NativeValueTraits<
a058070
 // [AllowShared, FlexibleArrayBufferView] ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-T NativeValueTraits
a058070
-                    typename std::enable_if_t<
a058070
-                        std::is_base_of<FlexibleArrayBufferView, T>::value>>::
a058070
-    ArgumentValue(v8::Isolate* isolate,
a058070
-                  int argument_index,
a058070
-                  v8::Local<v8::Value> value,
a058070
-                  ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, FlexibleArrayBufferView>
a058070
+T NativeValueTraits<T>::ArgumentValue(v8::Isolate* isolate,
a058070
+                                      int argument_index,
a058070
+                                      v8::Local<v8::Value> value,
a058070
+                                      ExceptionState& exception_state) {
a058070
   return ArgumentValueImpl<RecipeTrait<T>, ToFlexibleArrayBufferView,
a058070
                            Nullablity::kIsNotNullable, BufferSizeCheck::kCheck,
a058070
                            ResizableAllowance::kDisallowResizable,
a058070
@@ -888,13 +878,12 @@ T NativeValueTraits
a058070
 // ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-T NativeValueTraits<IDLBufferSourceTypeNoSizeLimit<T>,
a058070
-                    typename std::enable_if_t<
a058070
-                        std::is_base_of<FlexibleArrayBufferView, T>::value>>::
a058070
-    ArgumentValue(v8::Isolate* isolate,
a058070
-                  int argument_index,
a058070
-                  v8::Local<v8::Value> value,
a058070
-                  ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, FlexibleArrayBufferView>
a058070
+T NativeValueTraits<IDLBufferSourceTypeNoSizeLimit<T>>::ArgumentValue(
a058070
+    v8::Isolate* isolate,
a058070
+    int argument_index,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return ArgumentValueImpl<
a058070
       RecipeTrait<T>, ToFlexibleArrayBufferView, Nullablity::kIsNotNullable,
a058070
       BufferSizeCheck::kDoNotCheck, ResizableAllowance::kDisallowResizable,
a058070
@@ -905,13 +894,12 @@ T NativeValueTraits<IDLBufferSourceTypeNoSizeLimit<T>,
a058070
 // Nullable [AllowShared, FlexibleArrayBufferView] ArrayBufferView
a058070
 
a058070
 template <typename T>
a058070
-T NativeValueTraits<IDLNullable<T>,
a058070
-                    typename std::enable_if_t<
a058070
-                        std::is_base_of<FlexibleArrayBufferView, T>::value>>::
a058070
-    ArgumentValue(v8::Isolate* isolate,
a058070
-                  int argument_index,
a058070
-                  v8::Local<v8::Value> value,
a058070
-                  ExceptionState& exception_state) {
a058070
+  requires std::derived_from<T, FlexibleArrayBufferView>
a058070
+T NativeValueTraits<IDLNullable<T>>::ArgumentValue(
a058070
+    v8::Isolate* isolate,
a058070
+    int argument_index,
a058070
+    v8::Local<v8::Value> value,
a058070
+    ExceptionState& exception_state) {
a058070
   return ArgumentValueImpl<RecipeTrait<T>, ToFlexibleArrayBufferView,
a058070
                            Nullablity::kIsNullable, BufferSizeCheck::kCheck,
a058070
                            ResizableAllowance::kDisallowResizable,
a058070
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
a058070
index 899929dcf49f9..5011503dcf1c0 100644
a058070
--- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
a058070
+++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
a058070
@@ -715,9 +718,8 @@ struct CORE_EXPORT NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    T,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>> {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+struct NativeValueTraits<T> {
a058070
   // NotShared<T> or MaybeShared<T> should be used instead.
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
@@ -729,9 +731,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>> {
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+struct NativeValueTraits<IDLNullable<T>> {
a058070
   // NotShared<T> or MaybeShared<T> should be used instead.
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
@@ -743,9 +744,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    NotShared<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+struct NativeValueTraits<NotShared<T>>
a058070
     : public NativeValueTraitsBase<NotShared<T>> {
a058070
   static NotShared<T> NativeValue(v8::Isolate* isolate,
a058070
                                   v8::Local<v8::Value> value,
a058070
@@ -758,9 +758,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<NotShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+struct NativeValueTraits<IDLNullable<NotShared<T>>>
a058070
     : public NativeValueTraitsBase<NotShared<T>> {
a058070
   static NotShared<T> NativeValue(v8::Isolate* isolate,
a058070
                                   v8::Local<v8::Value> value,
a058070
@@ -773,9 +772,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    MaybeShared<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+struct NativeValueTraits<MaybeShared<T>>
a058070
     : public NativeValueTraitsBase<MaybeShared<T>> {
a058070
   static MaybeShared<T> NativeValue(v8::Isolate* isolate,
a058070
                                     v8::Local<v8::Value> value,
a058070
@@ -788,9 +786,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+struct NativeValueTraits<IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>>
a058070
     : public NativeValueTraitsBase<MaybeShared<T>> {
a058070
   // FlexibleArrayBufferView uses this in its implementation, so we cannot
a058070
   // delete it.
a058070
@@ -805,9 +802,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<MaybeShared<T>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
+struct NativeValueTraits<IDLNullable<MaybeShared<T>>>
a058070
     : public NativeValueTraitsBase<MaybeShared<T>> {
a058070
   static MaybeShared<T> NativeValue(v8::Isolate* isolate,
a058070
                                     v8::Local<v8::Value> value,
a058070
@@ -820,9 +816,9 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
+  requires std::derived_from<T, DOMArrayBufferView>
a058070
 struct NativeValueTraits<
a058070
-    IDLNullable<IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>>,
a058070
-    typename std::enable_if_t<std::is_base_of<DOMArrayBufferView, T>::value>>
a058070
+    IDLNullable<IDLBufferSourceTypeNoSizeLimit<MaybeShared<T>>>>
a058070
     : public NativeValueTraitsBase<MaybeShared<T>> {
a058070
   // BufferSourceTypeNoSizeLimit must be used only as arguments.
a058070
   static MaybeShared<T> NativeValue(v8::Isolate* isolate,
a058070
@@ -836,11 +832,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    T,
a058070
-    typename std::enable_if_t<
a058070
-        std::is_base_of<FlexibleArrayBufferView, T>::value>>
a058070
-    : public NativeValueTraitsBase<T> {
a058070
+  requires std::derived_from<T, FlexibleArrayBufferView>
a058070
+struct NativeValueTraits<T> : public NativeValueTraitsBase<T> {
a058070
   // FlexibleArrayBufferView must be used only as arguments.
a058070
   static T NativeValue(v8::Isolate* isolate,
a058070
                        v8::Local<v8::Value> value,
a058070
@@ -853,10 +846,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLBufferSourceTypeNoSizeLimit<T>,
a058070
-    typename std::enable_if_t<
a058070
-        std::is_base_of<FlexibleArrayBufferView, T>::value>>
a058070
+  requires std::derived_from<T, FlexibleArrayBufferView>
a058070
+struct NativeValueTraits<IDLBufferSourceTypeNoSizeLimit<T>>
a058070
     : public NativeValueTraitsBase<T> {
a058070
   // BufferSourceTypeNoSizeLimit and FlexibleArrayBufferView must be used only
a058070
   // as arguments.
a058070
@@ -871,11 +862,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<T>,
a058070
-    typename std::enable_if_t<
a058070
-        std::is_base_of<FlexibleArrayBufferView, T>::value>>
a058070
-    : public NativeValueTraitsBase<T> {
a058070
+  requires std::derived_from<T, FlexibleArrayBufferView>
a058070
+struct NativeValueTraits<IDLNullable<T>> : public NativeValueTraitsBase<T> {
a058070
   // FlexibleArrayBufferView must be used only as arguments.
a058070
   static T NativeValue(v8::Isolate* isolate,
a058070
                        v8::Local<v8::Value> value,
a058070
@@ -1134,9 +1122,8 @@ NativeValueTraits<IDLSequence<T>>::NativeValue(
a058070
 }
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<IDLNullable<IDLSequence<T>>,
a058070
-                         typename std::enable_if_t<
a058070
-                             NativeValueTraits<IDLSequence<T>>::has_null_value>>
a058070
+  requires NativeValueTraits<IDLSequence<T>>::has_null_value
a058070
+struct NativeValueTraits<IDLNullable<IDLSequence<T>>>
a058070
     : public NativeValueTraitsBase<HeapVector<AddMemberIfNeeded<T>>*> {
a058070
   using ImplType = typename NativeValueTraits<IDLSequence<T>>::ImplType*;
a058070
 
a058070
@@ -1203,9 +1190,8 @@ struct NativeValueTraits<IDLArray<T>>
a058070
     : public NativeValueTraits<IDLSequence<T>> {};
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<IDLNullable<IDLArray<T>>,
a058070
-                         typename std::enable_if_t<
a058070
-                             NativeValueTraits<IDLSequence<T>>::has_null_value>>
a058070
+  requires NativeValueTraits<IDLSequence<T>>::has_null_value
a058070
+struct NativeValueTraits<IDLNullable<IDLArray<T>>>
a058070
     : public NativeValueTraits<IDLNullable<IDLSequence<T>>> {};
a058070
 
a058070
 // Record types
a058070
@@ -1335,10 +1321,8 @@ struct NativeValueTraits<IDLRecord<K, V>>
a058070
 
a058070
 // Callback function types
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    T,
a058070
-    typename std::enable_if_t<std::is_base_of<CallbackFunctionBase, T>::value>>
a058070
-    : public NativeValueTraitsBase<T*> {
a058070
+  requires std::derived_from<T, CallbackFunctionBase>
a058070
+struct NativeValueTraits<T> : public NativeValueTraitsBase<T*> {
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
                         ExceptionState& exception_state) {
a058070
@@ -1361,9 +1345,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<CallbackFunctionBase, T>::value>>
a058070
+  requires std::derived_from<T, CallbackFunctionBase>
a058070
+struct NativeValueTraits<IDLNullable<T>>
a058070
     : public NativeValueTraitsBase<IDLNullable<T>> {
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
@@ -1392,10 +1375,8 @@ struct NativeValueTraits<
a058070
 
a058070
 // Callback interface types
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    T,
a058070
-    typename std::enable_if_t<std::is_base_of<CallbackInterfaceBase, T>::value>>
a058070
-    : public NativeValueTraitsBase<T*> {
a058070
+  requires std::derived_from<T, CallbackInterfaceBase>
a058070
+struct NativeValueTraits<T> : public NativeValueTraitsBase<T*> {
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
                         ExceptionState& exception_state) {
a058070
@@ -1418,9 +1399,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<CallbackInterfaceBase, T>::value>>
a058070
+  requires std::derived_from<T, CallbackInterfaceBase>
a058070
+struct NativeValueTraits<IDLNullable<T>>
a058070
     : public NativeValueTraitsBase<IDLNullable<T>> {
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
@@ -1449,11 +1429,8 @@ struct NativeValueTraits<
a058070
 
a058070
 // Dictionary types
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    T,
a058070
-    typename std::enable_if_t<
a058070
-        std::is_base_of<bindings::DictionaryBase, T>::value>>
a058070
-    : public NativeValueTraitsBase<T*> {
a058070
+  requires std::derived_from<T, bindings::DictionaryBase>
a058070
+struct NativeValueTraits<T> : public NativeValueTraitsBase<T*> {
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
                         ExceptionState& exception_state) {
a058070
@@ -1464,14 +1441,11 @@ struct NativeValueTraits<
a058070
 // We don't support nullable dictionary types in general since it's quite
a058070
 // confusing and often misused.
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<T>,
a058070
-    typename std::enable_if_t<
a058070
-        std::is_base_of<bindings::DictionaryBase, T>::value &&
a058070
-        (std::is_same<T, GPUColorTargetState>::value ||
a058070
-         std::is_same<T, GPURenderPassColorAttachment>::value ||
a058070
-         std::is_same<T, GPUVertexBufferLayout>::value)>>
a058070
-    : public NativeValueTraitsBase<T*> {
a058070
+  requires std::derived_from<T, bindings::DictionaryBase> &&
a058070
+           (std::same_as<T, GPUColorTargetState> ||
a058070
+            std::same_as<T, GPURenderPassColorAttachment> ||
a058070
+            std::same_as<T, GPUVertexBufferLayout>)
a058070
+struct NativeValueTraits<IDLNullable<T>> : public NativeValueTraitsBase<T*> {
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
                         ExceptionState& exception_state) {
a058070
@@ -1483,11 +1457,8 @@ struct NativeValueTraits<
a058070
 
a058070
 // Enumeration types
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    T,
a058070
-    typename std::enable_if_t<
a058070
-        std::is_base_of<bindings::EnumerationBase, T>::value>>
a058070
-    : public NativeValueTraitsBase<T> {
a058070
+  requires std::derived_from<T, bindings::EnumerationBase>
a058070
+struct NativeValueTraits<T> : public NativeValueTraitsBase<T> {
a058070
   static T NativeValue(v8::Isolate* isolate,
a058070
                        v8::Local<v8::Value> value,
a058070
                        ExceptionState& exception_state) {
a058070
@@ -1497,10 +1468,8 @@ struct NativeValueTraits<
a058070
 
a058070
 // Interface types
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    T,
a058070
-    typename std::enable_if_t<std::is_base_of<ScriptWrappable, T>::value>>
a058070
-    : public NativeValueTraitsBase<T*> {
a058070
+  requires std::derived_from<T, ScriptWrappable>
a058070
+struct NativeValueTraits<T> : public NativeValueTraitsBase<T*> {
a058070
   static inline T* NativeValue(v8::Isolate* isolate,
a058070
                                v8::Local<v8::Value> value,
a058070
                                ExceptionState& exception_state) {
a058070
@@ -1528,9 +1497,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<ScriptWrappable, T>::value>>
a058070
+  requires std::derived_from<T, ScriptWrappable>
a058070
+struct NativeValueTraits<IDLNullable<T>>
a058070
     : public NativeValueTraitsBase<IDLNullable<T>> {
a058070
   static inline T* NativeValue(v8::Isolate* isolate,
a058070
                                v8::Local<v8::Value> value,
a058070
@@ -1565,10 +1533,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    T,
a058070
-    typename std::enable_if_t<std::is_base_of<bindings::UnionBase, T>::value>>
a058070
-    : public NativeValueTraitsBase<T*> {
a058070
+  requires std::derived_from<T, bindings::UnionBase>
a058070
+struct NativeValueTraits<T> : public NativeValueTraitsBase<T*> {
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
                         ExceptionState& exception_state) {
a058070
@@ -1584,10 +1550,8 @@ struct NativeValueTraits<
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<T>,
a058070
-    typename std::enable_if_t<std::is_base_of<bindings::UnionBase, T>::value>>
a058070
-    : public NativeValueTraitsBase<T*> {
a058070
+  requires std::derived_from<T, bindings::UnionBase>
a058070
+struct NativeValueTraits<IDLNullable<T>> : public NativeValueTraitsBase<T*> {
a058070
   static T* NativeValue(v8::Isolate* isolate,
a058070
                         v8::Local<v8::Value> value,
a058070
                         ExceptionState& exception_state) {
a058070
@@ -1608,9 +1572,8 @@ struct NativeValueTraits<
a058070
 
a058070
 // Nullable types
a058070
 template <typename InnerType>
a058070
-struct NativeValueTraits<
a058070
-    IDLNullable<InnerType>,
a058070
-    typename std::enable_if_t::has_null_value>>
a058070
+  requires(!NativeValueTraits<InnerType>::has_null_value)
a058070
+struct NativeValueTraits<IDLNullable<InnerType>>
a058070
     : public NativeValueTraitsBase<IDLNullable<InnerType>> {
a058070
   // https://webidl.spec.whatwg.org/#es-nullable-type
a058070
   using ImplType =
a058070
@@ -1642,9 +1605,8 @@ struct NativeValueTraits<IDLNullable<IDLNullable<T>>>;
a058070
 
a058070
 // Optional types
a058070
 template <typename T>
a058070
-struct NativeValueTraits<IDLOptional<T>,
a058070
-                         typename std::enable_if_t
a058070
-                             typename NativeValueTraits<T>::ImplType>::value>>
a058070
+  requires std::is_arithmetic_v<typename NativeValueTraits<T>::ImplType>
a058070
+struct NativeValueTraits<IDLOptional<T>>
a058070
     : public NativeValueTraitsBase<typename NativeValueTraits<T>::ImplType> {
a058070
   using ImplType = typename NativeValueTraits<T>::ImplType;
a058070
 
a058070
@@ -1666,9 +1628,8 @@ struct NativeValueTraits<IDLOptional<T>,
a058070
 };
a058070
 
a058070
 template <typename T>
a058070
-struct NativeValueTraits<IDLOptional<T>,
a058070
-                         typename std::enable_if_t
a058070
-                             typename NativeValueTraits<T>::ImplType>::value>>
a058070
+  requires std::is_pointer_v<typename NativeValueTraits<T>::ImplType>
a058070
+struct NativeValueTraits<IDLOptional<T>>
a058070
     : public NativeValueTraitsBase<typename NativeValueTraits<T>::ImplType> {
a058070
   using ImplType = typename NativeValueTraits<T>::ImplType;
a058070