WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
WIP
wip155424.patch (text/plain), 19.97 KB, created by
Ryosuke Niwa
on 2016-03-14 00:32:39 PDT
(
hide
)
Description:
WIP
Filename:
MIME Type:
Creator:
Ryosuke Niwa
Created:
2016-03-14 00:32:39 PDT
Size:
19.97 KB
patch
obsolete
>Index: LayoutTests/fast/shadow-dom/ShadowRoot-interface-expected.txt >=================================================================== >--- LayoutTests/fast/shadow-dom/ShadowRoot-interface-expected.txt (revision 198056) >+++ LayoutTests/fast/shadow-dom/ShadowRoot-interface-expected.txt (working copy) >@@ -1,4 +1,3 @@ >-Blocked access to external URL https://svn.webkit.org/repository/webkit/trunk/LayoutTests/resources/testharness.css > > PASS Check the existence of ShadowRoot interface > PASS ShadowRoot must inherit from DocumentFragment >Index: LayoutTests/fast/shadow-dom/ShadowRoot-interface.html >=================================================================== >--- LayoutTests/fast/shadow-dom/ShadowRoot-interface.html (revision 198056) >+++ LayoutTests/fast/shadow-dom/ShadowRoot-interface.html (working copy) >@@ -7,7 +7,7 @@ > <link rel="help" href="https://w3c.github.io/webcomponents/spec/shadow/#the-shadowroot-interface"> > <script src="../../resources/testharness.js"></script> > <script src="../../resources/testharnessreport.js"></script> >-<link rel='stylesheet' href='https://svn.webkit.org/repository/webkit/trunk/LayoutTests/resources/testharness.css'> >+<link rel='stylesheet' href='../../resources/testharness.css'> > </head> > <body> > <div id="log"></div> >Index: Source/WebCore/dom/Document.cpp >=================================================================== >--- Source/WebCore/dom/Document.cpp (revision 198056) >+++ Source/WebCore/dom/Document.cpp (working copy) >@@ -4172,6 +4172,11 @@ > m_eventQueue.enqueueEvent(WTFMove(event)); > } > >+void Document::enqueueSlotchangeEvent(Ref<Event>&& event) >+{ >+ m_eventQueue.enqueueEvent(WTFMove(event)); >+} >+ > RefPtr<Event> Document::createEvent(const String& type, ExceptionCode& ec) > { > // Please do *not* add new event classes to this function unless they are >Index: Source/WebCore/dom/Document.h >=================================================================== >--- Source/WebCore/dom/Document.h (revision 198056) >+++ Source/WebCore/dom/Document.h (working copy) >@@ -1088,6 +1088,7 @@ > void enqueueWindowEvent(Ref<Event>&&); > void enqueueDocumentEvent(Ref<Event>&&); > void enqueueOverflowEvent(Ref<Event>&&); >+ void enqueueSlotchangeEvent(Ref<Event>&&); > void enqueuePageshowEvent(PageshowEventPersistence); > void enqueueHashchangeEvent(const String& oldURL, const String& newURL); > void enqueuePopstateEvent(RefPtr<SerializedScriptValue>&& stateObject); >Index: Source/WebCore/dom/Element.cpp >=================================================================== >--- Source/WebCore/dom/Element.cpp (revision 198056) >+++ Source/WebCore/dom/Element.cpp (working copy) >@@ -83,6 +83,7 @@ > #include "SelectorQuery.h" > #include "Settings.h" > #include "SimulatedClick.h" >+#include "SlotAssignment.h" > #include "StyleProperties.h" > #include "StyleResolver.h" > #include "StyleTreeResolver.h" >@@ -1254,7 +1255,7 @@ > else if (name == HTMLNames::slotAttr) { > if (auto* parent = parentElement()) { > if (auto* shadowRoot = parent->shadowRoot()) >- shadowRoot->invalidateSlotAssignments(); >+ shadowRoot->hostChildElementDidChangeSlotAttr(oldValue, newValue); > } > } > #endif >@@ -1496,6 +1497,11 @@ > setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(true); > #endif > >+ if (parentNode() == &insertionPoint) { >+ if (auto* shadowRoot = parentNode()->shadowRoot()) >+ shadowRoot->hostChildElementDidChange(*this); >+ } >+ > if (!insertionPoint.isInTreeScope()) > return InsertionDone; > >@@ -1575,6 +1581,11 @@ > } > } > >+ if (!parentNode()) { >+ if (auto* shadowRoot = insertionPoint.shadowRoot()) >+ shadowRoot->hostChildElementDidChange(*this); >+ } >+ > ContainerNode::removedFrom(insertionPoint); > > if (hasPendingResources()) >@@ -1832,13 +1843,15 @@ > switch (change.type) { > case ElementInserted: > case ElementRemoved: >+ // For elements, we notify shadowRoot in Element::insertedInto and Element::removedFrom. >+ break; > case AllChildrenRemoved: >- shadowRoot->invalidateSlotAssignments(); >+ shadowRoot->didRemoveAllChildrenOfShadowHost(); > break; > case TextInserted: > case TextRemoved: > case TextChanged: >- shadowRoot->invalidateDefaultSlotAssignments(); >+ shadowRoot->didChangeDefaultSlot(); > break; > case NonContentsChildChanged: > break; >Index: Source/WebCore/dom/Event.cpp >=================================================================== >--- Source/WebCore/dom/Event.cpp (revision 198056) >+++ Source/WebCore/dom/Event.cpp (working copy) >@@ -103,7 +103,8 @@ > || m_type == eventNames().resizeEvent > || m_type == eventNames().scrollEvent > || m_type == eventNames().selectEvent >- || m_type == eventNames().selectstartEvent; >+ || m_type == eventNames().selectstartEvent >+ || m_type == eventNames().slotchangeEvent; > } > > EventInterface Event::eventInterface() const >Index: Source/WebCore/dom/EventNames.h >=================================================================== >--- Source/WebCore/dom/EventNames.h (revision 198056) >+++ Source/WebCore/dom/EventNames.h (working copy) >@@ -195,6 +195,7 @@ > macro(selectstart) \ > macro(show) \ > macro(signalingstatechange) \ >+ macro(slotchange) \ > macro(soundend) \ > macro(soundstart) \ > macro(sourceclose) \ >Index: Source/WebCore/dom/ShadowRoot.cpp >=================================================================== >--- Source/WebCore/dom/ShadowRoot.cpp (revision 198056) >+++ Source/WebCore/dom/ShadowRoot.cpp (working copy) >@@ -200,18 +200,6 @@ > return m_slotAssignment->removeSlotElementByName(name, slot, *this); > } > >-void ShadowRoot::invalidateSlotAssignments() >-{ >- if (m_slotAssignment) >- m_slotAssignment->invalidate(*this); >-} >- >-void ShadowRoot::invalidateDefaultSlotAssignments() >-{ >- if (m_slotAssignment) >- m_slotAssignment->invalidateDefaultSlot(*this); >-} >- > const Vector<Node*>* ShadowRoot::assignedNodesForSlot(const HTMLSlotElement& slot) > { > if (!m_slotAssignment) >Index: Source/WebCore/dom/ShadowRoot.h >=================================================================== >--- Source/WebCore/dom/ShadowRoot.h (revision 198056) >+++ Source/WebCore/dom/ShadowRoot.h (working copy) >@@ -91,8 +91,11 @@ > void addSlotElementByName(const AtomicString&, HTMLSlotElement&); > void removeSlotElementByName(const AtomicString&, HTMLSlotElement&); > >- void invalidateSlotAssignments(); >- void invalidateDefaultSlotAssignments(); >+ void didRemoveAllChildrenOfShadowHost(); >+ void didChangeDefaultSlot(); >+ void hostChildElementDidChange(const Element&); >+ void hostChildElementDidChangeSlotAttr(const AtomicString& oldValue, const AtomicString& newValue); >+ void innerSlotDidChange(const AtomicString&); > > const Vector<Node*>* assignedNodesForSlot(const HTMLSlotElement&); > #endif >Index: Source/WebCore/dom/SlotAssignment.cpp >=================================================================== >--- Source/WebCore/dom/SlotAssignment.cpp (revision 198056) >+++ Source/WebCore/dom/SlotAssignment.cpp (working copy) >@@ -50,12 +50,10 @@ > } > > SlotAssignment::SlotAssignment() >- : m_slotNameFunction(slotNameFromSlotAttribute) > { > } > >-SlotAssignment::SlotAssignment(SlotNameFunction function) >- : m_slotNameFunction(WTFMove(function)) >+SlotAssignment::~SlotAssignment() > { > } > >@@ -64,10 +62,7 @@ > if (!is<Text>(node) && !is<Element>(node)) > return nullptr; > >- if (!m_slotAssignmentsIsValid) >- assignSlots(shadowRoot); >- >- auto slotName = m_slotNameFunction(node); >+ auto slotName = slotNameForHostChild(node); > if (!slotName) > return nullptr; > >@@ -136,17 +131,58 @@ > ASSERT(slotInfo.element || m_needsToResolveSlotElements); > } > >+static void recursivelyFireSlotChangeEvent(HTMLSlotElement* slotElement) >+{ >+ slotElement->enqueueSlotChangeEvent(); >+ >+ if (auto* slotParent = slotElement->parentElement()) { >+ if (auto* shadowRootOfSlotParent = slotParent->shadowRoot()) >+ shadowRootOfSlotParent->innerSlotDidChange(slotElement->fastGetAttribute(slotAttr)); >+ } >+} >+ >+void SlotAssignment::didChangeSlot(const AtomicString& slotAttrValue, ChangeType changeType, ShadowRoot& shadowRoot) >+{ >+ auto& slotName = slotNameFromAttributeValue(slotAttrValue); >+ auto it = m_slots.find(slotName); >+ if (it == m_slots.end()) >+ return; >+ >+ HTMLSlotElement* slotElement = findFirstSlotElement(*it->value, shadowRoot); >+ if (!slotElement) >+ return; >+ >+ if (changeType == ChangeType::DirectChild) { >+ shadowRoot.host()->setNeedsStyleRecalc(ReconstructRenderTree); >+ m_slotAssignmentsIsValid = false; >+ } >+ >+ if (shadowRoot.type() == ShadowRoot::Type::UserAgent) >+ return; >+ >+ recursivelyFireSlotChangeEvent(slotElement); >+} >+ >+void SlotAssignment::didRemoveAllChildrenOfShadowHost(ShadowRoot& shadowRoot) >+{ >+ didChangeSlot(nullAtom, SlotAssignment::ChangeType::DirectChild, shadowRoot); >+} >+ >+void SlotAssignment::hostChildElementDidChange(const Element& childElement, ShadowRoot& shadowRoot) >+{ >+ didChangeSlot(childElement.fastGetAttribute(slotAttr), ChangeType::DirectChild, shadowRoot); >+} >+ > const Vector<Node*>* SlotAssignment::assignedNodesForSlot(const HTMLSlotElement& slotElement, ShadowRoot& shadowRoot) > { >- if (!m_slotAssignmentsIsValid) >- assignSlots(shadowRoot); >- > const AtomicString& slotName = slotNameFromAttributeValue(slotElement.fastGetAttribute(nameAttr)); > auto it = m_slots.find(slotName); > if (it == m_slots.end()) > return nullptr; > > auto& slotInfo = *it->value; >+ if (!m_slotAssignmentsIsValid) >+ assignSlots(shadowRoot); > > if (!slotInfo.assignedNodes.size()) > return nullptr; >@@ -158,20 +194,11 @@ > return &slotInfo.assignedNodes; > } > >-void SlotAssignment::invalidate(ShadowRoot& shadowRoot) >+const AtomicString& SlotAssignment::slotNameForHostChild(const Node& child) const > { >- // FIXME: We should be able to do a targeted reconstruction. >- shadowRoot.host()->setNeedsStyleRecalc(ReconstructRenderTree); >- m_slotAssignmentsIsValid = false; >+ return slotNameFromSlotAttribute(child); > } > >-void SlotAssignment::invalidateDefaultSlot(ShadowRoot& shadowRoot) >-{ >- auto it = m_slots.find(defaultSlotName()); >- if (it != m_slots.end() && it->value->elementCount) >- invalidate(shadowRoot); // FIXME: We should be able to reconstruct only under the default slot. >-} >- > HTMLSlotElement* SlotAssignment::findFirstSlotElement(SlotInfo& slotInfo, ShadowRoot& shadowRoot) > { > if (slotInfo.shouldResolveSlotElement()) >@@ -179,6 +206,7 @@ > > #ifndef NDEBUG > ASSERT(!slotInfo.element || m_slotElementsForConsistencyCheck.contains(slotInfo.element)); >+ ASSERT(!!slotInfo.element == !!slotInfo.elementCount); > #endif > > return slotInfo.element; >@@ -226,7 +254,7 @@ > for (auto* child = host.firstChild(); child; child = child->nextSibling()) { > if (!is<Text>(*child) && !is<Element>(*child)) > continue; >- auto slotName = m_slotNameFunction(*child); >+ auto slotName = slotNameForHostChild(*child); > if (!slotName) > continue; > assignToSlot(*child, slotName); >Index: Source/WebCore/dom/SlotAssignment.h >=================================================================== >--- Source/WebCore/dom/SlotAssignment.h (revision 198056) >+++ Source/WebCore/dom/SlotAssignment.h (working copy) >@@ -28,6 +28,7 @@ > > #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) > >+#include "ShadowRoot.h" > #include <wtf/HashMap.h> > #include <wtf/HashSet.h> > #include <wtf/Vector.h> >@@ -36,18 +37,15 @@ > > namespace WebCore { > >+class Element; > class HTMLSlotElement; > class Node; >-class ShadowRoot; > > class SlotAssignment { > WTF_MAKE_NONCOPYABLE(SlotAssignment); > public: >- using SlotNameFunction = std::function<AtomicString (const Node& child)>; >- > SlotAssignment(); >- SlotAssignment(SlotNameFunction); >- ~SlotAssignment() { } >+ virtual ~SlotAssignment(); > > static const AtomicString& defaultSlotName() { return emptyAtom; } > >@@ -55,11 +53,15 @@ > > void addSlotElementByName(const AtomicString&, HTMLSlotElement&, ShadowRoot&); > void removeSlotElementByName(const AtomicString&, HTMLSlotElement&, ShadowRoot&); >+ >+ void didRemoveAllChildrenOfShadowHost(ShadowRoot&); >+ enum class ChangeType { DirectChild, InnerSlot }; >+ void didChangeSlot(const AtomicString&, ChangeType, ShadowRoot&); >+ void enqueueSlotChangeEvent(const AtomicString&, ShadowRoot&); > > const Vector<Node*>* assignedNodesForSlot(const HTMLSlotElement&, ShadowRoot&); > >- void invalidate(ShadowRoot&); >- void invalidateDefaultSlot(ShadowRoot&); >+ virtual void hostChildElementDidChange(const Element&, ShadowRoot&); > > private: > struct SlotInfo { >@@ -77,6 +79,8 @@ > unsigned elementCount { 0 }; > Vector<Node*> assignedNodes; > }; >+ >+ virtual const AtomicString& slotNameForHostChild(const Node&) const; > > HTMLSlotElement* findFirstSlotElement(SlotInfo&, ShadowRoot&); > void resolveAllSlotElements(ShadowRoot&); >@@ -84,8 +88,6 @@ > void assignSlots(ShadowRoot&); > void assignToSlot(Node& child, const AtomicString& slotName); > >- SlotNameFunction m_slotNameFunction; >- > HashMap<AtomicString, std::unique_ptr<SlotInfo>> m_slots; > > #ifndef NDEBUG >@@ -96,8 +98,40 @@ > bool m_slotAssignmentsIsValid { false }; > }; > >+inline void ShadowRoot::didRemoveAllChildrenOfShadowHost() >+{ >+ if (m_slotAssignment) // FIXME: This is incorrect when there were no elements or text nodes removed. >+ m_slotAssignment->didChangeSlot(nullAtom, SlotAssignment::ChangeType::DirectChild, *this); > } > >+inline void ShadowRoot::didChangeDefaultSlot() >+{ >+ if (m_slotAssignment) >+ m_slotAssignment->didChangeSlot(nullAtom, SlotAssignment::ChangeType::DirectChild, *this); >+} >+ >+inline void ShadowRoot::hostChildElementDidChange(const Element& childElement) >+{ >+ if (m_slotAssignment) >+ m_slotAssignment->hostChildElementDidChange(childElement, *this); >+} >+ >+inline void ShadowRoot::hostChildElementDidChangeSlotAttr(const AtomicString& oldValue, const AtomicString& newValue) >+{ >+ if (m_slotAssignment) { >+ m_slotAssignment->didChangeSlot(oldValue, SlotAssignment::ChangeType::DirectChild, *this); >+ m_slotAssignment->didChangeSlot(newValue, SlotAssignment::ChangeType::DirectChild, *this); >+ } >+} >+ >+inline void ShadowRoot::innerSlotDidChange(const AtomicString& name) >+{ >+ if (m_slotAssignment) >+ m_slotAssignment->didChangeSlot(name, SlotAssignment::ChangeType::InnerSlot, *this); >+} >+ >+} >+ > #endif > > #endif /* SlotAssignment_h */ >Index: Source/WebCore/html/HTMLDetailsElement.cpp >=================================================================== >--- Source/WebCore/html/HTMLDetailsElement.cpp (revision 198056) >+++ Source/WebCore/html/HTMLDetailsElement.cpp (working copy) >@@ -44,8 +44,24 @@ > return summarySlot; > } > >-static AtomicString slotNameFunction(const Node& child) >+class DetailsSlotAssignment final : public SlotAssignment { >+private: >+ void hostChildElementDidChange(const Element&, ShadowRoot&) override; >+ const AtomicString& slotNameForHostChild(const Node&) const override; >+}; >+ >+void DetailsSlotAssignment::hostChildElementDidChange(const Element& childElement, ShadowRoot& shadowRoot) > { >+ if (is<HTMLSummaryElement>(childElement)) { >+ // Don't check whether this is the first summary element >+ // since we don't know the answer when this function is called inside Element::removedFrom. >+ didChangeSlot(summarySlotName(), ChangeType::DirectChild, shadowRoot); >+ } else >+ didChangeSlot(SlotAssignment::defaultSlotName(), ChangeType::DirectChild, shadowRoot); >+} >+ >+const AtomicString& DetailsSlotAssignment::slotNameForHostChild(const Node& child) const >+{ > auto& parent = *child.parentNode(); > ASSERT(is<HTMLDetailsElement>(parent)); > auto& details = downcast<HTMLDetailsElement>(parent); >@@ -55,18 +71,13 @@ > if (&child == childrenOfType<HTMLSummaryElement>(details).first()) > return summarySlotName(); > } >- // Everything else is assigned to the default slot if details is open. >- if (details.isOpen()) >- return SlotAssignment::defaultSlotName(); >+ return SlotAssignment::defaultSlotName(); >+} > >- // Otherwise don't render the content. >- return nullAtom; >-}; >- > Ref<HTMLDetailsElement> HTMLDetailsElement::create(const QualifiedName& tagName, Document& document) > { > auto details = adoptRef(*new HTMLDetailsElement(tagName, document)); >- details->addShadowRoot(ShadowRoot::create(document, std::make_unique<SlotAssignment>(slotNameFunction))); >+ details->addShadowRoot(ShadowRoot::create(document, std::make_unique<DetailsSlotAssignment>())); > return details; > } > >@@ -94,8 +105,8 @@ > summarySlot->appendChild(WTFMove(defaultSummary)); > root->appendChild(WTFMove(summarySlot)); > >- auto defaultSlot = HTMLSlotElement::create(slotTag, document()); >- root->appendChild(WTFMove(defaultSlot)); >+ m_defaultSlot = HTMLSlotElement::create(slotTag, document()); >+ ASSERT(!m_isOpen); > } > > bool HTMLDetailsElement::isActiveSummary(const HTMLSummaryElement& summary) const >@@ -114,8 +125,14 @@ > if (name == openAttr) { > bool oldValue = m_isOpen; > m_isOpen = !value.isNull(); >- if (oldValue != m_isOpen) >- shadowRoot()->invalidateSlotAssignments(); >+ if (oldValue != m_isOpen) { >+ auto* root = shadowRoot(); >+ ASSERT(root); >+ if (m_isOpen) >+ root->appendChild(*m_defaultSlot); >+ else >+ root->removeChild(*m_defaultSlot); >+ } > } else > HTMLElement::parseAttribute(name, value); > } >Index: Source/WebCore/html/HTMLDetailsElement.h >=================================================================== >--- Source/WebCore/html/HTMLDetailsElement.h (revision 198056) >+++ Source/WebCore/html/HTMLDetailsElement.h (working copy) >@@ -47,6 +47,7 @@ > bool m_isOpen { false }; > HTMLSlotElement* m_summarySlot { nullptr }; > HTMLSummaryElement* m_defaultSummary { nullptr }; >+ RefPtr<HTMLSlotElement> m_defaultSlot; > }; > > } // namespace WebCore >Index: Source/WebCore/html/HTMLSlotElement.cpp >=================================================================== >--- Source/WebCore/html/HTMLSlotElement.cpp (revision 198056) >+++ Source/WebCore/html/HTMLSlotElement.cpp (working copy) >@@ -29,6 +29,8 @@ > #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) > > #include "ElementChildIterator.h" >+#include "Event.h" >+#include "EventNames.h" > #include "HTMLNames.h" > #include "ShadowRoot.h" > >@@ -97,6 +99,27 @@ > return shadowRoot->assignedNodesForSlot(*this); > } > >+void HTMLSlotElement::enqueueSlotChangeEvent() >+{ >+ if (m_hasEnqueuedSlotChangeEvent) >+ return; >+ >+ bool bubbles = false; >+ bool cancelable = false; >+ auto event = Event::create(eventNames().slotchangeEvent, bubbles, cancelable); >+ event->setTarget(this); >+ document().enqueueSlotchangeEvent(WTFMove(event)); >+ >+ m_hasEnqueuedSlotChangeEvent = true; > } > >+bool HTMLSlotElement::dispatchEvent(Event& event) >+{ >+ if (event.type() == eventNames().slotchangeEvent) >+ m_hasEnqueuedSlotChangeEvent = false; >+ return HTMLElement::dispatchEvent(event); >+} >+ >+} >+ > #endif >Index: Source/WebCore/html/HTMLSlotElement.h >=================================================================== >--- Source/WebCore/html/HTMLSlotElement.h (revision 198056) >+++ Source/WebCore/html/HTMLSlotElement.h (working copy) >@@ -39,12 +39,18 @@ > > const Vector<Node*>* assignedNodes() const; > >+ void enqueueSlotChangeEvent(); >+ > private: > HTMLSlotElement(const QualifiedName&, Document&); > > InsertionNotificationRequest insertedInto(ContainerNode&) override; > void removedFrom(ContainerNode&) override; > void attributeChanged(const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason) override; >+ >+ bool dispatchEvent(Event&) override; >+ >+ bool m_hasEnqueuedSlotChangeEvent { false }; > }; > > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 155424
:
273933
|
273943
|
273944
|
273950