Source/WebCore:
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Aug 2016 20:31:42 +0000 (20:31 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Aug 2016 20:31:42 +0000 (20:31 +0000)
Replace NodeOrString with std::variant<Ref<Node>, String>
https://bugs.webkit.org/show_bug.cgi?id=160638

Reviewed by Anders Carlsson.

* WebCore.xcodeproj/project.pbxproj:
Remove NodeOrString.h/cpp

* bindings/js/JSNodeOrString.cpp:
* bindings/js/JSNodeOrString.h:
* dom/ContainerNode.cpp:
(WebCore::ContainerNode::append):
(WebCore::ContainerNode::prepend):
* dom/ContainerNode.h:
* dom/Node.cpp:
(WebCore::nodeSetPreTransformedFromNodeOrStringVector):
(WebCore::firstFollowingSiblingNotInNodeSet):
(WebCore::Node::convertNodesOrStringsIntoNode):
(WebCore::Node::before):
(WebCore::Node::after):
(WebCore::Node::replaceWith):
* dom/Node.h:
Replace NodeOrString with std::variant<Ref<Node>, String> and move convertNodesOrStringsIntoNode
into Node.

* dom/NodeOrString.cpp: Removed.
* dom/NodeOrString.h: Removed.

Source/WTF:
Replace NodeOrString with std::variant<RefPtr<Node>, String>
https://bugs.webkit.org/show_bug.cgi?id=160638

Reviewed by Anders Carlsson.

* wtf/StdLibExtras.h:
(WTF::Visitor::Visitor):
(WTF::makeVisitor):
Add WTF::makeVisitor() which takes a list of lambdas to use
an an overload set for a visitor object.

Also, re-export std::experimental::variant (and helpers) in the std
namespace using type aliasing.

* wtf/Variant.h:
Make std::experimental::variant work in WebCore.

Tools:
Replace NodeOrString with std::variant<RefPtr<Node>, String>
https://bugs.webkit.org/show_bug.cgi?id=160638

Reviewed by Anders Carlsson.

* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/Tests/WTF/Variant.cpp:
Add additional tests for the initial state of std::variant and using
makeVisitor for visiting.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@204291 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
Source/WTF/ChangeLog
Source/WTF/wtf/StdLibExtras.h
Source/WTF/wtf/Variant.h
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSNodeOrString.cpp
Source/WebCore/bindings/js/JSNodeOrString.h
Source/WebCore/dom/ContainerNode.cpp
Source/WebCore/dom/ContainerNode.h
Source/WebCore/dom/DOMAllInOne.cpp
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/NodeOrString.cpp [deleted file]
Source/WebCore/dom/NodeOrString.h [deleted file]
Tools/ChangeLog
Tools/TestWebKitAPI/CMakeLists.txt
Tools/TestWebKitAPI/Tests/WTF/Variant.cpp

index f26b2eb..2b00baf 100644 (file)
@@ -1,5 +1,24 @@
 2016-08-06  Sam Weinig  <sam@webkit.org>
 
+        Replace NodeOrString with std::variant<RefPtr<Node>, String>
+        https://bugs.webkit.org/show_bug.cgi?id=160638
+
+        Reviewed by Anders Carlsson.
+
+        * wtf/StdLibExtras.h:
+        (WTF::Visitor::Visitor):
+        (WTF::makeVisitor):
+        Add WTF::makeVisitor() which takes a list of lambdas to use
+        an an overload set for a visitor object.
+
+        Also, re-export std::experimental::variant (and helpers) in the std
+        namespace using type aliasing.
+
+        * wtf/Variant.h:
+        Make std::experimental::variant work in WebCore.
+
+2016-08-06  Sam Weinig  <sam@webkit.org>
+
         WTF needs a variant implementation
         https://bugs.webkit.org/show_bug.cgi?id=160618
 
index 4457ba2..7945432 100644 (file)
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <wtf/Assertions.h>
 #include <wtf/CheckedArithmetic.h>
+#include <wtf/Variant.h>
 
 // This was used to declare and define a static local variable (static T;) so that
 //  it was leaked so that its destructors were not called at exit.
@@ -309,6 +310,36 @@ bool checkAndSet(T& left, U right)
     return true;
 }
 
+// Visitor adapted from http://stackoverflow.com/questions/25338795/is-there-a-name-for-this-tuple-creation-idiom
+
+template <class A, class... B>
+struct Visitor : Visitor<A>, Visitor<B...> {
+    Visitor(A a, B... b)
+        : Visitor<A>(a)
+        , Visitor<B...>(b...)
+    {
+    }
+
+    using Visitor<A>::operator ();
+    using Visitor<B...>::operator ();
+};
+  
+template <class A>
+struct Visitor<A> : A {
+    Visitor(A a)
+        : A(a)
+    {
+    }
+
+    using A::operator();
+};
+template <class... F>
+auto makeVisitor(F... f)
+{
+    return Visitor<F...>(f...);
+}
+
 } // namespace WTF
 
 // This version of placement new omits a 0 check.
@@ -372,6 +403,14 @@ ALWAYS_INLINE constexpr typename remove_reference<T>::type&& move(T&& value)
     return move(forward<T>(value));
 }
 
+template<typename... Types>
+using variant = std::experimental::variant<Types...>;
+
+using std::experimental::get;
+using std::experimental::get_if;
+using std::experimental::holds_alternative;
+using std::experimental::visit;
+
 } // namespace std
 
 #define WTFMove(value) std::move<WTF::CheckMoveParameter>(value)
index 79bee6a..d6f24f1 100644 (file)
@@ -39,6 +39,7 @@
 
 #pragma once
 
