Changeset 208817 in webkit


Ignore:
Timestamp:
Nov 16, 2016 3:06:47 PM (7 years ago)
Author:
rniwa@webkit.org
Message:

slotchange event should bubble and dispatched once
https://bugs.webkit.org/show_bug.cgi?id=164770

Reviewed by Antti Koivisto.

LayoutTests/imported/w3c:

Rebaselined the test. Some test cases fail as they do on Chrome because it's testing an outdated version of the spec.
Will fix the test upstream later.

  • web-platform-tests/shadow-dom/slotchange-event-expected.txt:

Source/WebCore:

Updated our implementation of slotchange event to match the latest specification after:
https://github.com/w3c/webcomponents/issues/571
https://dom.spec.whatwg.org/#signal-a-slot-change
The new behavior matches that of Google Chrome Canary.

In the latest specification, we no longer dispatch a separate event on ancestor slots.
Instead, we fire a single slotchange event to which a new node is assigned or from which
an existing assigned node is removed. This patch mostly removes the code that existed to
locate ancestor slot elements, and makes the event bubble up by changing a single line in
HTMLSlotElement::dispatchSlotChangeEvent.

Test: fast/shadow-dom/slotchange-event-bubbling.html

  • dom/ShadowRoot.h:
  • dom/SlotAssignment.cpp:

(WebCore::recursivelyFireSlotChangeEvent): Deleted.
(WebCore::SlotAssignment::didChangeSlot): Removed ChangeType from the arguments since we
no longer notify the ancestor slot elements.
(WebCore::SlotAssignment::hostChildElementDidChange):

  • dom/SlotAssignment.h:

(WebCore::ShadowRoot::didRemoveAllChildrenOfShadowHost):
(WebCore::ShadowRoot::didChangeDefaultSlot):
(WebCore::ShadowRoot::hostChildElementDidChangeSlotAttribute):
(WebCore::ShadowRoot::innerSlotDidChange): Deleted.

  • html/HTMLDetailsElement.cpp:

(WebCore::DetailsSlotAssignment::hostChildElementDidChange):

  • html/HTMLSlotElement.cpp:

(WebCore::HTMLSlotElement::dispatchSlotChangeEvent): Make slotchange event bubble.

LayoutTests:

  • fast/shadow-dom/slotchange-event-bubbling-expected.txt: Added.
  • fast/shadow-dom/slotchange-event-bubbling.html: Added.
