Changeset 167689 in webkit


Ignore:
Timestamp:
Apr 22, 2014 4:25:59 PM (10 years ago)
Author:
rniwa@webkit.org
Message:

REGRESSION (r157328): popover to check into flight ba.com dismisses instantly when focusing form
https://bugs.webkit.org/show_bug.cgi?id=131949

Reviewed by Darin Adler.

Source/WebCore:
The regression was caused by two bugs:

  1. The event didn't stop propagating itself even when it should. If the related target is same as the event origin, the event propagation should stop when the event reaches the root of the related target's tree scope. Otherwise, it should stop when it reaches the related target.
  1. Mouse event's related target exposed nodes inside a user-agent shadow DOM when the related target appeared inside the origin.

Fixed the bugs by re-introducing path shrinkage algorithm removed in r157328 into EventPath::setRelatedTarget
and adding an algorithm to determine the least common ancestor of the related target and the current target
in moveToParentOrShadowHost. The latter algorithm doesn't match the shadow DOM specification:
http://www.w3.org/TR/2013/WD-shadow-dom-20130514/
but it's good enough in terms of the Web exposed behavior as we don't support author defined insertion points.

Test: fast/events/shadow-event-path.html

  • dom/EventDispatcher.cpp:

(WebCore::EventRelatedNodeResolver::moveToParentOrShadowHost):
(WebCore::EventRelatedNodeResolver::findHostOfTreeScopeInTargetTreeScope): Added.
(WebCore::EventDispatcher::dispatchEvent):
(WebCore::EventPath::setRelatedTarget):

LayoutTests:
Add a test that dumps the event target and the related target of every mouse event
when dispatched inside an input element inside a details element.

This catches the regression as well as other bugs I encountered while fixing the bug.

We need a WK2 specific results because WK1 mac results contain an extra fake mouse move event.

  • fast/events/shadow-event-path-expected.txt: Added.
  • fast/events/shadow-event-path.html: Added.
  • platform/mac-wk2/fast/events/shadow-event-expected.txt: Added.
