WTF shouldn't have both Thread and ThreadIdentifier
[WebKit.git] / Source / WebCore / bindings / js / JSCallbackData.h
1 /*
2  * Copyright (C) 2007-2009, 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #pragma once
30
31 #include "JSDOMBinding.h"
32 #include "JSDOMGlobalObject.h"
33 #include "ScriptExecutionContext.h"
34 #include <heap/Strong.h>
35 #include <heap/StrongInlines.h>
36 #include <runtime/JSObject.h>
37 #include <wtf/Threading.h>
38
39 namespace WebCore {
40
41 // We have to clean up this data on the context thread because unprotecting a
42 // JSObject on the wrong thread without synchronization would corrupt the heap
43 // (and synchronization would be slow).
44
45 class JSCallbackData {
46 public:
47     enum class CallbackType { Function, Object, FunctionOrObject };
48
49     JSDOMGlobalObject* globalObject() { return m_globalObject.get(); }
50
51 protected:
52     explicit JSCallbackData(JSDOMGlobalObject* globalObject)
53         : m_globalObject(globalObject)
54 #ifndef NDEBUG
55         , m_thread(Thread::current())
56 #endif
57     {
58     }
59     
60     ~JSCallbackData()
61     {
62 #if !PLATFORM(IOS)
63         ASSERT(m_thread.ptr() == &Thread::current());
64 #endif
65     }
66     
67     static JSC::JSValue invokeCallback(JSDOMGlobalObject&, JSC::JSObject* callback, JSC::JSValue thisValue, JSC::MarkedArgumentBuffer&, CallbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException);
68
69 private:
70     JSC::Weak<JSDOMGlobalObject> m_globalObject;
71 #ifndef NDEBUG
72     Ref<Thread> m_thread;
73 #endif
74 };
75
76 class JSCallbackDataStrong : public JSCallbackData {
77 public:
78     JSCallbackDataStrong(JSC::JSObject* callback, JSDOMGlobalObject* globalObject, void*)
79         : JSCallbackData(globalObject)
80         , m_callback(globalObject->vm(), callback)
81     {
82     }
83
84     JSC::JSObject* callback() { return m_callback.get(); }
85
86     JSC::JSValue invokeCallback(JSC::JSValue thisValue, JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException)
87     {
88         auto* globalObject = this->globalObject();
89         if (!globalObject)
90             return { };
91
92         return JSCallbackData::invokeCallback(*globalObject, callback(), thisValue, args, callbackType, functionName, returnedException);
93     }
94
95 private:
96     JSC::Strong<JSC::JSObject> m_callback;
97 };
98
99 class JSCallbackDataWeak : public JSCallbackData {
100 public:
101     JSCallbackDataWeak(JSC::JSObject* callback, JSDOMGlobalObject* globalObject, void* owner)
102         : JSCallbackData(globalObject)
103         , m_callback(callback, &m_weakOwner, owner)
104     {
105     }
106
107     JSC::JSObject* callback() { return m_callback.get(); }
108
109     JSC::JSValue invokeCallback(JSC::JSValue thisValue, JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException)
110     {
111         auto* globalObject = this->globalObject();
112         if (!globalObject)
113             return { };
114
115         return JSCallbackData::invokeCallback(*globalObject, callback(), thisValue, args, callbackType, functionName, returnedException);
116     }
117
118     void visitJSFunction(JSC::SlotVisitor&);
119
120 private:
121     class WeakOwner : public JSC::WeakHandleOwner {
122         bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&) override;
123     };
124     WeakOwner m_weakOwner;
125     JSC::Weak<JSC::JSObject> m_callback;
126 };
127
128 class DeleteCallbackDataTask : public ScriptExecutionContext::Task {
129 public:
130     template <typename CallbackDataType>
131     explicit DeleteCallbackDataTask(CallbackDataType* data)
132         : ScriptExecutionContext::Task(ScriptExecutionContext::Task::CleanupTask, [data = std::unique_ptr<CallbackDataType>(data)] (ScriptExecutionContext&) {
133         })
134     {
135     }
136 };
137
138 } // namespace WebCore