Location:
trunk
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r208816 r208817  
     12016-11-16  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        slotchange event should bubble and dispatched once
     4        https://bugs.webkit.org/show_bug.cgi?id=164770
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * fast/shadow-dom/slotchange-event-bubbling-expected.txt: Added.
     9        * fast/shadow-dom/slotchange-event-bubbling.html: Added.
     10
    1112016-11-16  Simon Fraser  <simon.fraser@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r208737 r208817  
     12016-11-16  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        slotchange event should bubble and dispatched once
     4        https://bugs.webkit.org/show_bug.cgi?id=164770
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Rebaselined the test. Some test cases fail as they do on Chrome because it's testing an outdated version of the spec.
     9        Will fix the test upstream later.
     10
     11        * web-platform-tests/shadow-dom/slotchange-event-expected.txt:
     12
    1132016-11-14  Jiewen Tan  <jiewen_tan@apple.com>
    214
  • trunk/LayoutTests/imported/w3c/web-platform-tests/shadow-dom/slotchange-event-expected.txt

    r206463 r208817  
    2424PASS slotchange event must fire on a slot element inside an open shadow root  not in a document when innerHTML modifies the children of the shadow host
    2525PASS slotchange event must fire on a slot element inside a closed shadow root  not in a document when innerHTML modifies the children of the shadow host
    26 PASS slotchange event must fire on a slot element inside an open shadow root  in a document when nested slots's contents change
    27 PASS slotchange event must fire on a slot element inside a closed shadow root  in a document when nested slots's contents change
    28 PASS slotchange event must fire on a slot element inside an open shadow root  not in a document when nested slots's contents change
    29 PASS slotchange event must fire on a slot element inside a closed shadow root  not in a document when nested slots's contents change
    30 PASS slotchange event must fire at the end of current microtask after mutation observers are invoked inside an open shadow root  in a document when slots's contents change
    31 PASS slotchange event must fire at the end of current microtask after mutation observers are invoked inside a closed shadow root  in a document when slots's contents change
    32 PASS slotchange event must fire at the end of current microtask after mutation observers are invoked inside an open shadow root  not in a document when slots's contents change
    33 PASS slotchange event must fire at the end of current microtask after mutation observers are invoked inside a closed shadow root  not in a document when slots's contents change
     26FAIL slotchange event must fire on a slot element inside an open shadow root  in a document when nested slots's contents change assert_equals: slotchange must be fired on a slot element if the assigned nodes changed expected 1 but got 0
     27FAIL slotchange event must fire on a slot element inside a closed shadow root  in a document when nested slots's contents change assert_equals: slotchange must be fired on a slot element if the assigned nodes changed expected 1 but got 0
     28FAIL slotchange event must fire on a slot element inside an open shadow root  not in a document when nested slots's contents change assert_equals: slotchange must be fired on a slot element if the assigned nodes changed expected 1 but got 0
     29FAIL slotchange event must fire on a slot element inside a closed shadow root  not in a document when nested slots's contents change assert_equals: slotchange must be fired on a slot element if the assigned nodes changed expected 1 but got 0
     30FAIL slotchange event must fire at the end of current microtask after mutation observers are invoked inside an open shadow root  in a document when slots's contents change assert_array_equals: slotchange event must be fired during a single compound microtask lengths differ, expected 2 got 1
     31FAIL slotchange event must fire at the end of current microtask after mutation observers are invoked inside a closed shadow root  in a document when slots's contents change assert_array_equals: slotchange event must be fired during a single compound microtask lengths differ, expected 2 got 1
     32FAIL slotchange event must fire at the end of current microtask after mutation observers are invoked inside an open shadow root  not in a document when slots's contents change assert_array_equals: slotchange event must be fired during a single compound microtask lengths differ, expected 2 got 1
     33FAIL slotchange event must fire at the end of current microtask after mutation observers are invoked inside a closed shadow root  not in a document when slots's contents change assert_array_equals: slotchange event must be fired during a single compound microtask lengths differ, expected 2 got 1
    3434hello
    3535hello
  • trunk/Source/WebCore/ChangeLog

    r208815 r208817  
     12016-11-16  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        slotchange event should bubble and dispatched once
     4        https://bugs.webkit.org/show_bug.cgi?id=164770
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Updated our implementation of slotchange event to match the latest specification after:
     9        https://github.com/w3c/webcomponents/issues/571
     10        https://dom.spec.whatwg.org/#signal-a-slot-change
     11        The new behavior matches that of Google Chrome Canary.
     12
     13        In the latest specification, we no longer dispatch a separate event on ancestor slots.
     14        Instead, we fire a single slotchange event to which a new node is assigned or from which
     15        an existing assigned node is removed. This patch mostly removes the code that existed to
     16        locate ancestor slot elements, and makes the event bubble up by changing a single line in
     17        HTMLSlotElement::dispatchSlotChangeEvent.
     18
     19        Test: fast/shadow-dom/slotchange-event-bubbling.html
     20
     21        * dom/ShadowRoot.h:
     22        * dom/SlotAssignment.cpp:
     23        (WebCore::recursivelyFireSlotChangeEvent): Deleted.
     24        (WebCore::SlotAssignment::didChangeSlot): Removed ChangeType from the arguments since we
     25        no longer notify the ancestor slot elements.
     26        (WebCore::SlotAssignment::hostChildElementDidChange):
     27        * dom/SlotAssignment.h:
     28        (WebCore::ShadowRoot::didRemoveAllChildrenOfShadowHost):
     29        (WebCore::ShadowRoot::didChangeDefaultSlot):
     30        (WebCore::ShadowRoot::hostChildElementDidChangeSlotAttribute):
     31        (WebCore::ShadowRoot::innerSlotDidChange): Deleted.
     32        * html/HTMLDetailsElement.cpp:
     33        (WebCore::DetailsSlotAssignment::hostChildElementDidChange):
     34        * html/HTMLSlotElement.cpp:
     35        (WebCore::HTMLSlotElement::dispatchSlotChangeEvent): Make slotchange event bubble.
     36
    1372016-11-16  Alex Christensen  <achristensen@webkit.org>
    238
  • trunk/Source/WebCore/dom/ShadowRoot.h

    r208616 r208817  
    7979    void hostChildElementDidChange(const Element&);
    8080    void hostChildElementDidChangeSlotAttribute(const AtomicString& oldValue, const AtomicString& newValue);
    81     void innerSlotDidChange(const AtomicString&);
    8281
    8382    const Vector<Node*>* assignedNodesForSlot(const HTMLSlotElement&);
  • trunk/Source/WebCore/dom/SlotAssignment.cpp

    r208001 r208817  
    128128}
    129129
    130 static void recursivelyFireSlotChangeEvent(HTMLSlotElement& slotElement)
    131 {
    132     slotElement.enqueueSlotChangeEvent();
    133 
    134     auto* slotParent = slotElement.parentElement();
    135     if (!slotParent)
    136         return;
    137 
    138     auto* shadowRootOfSlotParent = slotParent->shadowRoot();
    139     if (!shadowRootOfSlotParent)
    140         return;
    141 
    142     shadowRootOfSlotParent->innerSlotDidChange(slotElement.attributeWithoutSynchronization(slotAttr));
    143 }
    144 
    145 void SlotAssignment::didChangeSlot(const AtomicString& slotAttrValue, ChangeType changeType, ShadowRoot& shadowRoot)
     130void SlotAssignment::didChangeSlot(const AtomicString& slotAttrValue, ShadowRoot& shadowRoot)
    146131{
    147132    auto& slotName = slotNameFromAttributeValue(slotAttrValue);
     
    154139        return;
    155140
    156     if (changeType == ChangeType::DirectChild) {
    157         shadowRoot.host()->invalidateStyleAndRenderersForSubtree();
    158         m_slotAssignmentsIsValid = false;
    159     }
     141    shadowRoot.host()->invalidateStyleAndRenderersForSubtree();
     142    m_slotAssignmentsIsValid = false;
    160143
    161144    if (shadowRoot.mode() == ShadowRootMode::UserAgent)
    162145        return;
    163146
    164     recursivelyFireSlotChangeEvent(*slotElement);
     147    slotElement->enqueueSlotChangeEvent();
    165148}
    166149
    167150void SlotAssignment::hostChildElementDidChange(const Element& childElement, ShadowRoot& shadowRoot)
    168151{
    169     didChangeSlot(childElement.attributeWithoutSynchronization(slotAttr), ChangeType::DirectChild, shadowRoot);
     152    didChangeSlot(childElement.attributeWithoutSynchronization(slotAttr), shadowRoot);
    170153}
    171154
  • trunk/Source/WebCore/dom/SlotAssignment.h

    r208179 r208817  
    5252    void removeSlotElementByName(const AtomicString&, HTMLSlotElement&, ShadowRoot&);
    5353
    54     enum class ChangeType { DirectChild, InnerSlot };
    55     void didChangeSlot(const AtomicString&, ChangeType, ShadowRoot&);
     54    void didChangeSlot(const AtomicString&, ShadowRoot&);
    5655    void enqueueSlotChangeEvent(const AtomicString&, ShadowRoot&);
    5756
     
    10099{
    101100    if (m_slotAssignment) // FIXME: This is incorrect when there were no elements or text nodes removed.
    102         m_slotAssignment->didChangeSlot(nullAtom, SlotAssignment::ChangeType::DirectChild, *this);
     101        m_slotAssignment->didChangeSlot(nullAtom, *this);
    103102}
    104103
     
    106105{
    107106    if (m_slotAssignment)
    108         m_slotAssignment->didChangeSlot(nullAtom, SlotAssignment::ChangeType::DirectChild, *this);
     107        m_slotAssignment->didChangeSlot(nullAtom, *this);
    109108}
    110109
     
    118117{
    119118    if (m_slotAssignment) {
    120         m_slotAssignment->didChangeSlot(oldValue, SlotAssignment::ChangeType::DirectChild, *this);
    121         m_slotAssignment->didChangeSlot(newValue, SlotAssignment::ChangeType::DirectChild, *this);
     119        m_slotAssignment->didChangeSlot(oldValue, *this);
     120        m_slotAssignment->didChangeSlot(newValue, *this);
    122121    }
    123122}
    124123
    125 inline void ShadowRoot::innerSlotDidChange(const AtomicString& name)
    126 {
    127     if (m_slotAssignment)
    128         m_slotAssignment->didChangeSlot(name, SlotAssignment::ChangeType::InnerSlot, *this);
    129 }
    130 
    131124} // namespace WebCore
  • trunk/Source/WebCore/html/HTMLDetailsElement.cpp

    r208603 r208817  
    6565        // Don't check whether this is the first summary element
    6666        // since we don't know the answer when this function is called inside Element::removedFrom.
    67         didChangeSlot(summarySlotName(), ChangeType::DirectChild, shadowRoot);
     67        didChangeSlot(summarySlotName(), shadowRoot);
    6868    } else
    69         didChangeSlot(SlotAssignment::defaultSlotName(), ChangeType::DirectChild, shadowRoot);
     69        didChangeSlot(SlotAssignment::defaultSlotName(), shadowRoot);
    7070}
    7171
  • trunk/Source/WebCore/html/HTMLSlotElement.cpp

    r206534 r208817  
    145145    m_inSignalSlotList = false;
    146146
    147     bool bubbles = false;
     147    bool bubbles = true;
    148148    bool cancelable = false;
    149149    Ref<Event> event = Event::create(eventNames().slotchangeEvent, bubbles, cancelable);
Note: See TracChangeset for help on using the changeset viewer.