• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Google 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
12  *    in the documentation and/or other materials provided with the
13  *    distribution.
14  * 3. Neither the name of Google Inc. nor the names of its contributors
15  *    may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "core/dom/custom/CustomElementCallbackScheduler.h"
33 
34 #include "core/dom/Element.h"
35 #include "core/dom/custom/CustomElementCallbackDispatcher.h"
36 #include "core/dom/custom/CustomElementLifecycleCallbacks.h"
37 
38 namespace WebCore {
39 
scheduleAttributeChangedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks,PassRefPtr<Element> element,const AtomicString & name,const AtomicString & oldValue,const AtomicString & newValue)40 void CustomElementCallbackScheduler::scheduleAttributeChangedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue)
41 {
42     if (!callbacks->hasAttributeChangedCallback())
43         return;
44 
45     CustomElementCallbackQueue* queue = instance().schedule(element);
46     queue->append(CustomElementCallbackInvocation::createAttributeChangedInvocation(callbacks, name, oldValue, newValue));
47 }
48 
scheduleCreatedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks,PassRefPtr<Element> element)49 void CustomElementCallbackScheduler::scheduleCreatedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element)
50 {
51     if (!callbacks->hasCreatedCallback())
52         return;
53 
54     CustomElementCallbackQueue* queue = instance().scheduleInCurrentElementQueue(element);
55     queue->append(CustomElementCallbackInvocation::createInvocation(callbacks, CustomElementLifecycleCallbacks::Created));
56 }
57 
scheduleAttachedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks,PassRefPtr<Element> element)58 void CustomElementCallbackScheduler::scheduleAttachedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element)
59 {
60     if (!callbacks->hasAttachedCallback())
61         return;
62 
63     CustomElementCallbackQueue* queue = instance().schedule(element);
64     queue->append(CustomElementCallbackInvocation::createInvocation(callbacks, CustomElementLifecycleCallbacks::Attached));
65 }
66 
scheduleDetachedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks,PassRefPtr<Element> element)67 void CustomElementCallbackScheduler::scheduleDetachedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element)
68 {
69     if (!callbacks->hasDetachedCallback())
70         return;
71 
72     CustomElementCallbackQueue* queue = instance().schedule(element);
73     queue->append(CustomElementCallbackInvocation::createInvocation(callbacks, CustomElementLifecycleCallbacks::Detached));
74 }
75 
instance()76 CustomElementCallbackScheduler& CustomElementCallbackScheduler::instance()
77 {
78     DEFINE_STATIC_LOCAL(CustomElementCallbackScheduler, instance, ());
79     return instance;
80 }
81 
ensureCallbackQueue(PassRefPtr<Element> element)82 CustomElementCallbackQueue* CustomElementCallbackScheduler::ensureCallbackQueue(PassRefPtr<Element> element)
83 {
84     Element* key = element.get();
85     ElementCallbackQueueMap::iterator it = m_elementCallbackQueueMap.find(key);
86     if (it == m_elementCallbackQueueMap.end())
87         it = m_elementCallbackQueueMap.add(key, CustomElementCallbackQueue::create(element)).iterator;
88     return it->value.get();
89 }
90 
clearElementCallbackQueueMap()91 void CustomElementCallbackScheduler::clearElementCallbackQueueMap()
92 {
93     ElementCallbackQueueMap emptyMap;
94     instance().m_elementCallbackQueueMap.swap(emptyMap);
95 }
96 
97 // Finds or creates the callback queue for element. If the
98 // createdCallback has not finished running, the callback queue is not
99 // moved to the top-of-stack. Otherwise like
100 // scheduleInCurrentElementQueue.
schedule(PassRefPtr<Element> element)101 CustomElementCallbackQueue* CustomElementCallbackScheduler::schedule(PassRefPtr<Element> element)
102 {
103     CustomElementCallbackQueue* callbackQueue = ensureCallbackQueue(element);
104     if (!callbackQueue->inCreatedCallback())
105         CustomElementCallbackDispatcher::instance().enqueue(callbackQueue);
106     return callbackQueue;
107 }
108 
109 // Finds or creates the callback queue for element. If the element's
110 // callback queue is scheduled in an earlier processing stack frame,
111 // its owner is set to the element queue on the top of the processing
112 // stack. Because callback queues are processed exhaustively, this
113 // effectively moves the callback queue to the top of the stack.
scheduleInCurrentElementQueue(PassRefPtr<Element> element)114 CustomElementCallbackQueue* CustomElementCallbackScheduler::scheduleInCurrentElementQueue(PassRefPtr<Element> element)
115 {
116     CustomElementCallbackQueue* callbackQueue = ensureCallbackQueue(element);
117     CustomElementCallbackDispatcher::instance().enqueue(callbackQueue);
118     return callbackQueue;
119 }
120 
121 } // namespace WebCore
122