namespace WebCore {
+class MicrotaskQueueInvocationScope {
+public:
+#if defined(NDEBUG)
+ explicit MicrotaskQueueInvocationScope(CustomElementMicrotaskQueue*) { }
+#else
+ explicit MicrotaskQueueInvocationScope(CustomElementMicrotaskQueue* queue)
+ : m_parent(s_top)
+ , m_queue(queue)
+ {
+ s_top = this;
+ ASSERT(m_queue->isEmpty() || !hasReenter());
+ }
+
+ ~MicrotaskQueueInvocationScope()
+ {
+ s_top = m_parent;
+ }
+
+private:
+ bool hasReenter() const
+ {
+ for (MicrotaskQueueInvocationScope* scope = this->m_parent; scope; scope = scope->m_parent) {
+ if (scope->m_queue == m_queue)
+ return true;
+ }
+
+ return false;
+ }
+
+ MicrotaskQueueInvocationScope* m_parent;
+ CustomElementMicrotaskQueue* m_queue;
+
+ static MicrotaskQueueInvocationScope* s_top;
+#endif
+};
+
+#if !defined(NDEBUG)
+MicrotaskQueueInvocationScope* MicrotaskQueueInvocationScope::s_top = 0;
+#endif
+
void CustomElementMicrotaskQueue::enqueue(PassOwnPtr<CustomElementMicrotaskStep> step)
{
m_queue.append(step);
CustomElementMicrotaskStep::Result CustomElementMicrotaskQueue::dispatch()
{
- Result result = Result(0);
+ MicrotaskQueueInvocationScope scope(this);
+ Vector<OwnPtr<CustomElementMicrotaskStep> > remaining;
+ Result accumulatedResult = CustomElementMicrotaskStep::ContinueWithRemoving;
unsigned i;
for (i = 0; i < m_queue.size(); ++i) {
- result = Result(result | m_queue[i]->process());
-
+ Result result = m_queue[i]->process();
+ accumulatedResult = CustomElementMicrotaskStep::Result(result | accumulatedResult);
+ if (result & CustomElementMicrotaskStep::ShouldRemain)
+ remaining.append(m_queue[i].release());
if (result & CustomElementMicrotaskStep::ShouldStop)
break;
}
- bool wasStopped = i < m_queue.size();
- if (wasStopped)
- m_queue.remove(0, i);
- else
- m_queue.resize(0);
+ for (++i; i < m_queue.size(); ++i)
+ remaining.append(m_queue[i].release());
+ m_queue.swap(remaining);
- return result;
+ return accumulatedResult;
+}
+
+#if !defined(NDEBUG)
+void CustomElementMicrotaskQueue::show(unsigned indent)
+{
+ for (unsigned q = 0; q < m_queue.size(); ++q) {
+ if (m_queue[q])
+ m_queue[q]->show(indent);
+ else
+ fprintf(stderr, "%*snull\n", indent, "");
+ }
}
+#endif
} // namespace WebCore