Unreviewed, reverting r263195, r263252, and r265394.
[WebKit-https.git] / Source / WebCore / dom / CustomElementReactionQueue.h
1 /*
2  * Copyright (C) 2015, 2016 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "GCReachableRef.h"
29 #include <wtf/Forward.h>
30 #include <wtf/Noncopyable.h>
31 #include <wtf/Vector.h>
32
33 namespace JSC {
34
35 class JSGlobalObject;
36 class CallFrame;
37
38 }
39
40 namespace WebCore {
41
42 class CustomElementReactionQueueItem;
43 class Document;
44 class Element;
45 class JSCustomElementInterface;
46 class QualifiedName;
47
48 // https://html.spec.whatwg.org/multipage/custom-elements.html#element-queue
49 class CustomElementQueue {
50     WTF_MAKE_FAST_ALLOCATED;
51     WTF_MAKE_NONCOPYABLE(CustomElementQueue);
52 public:
53     CustomElementQueue() = default;
54
55     void add(Element&);
56     void processQueue(JSC::JSGlobalObject*);
57
58 private:
59     void invokeAll();
60
61     Vector<GCReachableRef<Element>> m_elements;
62     bool m_invoking { false };
63 };
64
65 class CustomElementReactionQueue {
66     WTF_MAKE_FAST_ALLOCATED;
67     WTF_MAKE_NONCOPYABLE(CustomElementReactionQueue);
68 public:
69     CustomElementReactionQueue(JSCustomElementInterface&);
70     ~CustomElementReactionQueue();
71
72     static void enqueueElementUpgrade(Element&, bool alreadyScheduledToUpgrade);
73     static void enqueueElementUpgradeIfDefined(Element&);
74     static void enqueueConnectedCallbackIfNeeded(Element&);
75     static void enqueueDisconnectedCallbackIfNeeded(Element&);
76     static void enqueueAdoptedCallbackIfNeeded(Element&, Document& oldDocument, Document& newDocument);
77     static void enqueueAttributeChangedCallbackIfNeeded(Element&, const QualifiedName&, const AtomString& oldValue, const AtomString& newValue);
78     static void enqueuePostUpgradeReactions(Element&);
79
80     bool observesStyleAttribute() const;
81     void invokeAll(Element&);
82     void clear();
83
84     static void processBackupQueue(CustomElementQueue&);
85
86 private:
87     static void enqueueElementOnAppropriateElementQueue(Element&);
88
89     Ref<JSCustomElementInterface> m_interface;
90     Vector<CustomElementReactionQueueItem> m_items;
91 };
92
93 class CustomElementReactionDisallowedScope {
94 public:
95     CustomElementReactionDisallowedScope()
96     {
97 #if ASSERT_ENABLED
98         s_customElementReactionDisallowedCount++;
99 #endif
100     }
101
102     ~CustomElementReactionDisallowedScope()
103     {
104 #if ASSERT_ENABLED
105         ASSERT(s_customElementReactionDisallowedCount);
106         s_customElementReactionDisallowedCount--;
107 #endif
108     }
109
110 #if ASSERT_ENABLED
111     static bool isReactionAllowed() { return !s_customElementReactionDisallowedCount; }
112 #endif
113
114     class AllowedScope {
115 #if ASSERT_ENABLED
116     public:
117         AllowedScope()
118             : m_originalCount(s_customElementReactionDisallowedCount)
119         {
120             s_customElementReactionDisallowedCount = 0;
121         }
122
123         ~AllowedScope()
124         {
125             s_customElementReactionDisallowedCount = m_originalCount;
126         }
127
128     private:
129         unsigned m_originalCount;
130 #endif // ASSERT_ENABLED
131     };
132
133 private:
134 #if ASSERT_ENABLED
135     WEBCORE_EXPORT static unsigned s_customElementReactionDisallowedCount;
136
137     friend class AllowedScope;
138 #endif
139 };
140
141 class CustomElementReactionStack : public CustomElementReactionDisallowedScope::AllowedScope {
142 public:
143     ALWAYS_INLINE CustomElementReactionStack(JSC::JSGlobalObject* state)
144         : m_previousProcessingStack(s_currentProcessingStack)
145         , m_state(state)
146     {
147         s_currentProcessingStack = this;
148     }
149
150     ALWAYS_INLINE CustomElementReactionStack(JSC::JSGlobalObject& state)
151         : CustomElementReactionStack(&state)
152     { }
153
154     ALWAYS_INLINE ~CustomElementReactionStack()
155     {
156         if (UNLIKELY(m_queue))
157             processQueue(m_state);
158         s_currentProcessingStack = m_previousProcessingStack;
159     }
160
161 private:
162     WEBCORE_EXPORT void processQueue(JSC::JSGlobalObject*);
163
164     CustomElementQueue* m_queue { nullptr }; // Use raw pointer to avoid generating delete in the destructor.
165     CustomElementReactionStack* m_previousProcessingStack;
166     JSC::JSGlobalObject* m_state;
167
168     WEBCORE_EXPORT static CustomElementReactionStack* s_currentProcessingStack;
169
170     friend CustomElementReactionQueue;
171 };
172
173 }