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 15namespace blink { 16 17static const CustomElementCallbackQueue::ElementQueueId kMicrotaskQueueId = 0; 18 19CustomElementMicrotaskDispatcher::CustomElementMicrotaskDispatcher() 20 : m_hasScheduledMicrotask(false) 21 , m_phase(Quiescent) 22{ 23} 24 25DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CustomElementMicrotaskDispatcher) 26 27CustomElementMicrotaskDispatcher& CustomElementMicrotaskDispatcher::instance() 28{ 29 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<CustomElementMicrotaskDispatcher>, instance, (adoptPtrWillBeNoop(new CustomElementMicrotaskDispatcher()))); 30 return *instance; 31} 32 33void CustomElementMicrotaskDispatcher::enqueue(CustomElementCallbackQueue* queue) 34{ 35 ensureMicrotaskScheduledForElementQueue(); 36 queue->setOwner(kMicrotaskQueueId); 37 m_elements.append(queue); 38} 39 40void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduledForElementQueue() 41{ 42 ASSERT(m_phase == Quiescent || m_phase == Resolving); 43 ensureMicrotaskScheduled(); 44} 45 46void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduled() 47{ 48 if (!m_hasScheduledMicrotask) { 49 Microtask::enqueueMicrotask(WTF::bind(&dispatch)); 50 m_hasScheduledMicrotask = true; 51 } 52} 53 54void CustomElementMicrotaskDispatcher::dispatch() 55{ 56 instance().doDispatch(); 57} 58 59void 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 85void CustomElementMicrotaskDispatcher::trace(Visitor* visitor) 86{ 87#if ENABLE(OILPAN) 88 visitor->trace(m_elements); 89#endif 90} 91 92} // namespace blink 93