Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / custom / CustomElementMicrotaskQueue.cpp
index c6af626..4e2c25f 100644 (file)
 
 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);
@@ -42,23 +82,37 @@ void CustomElementMicrotaskQueue::enqueue(PassOwnPtr<CustomElementMicrotaskStep>
 
 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