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.
6 #include "core/dom/custom/CustomElementMicrotaskDispatcher.h"
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/CustomElementMicrotaskQueue.h"
13 #include "core/dom/custom/CustomElementScheduler.h"
14 #include "core/html/imports/HTMLImportLoader.h"
15 #include "wtf/MainThread.h"
19 static const CustomElementCallbackQueue::ElementQueueId kMicrotaskQueueId = 0;
21 CustomElementMicrotaskDispatcher::CustomElementMicrotaskDispatcher()
22 : m_hasScheduledMicrotask(false)
24 , m_resolutionAndImports(CustomElementMicrotaskQueue::create())
28 CustomElementMicrotaskDispatcher& CustomElementMicrotaskDispatcher::instance()
30 DEFINE_STATIC_LOCAL(CustomElementMicrotaskDispatcher, instance, ());
34 void CustomElementMicrotaskDispatcher::enqueue(HTMLImportLoader* importLoader, PassOwnPtr<CustomElementMicrotaskStep> step)
36 ASSERT(m_phase == Quiescent || m_phase == DispatchingCallbacks);
37 ensureMicrotaskScheduled();
39 importLoader->microtaskQueue()->enqueue(step);
41 m_resolutionAndImports->enqueue(step);
44 void CustomElementMicrotaskDispatcher::enqueue(CustomElementCallbackQueue* queue)
46 ASSERT(m_phase == Quiescent || m_phase == Resolving);
47 ensureMicrotaskScheduled();
48 queue->setOwner(kMicrotaskQueueId);
49 m_elements.append(queue);
52 void CustomElementMicrotaskDispatcher::importDidFinish(CustomElementMicrotaskImportStep* step)
54 ASSERT(m_phase == Quiescent || m_phase == DispatchingCallbacks);
55 ensureMicrotaskScheduled();
58 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduled()
60 if (!m_hasScheduledMicrotask) {
61 Microtask::enqueueMicrotask(WTF::bind(&dispatch));
62 m_hasScheduledMicrotask = true;
66 void CustomElementMicrotaskDispatcher::dispatch()
68 instance().doDispatch();
71 void CustomElementMicrotaskDispatcher::doDispatch()
73 ASSERT(isMainThread());
75 ASSERT(m_phase == Quiescent && m_hasScheduledMicrotask);
76 m_hasScheduledMicrotask = false;
78 // Finishing microtask work deletes all
79 // CustomElementCallbackQueues. Being in a callback delivery scope
80 // implies those queues could still be in use.
81 ASSERT_WITH_SECURITY_IMPLICATION(!CustomElementCallbackDispatcher::inCallbackDeliveryScope());
84 m_resolutionAndImports->dispatch();
86 m_phase = DispatchingCallbacks;
87 for (Vector<CustomElementCallbackQueue*>::iterator it = m_elements.begin();it != m_elements.end(); ++it) {
88 // Created callback may enqueue an attached callback.
89 CustomElementCallbackDispatcher::CallbackDeliveryScope scope;
90 (*it)->processInElementQueue(kMicrotaskQueueId);
94 CustomElementScheduler::microtaskDispatcherDidFinish();
99 void CustomElementMicrotaskDispatcher::show()
101 fprintf(stderr, "Dispatcher:\n");
102 m_resolutionAndImports->show(1);
106 } // namespace WebCore
111 WebCore::CustomElementMicrotaskDispatcher::instance().show();