| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 #include "core/dom/MutationObserver.h" | 31 #include "core/dom/MutationObserver.h" |
| 32 | 32 |
| 33 #include "bindings/core/v8/ExceptionState.h" | 33 #include "bindings/core/v8/ExceptionState.h" |
| 34 #include "bindings/core/v8/Microtask.h" | 34 #include "bindings/core/v8/Microtask.h" |
| 35 #include "core/dom/MutationCallback.h" | 35 #include "core/dom/MutationCallback.h" |
| 36 #include "core/dom/MutationObserverInit.h" | 36 #include "core/dom/MutationObserverInit.h" |
| 37 #include "core/dom/MutationObserverRegistration.h" | 37 #include "core/dom/MutationObserverRegistration.h" |
| 38 #include "core/dom/MutationRecord.h" | 38 #include "core/dom/MutationRecord.h" |
| 39 #include "core/dom/Node.h" | 39 #include "core/dom/Node.h" |
| 40 #include "core/html/HTMLSlotElement.h" |
| 40 #include "core/inspector/InspectorInstrumentation.h" | 41 #include "core/inspector/InspectorInstrumentation.h" |
| 41 #include <algorithm> | 42 #include <algorithm> |
| 42 | 43 |
| 43 namespace blink { | 44 namespace blink { |
| 44 | 45 |
| 45 static unsigned s_observerPriority = 0; | 46 static unsigned s_observerPriority = 0; |
| 46 | 47 |
| 47 struct MutationObserver::ObserverLessThan { | 48 struct MutationObserver::ObserverLessThan { |
| 48 bool operator()(const Member<MutationObserver>& lhs, | 49 bool operator()(const Member<MutationObserver>& lhs, |
| 49 const Member<MutationObserver>& rhs) { | 50 const Member<MutationObserver>& rhs) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 DCHECK(m_registrations.contains(registration)); | 165 DCHECK(m_registrations.contains(registration)); |
| 165 m_registrations.remove(registration); | 166 m_registrations.remove(registration); |
| 166 } | 167 } |
| 167 | 168 |
| 168 static MutationObserverSet& activeMutationObservers() { | 169 static MutationObserverSet& activeMutationObservers() { |
| 169 DEFINE_STATIC_LOCAL(MutationObserverSet, activeObservers, | 170 DEFINE_STATIC_LOCAL(MutationObserverSet, activeObservers, |
| 170 (new MutationObserverSet)); | 171 (new MutationObserverSet)); |
| 171 return activeObservers; | 172 return activeObservers; |
| 172 } | 173 } |
| 173 | 174 |
| 175 using SlotChangeList = HeapVector<Member<HTMLSlotElement>>; |
| 176 |
| 177 // TODO(hayato): We should have a SlotChangeList for each unit of related |
| 178 // similar-origin browsing context. |
| 179 // https://html.spec.whatwg.org/multipage/browsers.html#unit-of-related-similar-
origin-browsing-contexts |
| 180 static SlotChangeList& activeSlotChangeList() { |
| 181 DEFINE_STATIC_LOCAL(SlotChangeList, slotChangeList, (new SlotChangeList)); |
| 182 return slotChangeList; |
| 183 } |
| 184 |
| 174 static MutationObserverSet& suspendedMutationObservers() { | 185 static MutationObserverSet& suspendedMutationObservers() { |
| 175 DEFINE_STATIC_LOCAL(MutationObserverSet, suspendedObservers, | 186 DEFINE_STATIC_LOCAL(MutationObserverSet, suspendedObservers, |
| 176 (new MutationObserverSet)); | 187 (new MutationObserverSet)); |
| 177 return suspendedObservers; | 188 return suspendedObservers; |
| 178 } | 189 } |
| 179 | 190 |
| 191 static void ensureEnqueueMicrotask() { |
| 192 if (activeMutationObservers().isEmpty() && activeSlotChangeList().isEmpty()) |
| 193 Microtask::enqueueMicrotask(WTF::bind(&MutationObserver::deliverMutations)); |
| 194 } |
| 195 |
| 196 void MutationObserver::enqueueSlotChange(HTMLSlotElement& slot) { |
| 197 DCHECK(isMainThread()); |
| 198 ensureEnqueueMicrotask(); |
| 199 activeSlotChangeList().push_back(&slot); |
| 200 } |
| 201 |
| 202 void MutationObserver::cleanSlotChangeList(Document& document) { |
| 203 SlotChangeList kept; |
| 204 kept.reserveCapacity(activeSlotChangeList().size()); |
| 205 for (auto& slot : activeSlotChangeList()) { |
| 206 if (slot->document() != document) |
| 207 kept.push_back(slot); |
| 208 } |
| 209 activeSlotChangeList().swap(kept); |
| 210 } |
| 211 |
| 180 static void activateObserver(MutationObserver* observer) { | 212 static void activateObserver(MutationObserver* observer) { |
| 181 if (activeMutationObservers().isEmpty()) | 213 ensureEnqueueMicrotask(); |
| 182 Microtask::enqueueMicrotask(WTF::bind(&MutationObserver::deliverMutations)); | |
| 183 | |
| 184 activeMutationObservers().add(observer); | 214 activeMutationObservers().add(observer); |
| 185 } | 215 } |
| 186 | 216 |
| 187 void MutationObserver::enqueueMutationRecord(MutationRecord* mutation) { | 217 void MutationObserver::enqueueMutationRecord(MutationRecord* mutation) { |
| 188 DCHECK(isMainThread()); | 218 DCHECK(isMainThread()); |
| 189 m_records.push_back(mutation); | 219 m_records.push_back(mutation); |
| 190 activateObserver(this); | 220 activateObserver(this); |
| 191 InspectorInstrumentation::asyncTaskScheduled( | 221 InspectorInstrumentation::asyncTaskScheduled( |
| 192 m_callback->getExecutionContext(), mutation->type(), mutation); | 222 m_callback->getExecutionContext(), mutation->type(), mutation); |
| 193 } | 223 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 copyToVector(suspendedMutationObservers(), suspended); | 280 copyToVector(suspendedMutationObservers(), suspended); |
| 251 for (const auto& observer : suspended) { | 281 for (const auto& observer : suspended) { |
| 252 if (!observer->shouldBeSuspended()) { | 282 if (!observer->shouldBeSuspended()) { |
| 253 suspendedMutationObservers().remove(observer); | 283 suspendedMutationObservers().remove(observer); |
| 254 activateObserver(observer); | 284 activateObserver(observer); |
| 255 } | 285 } |
| 256 } | 286 } |
| 257 } | 287 } |
| 258 | 288 |
| 259 void MutationObserver::deliverMutations() { | 289 void MutationObserver::deliverMutations() { |
| 290 // These steps are defined in DOM Standard's "notify mutation observers". |
| 291 // https://dom.spec.whatwg.org/#notify-mutation-observers |
| 260 DCHECK(isMainThread()); | 292 DCHECK(isMainThread()); |
| 293 |
| 261 MutationObserverVector observers; | 294 MutationObserverVector observers; |
| 262 copyToVector(activeMutationObservers(), observers); | 295 copyToVector(activeMutationObservers(), observers); |
| 263 activeMutationObservers().clear(); | 296 activeMutationObservers().clear(); |
| 297 |
| 298 SlotChangeList slots; |
| 299 slots.swap(activeSlotChangeList()); |
| 300 for (const auto& slot : slots) |
| 301 slot->clearSlotChangeEventEnqueued(); |
| 302 |
| 264 std::sort(observers.begin(), observers.end(), ObserverLessThan()); | 303 std::sort(observers.begin(), observers.end(), ObserverLessThan()); |
| 265 for (const auto& observer : observers) { | 304 for (const auto& observer : observers) { |
| 266 if (observer->shouldBeSuspended()) | 305 if (observer->shouldBeSuspended()) |
| 267 suspendedMutationObservers().add(observer); | 306 suspendedMutationObservers().add(observer); |
| 268 else | 307 else |
| 269 observer->deliver(); | 308 observer->deliver(); |
| 270 } | 309 } |
| 310 for (const auto& slot : slots) |
| 311 slot->dispatchSlotChangeEvent(); |
| 271 } | 312 } |
| 272 | 313 |
| 273 DEFINE_TRACE(MutationObserver) { | 314 DEFINE_TRACE(MutationObserver) { |
| 274 visitor->trace(m_callback); | 315 visitor->trace(m_callback); |
| 275 visitor->trace(m_records); | 316 visitor->trace(m_records); |
| 276 visitor->trace(m_registrations); | 317 visitor->trace(m_registrations); |
| 277 visitor->trace(m_callback); | 318 visitor->trace(m_callback); |
| 278 } | 319 } |
| 279 | 320 |
| 280 } // namespace blink | 321 } // namespace blink |
| OLD | NEW |