Assert that updateStyle and updateLayout are only called when it's safe to dispatch...
[WebKit-https.git] / Source / WebCore / dom / NoEventDispatchAssertion.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004-2016 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #pragma once
25
26 #include "ContainerNode.h"
27 #include <wtf/MainThread.h>
28
29 namespace WebCore {
30
31 class NoEventDispatchAssertion {
32 public:
33     NoEventDispatchAssertion()
34     {
35 #if !ASSERT_DISABLED
36         if (!isMainThread())
37             return;
38         ++s_count;
39 #endif
40     }
41
42     NoEventDispatchAssertion(const NoEventDispatchAssertion&)
43         : NoEventDispatchAssertion()
44     {
45     }
46
47     ~NoEventDispatchAssertion()
48     {
49 #if !ASSERT_DISABLED
50         if (!isMainThread())
51             return;
52         ASSERT(s_count);
53         s_count--;
54 #endif
55     }
56
57     static bool isEventAllowedInMainThread()
58     {
59 #if ASSERT_DISABLED
60         return true;
61 #else
62         return !isMainThread() || !s_count;
63 #endif
64     }
65
66     class InMainThread {
67     public:
68         InMainThread()
69         {
70             ASSERT(isMainThread());
71 #if !ASSERT_DISABLED
72             ++s_count;
73 #endif
74         }
75
76         ~InMainThread()
77         {
78             ASSERT(isMainThread());
79 #if !ASSERT_DISABLED
80             ASSERT(s_count);
81             --s_count;
82 #endif
83         }
84
85         static bool isEventDispatchAllowedInSubtree(Node& node)
86         {
87             return isEventAllowed() || EventAllowedScope::isAllowedNode(node);
88         }
89
90         static bool isEventAllowed()
91         {
92             ASSERT(isMainThread());
93 #if !ASSERT_DISABLED
94             return !s_count;
95 #else
96             return true;
97 #endif
98         }
99     };
100     
101 #if !ASSERT_DISABLED
102     class EventAllowedScope {
103     public:
104         explicit EventAllowedScope(ContainerNode& userAgentContentRoot)
105             : m_eventAllowedTreeRoot(userAgentContentRoot)
106             , m_previousScope(s_currentScope)
107         {
108             s_currentScope = this;
109         }
110
111         ~EventAllowedScope()
112         {
113             s_currentScope = m_previousScope;
114         }
115
116         static bool isAllowedNode(Node& node)
117         {
118             return s_currentScope && s_currentScope->isAllowedNodeInternal(node);
119         }
120
121     private:
122         bool isAllowedNodeInternal(Node& node)
123         {
124             return m_eventAllowedTreeRoot->contains(&node) || (m_previousScope && m_previousScope->isAllowedNodeInternal(node));
125         }
126
127         Ref<ContainerNode> m_eventAllowedTreeRoot;
128
129         EventAllowedScope* m_previousScope;
130         static EventAllowedScope* s_currentScope;
131     };
132 #else
133     class EventAllowedScope {
134     public:
135         explicit EventAllowedScope(ContainerNode&) { }
136         static bool isAllowedNode(Node&) { return true; }
137     };
138 #endif
139
140 #if !ASSERT_DISABLED
141     // FIXME: Remove this class once the sync layout inside SVGImage::draw is removed.
142     class DisableAssertionsInScope {
143     public:
144         DisableAssertionsInScope()
145         {
146             ASSERT(isMainThread());
147             std::swap(s_count, m_originalCount);
148         }
149
150         ~DisableAssertionsInScope()
151         {
152             s_count = m_originalCount;
153         }
154     private:
155         unsigned m_originalCount { 0 };
156     };
157 #else
158     class DisableAssertionsInScope {
159     public:
160         DisableAssertionsInScope() { }
161     };
162 #endif
163
164 #if !ASSERT_DISABLED
165 private:
166     WEBCORE_EXPORT static unsigned s_count;
167 #endif
168 };
169
170 } // namespace WebCore