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/CustomElementCallbackQueue.h" 10 #include "core/dom/custom/CustomElementMicrotaskImportStep.h" 11 #include "core/dom/custom/CustomElementProcessingStack.h" 12 #include "core/dom/custom/CustomElementScheduler.h" 13 #include "wtf/MainThread.h" 14 15 namespace blink { 16 17 static const CustomElementCallbackQueue::ElementQueueId kMicrotaskQueueId = 0; 18 19 CustomElementMicrotaskDispatcher::CustomElementMicrotaskDispatcher() 20 : m_hasScheduledMicrotask(false) 21 , m_phase(Quiescent) 22 { 23 } 24 25 DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CustomElementMicrotaskDispatcher) 26 27 CustomElementMicrotaskDispatcher& CustomElementMicrotaskDispatcher::instance() 28 { 29 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<CustomElementMicrotaskDispatcher>, instance, (adoptPtrWillBeNoop(new CustomElementMicrotaskDispatcher()))); 30 return *instance; 31 } 32 33 void CustomElementMicrotaskDispatcher::enqueue(CustomElementCallbackQueue* queue) 34 { 35 ensureMicrotaskScheduledForElementQueue(); 36 queue->setOwner(kMicrotaskQueueId); 37 m_elements.append(queue); 38 } 39 40 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduledForElementQueue() 41 { 42 ASSERT(m_phase == Quiescent || m_phase == Resolving); 43 ensureMicrotaskScheduled(); 44 } 45 46 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduled() 47 { 48 if (!m_hasScheduledMicrotask) { 49 Microtask::enqueueMicrotask(WTF::bind(&dispatch)); 50 m_hasScheduledMicrotask = true; 51 } 52 } 53 54 void CustomElementMicrotaskDispatcher::dispatch() 55 { 56 instance().doDispatch(); 57 } 58 59 void CustomElementMicrotaskDispatcher::doDispatch() 60 { 61 ASSERT(isMainThread()); 62 63 ASSERT(m_phase == Quiescent && m_hasScheduledMicrotask); 64 m_hasScheduledMicrotask = false; 65 66 // Finishing microtask work deletes all 67 // CustomElementCallbackQueues. Being in a callback delivery scope 68 // implies those queues could still be in use. 69 ASSERT_WITH_SECURITY_IMPLICATION(!CustomElementProcessingStack::inCallbackDeliveryScope()); 70 71 m_phase = Resolving; 72 73 m_phase = DispatchingCallbacks; 74 for (WillBeHeapVector<RawPtrWillBeMember<CustomElementCallbackQueue> >::iterator it = m_elements.begin(); it != m_elements.end(); ++it) { 75 // Created callback may enqueue an attached callback. 76 CustomElementProcessingStack::CallbackDeliveryScope scope; 77 (*it)->processInElementQueue(kMicrotaskQueueId); 78 } 79 80 m_elements.clear(); 81 CustomElementScheduler::microtaskDispatcherDidFinish(); 82 m_phase = Quiescent; 83 } 84 85 void CustomElementMicrotaskDispatcher::trace(Visitor* visitor) 86 { 87 #if ENABLE(OILPAN) 88 visitor->trace(m_elements); 89 #endif 90 } 91 92 } // namespace blink 93