Add a release assertion that Functions can only be constructed from non-null Completi...
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 May 2019 19:54:00 +0000 (19:54 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 May 2019 19:54:00 +0000 (19:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=197641

Reviewed by Chris Dumez.

This will help us find the cause of rdar://problem/48679972 by seeing the crash when the Function is dispatched,
not when it's called with no interesting stack trace.  I manually verified this assertion is hit in such a case.
We should also have no legitimate use of creating a Function out of a null CompletionHandler then never calling it.

* wtf/CompletionHandler.h:
(WTF::Detail::CallableWrapper<CompletionHandler<Out):
* wtf/Function.h:
(WTF::Detail::CallableWrapperBase::~CallableWrapperBase):
(WTF::Detail::CallableWrapper::CallableWrapper):
(WTF::Function<Out):

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

Source/WTF/ChangeLog
Source/WTF/wtf/CompletionHandler.h
Source/WTF/wtf/Function.h

index c6d49c9..2bf7ae4 100644 (file)
@@ -1,3 +1,21 @@
+2019-05-07  Alex Christensen  <achristensen@webkit.org>
+
+        Add a release assertion that Functions can only be constructed from non-null CompletionHandlers
+        https://bugs.webkit.org/show_bug.cgi?id=197641
+
+        Reviewed by Chris Dumez.
+
+        This will help us find the cause of rdar://problem/48679972 by seeing the crash when the Function is dispatched,
+        not when it's called with no interesting stack trace.  I manually verified this assertion is hit in such a case.
+        We should also have no legitimate use of creating a Function out of a null CompletionHandler then never calling it.
+
+        * wtf/CompletionHandler.h:
+        (WTF::Detail::CallableWrapper<CompletionHandler<Out):
+        * wtf/Function.h:
+        (WTF::Detail::CallableWrapperBase::~CallableWrapperBase):
+        (WTF::Detail::CallableWrapper::CallableWrapper):
+        (WTF::Function<Out):
+
 2019-05-06  Christopher Reid  <chris.reid@sony.com>
 
         [JSC] Respect already defined USE_LLINT_EMBEDDED_OPCODE_ID compiler variable.
index 09f4436..fda54a6 100644 (file)
@@ -63,6 +63,23 @@ private:
     Function<Out(In...)> m_function;
 };
 
+namespace Detail {
+
+template<typename Out, typename... In>
+class CallableWrapper<CompletionHandler<Out(In...)>, Out, In...> : public CallableWrapperBase<Out, In...> {
+public:
+    explicit CallableWrapper(CompletionHandler<Out(In...)>&& completionHandler)
+        : m_completionHandler(WTFMove(completionHandler))
+    {
+        RELEASE_ASSERT(m_completionHandler);
+    }
+    Out call(In... in) final { return m_completionHandler(std::forward<In>(in)...); }
+private:
+    CompletionHandler<Out(In...)> m_completionHandler;
+};
+
+} // namespace Detail
+
 class CompletionHandlerCallingScope {
 public:
     CompletionHandlerCallingScope() = default;
index 3ea4123..05e3697 100644 (file)
 
 namespace WTF {
 
+namespace Detail {
+
+template<typename Out, typename... In>
+class CallableWrapperBase {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    virtual ~CallableWrapperBase() { }
+    virtual Out call(In...) = 0;
+};
+
+template<typename, typename, typename...> class CallableWrapper;
+
+template<typename CallableType, typename Out, typename... In>
+class CallableWrapper : public CallableWrapperBase<Out, In...> {
+public:
+    explicit CallableWrapper(CallableType&& callable)
+        : m_callable(WTFMove(callable)) { }
+    CallableWrapper(const CallableWrapper&) = delete;
+    CallableWrapper& operator=(const CallableWrapper&) = delete;
+    Out call(In... in) final { return m_callable(std::forward<In>(in)...); }
+private:
+    CallableType m_callable;
+};
+
+} // namespace Detail
+
 template<typename> class Function;
 
 template <typename Out, typename... In>
@@ -41,15 +67,11 @@ public:
 
     template<typename CallableType, class = typename std::enable_if<!(std::is_pointer<CallableType>::value && std::is_function<typename std::remove_pointer<CallableType>::type>::value) && std::is_rvalue_reference<CallableType&&>::value>::type>
     Function(CallableType&& callable)
-        : m_callableWrapper(std::make_unique<CallableWrapper<CallableType>>(WTFMove(callable)))
-    {
-    }
+        : m_callableWrapper(std::make_unique<Detail::CallableWrapper<CallableType, Out, In...>>(WTFMove(callable))) { }
 
     template<typename FunctionType, class = typename std::enable_if<std::is_pointer<FunctionType>::value && std::is_function<typename std::remove_pointer<FunctionType>::type>::value>::type>
     Function(FunctionType f)
-        : m_callableWrapper(std::make_unique<CallableWrapper<FunctionType>>(WTFMove(f)))
-    {
-    }
+        : m_callableWrapper(std::make_unique<Detail::CallableWrapper<FunctionType, Out, In...>>(WTFMove(f))) { }
 
     Out operator()(In... in) const
     {
@@ -62,14 +84,14 @@ public:
     template<typename CallableType, class = typename std::enable_if<!(std::is_pointer<CallableType>::value && std::is_function<typename std::remove_pointer<CallableType>::type>::value) && std::is_rvalue_reference<CallableType&&>::value>::type>
     Function& operator=(CallableType&& callable)
     {
-        m_callableWrapper = std::make_unique<CallableWrapper<CallableType>>(WTFMove(callable));
+        m_callableWrapper = std::make_unique<Detail::CallableWrapper<CallableType, Out, In...>>(WTFMove(callable));
         return *this;
     }
 
     template<typename FunctionType, class = typename std::enable_if<std::is_pointer<FunctionType>::value && std::is_function<typename std::remove_pointer<FunctionType>::type>::value>::type>
     Function& operator=(FunctionType f)
     {
-        m_callableWrapper = std::make_unique<CallableWrapper<FunctionType>>(WTFMove(f));
+        m_callableWrapper = std::make_unique<Detail::CallableWrapper<FunctionType, Out, In...>>(WTFMove(f));
         return *this;
     }
 
@@ -80,32 +102,7 @@ public:
     }
 
 private:
-    class CallableWrapperBase {
-        WTF_MAKE_FAST_ALLOCATED;
-    public:
-        virtual ~CallableWrapperBase() { }
-
-        virtual Out call(In...) = 0;
-    };
-
-    template<typename CallableType>
-    class CallableWrapper : public CallableWrapperBase {
-    public:
-        explicit CallableWrapper(CallableType&& callable)
-            : m_callable(WTFMove(callable))
-        {
-        }
-
-        CallableWrapper(const CallableWrapper&) = delete;
-        CallableWrapper& operator=(const CallableWrapper&) = delete;
-
-        Out call(In... in) final { return m_callable(std::forward<In>(in)...); }
-
-    private:
-        CallableType m_callable;
-    };
-
-    std::unique_ptr<CallableWrapperBase> m_callableWrapper;
+    std::unique_ptr<Detail::CallableWrapperBase<Out, In...>> m_callableWrapper;
 };
 
 } // namespace WTF