+#include <functional>
 #include <limits.h>
 #include <new>
 #include <stddef.h>
 #include <utility>
 #include <wtf/Compiler.h>
 
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable:4245)
+#pragma warning(disable:4521)
+#pragma warning(disable:4522)
+#pragma warning(disable:4814)
+#endif
+
 namespace std {
 namespace experimental {
 
 #if COMPILER_SUPPORTS(EXCEPTIONS)
-
 #define __THROW_EXCEPTION(__exception) throw __exception;
-#define __CONST_EXPR_THROW_EXCPETION_IF(__predicate, __exception) \
-    do { \
-        if ((__predicate)) { \
-            throw __exception; \
-        } \
-    while (0); \
-
+#define __NOEXCEPT noexcept
+#define __NOEXCEPT_(__exception) noexcept(__exception)
 #else
-
-static inline void __crash_helper(bool){
-    CRASH();
-}
-static inline constexpr bool __constexpr_crash_if(bool test){
-    return !test ? true : (__crash_helper(test), false);
-}
-
-#define __THROW_EXCEPTION(...) CRASH();
-#define __CONST_EXPR_THROW_EXCPETION_IF(__predicate, __exception) __constexpr_crash_if((__predicate));
+#define __THROW_EXCEPTION(__exception) do { (void)__exception; CRASH(); } while (0);
+#define __NOEXCEPT
+#define __NOEXCEPT_(...)
 #endif
 
 struct __in_place_private{
@@ -117,6 +113,11 @@ public:
     {}
 };
 
+template<typename T>
+NO_RETURN_DUE_TO_CRASH inline T __throw_bad_variant_access(const char* what_arg){
+    __THROW_EXCEPTION(bad_variant_access(what_arg))
+}
+
 template<ptrdiff_t _Offset,typename _Type,typename ... _Types>
 struct __type_index_helper;
 
@@ -306,7 +307,7 @@ struct __all_trivially_destructible<_Head,_Rest...> {
 template<typename _Target,typename ... _Args>
 struct __storage_nothrow_constructible{
     static const bool __value=
-        noexcept(_Target(std::declval<_Args>()...));
+        std::is_nothrow_constructible<_Target, _Args...>::value;
 };
 
 template<typename ... _Types>
@@ -535,7 +536,7 @@ union __variant_data<_Type>{
     _Type& __get(in_place_index_t<0>){
         return __variant_storage<_Type>::__get(__val);
     }
-    constexpr _Type&& __get_rref(in_place_index_t<0>){
+    /*constexpr*/ _Type&& __get_rref(in_place_index_t<0>){
         return __variant_storage<_Type>::__get_rref(__val);
     }
     constexpr const _Type& __get(in_place_index_t<0>) const{
@@ -626,7 +627,7 @@ union __variant_data<_Head,_Rest...>{
         return __head.__get(in_place<0>);
     }
 
-    constexpr _Head&& __get_rref(in_place_index_t<0>){
+    /*constexpr*/ _Head&& __get_rref(in_place_index_t<0>){
         return __head.__get_rref(in_place<0>);
     }
     
@@ -645,7 +646,7 @@ union __variant_data<_Head,_Rest...>{
     }
 
     template<size_t _Index>
-    constexpr typename __indexed_type<_Index-1,_Rest...>::__type&& __get_rref(
+    /*constexpr*/ typename __indexed_type<_Index-1,_Rest...>::__type&& __get_rref(
         in_place_index_t<_Index>){
         return __rest.__get_rref(in_place<_Index-1>);
     }
@@ -1169,10 +1170,10 @@ struct __backup_storage_ops{
 
 template<ptrdiff_t _Index,typename _Storage>
 struct __backup_storage_ops<_Index,_Index,_Storage>{
-    static void __move_construct_func(_Storage * __dest,_Storage& __source){
+    static void __move_construct_func(_Storage *,_Storage&){
         __THROW_EXCEPTION(std::bad_alloc());
     };
-    static void __destroy_func(_Storage * __obj){
+    static void __destroy_func(_Storage *){
         __THROW_EXCEPTION(std::bad_alloc());
     };
 };
@@ -1529,27 +1530,27 @@ class variant:
 
 public:
     constexpr variant()
-        noexcept(noexcept(typename __indexed_type<0,_Types...>::__type())):
+        __NOEXCEPT_(noexcept(typename __indexed_type<0,_Types...>::__type())):
         __storage(in_place<0>),
         __index(0)
     {}
 
     constexpr variant(typename std::conditional<__all_move_constructible<_Types...>::value,variant,__private_type>::type&& __other)
-    noexcept(__noexcept_variant_move_construct<_Types...>::value):
+    __NOEXCEPT_(__noexcept_variant_move_construct<_Types...>::value):
         __index(__move_construct(__other))
     {}
 
     constexpr variant(typename std::conditional<!__all_move_constructible<_Types...>::value,variant,__private_type>::type&& __other)=delete;
     
     constexpr variant(typename std::conditional<__all_copy_constructible<_Types...>::value,variant,__private_type>::type& __other)
-    noexcept(__noexcept_variant_non_const_copy_construct<_Types...>::value):
+    __NOEXCEPT_(__noexcept_variant_non_const_copy_construct<_Types...>::value):
         __index(__copy_construct(__other))
     {}
 
     constexpr variant(typename std::conditional<!__all_copy_constructible<_Types...>::value,variant,__private_type>::type& __other)=delete;
 
     constexpr variant(typename std::conditional<__all_copy_constructible<_Types...>::value,variant,__private_type>::type const& __other)
-    noexcept(__noexcept_variant_const_copy_construct<_Types...>::value):
+    __NOEXCEPT_(__noexcept_variant_const_copy_construct<_Types...>::value):
         __index(__copy_construct(__other))
     {}
 
@@ -1668,7 +1669,7 @@ public:
         typename std::conditional<__all_move_constructible<_Types...>::value &&
                                       __all_move_assignable<_Types...>::value,
                                   variant, __private_type>::type &&
-            __other) noexcept(__noexcept_variant_move_assign<_Types...>::value) {
+            __other) __NOEXCEPT_(__noexcept_variant_move_assign<_Types...>::value) {
         if (__other.valueless_by_exception()) {
             __destroy_self();
         }
@@ -1694,10 +1695,10 @@ public:
         __direct_replace<_Index>(std::forward<_Args>(__args)...);
     }
     
-    constexpr bool valueless_by_exception() const noexcept{
+    constexpr bool valueless_by_exception() const __NOEXCEPT{
         return __index==-1;
     }
-    constexpr ptrdiff_t index() const noexcept{
+    constexpr ptrdiff_t index() const __NOEXCEPT{
         return __index;
     }
 
@@ -1706,7 +1707,7 @@ public:
             __all_swappable<_Types...>::value &&
                 __all_move_constructible<_Types...>::value,
             variant, __private_type>::type
-            &__other) noexcept(__noexcept_variant_swap<_Types...>::value) {
+            &__other) __NOEXCEPT_(__noexcept_variant_swap<_Types...>::value) {
         if (__other.index() == index()) {
             if(!valueless_by_exception())
                 __swap_op_table<variant>::__apply[index()](*this,__other);
@@ -1724,10 +1725,10 @@ class variant<>{
 public:
     variant()=delete;
     
-    constexpr bool valueless_by_exception() const noexcept{
+    constexpr bool valueless_by_exception() const __NOEXCEPT{
         return true;
     }
-    constexpr ptrdiff_t index() const noexcept{
+    constexpr ptrdiff_t index() const __NOEXCEPT{
         return -1;
     }
 
@@ -1738,7 +1739,7 @@ template <typename... _Types>
 typename std::enable_if<__all_swappable<_Types...>::value &&
                             __all_move_constructible<_Types...>::value,
                         void>::type
-swap(variant<_Types...> &__lhs, variant<_Types...> &__rhs) noexcept(
+swap(variant<_Types...> &__lhs, variant<_Types...> &__rhs) __NOEXCEPT_(
     __noexcept_variant_swap<_Types...>::value) {
     __lhs.swap(__rhs);
 }
@@ -1783,26 +1784,34 @@ constexpr const _Type&& get(variant<_Types...> const&& __v){
 
 template<ptrdiff_t _Index,typename ... _Types>
 constexpr typename __indexed_type<_Index,_Types...>::__type const& get(variant<_Types...> const& __v){
-    __CONST_EXPR_THROW_EXCPETION_IF(_Index!=__v.index(), bad_variant_access("Bad variant index in get"));
-    return *(&__variant_accessor<_Index,_Types...>::get(__v));
+    return *(
+        (_Index!=__v.index())
+            ? &__throw_bad_variant_access<typename __indexed_type<_Index,_Types...>::__type const&>("Bad variant index in get")
+            : &__variant_accessor<_Index,_Types...>::get(__v)
+    );
 }
 
 template<ptrdiff_t _Index,typename ... _Types>
 constexpr typename __indexed_type<_Index,_Types...>::__type& get(variant<_Types...>& __v){
-    __CONST_EXPR_THROW_EXCPETION_IF(_Index!=__v.index(), bad_variant_access("Bad variant index in get"));
-    return *(&__variant_accessor<_Index,_Types...>::get(__v));
+    return *(
+        (_Index!=__v.index())
+            ? &__throw_bad_variant_access<typename __indexed_type<_Index,_Types...>::__type&>("Bad variant index in get")
+            : &__variant_accessor<_Index,_Types...>::get(__v)
+    );
 }
 
 template<ptrdiff_t _Index,typename ... _Types>
 constexpr typename __indexed_type<_Index,_Types...>::__type&& get(variant<_Types...>&& __v){
-    __CONST_EXPR_THROW_EXCPETION_IF(_Index!=__v.index(), bad_variant_access("Bad variant index in get"));
-    return __variant_accessor<_Index,_Types...>::get(std::move(__v));
+    return __variant_accessor<_Index,_Types...>::get(
+        (((_Index!=__v.index()) ? __throw_bad_variant_access<int>("Bad variant index in get") : 0), std::move(__v))
+    );
 }
 
 template<ptrdiff_t _Index,typename ... _Types>
 constexpr const typename __indexed_type<_Index,_Types...>::__type&& get(variant<_Types...> const&& __v){
-    __CONST_EXPR_THROW_EXCPETION_IF(_Index!=__v.index(), bad_variant_access("Bad variant index in get"));
-    return __variant_accessor<_Index,_Types...>::get(std::move(__v));
+    return __variant_accessor<_Index,_Types...>::get(
+        (((_Index!=__v.index()) ? __throw_bad_variant_access<int>("Bad variant index in get") : 0), std::move(__v))
+    );
 }
 
 template<typename _Type,typename ... _Types>
@@ -1829,7 +1838,7 @@ constexpr std::add_pointer_t<typename __indexed_type<_Index,_Types...>::__type c
 }
 
 template<typename _Type,typename ... _Types>
-constexpr bool holds_alternative(variant<_Types...> const& __v) noexcept{
+constexpr bool holds_alternative(variant<_Types...> const& __v) __NOEXCEPT{
     return __v.index()==__type_index<_Type,_Types...>::__value;
 }
 
@@ -1868,8 +1877,9 @@ const typename __visitor_table<_Visitor,_Types...>::__func_type __visitor_table<
 template<typename _Visitor,typename ... _Types>
 constexpr typename __visitor_return_type<_Visitor,_Types...>::__type
 visit(_Visitor&& __visitor,variant<_Types...>& __v){
-    __CONST_EXPR_THROW_EXCPETION_IF(__v.valueless_by_exception(), bad_variant_access("Visiting of empty variant"));
-    return __visitor_table<_Visitor,_Types...>::__trampoline[__v.index()](__visitor,__v);
+    return (__v.valueless_by_exception())
+        ? __throw_bad_variant_access<typename __visitor_return_type<_Visitor,_Types...>::__type>("Visiting of empty variant")
+        : __visitor_table<_Visitor,_Types...>::__trampoline[__v.index()](__visitor,__v);
 }
 
 template<typename _Visitor,typename ... _Variants>
@@ -1938,8 +1948,8 @@ template<size_t _VariantIndex,ptrdiff_t ... _Indices>
 struct __visit_helper2<-1,_VariantIndex,_Indices...>{
     template<typename _Visitor,typename ... _Variants>
     static constexpr typename __multi_visitor_return_type<_Visitor,_Variants...>::__type
-    __visit(_Visitor& __visitor,_Variants&& ... __v){
-        __CONST_EXPR_THROW_EXCPETION_IF(true, bad_variant_access("Visiting of empty variant"));
+    __visit(_Visitor&,_Variants&& ...){
+        __throw_bad_variant_access<typename __multi_visitor_return_type<_Visitor,_Variants...>::__type>("Visiting of empty variant");
     }
 };
 
@@ -2040,17 +2050,21 @@ struct __hash_visitor{
 
 template<>
 struct hash<experimental::monostate>{
-    size_t operator()(experimental::monostate) noexcept{
+    size_t operator()(experimental::monostate) __NOEXCEPT{
         return 42;
     }
 };
 
 template<typename ... _Types>
 struct hash<experimental::variant<_Types...>>{
-    size_t operator()(experimental::variant<_Types...> const &v) noexcept {
+    size_t operator()(experimental::variant<_Types...> const &v) __NOEXCEPT {
         return std::hash<ptrdiff_t>()(v.index()) ^
                experimental::visit(experimental::__hash_visitor(), v);
     }
 };
 
 } // namespace std
+
+#if COMPILER(MSVC)
+#pragma warning(pop)
+#endif
index 615febb..72d172b 100644 (file)
@@ -1487,7 +1487,6 @@ set(WebCore_SOURCES
     dom/Node.cpp
     dom/NodeFilterCondition.cpp
     dom/NodeIterator.cpp
-    dom/NodeOrString.cpp
     dom/NodeRareData.cpp
     dom/NodeTraversal.cpp
     dom/OverflowEvent.cpp
index 8c92362..6217547 100644 (file)
@@ -1,3 +1,33 @@
+2016-08-06  Sam Weinig  <sam@webkit.org>
+
+        Replace NodeOrString with std::variant<Ref<Node>, String>
+        https://bugs.webkit.org/show_bug.cgi?id=160638
+
+        Reviewed by Anders Carlsson.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        Remove NodeOrString.h/cpp
+
+        * bindings/js/JSNodeOrString.cpp:
+        * bindings/js/JSNodeOrString.h:
+        * dom/ContainerNode.cpp:
+        (WebCore::ContainerNode::append):
+        (WebCore::ContainerNode::prepend):
+        * dom/ContainerNode.h:
+        * dom/Node.cpp:
+        (WebCore::nodeSetPreTransformedFromNodeOrStringVector):
+        (WebCore::firstFollowingSiblingNotInNodeSet):
+        (WebCore::Node::convertNodesOrStringsIntoNode):
+        (WebCore::Node::before):
+        (WebCore::Node::after):
+        (WebCore::Node::replaceWith):
+        * dom/Node.h:
+        Replace NodeOrString with std::variant<Ref<Node>, String> and move convertNodesOrStringsIntoNode
+        into Node.
+
+        * dom/NodeOrString.cpp: Removed.
+        * dom/NodeOrString.h: Removed.
+
 2016-08-09  Chris Dumez  <cdumez@apple.com>
 
         It should be possible to re-initialize a CustomEvent after it's been dispatched
index dab59a4..d7a7042 100644 (file)
                7CE683471921821500F4D928 /* UserMessageHandlerDescriptorTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CE683461921821500F4D928 /* UserMessageHandlerDescriptorTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7CE6CBFB187F370700D46BF5 /* FormatConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CE6CBFA187F370700D46BF5 /* FormatConverter.h */; };
                7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CE6CBFC187F394900D46BF5 /* FormatConverter.cpp */; };
-               7CEAC1071B483D1D00334482 /* NodeOrString.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CEAC1061B483D1D00334482 /* NodeOrString.h */; };
-               7CEAC1091B483D7F00334482 /* NodeOrString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CEAC1081B483D7F00334482 /* NodeOrString.cpp */; };
                7CFDC57C1AC1D80500E24A57 /* ContentExtensionError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CFDC57A1AC1D80500E24A57 /* ContentExtensionError.cpp */; };
                7CFDC57D1AC1D80500E24A57 /* ContentExtensionError.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CFDC57B1AC1D80500E24A57 /* ContentExtensionError.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7D4C96DC1AD4483500365A50 /* JSFetchHeaders.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7D4C96D81AD4483500365A50 /* JSFetchHeaders.cpp */; };
                7CE683461921821500F4D928 /* UserMessageHandlerDescriptorTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserMessageHandlerDescriptorTypes.h; sourceTree = "<group>"; };
                7CE6CBFA187F370700D46BF5 /* FormatConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatConverter.h; sourceTree = "<group>"; };
                7CE6CBFC187F394900D46BF5 /* FormatConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormatConverter.cpp; sourceTree = "<group>"; };
-               7CEAC1061B483D1D00334482 /* NodeOrString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeOrString.h; sourceTree = "<group>"; };
-               7CEAC1081B483D7F00334482 /* NodeOrString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodeOrString.cpp; sourceTree = "<group>"; };
                7CFDC57A1AC1D80500E24A57 /* ContentExtensionError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtensionError.cpp; sourceTree = "<group>"; };
                7CFDC57B1AC1D80500E24A57 /* ContentExtensionError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentExtensionError.h; sourceTree = "<group>"; };
                7D4C96D81AD4483500365A50 /* JSFetchHeaders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFetchHeaders.cpp; sourceTree = "<group>"; };
                                1A750D870A90E394000FF215 /* NodeIterator.idl */,
                                A81872100977D3C0005826D9 /* NodeList.h */,
                                85ACA9FA0A9B631000671E90 /* NodeList.idl */,
-                               7CEAC1081B483D7F00334482 /* NodeOrString.cpp */,
-                               7CEAC1061B483D1D00334482 /* NodeOrString.h */,
                                4FAB48661643A67E00F70C07 /* NodeRareData.cpp */,
                                63189AE20E83A33300012E41 /* NodeRareData.h */,
                                63D7B32C0E78CD3F00F7617C /* NodeRenderStyle.h */,
                                854FE7330A2297BE0058D7AD /* NodeFilterCondition.h in Headers */,
                                854FE7350A2297BE0058D7AD /* NodeIterator.h in Headers */,
                                A818721B0977D3C0005826D9 /* NodeList.h in Headers */,
-                               7CEAC1071B483D1D00334482 /* NodeOrString.h in Headers */,
                                63189AE30E83A33300012E41 /* NodeRareData.h in Headers */,
                                63D7B32D0E78CD3F00F7617C /* NodeRenderStyle.h in Headers */,
                                E43105BB16750F1600DB2FB8 /* NodeTraversal.h in Headers */,
                                A8C4A80009D563270003AC8D /* Node.cpp in Sources */,
                                854FE7320A2297BE0058D7AD /* NodeFilterCondition.cpp in Sources */,
                                854FE7340A2297BE0058D7AD /* NodeIterator.cpp in Sources */,
-                               7CEAC1091B483D7F00334482 /* NodeOrString.cpp in Sources */,
                                4FFC022B1643B710004E1638 /* NodeRareData.cpp in Sources */,
                                E43105B816750F0C00DB2FB8 /* NodeTraversal.cpp in Sources */,
                                33503CC71017A1B1003B47E1 /* Notification.cpp in Sources */,
index 447c5d7..e2d654f 100644 (file)
@@ -33,17 +33,17 @@ using namespace JSC;
 
 namespace WebCore {
 
-Vector<NodeOrString> toNodeOrStringVector(ExecState& state)
+Vector<std::variant<Ref<Node>, String>> toNodeOrStringVector(ExecState& state)
 {
     size_t argumentCount = state.argumentCount();
 
-    Vector<NodeOrString> result;
+    Vector<std::variant<Ref<Node>, String>> result;
     result.reserveInitialCapacity(argumentCount);
 
     for (size_t i = 0; i < argumentCount; ++i) {
         JSValue value = state.uncheckedArgument(i);
         if (auto* node = jsDynamicCast<JSNode*>(value))
-            result.uncheckedAppend(&node->wrapped());
+            result.uncheckedAppend(node->wrapped());
         else {
             String string = value.toWTFString(&state);
             if (state.hadException())
index c50f241..fda3b7e 100644 (file)
@@ -26,7 +26,8 @@
 #ifndef JSNodeOrString_h
 #define JSNodeOrString_h
 
-#include "NodeOrString.h"
+#include <wtf/Forward.h>
+#include <wtf/Variant.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
@@ -35,7 +36,9 @@ class ExecState;
 
 namespace WebCore {
 
-Vector<NodeOrString> toNodeOrStringVector(JSC::ExecState&);
+class Node;
+
+Vector<std::variant<Ref<Node>, String>> toNodeOrStringVector(JSC::ExecState&);
 
 } // namespace WebCore
 
index 632f5ec..ccee698 100644 (file)
@@ -44,7 +44,6 @@
 #include "MutationEvent.h"
 #include "NameNodeList.h"
 #include "NoEventDispatchAssertion.h"
-#include "NodeOrString.h"
 #include "NodeRareData.h"
 #include "NodeRenderStyle.h"
 #include "RadioNodeList.h"
@@ -873,18 +872,18 @@ unsigned ContainerNode::childElementCount() const
     return std::distance(children.begin(), children.end());
 }
 
-void ContainerNode::append(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
+void ContainerNode::append(Vector<std::variant<Ref<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
 {
-    RefPtr<Node> node = convertNodesOrStringsIntoNode(*this, WTFMove(nodeOrStringVector), ec);
+    RefPtr<Node> node = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector), ec);
     if (ec || !node)
         return;
 
     appendChild(*node, ec);
 }
 
-void ContainerNode::prepend(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
+void ContainerNode::prepend(Vector<std::variant<Ref<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
 {
-    RefPtr<Node> node = convertNodesOrStringsIntoNode(*this, WTFMove(nodeOrStringVector), ec);
+    RefPtr<Node> node = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector), ec);
     if (ec || !node)
         return;
 
index 9073e90..9da795c 100644 (file)
@@ -99,8 +99,8 @@ public:
     Element* firstElementChild() const;
     Element* lastElementChild() const;
     unsigned childElementCount() const;
-    void append(Vector<NodeOrString>&&, ExceptionCode&);
-    void prepend(Vector<NodeOrString>&&, ExceptionCode&);
+    void append(Vector<std::variant<Ref<Node>, String>>&&, ExceptionCode&);
+    void prepend(Vector<std::variant<Ref<Node>, String>>&&, ExceptionCode&);
 
     bool ensurePreInsertionValidity(Node& newChild, Node* refChild, ExceptionCode&);
 
index 8c72862..d3d5ea3 100644 (file)
 #include "Node.cpp"
 #include "NodeFilterCondition.cpp"
 #include "NodeIterator.cpp"
-#include "NodeOrString.cpp"
 #include "NodeRareData.cpp"
 #include "NodeTraversal.cpp"
 #include "OverflowEvent.cpp"
index 88d8707..56d7f58 100644 (file)
@@ -53,7 +53,6 @@
 #include "Logging.h"
 #include "MutationEvent.h"
 #include "NoEventDispatchAssertion.h"
-#include "NodeOrString.h"
 #include "NodeRenderStyle.h"
 #include "ProcessingInstruction.h"
 #include "ProgressEvent.h"
@@ -438,18 +437,17 @@ bool Node::appendChild(Node& newChild, ExceptionCode& ec)
     return downcast<ContainerNode>(*this).appendChild(newChild, ec);
 }
 
-static HashSet<RefPtr<Node>> nodeSetPreTransformedFromNodeOrStringVector(const Vector<NodeOrString>& nodeOrStringVector)
+static HashSet<RefPtr<Node>> nodeSetPreTransformedFromNodeOrStringVector(const Vector<std::variant<Ref<Node>, String>>& vector)
 {
     HashSet<RefPtr<Node>> nodeSet;
-    for (auto& nodeOrString : nodeOrStringVector) {
-        switch (nodeOrString.type()) {
-        case NodeOrString::Type::String:
-            break;
-        case NodeOrString::Type::Node:
-            nodeSet.add(&nodeOrString.node());
-            break;
-        }
-    }
+
+    auto visitor = WTF::makeVisitor(
+        [&](const Ref<Node>& node) { nodeSet.add(const_cast<Node*>(node.ptr())); },
+        [](const String&) { }
+    );
+
+    for (const auto& variant : vector)
+        std::visit(visitor, variant);
 
     return nodeSet;
 }
@@ -472,7 +470,34 @@ static RefPtr<Node> firstFollowingSiblingNotInNodeSet(Node& context, const HashS
     return nullptr;
 }
 
-void Node::before(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
+RefPtr<Node> Node::convertNodesOrStringsIntoNode(Vector<std::variant<Ref<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
+{
+    if (nodeOrStringVector.isEmpty())
+        return nullptr;
+
+    Vector<Ref<Node>> nodes;
+    nodes.reserveInitialCapacity(nodeOrStringVector.size());
+
+    auto visitor = WTF::makeVisitor(
+        [&](Ref<Node>& node) { nodes.uncheckedAppend(node.copyRef()); },
+        [&](String& string) { nodes.uncheckedAppend(Text::create(document(), string)); }
+    );
+
+    for (auto& variant : nodeOrStringVector)
+        std::visit(visitor, variant);
+
+    if (nodes.size() == 1)
+        return WTFMove(nodes.first());
+
+    auto nodeToReturn = DocumentFragment::create(document());
+    for (auto& node : nodes) {
+        if (!nodeToReturn->appendChild(node, ec))
+            return nullptr;
+    }
+    return WTFMove(nodeToReturn);
+}
+
+void Node::before(Vector<std::variant<Ref<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
 {
     RefPtr<ContainerNode> parent = parentNode();
     if (!parent)
@@ -481,7 +506,7 @@ void Node::before(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
     auto nodeSet = nodeSetPreTransformedFromNodeOrStringVector(nodeOrStringVector);
     auto viablePreviousSibling = firstPrecedingSiblingNotInNodeSet(*this, nodeSet);
 
-    auto node = convertNodesOrStringsIntoNode(*this, WTFMove(nodeOrStringVector), ec);
+    auto node = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector), ec);
     if (ec || !node)
         return;
 
@@ -493,7 +518,7 @@ void Node::before(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
     parent->insertBefore(*node, viablePreviousSibling.get(), ec);
 }
 
-void Node::after(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
+void Node::after(Vector<std::variant<Ref<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
 {
     RefPtr<ContainerNode> parent = parentNode();
     if (!parent)
@@ -502,14 +527,14 @@ void Node::after(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
     auto nodeSet = nodeSetPreTransformedFromNodeOrStringVector(nodeOrStringVector);
     auto viableNextSibling = firstFollowingSiblingNotInNodeSet(*this, nodeSet);
 
-    auto node = convertNodesOrStringsIntoNode(*this, WTFMove(nodeOrStringVector), ec);
+    auto node = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector), ec);
     if (ec || !node)
         return;
 
     parent->insertBefore(*node, viableNextSibling.get(), ec);
 }
 
-void Node::replaceWith(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
+void Node::replaceWith(Vector<std::variant<Ref<Node>, String>>&& nodeOrStringVector, ExceptionCode& ec)
 {
     RefPtr<ContainerNode> parent = parentNode();
     if (!parent)
@@ -518,7 +543,7 @@ void Node::replaceWith(Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode&
     auto nodeSet = nodeSetPreTransformedFromNodeOrStringVector(nodeOrStringVector);
     auto viableNextSibling = firstFollowingSiblingNotInNodeSet(*this, nodeSet);
 
-    auto node = convertNodesOrStringsIntoNode(*this, WTFMove(nodeOrStringVector), ec);
+    auto node = convertNodesOrStringsIntoNode(WTFMove(nodeOrStringVector), ec);
     if (ec)
         return;
 
index ec71b9c..80dfabc 100644 (file)
@@ -35,6 +35,7 @@
 #include <wtf/ListHashSet.h>
 #include <wtf/MainThread.h>
 #include <wtf/TypeCasts.h>
+#include <wtf/Variant.h>
 
 // This needs to be here because Document.h also depends on it.
 #define DUMP_NODE_STATISTICS 0
@@ -51,7 +52,6 @@ class MathMLQualifiedName;
 class NamedNodeMap;
 class NodeList;
 class NodeListsNodeData;
-class NodeOrString;
 class NodeRareData;
 class QualifiedName;
 class RenderBox;
@@ -208,9 +208,9 @@ public:
     Element* nextElementSibling() const;
 
     // From the ChildNode - https://dom.spec.whatwg.org/#childnode
-    void before(Vector<NodeOrString>&&, ExceptionCode&);
-    void after(Vector<NodeOrString>&&, ExceptionCode&);
-    void replaceWith(Vector<NodeOrString>&&, ExceptionCode&);
+    void before(Vector<std::variant<Ref<Node>, String>>&&, ExceptionCode&);
+    void after(Vector<std::variant<Ref<Node>, String>>&&, ExceptionCode&);
+    void replaceWith(Vector<std::variant<Ref<Node>, String>>&&, ExceptionCode&);
     WEBCORE_EXPORT void remove(ExceptionCode&);
 
     // Other methods (not part of DOM)
@@ -661,6 +661,8 @@ protected:
     void setStyleChange(StyleChangeType changeType) { m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType; }
     void updateAncestorsForStyleRecalc();
 
+    RefPtr<Node> convertNodesOrStringsIntoNode(Vector<std::variant<Ref<Node>, String>>&&, ExceptionCode&);
+
 private:
     virtual PseudoId customPseudoId() const
     {
diff --git a/Source/WebCore/dom/NodeOrString.cpp b/Source/WebCore/dom/NodeOrString.cpp
deleted file mode 100644 (file)
index 7ba14b2..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "NodeOrString.h"
-
-#include "DocumentFragment.h"
-#include "Text.h"
-
-namespace WebCore {
-
-RefPtr<Node> convertNodesOrStringsIntoNode(Node& context, Vector<NodeOrString>&& nodeOrStringVector, ExceptionCode& ec)
-{
-    if (nodeOrStringVector.isEmpty())
-        return nullptr;
-
-    Vector<Ref<Node>> nodes;
-    nodes.reserveInitialCapacity(nodeOrStringVector.size());
-    for (auto& nodeOrString : nodeOrStringVector) {
-        switch (nodeOrString.type()) {
-        case NodeOrString::Type::String:
-            nodes.uncheckedAppend(Text::create(context.document(), nodeOrString.string()));
-            break;
-        case NodeOrString::Type::Node:
-            nodes.uncheckedAppend(nodeOrString.node());
-            break;
-        }
-    }
-
-    if (nodes.size() == 1)
-        return WTFMove(nodes.first());
-
-    auto nodeToReturn = DocumentFragment::create(context.document());
-    for (auto& node : nodes) {
-        if (!nodeToReturn->appendChild(node, ec))
-            return nullptr;
-    }
-    return WTFMove(nodeToReturn);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/dom/NodeOrString.h b/Source/WebCore/dom/NodeOrString.h
deleted file mode 100644 (file)
index 14ff632..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef NodeOrString_h
-#define NodeOrString_h
-
-#include "Node.h"
-#include <wtf/StdLibExtras.h>
-#include <wtf/Vector.h>
-#include <wtf/text/WTFString.h>
-
-namespace WebCore {
-
-class NodeOrString {
-public:
-    enum class Type {
-        String,
-        Node
-    };
-
-    NodeOrString(const String& string)
-        : m_type(Type::String)
-    {
-        m_data.string = string.impl();
-        m_data.string->ref();
-    }
-
-    NodeOrString(Node* node)
-        : m_type(Type::Node)
-    {
-        m_data.node = node;
-        m_data.node->ref();
-    }
-
-    NodeOrString(const NodeOrString& other)
-        : m_type(other.m_type)
-    {
-        switch (m_type) {
-        case Type::String:
-            m_data.string = other.m_data.string;
-            m_data.string->ref();
-            break;
-        case Type::Node:
-            m_data.node = other.m_data.node;
-            m_data.node->ref();
-            break;
-        }
-    }
-
-    NodeOrString(NodeOrString&& other)
-        : m_type(other.m_type)
-    {
-        switch (m_type) {
-        case Type::String:
-            m_data.string = std::exchange(other.m_data.string, nullptr);
-            break;
-        case Type::Node:
-            m_data.node = std::exchange(other.m_data.node, nullptr);
-            break;
-        }
-    }
-
-    NodeOrString& operator=(const NodeOrString& other)
-    {
-        if (this == &other)
-            return *this;
-
-        derefData();
-
-        m_type = other.m_type;
-        switch (m_type) {
-        case Type::String:
-            m_data.string = other.m_data.string;
-            m_data.string->ref();
-            break;
-        case Type::Node:
-            m_data.node = other.m_data.node;
-            m_data.node->ref();
-            break;
-        }
-
-        return *this;
-    }
-
-    NodeOrString& operator=(NodeOrString&& other)
-    {
-        if (this == &other)
-            return *this;
-
-        derefData();
-
-        m_type = other.m_type;
-        switch (m_type) {
-        case Type::String:
-            m_data.string = std::exchange(other.m_data.string, nullptr);
-            break;
-        case Type::Node:
-            m_data.node = std::exchange(other.m_data.node, nullptr);
-            break;
-        }
-
-        return *this;
-    }
-
-    ~NodeOrString()
-    {
-        derefData();
-    }
-
-    Type type() const { return m_type; }
-
-    Node& node() const { ASSERT(m_type == Type::Node); ASSERT(m_data.node); return *m_data.node; }
-    StringImpl& string() const { ASSERT(m_type == Type::String); ASSERT(m_data.string); return *m_data.string; }
-    
-private:
-    void derefData()
-    {
-        switch (m_type) {
-        case Type::String:
-            if (m_data.string)
-                m_data.string->deref();
-            break;
-        case Type::Node:
-            if (m_data.node)
-                m_data.node->deref();
-            break;
-        }
-    }
-
-    Type m_type;
-    union {
-        StringImpl* string;
-        Node* node;
-    } m_data;
-};
-
-RefPtr<Node> convertNodesOrStringsIntoNode(Node& context, Vector<NodeOrString>&&, ExceptionCode&);
-
-} // namespace WebCore
-
-#endif // NodeOrString_h
index 0313233..3a9fafe 100644 (file)
@@ -1,3 +1,15 @@
+2016-08-06  Sam Weinig  <sam@webkit.org>
+
+        Replace NodeOrString with std::variant<RefPtr<Node>, String>
+        https://bugs.webkit.org/show_bug.cgi?id=160638
+
+        Reviewed by Anders Carlsson.
+
+        * TestWebKitAPI/CMakeLists.txt:
+        * TestWebKitAPI/Tests/WTF/Variant.cpp:
+        Add additional tests for the initial state of std::variant and using
+        makeVisitor for visiting.
+
 2016-08-09  Aakash Jain  <aakash_jain@apple.com>
 
         EWS logging should ensure the logging to file is stopped on queue termination
index d72bba2..41494eb 100644 (file)
@@ -76,6 +76,7 @@ set(TestWTF_SOURCES
     ${TESTWEBKITAPI_DIR}/Tests/WTF/StringView.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/TemporaryChange.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/UniqueRef.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WTF/Variant.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/Vector.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/WTFString.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/WeakPtr.cpp
index 1d5dfc5..ccd69c2 100644 (file)
 #include "config.h"
 
 #include "Counters.h"
-#include "MoveOnly.h"
 #include "RefLogger.h"
 #include <wtf/Ref.h>
 #include <wtf/RefPtr.h>
+#include <wtf/StdLibExtras.h>
 #include <wtf/Variant.h>
 #include <wtf/text/WTFString.h>
 
 namespace TestWebKitAPI {
 
+TEST(WTF_Variant, Initial)
+{
+    std::variant<int, double> v1;
+    EXPECT_TRUE(v1.index() == 0);
+    EXPECT_TRUE(std::get<int>(v1) == 0);
+
+    struct T {
+        T() : value(15) { }
+        int value;
+    };
+
+    std::variant<T, int> v2;
+    EXPECT_TRUE(v2.index() == 0);
+    EXPECT_TRUE(std::get<T>(v2).value == 15);
+}
+
 TEST(WTF_Variant, Basic)
 {
-    std::experimental::variant<int, double> variant = 1;
+    std::variant<int, double> variant = 1;
     EXPECT_TRUE(variant.index() == 0);
-    EXPECT_TRUE(std::experimental::get<int>(variant) == 1);
+    EXPECT_TRUE(std::get<int>(variant) == 1);
+    EXPECT_TRUE(*std::get_if<int>(variant) == 1);
+    EXPECT_TRUE(std::get_if<double>(variant) == nullptr);
+    EXPECT_TRUE(std::holds_alternative<int>(variant));
+    EXPECT_FALSE(std::holds_alternative<double>(variant));
+
+    variant = 1.0;
+    EXPECT_TRUE(variant.index() == 1);
+    EXPECT_TRUE(std::get<double>(variant) == 1);
+    EXPECT_TRUE(*std::get_if<double>(variant) == 1.0);
+    EXPECT_TRUE(std::get_if<int>(variant) == nullptr);
+    EXPECT_TRUE(std::holds_alternative<double>(variant));
+    EXPECT_FALSE(std::holds_alternative<int>(variant));
 }
 
 TEST(WTF_Variant, BasicVisitor)
 {
-    typedef std::experimental::variant<int, float, String> Variant;
-
     enum class Type {
         None,
         Int,
@@ -53,7 +79,6 @@ TEST(WTF_Variant, BasicVisitor)
         String,
     };
 
-
     struct Visitor {
         Visitor(Type& t)
             : type(t)
@@ -69,30 +94,60 @@ TEST(WTF_Variant, BasicVisitor)
 
     Type type = Type::None;
 
-    Variant variant = 8;
-    std::experimental::visit(Visitor(type), variant);
+    std::variant<int, float, String> variant = 8;
+    std::visit(Visitor(type), variant);
     EXPECT_TRUE(Type::Int == type);
 
 
     variant = 1.0f;
-    std::experimental::visit(Visitor(type), variant);
+    std::visit(Visitor(type), variant);
     EXPECT_TRUE(Type::Float == type);
 
 
     variant = "hello";
-    std::experimental::visit(Visitor(type), variant);
+    std::visit(Visitor(type), variant);
+    EXPECT_TRUE(Type::String == type);
+}
+
+TEST(WTF_Variant, VisitorUsingMakeVisitor)
+{
+    enum class Type {
+        None,
+        Int,
+        Float,
+        String,
+    };
+
+    Type type = Type::None;
+
+    auto visitor = WTF::makeVisitor(
+        [&](int) { type = Type::Int; },
+        [&](float) { type = Type::Float; },
+        [&](String) { type = Type::String; }
+    );
+
+    std::variant<int, float, String> variant = 8;
+    std::visit(visitor, variant);
+    EXPECT_TRUE(Type::Int == type);
+
+
+    variant = 1.0f;
+    std::visit(visitor, variant);
+    EXPECT_TRUE(Type::Float == type);
+
+
+    variant = "hello";
+    std::visit(visitor, variant);
     EXPECT_TRUE(Type::String == type);
 }
 
 TEST(WTF_Variant, ConstructorDestructor)
 {
-    typedef std::experimental::variant<std::unique_ptr<ConstructorDestructorCounter>, int> Variant;
     ConstructorDestructorCounter::TestingScope scope;
 
     {
         auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
-        Variant v = WTFMove(uniquePtr);
+        std::variant<std::unique_ptr<ConstructorDestructorCounter>, int> v = WTFMove(uniquePtr);
 
         EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
         EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
@@ -102,14 +157,12 @@ TEST(WTF_Variant, ConstructorDestructor)
     EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
 }
 
-TEST(WTF_Variant, RefCounting)
+TEST(WTF_Variant, RefPtr)
 {
-    typedef std::experimental::variant<RefPtr<RefLogger>, int> Variant;
-
     {
         RefLogger a("a");
         RefPtr<RefLogger> ref(&a);
-        Variant v = ref;
+        std::variant<RefPtr<RefLogger>, int> v = ref;
     }
 
     ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
@@ -117,7 +170,18 @@ TEST(WTF_Variant, RefCounting)
     {
         RefLogger a("a");
         RefPtr<RefLogger> ref(&a);
-        Variant v = WTFMove(ref);
+        std::variant<RefPtr<RefLogger>, int> v = WTFMove(ref);
+    }
+
+    ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_Variant, Ref)
+{
+    {
+        RefLogger a("a");
+        Ref<RefLogger> ref(a);
+        std::variant<Ref<RefLogger>, int> v = WTFMove(ref);
     }
 
     ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());