Chromium Code Reviews| 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)); | |
|
tkent
2017/01/11 11:24:17
I'm afraid static strong references to HTMLSlotEle
hayato
2017/01/12 03:47:41
The content of |slotlist| is always cleared at the
tkent
2017/01/12 06:24:35
Is the microtask guaranteed to be executed? Is v8
| |
| 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 | |
| 180 static void activateObserver(MutationObserver* observer) { | 202 static void activateObserver(MutationObserver* observer) { |
| 181 if (activeMutationObservers().isEmpty()) | 203 ensureEnqueueMicrotask(); |
| 182 Microtask::enqueueMicrotask(WTF::bind(&MutationObserver::deliverMutations)); | |
| 183 | |
| 184 activeMutationObservers().add(observer); | 204 activeMutationObservers().add(observer); |
| 185 } | 205 } |
| 186 | 206 |
| 187 void MutationObserver::enqueueMutationRecord(MutationRecord* mutation) { | 207 void MutationObserver::enqueueMutationRecord(MutationRecord* mutation) { |
| 188 DCHECK(isMainThread()); | 208 DCHECK(isMainThread()); |
| 189 m_records.push_back(mutation); | 209 m_records.push_back(mutation); |
| 190 activateObserver(this); | 210 activateObserver(this); |
| 191 InspectorInstrumentation::asyncTaskScheduled( | 211 InspectorInstrumentation::asyncTaskScheduled( |
| 192 m_callback->getExecutionContext(), mutation->type(), mutation); | 212 m_callback->getExecutionContext(), mutation->type(), mutation); |
| 193 } | 213 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 copyToVector(suspendedMutationObservers(), suspended); | 270 copyToVector(suspendedMutationObservers(), suspended); |
| 251 for (const auto& observer : suspended) { | 271 for (const auto& observer : suspended) { |
| 252 if (!observer->shouldBeSuspended()) { | 272 if (!observer->shouldBeSuspended()) { |
| 253 suspendedMutationObservers().remove(observer); | 273 suspendedMutationObservers().remove(observer); |
| 254 activateObserver(observer); | 274 activateObserver(observer); |
| 255 } | 275 } |
| 256 } | 276 } |
| 257 } | 277 } |
| 258 | 278 |
| 259 void MutationObserver::deliverMutations() { | 279 void MutationObserver::deliverMutations() { |
| 280 // These steps are defined in DOM Standard's "notify mutation observers". | |
| 281 // https://dom.spec.whatwg.org/#notify-mutation-observers | |
| 260 DCHECK(isMainThread()); | 282 DCHECK(isMainThread()); |
| 283 | |
| 261 MutationObserverVector observers; | 284 MutationObserverVector observers; |
| 262 copyToVector(activeMutationObservers(), observers); | 285 copyToVector(activeMutationObservers(), observers); |
| 263 activeMutationObservers().clear(); | 286 activeMutationObservers().clear(); |
| 287 | |
| 288 SlotChangeList slots; | |
| 289 copyToVector(activeSlotChangeList(), slots); | |
|
tkent
2017/01/11 11:24:17
slots.swap(activeSlotChangeList()) should work.
hayato
2017/01/12 03:47:41
Done
| |
| 290 activeSlotChangeList().clear(); | |
| 291 for (const auto& slot : slots) | |
| 292 slot->clearSlotChangeEventEnqueued(); | |
| 293 | |
| 264 std::sort(observers.begin(), observers.end(), ObserverLessThan()); | 294 std::sort(observers.begin(), observers.end(), ObserverLessThan()); |
| 265 for (const auto& observer : observers) { | 295 for (const auto& observer : observers) { |
| 266 if (observer->shouldBeSuspended()) | 296 if (observer->shouldBeSuspended()) |
| 267 suspendedMutationObservers().add(observer); | 297 suspendedMutationObservers().add(observer); |
| 268 else | 298 else |
| 269 observer->deliver(); | 299 observer->deliver(); |
| 270 } | 300 } |
| 301 for (const auto& slot : slots) | |
| 302 slot->dispatchSlotChangeEvent(); | |
| 271 } | 303 } |
| 272 | 304 |
| 273 DEFINE_TRACE(MutationObserver) { | 305 DEFINE_TRACE(MutationObserver) { |
| 274 visitor->trace(m_callback); | 306 visitor->trace(m_callback); |
| 275 visitor->trace(m_records); | 307 visitor->trace(m_records); |
| 276 visitor->trace(m_registrations); | 308 visitor->trace(m_registrations); |
| 277 visitor->trace(m_callback); | 309 visitor->trace(m_callback); |
| 278 } | 310 } |
| 279 | 311 |
| 280 } // namespace blink | 312 } // namespace blink |
| OLD | NEW |