Location:
trunk
Files:
3 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r167688 r167689  
     12014-04-22  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        REGRESSION (r157328): popover to check into flight ba.com dismisses instantly when focusing form
     4        https://bugs.webkit.org/show_bug.cgi?id=131949
     5
     6        Reviewed by Darin Adler.
     7
     8        Add a test that dumps the event target and the related target of every mouse event
     9        when dispatched inside an input element inside a details element.
     10
     11        This catches the regression as well as other bugs I encountered while fixing the bug.
     12
     13        We need a WK2 specific results because WK1 mac results contain an extra fake mouse move event.
     14
     15        * fast/events/shadow-event-path-expected.txt: Added.
     16        * fast/events/shadow-event-path.html: Added.
     17        * platform/mac-wk2/fast/events/shadow-event-expected.txt: Added.
     18
    1192014-04-22  Ryosuke Niwa  <rniwa@webkit.org>
    220
  • trunk/Source/WebCore/ChangeLog

    r167688 r167689  
     12014-04-22  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        REGRESSION (r157328): popover to check into flight ba.com dismisses instantly when focusing form
     4        https://bugs.webkit.org/show_bug.cgi?id=131949
     5
     6        Reviewed by Darin Adler.
     7
     8        The regression was caused by two bugs:
     9        1. The event didn't stop propagating itself even when it should.
     10           If the related target is same as the event origin, the event propagation should stop when the event reaches
     11           the root of the related target's tree scope. Otherwise, it should stop when it reaches the related target.
     12
     13        2. Mouse event's related target exposed nodes inside a user-agent shadow DOM when the related target appeared
     14           inside the origin.
     15
     16        Fixed the bugs by re-introducing path shrinkage algorithm removed in r157328 into EventPath::setRelatedTarget
     17        and adding an algorithm to determine the least common ancestor of the related target and the current target
     18        in moveToParentOrShadowHost. The latter algorithm doesn't match the shadow DOM specification:
     19        http://www.w3.org/TR/2013/WD-shadow-dom-20130514/
     20        but it's good enough in terms of the Web exposed behavior as we don't support author defined insertion points.
     21
     22        Test: fast/events/shadow-event-path.html
     23
     24        * dom/EventDispatcher.cpp:
     25        (WebCore::EventRelatedNodeResolver::moveToParentOrShadowHost):
     26        (WebCore::EventRelatedNodeResolver::findHostOfTreeScopeInTargetTreeScope): Added.
     27        (WebCore::EventDispatcher::dispatchEvent):
     28        (WebCore::EventPath::setRelatedTarget):
     29
    1302014-04-22  Ryosuke Niwa  <rniwa@webkit.org>
    231
  • trunk/Source/WebCore/dom/EventDispatcher.cpp

    r165607 r167689  
    9191    void updateTouchLists(const TouchEvent&);
    9292#endif
    93     void setRelatedTarget(EventTarget&);
     93    void setRelatedTarget(Node& origin, EventTarget&);
    9494
    9595    bool hasEventListeners(const AtomicString& eventType) const;
     
    149149        }
    150150
    151         if (m_relatedNodeInCurrentTreeScope) { // relatedNode is under the current tree scope
     151        if (&newTreeScope == &m_relatedNodeTreeScope)
     152            m_relatedNodeInCurrentTreeScope = &m_relatedNode;
     153        else if (m_relatedNodeInCurrentTreeScope) {
    152154            ASSERT(m_currentTreeScope);
    153155            m_relatedNodeInCurrentTreeScope = &newTarget;
    154         } else if (&newTreeScope == &m_relatedNodeTreeScope) // relatedNode is in the current tree scope;
    155             m_relatedNodeInCurrentTreeScope = &m_relatedNode;
    156         // Otherwise, we haven't reached the tree scope that contains relatedNode yet.
     156        } else {
     157            if (!m_currentTreeScope) {
     158                TreeScope* newTreeScopeAncestor = &newTreeScope;
     159                do {
     160                    m_relatedNodeInCurrentTreeScope = findHostOfTreeScopeInTargetTreeScope(m_relatedNodeTreeScope, *newTreeScopeAncestor);
     161                    newTreeScopeAncestor = newTreeScopeAncestor->parentTreeScope();
     162                    if (newTreeScopeAncestor == &m_relatedNodeTreeScope) {
     163                        m_relatedNodeInCurrentTreeScope = &m_relatedNode;
     164                        break;
     165                    }
     166                } while (newTreeScopeAncestor && !m_relatedNodeInCurrentTreeScope);
     167            }
     168            ASSERT(m_relatedNodeInCurrentTreeScope || findHostOfTreeScopeInTargetTreeScope(newTreeScope, m_relatedNodeTreeScope)
     169                || &newTreeScope.documentScope() != &m_relatedNodeTreeScope.documentScope());
     170        }
    157171
    158172        m_currentTreeScope = &newTreeScope;
    159173
    160174        return m_relatedNodeInCurrentTreeScope;
     175    }
     176
     177    static Node* findHostOfTreeScopeInTargetTreeScope(const TreeScope& startingTreeScope, const TreeScope& targetScope)
     178    {
     179        ASSERT(&targetScope != &startingTreeScope);
     180        Node* previousHost = 0;
     181        for (const TreeScope* scope = &startingTreeScope; scope; scope = scope->parentTreeScope()) {
     182            if (scope == &targetScope) {
     183                ASSERT(previousHost);
     184                ASSERT_WITH_SECURITY_IMPLICATION(&previousHost->treeScope() == &targetScope);
     185                return previousHost;
     186            }
     187            if (scope->rootNode().isShadowRoot())
     188                previousHost = toShadowRoot(scope->rootNode()).hostElement();
     189            else
     190                ASSERT_WITH_SECURITY_IMPLICATION(!scope->parentTreeScope());
     191        }
     192        return 0;
    161193    }
    162194
     
    306338
    307339    if (EventTarget* relatedTarget = event->relatedTarget())
    308         eventPath.setRelatedTarget(*relatedTarget);
     340        eventPath.setRelatedTarget(*node, *relatedTarget);
    309341#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
    310342    if (event->isTouchEvent())
     
    453485#endif
    454486
    455 void EventPath::setRelatedTarget(EventTarget& relatedTarget)
     487void EventPath::setRelatedTarget(Node& origin, EventTarget& relatedTarget)
    456488{
    457489    Node* relatedNode = relatedTarget.toNode();
     
    461493    EventRelatedNodeResolver resolver(*relatedNode);
    462494
     495    bool originIsRelatedTarget = &origin == relatedNode;
     496    Node& rootNodeInOriginTreeScope = origin.treeScope().rootNode();
     497
    463498    size_t eventPathSize = m_path.size();
    464     for (size_t i = 0; i < eventPathSize; i++)
    465         toMouseOrFocusEventContext(*m_path[i]).setRelatedTarget(resolver.moveToParentOrShadowHost(*m_path[i]->node()));
     499    size_t i = 0;
     500    while (i < eventPathSize) {
     501        Node* contextNode = m_path[i]->node();
     502        Node* currentRelatedNode = resolver.moveToParentOrShadowHost(*contextNode);
     503        if (!originIsRelatedTarget && m_path[i]->target() == currentRelatedNode)
     504            break;
     505        toMouseOrFocusEventContext(*m_path[i]).setRelatedTarget(currentRelatedNode);
     506        i++;
     507        if (originIsRelatedTarget && &rootNodeInOriginTreeScope == contextNode)
     508            break;
     509    }
     510    m_path.shrink(i);
    466511}
    467512
Note: See TracChangeset for help on using the changeset viewer.