Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Unified Diff: third_party/WebKit/Source/core/html/HTMLSlotElement.cpp

Issue 1899653002: Support slotchange event (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Bug fix Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLSlotElement.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
diff --git a/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp b/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
index 156689e76873104ff6fec7eaa50a98d24490e829..331437363377ec23e6146f20400e17cbe95f9bb0 100644
--- a/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSlotElement.cpp
@@ -32,8 +32,10 @@
#include "bindings/core/v8/Microtask.h"
#include "core/HTMLNames.h"
+#include "core/dom/ElementTraversal.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/StyleChangeReason.h"
+#include "core/dom/StyleEngine.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/InsertionPoint.h"
#include "core/events/Event.h"
@@ -46,6 +48,8 @@ using namespace HTMLNames;
inline HTMLSlotElement::HTMLSlotElement(Document& document)
: HTMLElement(slotTag, document)
, m_distributionState(DistributionDone)
+ , m_assignmentState(AssignmentDone)
+ , m_slotchangeEventAdded(false)
{
setHasCustomStyleCallbacks();
}
@@ -86,7 +90,7 @@ const HeapVector<Member<Node>>& HTMLSlotElement::getDistributedNodes()
void HTMLSlotElement::appendAssignedNode(Node& node)
{
- ASSERT(m_distributionState == DistributionOnGoing);
+ ASSERT(m_assignmentState == AssignmentOnGoing);
m_assignedNodes.append(&node);
}
@@ -98,6 +102,12 @@ void HTMLSlotElement::appendDistributedNode(Node& node)
m_distributedIndices.set(&node, size);
}
+void HTMLSlotElement::appendFallbackNode(Node& node)
+{
+ ASSERT(m_assignmentState == AssignmentOnGoing);
+ m_fallbackNodes.append(&node);
+}
+
void HTMLSlotElement::appendDistributedNodesFrom(const HTMLSlotElement& other)
{
ASSERT(m_distributionState == DistributionOnGoing);
@@ -107,19 +117,27 @@ void HTMLSlotElement::appendDistributedNodesFrom(const HTMLSlotElement& other)
m_distributedIndices.set(node.get(), index++);
}
+void HTMLSlotElement::willUpdateAssignment()
+{
+ ASSERT(m_assignmentState != AssignmentOnGoing);
+ m_assignmentState = AssignmentOnGoing;
+ m_oldAssignedNodes.swap(m_assignedNodes);
+ m_assignedNodes.clear();
+}
+
void HTMLSlotElement::willUpdateDistribution()
{
ASSERT(m_distributionState != DistributionOnGoing);
m_distributionState = DistributionOnGoing;
- m_assignedNodes.clear();
m_oldDistributedNodes.swap(m_distributedNodes);
m_distributedNodes.clear();
m_distributedIndices.clear();
}
-bool HTMLSlotElement::hasSlotChangeEventListener()
+void HTMLSlotElement::willUpdateFallback()
{
- return eventTargetData() && eventTargetData()->eventListenerMap.find(EventTypeNames::slotchange);
+ m_oldFallbackNodes.swap(m_fallbackNodes);
+ m_fallbackNodes.clear();
}
void HTMLSlotElement::dispatchSlotChangeEvent()
@@ -127,6 +145,7 @@ void HTMLSlotElement::dispatchSlotChangeEvent()
Event* event = Event::create(EventTypeNames::slotchange);
event->setTarget(this);
dispatchScopedEvent(event);
+ m_slotchangeEventAdded = false;
}
Node* HTMLSlotElement::distributedNodeNextTo(const Node& node) const
@@ -177,8 +196,11 @@ void HTMLSlotElement::detach(const AttachContext& context)
void HTMLSlotElement::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason reason)
{
if (name == nameAttr) {
- if (ShadowRoot* root = containingShadowRoot())
+ if (ShadowRoot* root = containingShadowRoot()) {
root->owner()->willAffectSelector();
+ if (root->isV1() && oldValue != newValue)
+ root->assignV1();
+ }
}
HTMLElement::attributeChanged(name, oldValue, newValue, reason);
}
@@ -187,15 +209,19 @@ void HTMLSlotElement::childrenChanged(const ChildrenChange& change)
{
HTMLElement::childrenChanged(change);
if (ShadowRoot* root = containingShadowRoot()) {
- if (ElementShadow* rootOwner = root->owner())
+ if (ElementShadow* rootOwner = root->owner()) {
rootOwner->setNeedsDistributionRecalc();
+ }
+ if (m_assignedNodes.isEmpty() && root->isV1())
+ root->assignV1();
}
}
Node::InsertionNotificationRequest HTMLSlotElement::insertedInto(ContainerNode* insertionPoint)
{
HTMLElement::insertedInto(insertionPoint);
- if (ShadowRoot* root = containingShadowRoot()) {
+ ShadowRoot* root = containingShadowRoot();
+ if (root) {
if (ElementShadow* rootOwner = root->owner())
rootOwner->setNeedsDistributionRecalc();
if (root == insertionPoint->treeScope().rootNode())
@@ -206,6 +232,9 @@ Node::InsertionNotificationRequest HTMLSlotElement::insertedInto(ContainerNode*
// clear the distribution when inserted again to avoid cycles.
clearDistribution();
+ if (root && root->isV1())
+ root->assignV1();
+
return InsertionDone;
}
@@ -222,9 +251,14 @@ void HTMLSlotElement::removedFrom(ContainerNode* insertionPoint)
// Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up.
clearDistribution();
- if (root == insertionPoint->treeScope().rootNode())
+ ContainerNode& rootNode = insertionPoint->treeScope().rootNode();
+ if (root == &rootNode)
root->didRemoveSlot();
+ else if (rootNode.isShadowRoot() && toShadowRoot(rootNode).isV1())
+ toShadowRoot(rootNode).assignV1();
+ if (root && root->isV1())
+ root->assignV1();
HTMLElement::removedFrom(insertionPoint);
}
@@ -237,9 +271,9 @@ void HTMLSlotElement::willRecalcStyle(StyleRecalcChange change)
node->setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::PropagateInheritChangeToDistributedNodes));
}
-void HTMLSlotElement::updateDistributedNodesWithFallback()
+void HTMLSlotElement::updateFallbackNodes()
{
- if (!m_distributedNodes.isEmpty())
+ if (!m_fallbackNodes.isEmpty())
return;
for (auto& child : NodeTraversal::childrenOf(*this)) {
if (!child.isSlotAssignable())
@@ -247,13 +281,30 @@ void HTMLSlotElement::updateDistributedNodesWithFallback()
// Insertion points are not supported as slots fallback
if (isActiveInsertionPoint(child))
continue;
- if (isHTMLSlotElement(child))
- appendDistributedNodesFrom(toHTMLSlotElement(child));
+ appendFallbackNode(child);
+ }
+}
+
+void HTMLSlotElement::updateDistributedNodesWithFallback()
+{
+ if (!m_distributedNodes.isEmpty())
+ return;
+ for (auto node : m_fallbackNodes) {
+ if (isHTMLSlotElement(node))
+ appendDistributedNodesFrom(*toHTMLSlotElement(node));
else
- appendDistributedNode(child);
+ appendDistributedNode(*node);
}
}
+bool HTMLSlotElement::assignmentChanged()
+{
+ ASSERT(m_assignmentState != AssignmentOnGoing);
+ if (m_assignmentState == AssignmentDone)
+ m_assignmentState = m_oldAssignedNodes == m_assignedNodes ? AssignmentUnchanged : AssignmentChanged;
+ return m_assignmentState == AssignmentChanged;
+}
+
bool HTMLSlotElement::distributionChanged()
{
ASSERT(m_distributionState != DistributionOnGoing);
@@ -262,6 +313,19 @@ bool HTMLSlotElement::distributionChanged()
return m_distributionState == DistributionChanged;
}
+bool HTMLSlotElement::fallbackChanged()
+{
+ return m_oldFallbackNodes == m_fallbackNodes;
+}
+
+void HTMLSlotElement::didUpdateAssignment()
+{
+ ASSERT(m_assignmentState == AssignmentOnGoing);
+ m_assignmentState = AssignmentDone;
+ if ((assignmentChanged() || fallbackChanged()) && !m_slotchangeEventAdded)
+ fireSlotChangeEvent();
+}
+
void HTMLSlotElement::didUpdateDistribution()
{
ASSERT(m_distributionState == DistributionOnGoing);
@@ -272,9 +336,21 @@ void HTMLSlotElement::didUpdateDistribution()
if (!shadow->needsDistributionRecalc() && distributionChanged())
shadow->setNeedsDistributionRecalc();
}
- if (hasSlotChangeEventListener() && distributionChanged()) {
- // TODO(hayato): Do not enqueue a slotchange event for the same slot twice in the microtask queue
- Microtask::enqueueMicrotask(WTF::bind(&HTMLSlotElement::dispatchSlotChangeEvent, this));
+}
+
+void HTMLSlotElement::fireSlotChangeEvent()
+{
+ ASSERT(!m_slotchangeEventAdded);
+ Microtask::enqueueMicrotask(WTF::bind(&HTMLSlotElement::dispatchSlotChangeEvent, this));
+ m_slotchangeEventAdded = true;
+
+ Element* shadowHost = isShadowHost(parentElement()) ? parentElement() : nullptr;
+ // If this slot is assigned to another slot, fire slot change event of that slot too.
+ if (shadowHost && shadowHost->shadowRootIfV1()) {
+ if (HTMLSlotElement* assigned = assignedSlot()) {
+ if (!assigned->m_slotchangeEventAdded)
+ assigned->fireSlotChangeEvent();
+ }
}
}
@@ -293,8 +369,11 @@ DEFINE_TRACE(HTMLSlotElement)
{
visitor->trace(m_assignedNodes);
visitor->trace(m_distributedNodes);
+ visitor->trace(m_fallbackNodes);
visitor->trace(m_distributedIndices);
+ visitor->trace(m_oldAssignedNodes);
visitor->trace(m_oldDistributedNodes);
+ visitor->trace(m_oldFallbackNodes);
HTMLElement::trace(visitor);
}
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLSlotElement.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698