Diff
Modified: trunk/Source/WTF/ChangeLog (278343 => 278344)
--- trunk/Source/WTF/ChangeLog 2021-06-02 08:28:32 UTC (rev 278343)
+++ trunk/Source/WTF/ChangeLog 2021-06-02 08:43:13 UTC (rev 278344)
@@ -1,3 +1,47 @@
+2021-05-23 Ryosuke Niwa <rn...@webkit.org>
+
+ Add CheckedPtr
+ https://bugs.webkit.org/show_bug.cgi?id=226158
+
+ Reviewed by Antti Koivisto.
+
+ This patch introduces a new type of smart pointer, CheckedPtr, which behaves like RefPtr and
+ let each object keep track of pointers pointing to the object. Unlike CheckedPtr, the purpose of
+ this internal counter is to release assert that there is no outstanding pointer at the time
+ of destruction instead of keeping the object alive when there is one.
+
+ * WTF.xcodeproj/project.pbxproj:
+ * wtf/CheckedPtr.h: Added.
+ (WTF::CheckedPtr): Added.
+ (WTF::CheckedPtr::CheckedPtr): Added.
+ (WTF::CheckedPtr::~CheckedPtr): Added.
+ (WTF::CheckedPtr::isHashTableDeletedValue const): Added.
+ (WTF::CheckedPtr::operator UnspecifiedBoolType const): Added.
+ (WTF::CheckedPtr::operator! const): Added.
+ (WTF::CheckedPtr::get const): Added.
+ (WTF::CheckedPtr::get): Added.
+ (WTF::CheckedPtr::operator* const): Added.
+ (WTF::CheckedPtr::operator*): Added.
+ (WTF::CheckedPtr::operator-> const): Added.
+ (WTF::CheckedPtr::operator->): Added.
+ (WTF::CheckedPtr::operator== const): Added.
+ (WTF::CheckedPtr::operator=): Added.
+ (WTF::CheckedPtr::unspecifiedBoolTypeInstance const): Added.
+ (WTF::CheckedPtr::refIfNotNull): Added.
+ (WTF::CheckedPtr::derefIfNotNull): Added.
+ (WTF::makeCheckedPtr): Added.
+ (WTF::is): Added.
+ (WTF::CanMakeCheckedPtr): Added.
+ (WTF::CanMakeCheckedPtr::~CanMakeCheckedPtr): Added. Release assert that m_ptrCount is 0.
+ (WTF::CanMakeCheckedPtr::ptrCount const): Added.
+ (WTF::CanMakeCheckedPtr::incrementPtrCount): Added.
+ (WTF::CanMakeCheckedPtr::decrementPtrCount): Added. Note that we don't do anything when m_ptrCount
+ becomes 0 unlike RefPtr.
+ (WTF::HashTraits<CheckedPtr<P>>): Added.
+ (WTF::HashTraits<CheckedPtr<P>>::emptyValue): Added.
+ (WTF::HashTraits<CheckedPtr<P>>::peek): Added.
+ (WTF::HashTraits<CheckedPtr<P>>::customDeleteBucket): Added.
+
2021-06-01 Darin Adler <da...@apple.com>
Remove <wtf/Optional.h>
Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (278343 => 278344)
--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2021-06-02 08:28:32 UTC (rev 278343)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2021-06-02 08:43:13 UTC (rev 278344)
@@ -507,6 +507,7 @@
996B17841EBA441C007E10EB /* DebugUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUtilities.h; sourceTree = "<group>"; };
9B67F3F12228D5310030DE9C /* WeakHashSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeakHashSet.h; sourceTree = "<group>"; };
9B96E9B324FF77B8001756C3 /* CompactUniquePtrTuple.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompactUniquePtrTuple.h; sourceTree = "<group>"; };
+ 9BB91F512648EA4D00A56217 /* CheckedPtr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckedPtr.h; sourceTree = "<group>"; };
9BC70F04176C379D00101DEC /* AtomStringTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtomStringTable.cpp; sourceTree = "<group>"; };
9BD8F40A176C2AD80002D865 /* AtomStringTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AtomStringTable.h; sourceTree = "<group>"; };
9C67C542589348E285B49699 /* IndexedContainerIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexedContainerIterator.h; sourceTree = "<group>"; };
@@ -983,6 +984,7 @@
413FE8F51F8D2EAB00F6D7D7 /* CallbackAggregator.h */,
A8A4726A151A825A004123FF /* CheckedArithmetic.h */,
A8A4726B151A825A004123FF /* CheckedBoolean.h */,
+ 9BB91F512648EA4D00A56217 /* CheckedPtr.h */,
0F66B2801DC97BAB004A1D3F /* ClockType.cpp */,
0F66B2811DC97BAB004A1D3F /* ClockType.h */,
0FC4EDE51696149600F65041 /* CommaPrinter.h */,
Added: trunk/Source/WTF/wtf/CheckedPtr.h (0 => 278344)
--- trunk/Source/WTF/wtf/CheckedPtr.h (rev 0)
+++ trunk/Source/WTF/wtf/CheckedPtr.h 2021-06-02 08:43:13 UTC (rev 278344)
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <wtf/HashTraits.h>
+#include <wtf/RawPtrTraits.h>
+
+namespace WTF {
+
+template<typename T, typename PtrTraits = RawPtrTraits<T>>
+class CheckedPtr {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+
+ CheckedPtr()
+ : m_ptr(nullptr)
+ { }
+
+ CheckedPtr(std::nullptr_t)
+ : m_ptr(nullptr)
+ { }
+
+ ALWAYS_INLINE CheckedPtr(T* ptr)
+ : m_ptr { ptr }
+ {
+ refIfNotNull();
+ }
+
+ ALWAYS_INLINE CheckedPtr(const CheckedPtr& other)
+ : m_ptr { other.m_ptr }
+ {
+ refIfNotNull();
+ }
+
+ ALWAYS_INLINE CheckedPtr(CheckedPtr&& other)
+ : m_ptr { PtrTraits::exchange(other.m_ptr, nullptr) }
+ { }
+
+ ALWAYS_INLINE ~CheckedPtr()
+ {
+ derefIfNotNull();
+ }
+
+ template<typename OtherType, typename OtherPtrTraits> CheckedPtr(const CheckedPtr<OtherType, OtherPtrTraits>& other)
+ : m_ptr { other.m_ptr }
+ {
+ refIfNotNull();
+ }
+
+ template<typename OtherType, typename OtherPtrTraits> CheckedPtr(CheckedPtr<OtherType, OtherPtrTraits>&& other)
+ : m_ptr { PtrTraits::exchange(other.m_ptr, nullptr) }
+ { }
+
+ CheckedPtr(HashTableDeletedValueType)
+ : m_ptr(PtrTraits::hashTableDeletedValue())
+ { }
+
+ bool isHashTableDeletedValue() const { return PtrTraits::isHashTableDeletedValue(m_ptr); }
+
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ using UnspecifiedBoolType = void (CheckedPtr::*)() const;
+ operator UnspecifiedBoolType() const { return m_ptr ? &CheckedPtr::unspecifiedBoolTypeInstance : nullptr; }
+
+ ALWAYS_INLINE bool operator!() const { return !PtrTraits::unwrap(m_ptr); }
+
+ ALWAYS_INLINE const T* get() const { return PtrTraits::unwrap(m_ptr); }
+ ALWAYS_INLINE T* get() { return PtrTraits::unwrap(m_ptr); }
+ ALWAYS_INLINE const T& operator*() const { ASSERT(this); return *get(); }
+ ALWAYS_INLINE T& operator*() { ASSERT(this); return *get(); }
+ ALWAYS_INLINE const T* operator->() const { return get(); }
+ ALWAYS_INLINE T* operator->() { return get(); }
+
+ bool operator==(const T* other) const { return m_ptr == other; }
+ template<typename U> bool operator==(U* other) const { return m_ptr == other; }
+
+ bool operator==(const CheckedPtr& other) const { return m_ptr == other.m_ptr; }
+
+ template<typename OtherType, typename OtherPtrTraits>
+ bool operator==(const CheckedPtr<OtherType, OtherPtrTraits>& other) const { return m_ptr == other.m_ptr; }
+
+ CheckedPtr& operator=(std::nullptr_t)
+ {
+ derefIfNotNull();
+ m_ptr = nullptr;
+ return *this;
+ }
+
+ CheckedPtr& operator=(T* ptr)
+ {
+ CheckedPtr copy { ptr };
+ PtrTraits::swap(m_ptr, copy.m_ptr);
+ return *this;
+ }
+
+ CheckedPtr& operator=(const CheckedPtr& other)
+ {
+ CheckedPtr copy { other };
+ PtrTraits::swap(m_ptr, copy.m_ptr);
+ return *this;
+ }
+
+ template<typename OtherType, typename OtherPtrTraits> CheckedPtr& operator=(const CheckedPtr<OtherType, OtherPtrTraits>& other)
+ {
+ CheckedPtr copy { other };
+ PtrTraits::swap(m_ptr, copy.m_ptr);
+ return *this;
+ }
+
+ CheckedPtr& operator=(CheckedPtr&& other)
+ {
+ CheckedPtr moved { WTFMove(other) };
+ PtrTraits::swap(m_ptr, moved.m_ptr);
+ return *this;
+ }
+
+ template<typename OtherType, typename OtherPtrTraits> CheckedPtr& operator=(CheckedPtr<OtherType, OtherPtrTraits>&& other)
+ {
+ CheckedPtr moved { WTFMove(other) };
+ PtrTraits::swap(m_ptr, moved.m_ptr);
+ return *this;
+ }
+
+private:
+ template<typename OtherType, typename OtherPtrTraits> friend class CheckedPtr;
+
+ void unspecifiedBoolTypeInstance() const { }
+
+ ALWAYS_INLINE void refIfNotNull()
+ {
+ if (T* ptr = PtrTraits::unwrap(m_ptr); LIKELY(ptr))
+ ptr->incrementPtrCount();
+ }
+
+ ALWAYS_INLINE void derefIfNotNull()
+ {
+ if (T* ptr = PtrTraits::unwrap(m_ptr); LIKELY(ptr))
+ ptr->decrementPtrCount();
+ }
+
+ typename PtrTraits::StorageType m_ptr;
+};
+
+template<typename T, typename PtrTraits = RawPtrTraits<T>> inline CheckedPtr<T, PtrTraits> makeCheckedPtr(T* pointer)
+{
+ return pointer;
+}
+
+template<typename T, typename PtrTraits = RawPtrTraits<T>> inline CheckedPtr<T, PtrTraits> makeCheckedPtr(T& reference)
+{
+ return &reference;
+}
+
+template <typename T, typename PtrTraits>
+struct GetPtrHelper<CheckedPtr<T, PtrTraits>> {
+ typedef T* PtrType;
+ static T* getPtr(const CheckedPtr<T, PtrTraits>& p) { return const_cast<T*>(p.get()); }
+};
+
+template <typename T, typename U>
+struct IsSmartPtr<CheckedPtr<T, U>> {
+ static constexpr bool value = true;
+};
+
+template<typename ExpectedType, typename ArgType, typename ArgPtrTraits>
+inline bool is(CheckedPtr<ArgType, ArgPtrTraits>& source)
+{
+ return is<ExpectedType>(source.get());
+}
+
+template<typename ExpectedType, typename ArgType, typename ArgPtrTraits>
+inline bool is(const CheckedPtr<ArgType, ArgPtrTraits>& source)
+{
+ return is<ExpectedType>(source.get());
+}
+
+class CanMakeCheckedPtr {
+public:
+ ~CanMakeCheckedPtr() { RELEASE_ASSERT(!m_count); }
+
+ uint16_t ptrCount() const { return m_count; }
+ void incrementPtrCount() { ++m_count; }
+ void decrementPtrCount() { ASSERT(m_count); --m_count; }
+private:
+ uint16_t m_count { 0 };
+};
+
+template<typename P> struct HashTraits<CheckedPtr<P>> : SimpleClassHashTraits<CheckedPtr<P>> {
+ static P* emptyValue() { return nullptr; }
+
+ typedef P* PeekType;
+ static PeekType peek(const CheckedPtr<P>& value) { return value.get(); }
+ static PeekType peek(P* value) { return value; }
+
+ static void customDeleteBucket(CheckedPtr<P>& value)
+ {
+ // See unique_ptr's customDeleteBucket() for an explanation.
+ ASSERT(!SimpleClassHashTraits<CheckedPtr<P>>::isDeletedValue(value));
+ auto valueToBeDestroyed = WTFMove(value);
+ SimpleClassHashTraits<CheckedPtr<P>>::constructDeletedValue(value);
+ }
+};
+
+template<typename P> struct DefaultHash<CheckedPtr<P>> : PtrHash<CheckedPtr<P>> { };
+
+} // namespace WTF
+
+using WTF::CheckedPtr;
+using WTF::CanMakeCheckedPtr;
+using WTF::makeCheckedPtr;
+
Modified: trunk/Tools/ChangeLog (278343 => 278344)
--- trunk/Tools/ChangeLog 2021-06-02 08:28:32 UTC (rev 278343)
+++ trunk/Tools/ChangeLog 2021-06-02 08:43:13 UTC (rev 278344)
@@ -1,3 +1,20 @@
+2021-05-23 Ryosuke Niwa <rn...@webkit.org>
+
+ Add CheckedPtr
+ https://bugs.webkit.org/show_bug.cgi?id=226158
+
+ Reviewed by Antti Koivisto.
+
+ Added basic tests.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WTF/CheckedPtr.cpp: Added.
+ (TestWebKitAPI::CheckedObject): Added.
+ (TestWebKitAPI::DerivedCheckedObject): Added.
+ (WTF_CheckedPtr.Basic):
+ (WTF_CheckedPtr.DerivedClass):
+ (WTF_CheckedPtr.HashSet):
+
2021-06-01 Darin Adler <da...@apple.com>
Remove <wtf/Optional.h>
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (278343 => 278344)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2021-06-02 08:28:32 UTC (rev 278343)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2021-06-02 08:43:13 UTC (rev 278344)
@@ -903,6 +903,7 @@
9B9332CE2320C745002D50E8 /* cocoa-writer-markup-with-lists.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9B9332CD2320C73E002D50E8 /* cocoa-writer-markup-with-lists.html */; };
9BAD7F3E22690F2000F8DA66 /* DeallocWebViewInEventListener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BAD7F3D22690F1400F8DA66 /* DeallocWebViewInEventListener.mm */; };
9BAE177B22E2BBFB00DF3098 /* cocoa-writer-markup-with-system-fonts.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9BAE177A22E2BB6B00DF3098 /* cocoa-writer-markup-with-system-fonts.html */; };
+ 9BBCA4DF265ACA5B00DFE723 /* CheckedPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BBCA4DE265ACA5B00DFE723 /* CheckedPtr.cpp */; };
9BCB7C2820130600003E7C0C /* PasteHTML.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BCB7C2620130600003E7C0C /* PasteHTML.mm */; };
9BCD411A206DBCA3001D71BE /* mso-list-on-h4.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9BCD4119206D5ED7001D71BE /* mso-list-on-h4.html */; };
9BD4239A1E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BD423991E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm */; };
@@ -2616,6 +2617,7 @@
9B9332CD2320C73E002D50E8 /* cocoa-writer-markup-with-lists.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "cocoa-writer-markup-with-lists.html"; sourceTree = "<group>"; };
9BAD7F3D22690F1400F8DA66 /* DeallocWebViewInEventListener.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DeallocWebViewInEventListener.mm; sourceTree = "<group>"; };
9BAE177A22E2BB6B00DF3098 /* cocoa-writer-markup-with-system-fonts.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "cocoa-writer-markup-with-system-fonts.html"; sourceTree = "<group>"; };
+ 9BBCA4DE265ACA5B00DFE723 /* CheckedPtr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CheckedPtr.cpp; sourceTree = "<group>"; };
9BCB7C2620130600003E7C0C /* PasteHTML.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteHTML.mm; sourceTree = "<group>"; };
9BCD4119206D5ED7001D71BE /* mso-list-on-h4.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "mso-list-on-h4.html"; sourceTree = "<group>"; };
9BD423991E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AttributedSubstringForProposedRangeWithImage.mm; sourceTree = "<group>"; };
@@ -4415,6 +4417,7 @@
93A427AE180DA60F00CD24D7 /* BoxPtr.cpp */,
0451A5A6235E438E009DF945 /* BumpPointerAllocator.cpp */,
A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */,
+ 9BBCA4DE265ACA5B00DFE723 /* CheckedPtr.cpp */,
E302BDA92404B92300865277 /* CompactRefPtrTuple.cpp */,
9B0C051824FDFB7000F2FE31 /* CompactUniquePtrTuple.cpp */,
0F30CB5B1FCE1792004B5323 /* ConcurrentPtrHashSet.cpp */,
@@ -5177,6 +5180,7 @@
7C83DF181D0A590C00FEBCF3 /* BoxPtr.cpp in Sources */,
04DB2396235E43EC00328F17 /* BumpPointerAllocator.cpp in Sources */,
7C83DEA01D0A590C00FEBCF3 /* CheckedArithmeticOperations.cpp in Sources */,
+ 9BBCA4DF265ACA5B00DFE723 /* CheckedPtr.cpp in Sources */,
E302BDAA2404B92400865277 /* CompactRefPtrTuple.cpp in Sources */,
9B0C051924FDFB7D00F2FE31 /* CompactUniquePtrTuple.cpp in Sources */,
0F30CB5C1FCE1796004B5323 /* ConcurrentPtrHashSet.cpp in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WTF/CheckedPtr.cpp (0 => 278344)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/CheckedPtr.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/CheckedPtr.cpp 2021-06-02 08:43:13 UTC (rev 278344)
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2021 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 "Utilities.h"
+#include <wtf/CheckedPtr.h>
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace TestWebKitAPI {
+
+class CheckedObject : public CanMakeCheckedPtr {
+public:
+ int someFunction() const { return -7; }
+};
+
+class DerivedCheckedObject : public CheckedObject {
+};
+
+TEST(WTF_CheckedPtr, Basic)
+{
+ {
+ CheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+ }
+
+ {
+ CheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+ {
+ auto ptr = makeCheckedPtr(checkedObject);
+ EXPECT_TRUE(!!ptr);
+ EXPECT_EQ(ptr.get(), &checkedObject);
+ EXPECT_EQ(ptr->someFunction(), -7);
+ EXPECT_EQ(checkedObject.ptrCount(), 1);
+ }
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+ }
+
+ {
+ CheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+ auto ptr = makeCheckedPtr(checkedObject);
+ EXPECT_TRUE(!!ptr);
+ EXPECT_EQ(ptr.get(), &checkedObject);
+ EXPECT_EQ(ptr->someFunction(), -7);
+ EXPECT_EQ(checkedObject.ptrCount(), 1);
+ ptr = nullptr;
+
+ EXPECT_FALSE(!!ptr);
+ EXPECT_EQ(ptr.get(), nullptr);
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+ }
+
+ {
+ CheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+ auto ptr1 = makeCheckedPtr(checkedObject);
+ EXPECT_TRUE(!!ptr1);
+ EXPECT_EQ(ptr1.get(), &checkedObject);
+ EXPECT_EQ(ptr1->someFunction(), -7);
+ EXPECT_EQ(checkedObject.ptrCount(), 1);
+
+ const CheckedPtr<CheckedObject> ptr2 = makeCheckedPtr(&checkedObject);
+ EXPECT_TRUE(!!ptr2);
+ EXPECT_EQ(ptr2.get(), &checkedObject);
+ EXPECT_EQ(ptr2->someFunction(), -7);
+ EXPECT_EQ(checkedObject.ptrCount(), 2);
+
+ CheckedPtr<CheckedObject> ptr3 = ptr2;
+ EXPECT_TRUE(!!ptr3);
+ EXPECT_EQ(ptr3.get(), &checkedObject);
+ EXPECT_EQ(checkedObject.ptrCount(), 3);
+
+ ptr1 = nullptr;
+ EXPECT_EQ(checkedObject.ptrCount(), 2);
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), &checkedObject);
+ EXPECT_EQ(ptr3.get(), &checkedObject);
+
+ ptr1 = WTFMove(ptr3);
+ EXPECT_EQ(checkedObject.ptrCount(), 2);
+ EXPECT_EQ(ptr1.get(), &checkedObject);
+ EXPECT_EQ(ptr2.get(), &checkedObject);
+ EXPECT_EQ(ptr3.get(), nullptr);
+ }
+}
+
+TEST(WTF_CheckedPtr, DerivedClass)
+{
+ {
+ DerivedCheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+ }
+
+ {
+ DerivedCheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+ {
+ auto ptr = makeCheckedPtr(checkedObject);
+ EXPECT_TRUE(!!ptr);
+ EXPECT_EQ(ptr.get(), &checkedObject);
+ EXPECT_EQ(ptr->someFunction(), -7);
+ EXPECT_EQ(checkedObject.ptrCount(), 1);
+ }
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+ }
+
+ {
+ CheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+ CheckedPtr<CheckedObject> ptr = makeCheckedPtr(checkedObject);
+ EXPECT_TRUE(!!ptr);
+ EXPECT_EQ(ptr.get(), &checkedObject);
+ EXPECT_EQ(ptr->someFunction(), -7);
+ EXPECT_EQ(checkedObject.ptrCount(), 1);
+ ptr = nullptr;
+
+ EXPECT_FALSE(!!ptr);
+ EXPECT_EQ(ptr.get(), nullptr);
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+ }
+
+ {
+ DerivedCheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+ CheckedPtr<DerivedCheckedObject> ptr1 = makeCheckedPtr(checkedObject);
+ EXPECT_TRUE(!!ptr1);
+ EXPECT_EQ(ptr1.get(), &checkedObject);
+ EXPECT_EQ(ptr1->someFunction(), -7);
+ EXPECT_EQ(checkedObject.ptrCount(), 1);
+
+ const CheckedPtr<CheckedObject> ptr2 = ptr1;
+ EXPECT_TRUE(!!ptr2);
+ EXPECT_EQ(ptr2.get(), &checkedObject);
+ EXPECT_EQ(ptr2->someFunction(), -7);
+ EXPECT_EQ(checkedObject.ptrCount(), 2);
+
+ CheckedPtr<CheckedObject> ptr3 = ptr1;
+ EXPECT_TRUE(!!ptr3);
+ EXPECT_EQ(ptr3.get(), &checkedObject);
+ EXPECT_EQ(checkedObject.ptrCount(), 3);
+
+ ptr1 = nullptr;
+ EXPECT_EQ(checkedObject.ptrCount(), 2);
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), &checkedObject);
+ EXPECT_EQ(ptr3.get(), &checkedObject);
+
+ CheckedPtr<CheckedObject> ptr4 = WTFMove(ptr3);
+ EXPECT_EQ(checkedObject.ptrCount(), 2);
+ EXPECT_EQ(ptr1.get(), nullptr);
+ EXPECT_EQ(ptr2.get(), &checkedObject);
+ EXPECT_EQ(ptr3.get(), nullptr);
+ EXPECT_EQ(ptr4.get(), &checkedObject);
+ }
+}
+
+TEST(WTF_CheckedPtr, HashSet)
+{
+ {
+ CheckedObject checkedObject;
+ EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+ auto ptr = makeCheckedPtr(checkedObject);
+ EXPECT_EQ(ptr.get(), &checkedObject);
+ EXPECT_EQ(checkedObject.ptrCount(), 1);
+
+ HashSet<CheckedPtr<CheckedObject>> set;
+ set.add(ptr);
+ EXPECT_EQ(checkedObject.ptrCount(), 2);
+
+ ptr = nullptr;
+ EXPECT_EQ(checkedObject.ptrCount(), 1);
+ }
+
+ {
+ CheckedObject object1;
+ DerivedCheckedObject object2;
+ EXPECT_EQ(object1.ptrCount(), 0);
+ EXPECT_EQ(object2.ptrCount(), 0);
+
+ HashSet<CheckedPtr<CheckedObject>> set;
+ set.add(&object1);
+ EXPECT_EQ(object1.ptrCount(), 1);
+ EXPECT_EQ(object2.ptrCount(), 0);
+
+ set.add(&object1);
+ EXPECT_EQ(object1.ptrCount(), 1);
+ EXPECT_EQ(object2.ptrCount(), 0);
+
+ CheckedPtr<DerivedCheckedObject> ptr { &object2 };
+ set.add(ptr);
+ EXPECT_EQ(object1.ptrCount(), 1);
+ EXPECT_EQ(object2.ptrCount(), 2);
+ ptr = nullptr;
+
+ EXPECT_EQ(object1.ptrCount(), 1);
+ EXPECT_EQ(object2.ptrCount(), 1);
+
+ set.remove(&object1);
+ EXPECT_EQ(object1.ptrCount(), 0);
+ EXPECT_EQ(object2.ptrCount(), 1);
+ }
+
+ {
+ Vector<std::unique_ptr<CheckedObject>> objects;
+ objects.append(makeUniqueWithoutFastMallocCheck<CheckedObject>());
+ EXPECT_EQ(objects[0]->ptrCount(), 0);
+
+ HashSet<CheckedPtr<CheckedObject>> set;
+ set.add(objects[0].get());
+ auto initialCapacity = set.capacity();
+
+ for (unsigned i = 0; set.capacity() == initialCapacity; ++i) {
+ if (i % 2)
+ objects.append(makeUniqueWithoutFastMallocCheck<DerivedCheckedObject>());
+ else
+ objects.append(makeUniqueWithoutFastMallocCheck<CheckedObject>());
+ set.add(objects.last().get());
+ }
+
+ for (auto& object : objects)
+ EXPECT_EQ(object->ptrCount(), 1);
+
+ auto setVector = WTF::copyToVector(set);
+
+ for (auto& object : objects)
+ EXPECT_EQ(object->ptrCount(), 2);
+ }
+}
+
+} // namespace TestWebKitAPI