Changeset 190214 in webkit


Ignore:
Timestamp:
Sep 24, 2015 12:00:11 PM (9 years ago)
Author:
rniwa@webkit.org
Message:

Make event dispatching respect slotting
https://bugs.webkit.org/show_bug.cgi?id=149243

Reviewed by Antti Koivisto.

Source/WebCore:

There are primarily two cases to consider: getting out of a shadow root to its host,
and moving into a slot from an assigned node.

When getting out of a shadow root, either the event originated in its shadow tree
including its nodes' shadow trees (1) or it moved into this shadow tree via a slot (2).
In (1), event.target should be set to the shadow host. In (2), it should be set to the
first node in the event path that belongs to the same tree as the shadow host. In order
to find such a node in O(1), we use a stack of event targets in each (shadow) tree. We
push event.target of the current tree whenever we move up to a slot from an assigned node
and pop it out of the stack when we move out of the shadow tree.

A follow up patch is needed to update the code to resolve related targets.

Tests: fast/shadow-dom/event-inside-shadow-tree.html

fast/shadow-dom/event-inside-slotted-node.html

  • dom/EventDispatcher.cpp:

(WebCore::EventPath::EventPath):

LayoutTests:

Added tests for dispatching events inside shadow trees and nodes assigned to slots using testharness.js.

  • fast/shadow-dom/event-inside-shadow-tree-expected.txt: Added.
  • fast/shadow-dom/event-inside-shadow-tree.html: Added.
  • fast/shadow-dom/event-inside-slotted-node-expected.txt: Added.
  • fast/shadow-dom/event-inside-slotted-node.html: Added.
Location:
trunk
Files:
4 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r190209 r190214  
     12015-09-24  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Make event dispatching respect slotting
     4        https://bugs.webkit.org/show_bug.cgi?id=149243
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Added tests for dispatching events inside shadow trees and nodes assigned to slots using testharness.js.
     9
     10        * fast/shadow-dom/event-inside-shadow-tree-expected.txt: Added.
     11        * fast/shadow-dom/event-inside-shadow-tree.html: Added.
     12        * fast/shadow-dom/event-inside-slotted-node-expected.txt: Added.
     13        * fast/shadow-dom/event-inside-slotted-node.html: Added.
     14
    1152015-09-24  David Hyatt  <hyatt@apple.com>
    216
  • trunk/Source/WebCore/ChangeLog

    r190210 r190214  
     12015-09-24  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Make event dispatching respect slotting
     4        https://bugs.webkit.org/show_bug.cgi?id=149243
     5
     6        Reviewed by Antti Koivisto.
     7
     8        There are primarily two cases to consider: getting out of a shadow root to its host,
     9        and moving into a slot from an assigned node.
     10
     11        When getting out of a shadow root, either the event originated in its shadow tree
     12        including its nodes' shadow trees (1) or it moved into this shadow tree via a slot (2).
     13        In (1), event.target should be set to the shadow host. In (2), it should be set to the
     14        first node in the event path that belongs to the same tree as the shadow host. In order
     15        to find such a node in O(1), we use a stack of event targets in each (shadow) tree. We
     16        push event.target of the current tree whenever we move up to a slot from an assigned node
     17        and pop it out of the stack when we move out of the shadow tree.
     18
     19        A follow up patch is needed to update the code to resolve related targets.
     20
     21        Tests: fast/shadow-dom/event-inside-shadow-tree.html
     22               fast/shadow-dom/event-inside-slotted-node.html
     23
     24        * dom/EventDispatcher.cpp:
     25        (WebCore::EventPath::EventPath):
     26
    1272015-09-24  Chris Dumez  <cdumez@apple.com>
    228
  • trunk/Source/WebCore/dom/EventDispatcher.cpp

    r190153 r190214  
    3232#include "HTMLInputElement.h"
    3333#include "HTMLMediaElement.h"
     34#include "HTMLSlotElement.h"
    3435#include "InsertionPoint.h"
    3536#include "InspectorInstrumentation.h"
     
    414415}
    415416
    416 EventPath::EventPath(Node& targetNode, Event& event)
    417 {
    418     bool isSVGElement = targetNode.isSVGElement();
     417EventPath::EventPath(Node& originalTarget, Event& event)
     418{
     419#if ENABLE(SHADOW_DOM)
     420    Vector<EventTarget*, 16> targetStack;
     421#endif
     422
    419423    bool isMouseOrFocusEvent = event.isMouseEvent() || event.isFocusEvent();
    420424#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
     
    423427    EventTarget* target = nullptr;
    424428
    425     Node* node = nodeOrHostIfPseudoElement(&targetNode);
     429    Node* node = nodeOrHostIfPseudoElement(&originalTarget);
    426430    while (node) {
    427         if (!target || !isSVGElement) // FIXME: This code doesn't make sense once we've climbed out of the SVG subtree in a HTML document.
     431        if (!target)
    428432            target = eventTargetRespectingTargetRules(*node);
    429         for (; node; node = node->parentNode()) {
     433        ContainerNode* parent;
     434        for (; node; node = parent) {
    430435            EventTarget* currentTarget = eventTargetRespectingTargetRules(*node);
    431436            if (isMouseOrFocusEvent)
     
    439444            if (is<ShadowRoot>(*node))
    440445                break;
     446            parent = node->parentNode();
     447            if (!parent)
     448                return;
     449#if ENABLE(SHADOW_DOM)
     450            if (ShadowRoot* shadowRootOfParent = parent->shadowRoot()) {
     451                if (auto* assignedSlot = shadowRootOfParent->findAssignedSlot(*node)) {
     452                    // node is assigned to a slot. Continue dispatching the event at this slot.
     453                    targetStack.append(target);
     454                    parent = assignedSlot;
     455                    target = assignedSlot;
     456                }
     457            }
     458#endif
     459            node = parent;
    441460        }
    442         if (!node || !shouldEventCrossShadowBoundary(event, downcast<ShadowRoot>(*node), *target))
     461
     462        ShadowRoot& shadowRoot = downcast<ShadowRoot>(*node);
     463        // At a shadow root. Continue dispatching the event at the shadow host.
     464#if ENABLE(SHADOW_DOM)
     465        if (!targetStack.isEmpty()) {
     466            // Move target back to a descendant of the shadow host if the event did not originate in this shadow tree or its inner shadow trees.
     467            target = targetStack.last();
     468            targetStack.removeLast();
     469            ASSERT(shadowRoot.host()->contains(target->toNode()));
     470        } else
     471            target = nullptr;
     472#endif
     473        if (!shouldEventCrossShadowBoundary(event, shadowRoot, originalTarget))
    443474            return;
    444         node = downcast<ShadowRoot>(*node).host();
     475        node = shadowRoot.host();
    445476    }
    446477}
Note: See TracChangeset for help on using the changeset viewer.