void MutationObserver::notifyMutationObservers() { // https://dom.spec.whatwg.org/#notify-mutation-observers // 1. Unset mutation observer compound microtask queued flag. mutationObserverCompoundMicrotaskQueuedFlag = false; ASSERT(isMainThread()); static bool deliveryInProgress = false; if (deliveryInProgress) return; deliveryInProgress = true; if (!suspendedMutationObservers().isEmpty()) { Vector<RefPtr<MutationObserver>> suspended; copyToVector(suspendedMutationObservers(), suspended); for (auto& observer : suspended) { if (!observer->canDeliver()) continue; suspendedMutationObservers().remove(observer); activeMutationObservers().add(observer); } } while (!activeMutationObservers().isEmpty() || !signalSlotList().isEmpty()) { // 2. Let notify list be a copy of unit of related similar-origin browsing contexts' list of MutationObserver objects. Vector<RefPtr<MutationObserver>> notifyList; copyToVector(activeMutationObservers(), notifyList); activeMutationObservers().clear(); std::sort(notifyList.begin(), notifyList.end(), [](auto& lhs, auto& rhs) { return lhs->m_priority < rhs->m_priority; }); // 3. Let signalList be a copy of unit of related similar-origin browsing contexts' signal slot list. // 4. Empty unit of related similar-origin browsing contexts' signal slot list. Vector<RefPtr<HTMLSlotElement>> slotList; if (!signalSlotList().isEmpty()) { slotList.swap(signalSlotList()); for (auto& slot : slotList) slot->didRemoveFromSignalSlotList(); } // 5. For each MutationObserver object mo in notify list, execute a compound microtask subtask for (auto& observer : notifyList) { if (observer->canDeliver()) observer->deliver(); else suspendedMutationObservers().add(observer); } // 6. For each slot slot in signalList, in order, fire an event named slotchange, with its bubbles attribute set to true, at slot. for (auto& slot : slotList) slot->dispatchSlotChangeEvent(); } deliveryInProgress = false; }
void MutationObserver::resumeSuspendedObservers() { DCHECK(isMainThread()); if (suspendedMutationObservers().isEmpty()) return; MutationObserverVector suspended; copyToVector(suspendedMutationObservers(), suspended); for (size_t i = 0; i < suspended.size(); ++i) { if (!suspended[i]->shouldBeSuspended()) { suspendedMutationObservers().remove(suspended[i]); activateObserver(suspended[i]); } } }
void MutationObserver::deliverMutations() { DCHECK(isMainThread()); MutationObserverVector observers; copyToVector(activeMutationObservers(), observers); activeMutationObservers().clear(); std::sort(observers.begin(), observers.end(), ObserverLessThan()); for (size_t i = 0; i < observers.size(); ++i) { if (observers[i]->shouldBeSuspended()) suspendedMutationObservers().add(observers[i]); else observers[i]->deliver(); } }