Home | History | Annotate | Download | only in custom
      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 
     20 CustomElementMicrotaskDispatcher::CustomElementMicrotaskDispatcher()
     21     : m_hasScheduledMicrotask(false)
     22     , m_phase(Quiescent)
     23     , m_steps(CustomElementMicrotaskStepDispatcher::create())
     24 {
     25 }
     26 
     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 
     35 void CustomElementMicrotaskDispatcher::enqueue(HTMLImportLoader* parentLoader, PassOwnPtrWillBeRawPtr<CustomElementMicrotaskStep> step)
     36 {
     37     ensureMicrotaskScheduledForMicrotaskSteps();
     38     m_steps->enqueue(parentLoader, step);
     39 }
     40 
     41 void CustomElementMicrotaskDispatcher::enqueue(HTMLImportLoader* parentLoader, PassOwnPtrWillBeRawPtr<CustomElementMicrotaskImportStep> step, bool importIsSync)
     42 {
     43     ensureMicrotaskScheduledForMicrotaskSteps();
     44     m_steps->enqueue(parentLoader, step, importIsSync);
     45 }
     46 
     47 void CustomElementMicrotaskDispatcher::enqueue(CustomElementCallbackQueue* queue)
     48 {
     49     ensureMicrotaskScheduledForElementQueue();
     50     queue->setOwner(kMicrotaskQueueId);
     51     m_elements.append(queue);
     52 }
     53 
     54 void CustomElementMicrotaskDispatcher::importDidFinish(CustomElementMicrotaskImportStep* step)
     55 {
     56     ensureMicrotaskScheduledForMicrotaskSteps();
     57 }
     58 
     59 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduledForMicrotaskSteps()
     60 {
     61     ASSERT(m_phase == Quiescent || m_phase == DispatchingCallbacks);
     62     ensureMicrotaskScheduled();
     63 }
     64 
     65 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduledForElementQueue()
     66 {
     67     ASSERT(m_phase == Quiescent || m_phase == Resolving);
     68     ensureMicrotaskScheduled();
     69 }
     70 
     71 void CustomElementMicrotaskDispatcher::ensureMicrotaskScheduled()
     72 {
     73     if (!m_hasScheduledMicrotask) {
     74         Microtask::enqueueMicrotask(WTF::bind(&dispatch));
     75         m_hasScheduledMicrotask = true;
     76     }
     77 }
     78 
     79 void CustomElementMicrotaskDispatcher::dispatch()
     80 {
     81     instance().doDispatch();
     82 }
     83 
     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 
    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)
    120 void CustomElementMicrotaskDispatcher::show()
    121 {
    122     m_steps->show(2);
    123 
    124 }
    125 #endif
    126 
    127 } // namespace WebCore
    128 
    129 #if !defined(NDEBUG)
    130 void showCEMD()
    131 {
    132     WebCore::CustomElementMicrotaskDispatcher::instance().show();
    133 }
    134 #endif
    135