• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "config.h"
6 #include "core/dom/custom/CustomElementMicrotaskDispatcher.h"
7 
8 #include "core/dom/Microtask.h"
9 #include "core/dom/custom/CustomElementCallbackDispatcher.h"
10 #include "core/dom/custom/CustomElementCallbackQueue.h"
11 #include "core/dom/custom/CustomElementMicrotaskImportStep.h"
12 #include "core/dom/custom/CustomElementMicrotaskStepDispatcher.h"
13 #include "core/dom/custom/CustomElementScheduler.h"
14 #include "wtf/MainThread.h"
15 
16 namespace WebCore {
17 
18 static const CustomElementCallbackQueue::ElementQueueId kMicrotaskQueueId = 0;
19 
CustomElementMicrotaskDispatcher()20 CustomElementMicrotaskDispatcher::CustomElementMicrotaskDispatcher()
21     : m_hasScheduledMicrotask(false)
22     , m_phase(Quiescent)
23     , m_steps(CustomElementMicrotaskStepDispatcher::create())
24 {
25 }
26 
DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CustomElementMicrotaskDispatcher)27 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CustomElementMicrotaskDispatcher)
28 
29 CustomElementMicrotaskDispatcher& CustomElementMicrotaskDispatcher::instance()
30 {
31     DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<CustomElementMicrotaskDispatcher>, instance, (adoptPtrWillBeNoop(new CustomElementMicrotaskDispatcher())));
32     return *instance;
33 }
34 
enqueue(HTMLImportLoader * parentLoader,PassOwnPtrWillBeRawPtr<CustomElementMicrotaskStep> step)35 void CustomElementMicrotaskDispatcher::enqueue(HTMLImportLoader* parentLoader, PassOwnPtrWillBeRawPtr<CustomElementMicrotaskStep> step)
36 {
37     ensureMicrotaskScheduledForMicrotaskSteps();
38     m_steps->enqueue(parentLoader, step);
39 }
40 
enqueue(HTMLImportLoader * parentLoader,PassOwnPtrWillBeRawPtr<CustomElementMicrotaskImportStep> step,bool importIsSync)41 void CustomElementMicrotaskDispatcher::enqueue(HTMLImportLoader* parentLoader, PassOwnPtrWillBeRawPtr<CustomElementMicrotaskImportStep> step, bool importIsSync)
42 {
43     ensureMicrotaskScheduledForMicrotaskSteps();
44     m_steps->enqueue(parentLoader, step, importIsSync);
45 }
46 
enqueue(CustomElementCallbackQueue * queue)47 void CustomElementMicrotaskDispatcher::enqueue(CustomElementCallbackQueue* queue)
48 {
49     ensureMicrotaskScheduledForElementQueue();
50     queue->setOwner(kMicrotaskQueueId);
51     m_elements.append(queue);
52 }
53 
importDidFinish(CustomElementMicrotaskImportStep * step)54 void CustomElementMicrotaskDispatcher::importDidFinish(CustomElementMicrotaskImportStep* step)
55 {
56     ensureMicrotaskScheduledForMicrotaskSteps();
57 }
58 
ensureMicrotaskScheduledForMicrotaskSteps()59 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduledForMicrotaskSteps()
60 {
61     ASSERT(m_phase == Quiescent || m_phase == DispatchingCallbacks);
62     ensureMicrotaskScheduled();
63 }
64 
ensureMicrotaskScheduledForElementQueue()65 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduledForElementQueue()
66 {
67     ASSERT(m_phase == Quiescent || m_phase == Resolving);
68     ensureMicrotaskScheduled();
69 }
70 
ensureMicrotaskScheduled()71 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduled()
72 {
73     if (!m_hasScheduledMicrotask) {
74         Microtask::enqueueMicrotask(WTF::bind(&dispatch));
75         m_hasScheduledMicrotask = true;
76     }
77 }
78 
dispatch()79 void CustomElementMicrotaskDispatcher::dispatch()
80 {
81     instance().doDispatch();
82 }
83 
doDispatch()84 void CustomElementMicrotaskDispatcher::doDispatch()
85 {
86     ASSERT(isMainThread());
87 
88     ASSERT(m_phase == Quiescent && m_hasScheduledMicrotask);
89     m_hasScheduledMicrotask = false;
90 
91     // Finishing microtask work deletes all
92     // CustomElementCallbackQueues. Being in a callback delivery scope
93     // implies those queues could still be in use.
94     ASSERT_WITH_SECURITY_IMPLICATION(!CustomElementCallbackDispatcher::inCallbackDeliveryScope());
95 
96     m_phase = Resolving;
97     m_steps->dispatch();
98 
99     m_phase = DispatchingCallbacks;
100     for (WillBeHeapVector<RawPtrWillBeMember<CustomElementCallbackQueue> >::iterator it = m_elements.begin(); it != m_elements.end(); ++it) {
101         // Created callback may enqueue an attached callback.
102         CustomElementCallbackDispatcher::CallbackDeliveryScope scope;
103         (*it)->processInElementQueue(kMicrotaskQueueId);
104     }
105 
106     m_elements.clear();
107     CustomElementScheduler::microtaskDispatcherDidFinish();
108     m_phase = Quiescent;
109 }
110 
trace(Visitor * visitor)111 void CustomElementMicrotaskDispatcher::trace(Visitor* visitor)
112 {
113     visitor->trace(m_steps);
114 #if ENABLE(OILPAN)
115     visitor->trace(m_elements);
116 #endif
117 }
118 
119 #if !defined(NDEBUG)
show()120 void CustomElementMicrotaskDispatcher::show()
121 {
122     m_steps->show(2);
123 
124 }
125 #endif
126 
127 } // namespace WebCore
128 
129 #if !defined(NDEBUG)
showCEMD()130 void showCEMD()
131 {
132     WebCore::CustomElementMicrotaskDispatcher::instance().show();
133 }
134 #endif
135