| Index: Source/core/dom/EventHandlerRegistry.cpp
|
| diff --git a/Source/core/dom/EventHandlerRegistry.cpp b/Source/core/dom/EventHandlerRegistry.cpp
|
| index b72b465ffaadc0a31187c14559227570e38b81e7..d7ce9523535ef5d2c2606d421bece0585ef0bbd8 100644
|
| --- a/Source/core/dom/EventHandlerRegistry.cpp
|
| +++ b/Source/core/dom/EventHandlerRegistry.cpp
|
| @@ -17,6 +17,25 @@
|
|
|
| namespace WebCore {
|
|
|
| +EventHandlerRegistry::DocumentObserver::DocumentObserver(Document& document)
|
| + : ActiveDOMObject(&document)
|
| +{
|
| +}
|
| +
|
| +EventHandlerRegistry::DocumentObserver::~DocumentObserver()
|
| +{
|
| +}
|
| +
|
| +void EventHandlerRegistry::DocumentObserver::stop()
|
| +{
|
| + Document* document = static_cast<Document*>(lifecycleContext());
|
| + Document* parentDocument = document->parentDocument();
|
| + if (!parentDocument)
|
| + return;
|
| + EventHandlerRegistry* parentRegistry = EventHandlerRegistry::from(*parentDocument);
|
| + parentRegistry->didRemoveAllEventHandlers(*document);
|
| +}
|
| +
|
| EventHandlerRegistry::HandlerState::HandlerState()
|
| {
|
| }
|
| @@ -27,7 +46,9 @@ EventHandlerRegistry::HandlerState::~HandlerState()
|
|
|
| EventHandlerRegistry::EventHandlerRegistry(Document& document)
|
| : m_document(document)
|
| + , m_documentObserver(DocumentObserver(document))
|
| {
|
| + m_documentObserver.suspendIfNeeded();
|
| }
|
|
|
| EventHandlerRegistry::~EventHandlerRegistry()
|
| @@ -75,8 +96,12 @@ bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa
|
| EventTargetSet* targets = m_eventHandlers[handlerClass].targets.get();
|
| if (op == Add) {
|
| #if ASSERT_ENABLED
|
| - if (Node* node = target->toNode())
|
| - ASSERT(&node->document() == &m_document);
|
| + if (Node* node = target->toNode()) {
|
| + // The node should either be in the document, or be the Document node of a child
|
| + // of the document.
|
| + ASSERT(&node->document() == &m_document
|
| + || (node->isDocumentNode() && toDocument(node)->parentDocument() == &m_document));
|
| + }
|
| #endif // ASSERT_ENABLED
|
|
|
| if (!targets) {
|
| @@ -86,6 +111,11 @@ bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa
|
|
|
| if (!targets->add(target).isNewEntry) {
|
| // Just incremented refcount, no real change.
|
| +#if ASSERT_ENABLED
|
| + // If this is a child document node, then the count should never go above 1.
|
| + if (Node* node = target->toNode())
|
| + ASSERT(!node->isDocumentNode() || &node->document() == &m_document);
|
| +#endif // ASSERT_ENABLED
|
| return false;
|
| }
|
| } else {
|
| @@ -112,20 +142,28 @@ bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHa
|
|
|
| void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
|
| {
|
| - // After the document has stopped, all updates become no-ops.
|
| - if (!m_document.isActive()) {
|
| - return;
|
| - }
|
| + // Notify our parent registry if we added the first or removed the last handler.
|
| + for (Document* document = &m_document; document; document = document->parentDocument()) {
|
| + // After the document has stopped, all updates become no-ops.
|
| + if (!document->isActive()) {
|
| + return;
|
| + }
|
| + EventHandlerRegistry* registry = EventHandlerRegistry::from(*document);
|
|
|
| - bool hadHandlers = hasEventHandlers(handlerClass);
|
| - updateEventHandlerTargets(op, handlerClass, target);
|
| - bool hasHandlers = hasEventHandlers(handlerClass);
|
| + bool hadHandlers = registry->hasEventHandlers(handlerClass);
|
| + registry->updateEventHandlerTargets(op, handlerClass, target);
|
| + bool hasHandlers = registry->hasEventHandlers(handlerClass);
|
|
|
| - // Notify the parent document's registry if we added the first or removed
|
| - // the last handler.
|
| - if (hadHandlers != hasHandlers && !m_document.parentDocument()) {
|
| - // This is the root registry; notify clients accordingly.
|
| - notifyHasHandlersChanged(handlerClass, hasHandlers);
|
| + if (hadHandlers == hasHandlers) {
|
| + break;
|
| + }
|
| + if (!document->parentDocument()) {
|
| + // This is the root registry; notify clients accordingly.
|
| + registry->notifyHasHandlersChanged(handlerClass, hasHandlers);
|
| + } else {
|
| + // Report change to parent with our Document as the target.
|
| + target = document;
|
| + }
|
| }
|
| }
|
|
|
|
|