From 5352b69a9286223272c0ed072900b4c78ba2ed7c Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Tue, 14 Apr 2020 21:24:51 -0400 Subject: Bug 1305458 - Changing -moz-appearence on hover breaks change event * Rename nsIDOMEventTarget::PreHandleEvent to nsIDOMEventTarget::GetEventTargetParent * Add nsIDOMEventTarget::PreHandleEvent * Add EventTargetChainItem::GetFirstEventTarget * Call EventTargetChainItem::PreHandleEvent even it sets mCanHandle=false * Move form control frame focus/blur from nsGenericHTMLFormElement::GetEventTargetParent to PreHandleEvent * Move fire change event from HTMLTextAreaElement::GetEventTargetParent to PreHandleEvent * Refine nsXULElement::GetEventTargetParent * Move dispatch XUL command from nsXULElement::GetEventTargetParent to PreHandleEvent * Move fire events and set value from HTMLInputElement::GetEventTargetParent to PreHandleEvent * Add test case * Let HTMLInputElement delegate event handling to it's parent class * Refine EventTargetChain flags to reduce overheads * Refine event target chain creation * Refine assertion in EventTargetChainItem::Create Tag #1375 --- dom/base/FragmentOrElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 526c3c9d4..ca00a49a5 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -718,7 +718,7 @@ FindChromeAccessOnlySubtreeOwner(nsIContent* aContent) } nsresult -nsIContent::PreHandleEvent(EventChainPreVisitor& aVisitor) +nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) { //FIXME! Document how this event retargeting works, Bug 329124. aVisitor.mCanHandle = true; -- cgit v1.2.3 From bebec8fcb84dba6b684dfe1cc6c8a1e7741df374 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Tue, 14 Apr 2020 21:50:13 -0400 Subject: Bug 1321284 - Crash in nsCSSFrameConstructor::GetInsertionPrevSibling when trying to reframe native anonymous content * Make StyleChildrenIterator skip NAC generated by root element primary frame ancestors. * Add nsINode::GetFlattenedTreeParentNodeForStyle. * Add iterator class to find all restyle roots. NOTE: Parts 1, 2, and "4.2" Tag #1375 --- dom/base/FragmentOrElement.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index ca00a49a5..d7e7a78f4 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -152,7 +152,7 @@ nsIContent::FindFirstNonChromeOnlyAccessContent() const } nsINode* -nsIContent::GetFlattenedTreeParentNodeInternal() const +nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const { nsINode* parentNode = GetParentNode(); if (!parentNode || !parentNode->IsContent()) { @@ -161,6 +161,45 @@ nsIContent::GetFlattenedTreeParentNodeInternal() const } nsIContent* parent = parentNode->AsContent(); + if (aType == eForStyle && + IsRootOfNativeAnonymousSubtree() && + OwnerDoc()->GetRootElement() == parent) { + // When getting the flattened tree parent for style, we return null + // for any "document level" native anonymous content subtree root. + // This is NAC generated by an ancestor frame of the document element's + // primary frame, and includes scrollbar elements created by the root + // scroll frame, and the "custom content container" and accessible caret + // generated by the nsCanvasFrame. We distinguish document level NAC + // from NAC generated by the root element's primary frame below. + nsIFrame* parentFrame = parent->GetPrimaryFrame(); + if (!parentFrame) { + // If the root element has no primary frame, it means it can't have + // generated any NAC itself. Thus any NAC we have here must have + // been generated by an ancestor frame. + // + // If we are in here, then either the root element is display:none, or + // we are in the middle of constructing the root of the frame tree and + // we are trying to eagerly restyle document level NAC in + // nsCSSFrameConstructor::GetAnonymousContent before the root + // element's frame has been constructed. + return nullptr; + } + nsIAnonymousContentCreator* creator = do_QueryFrame(parentFrame); + if (!creator) { + // If the root element does have a frame, but does not implement + // nsIAnonymousContentCreator, then this must be document level NAC. + return nullptr; + } + AutoTArray elements; + creator->AppendAnonymousContentTo(elements, 0); + if (!elements.Contains(this)) { + // If the root element does have a frame, and also does implement + // nsIAnonymousContentCreator, but didn't create this node, then + // it must be document level NAC. + return nullptr; + } + } + if (parent && nsContentUtils::HasDistributedChildren(parent) && nsContentUtils::IsInSameAnonymousTree(parent, this)) { // This node is distributed to insertion points, thus we -- cgit v1.2.3 From 5f12940329ba496da5730863cae94cd8c0b145da Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 06:34:38 -0400 Subject: Bug 1396584 - Remove support for multiple ShadowRoots Tag #1375 --- dom/base/FragmentOrElement.cpp | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index d7e7a78f4..592f5447d 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -861,23 +861,10 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) // for destination insertion points where nodes have been distributed. nsTArray* destPoints = GetExistingDestInsertionPoints(); if (destPoints && !destPoints->IsEmpty()) { - // Push destination insertion points to aVisitor.mDestInsertionPoints - // excluding shadow insertion points. - bool didPushNonShadowInsertionPoint = false; + // Push destination insertion points to aVisitor.mDestInsertionPoints. for (uint32_t i = 0; i < destPoints->Length(); i++) { nsIContent* point = destPoints->ElementAt(i); - if (!ShadowRoot::IsShadowInsertionPoint(point)) { - aVisitor.mDestInsertionPoints.AppendElement(point); - didPushNonShadowInsertionPoint = true; - } - } - - // Next node in the event path is the final destination - // (non-shadow) insertion point that was pushed. - if (didPushNonShadowInsertionPoint) { - parent = aVisitor.mDestInsertionPoints.LastElement(); - aVisitor.mDestInsertionPoints.SetLength( - aVisitor.mDestInsertionPoints.Length() - 1); + aVisitor.mDestInsertionPoints.AppendElement(point); } } @@ -901,10 +888,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) aVisitor.mDestInsertionPoints.SetLength( aVisitor.mDestInsertionPoints.Length() - 1); } else { - // The pool host for the youngest shadow root is shadow DOM host, - // for older shadow roots, it is the shadow insertion point - // where the shadow root is projected, nullptr if none exists. - parent = thisShadowRoot->GetPoolHost(); + parent = thisShadowRoot->GetHost(); } } @@ -2407,9 +2391,8 @@ FragmentOrElement::SetIsElementInStyleScopeFlagOnShadowTree(bool aInStyleScope) NS_ASSERTION(IsElement(), "calling SetIsElementInStyleScopeFlagOnShadowTree " "on a non-Element is useless"); ShadowRoot* shadowRoot = GetShadowRoot(); - while (shadowRoot) { + if (shadowRoot) { shadowRoot->SetIsElementInStyleScopeFlagOnSubtree(aInStyleScope); - shadowRoot = shadowRoot->GetOlderShadowRoot(); } } -- cgit v1.2.3 From 3758434680616e91edf696e546fe3cc3b1d4da9c Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 06:38:37 -0400 Subject: Bug 1408341 - Implement assignedSlot on Element and Text Tag #1375 --- dom/base/FragmentOrElement.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 592f5447d..486bbc88c 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -123,6 +123,7 @@ #include "mozilla/CORSMode.h" #include "mozilla/dom/ShadowRoot.h" +#include "mozilla/dom/HTMLSlotElement.h" #include "mozilla/dom/HTMLTemplateElement.h" #include "nsStyledElement.h" @@ -614,6 +615,9 @@ FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb) NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mContainingShadow"); cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mContainingShadow)); + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mAssignedSlot"); + cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mAssignedSlot.get())); + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLBinding"); cb.NoteNativeChild(mExtendedSlots->mXBLBinding, NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding)); @@ -657,6 +661,7 @@ FragmentOrElement::nsDOMSlots::Unlink() mExtendedSlots->mLabelsList = nullptr; mExtendedSlots->mShadowRoot = nullptr; mExtendedSlots->mContainingShadow = nullptr; + mExtendedSlots->mAssignedSlot = nullptr; MOZ_ASSERT(!(mExtendedSlots->mXBLBinding)); mExtendedSlots->mXBLInsertionParent = nullptr; if (mExtendedSlots->mCustomElementData) { @@ -1126,6 +1131,20 @@ FragmentOrElement::GetExistingDestInsertionPoints() const return nullptr; } +HTMLSlotElement* +FragmentOrElement::GetAssignedSlot() const +{ + nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); + return slots ? slots->mAssignedSlot.get() : nullptr; +} + +void +FragmentOrElement::SetAssignedSlot(HTMLSlotElement* aSlot) +{ + nsExtendedDOMSlots* slots = ExtendedDOMSlots(); + slots->mAssignedSlot = aSlot; +} + void FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent) { -- cgit v1.2.3 From 3a74795a56e92313c1b33a54500917794ba09b72 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 07:05:27 -0400 Subject: Bug 1411878 - Support Element.shadowRoot and Element.assignedSlot / TextNode.assignedSlot on closed shadow root Tag #1375 --- dom/base/FragmentOrElement.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 486bbc88c..766e2b115 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -152,6 +152,36 @@ nsIContent::FindFirstNonChromeOnlyAccessContent() const return nullptr; } +// https://dom.spec.whatwg.org/#dom-slotable-assignedslot +HTMLSlotElement* +nsIContent::GetAssignedSlotByMode() const +{ + /** + * Get slotable's assigned slot for the result of + * find a slot with open flag UNSET [1]. + * + * [1] https://dom.spec.whatwg.org/#assign-a-slot + */ + HTMLSlotElement* slot = GetAssignedSlot(); + if (!slot) { + return nullptr; + } + + MOZ_ASSERT(GetParent()); + MOZ_ASSERT(GetParent()->GetShadowRoot()); + + /** + * Additional check for open flag SET: + * If slotable’s parent’s shadow root's mode is not "open", + * then return null. + */ + if (GetParent()->GetShadowRoot()->IsClosed()) { + return nullptr; + } + + return slot; +} + nsINode* nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const { -- cgit v1.2.3 From e31ed5b07466d4a579fe4b025f97c971003fbc3f Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 07:10:54 -0400 Subject: Bug 1409975 - Implement node distribution for shadow tree slots * Implementation for assignedNodes * Include slots in the flat tree * Fix event get-the-parent algorithm for a node * Update and add reftests for Shadow DOM v1 * Update web platform tests expectations Tag #1375 --- dom/base/FragmentOrElement.cpp | 72 +++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 46 deletions(-) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 766e2b115..ecb18798f 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -182,6 +182,24 @@ nsIContent::GetAssignedSlotByMode() const return slot; } +nsINode* +nsIContent::GetFlattenedTreeParentForMaybeAssignedNode() const +{ + if (HTMLSlotElement* assignedSlot = GetAssignedSlot()) { + return assignedSlot; + } + + HTMLSlotElement* parentSlot = HTMLSlotElement::FromContent(GetParent()); + if (!parentSlot) { + return nullptr; + } + + // If this is not an unassigned node, then it must be a fallback content. + MOZ_ASSERT(parentSlot->AssignedNodes().IsEmpty()); + + return parentSlot; +} + nsINode* nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const { @@ -233,16 +251,10 @@ nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const if (parent && nsContentUtils::HasDistributedChildren(parent) && nsContentUtils::IsInSameAnonymousTree(parent, this)) { - // This node is distributed to insertion points, thus we - // need to consult the destination insertion points list to - // figure out where this node was inserted in the flattened tree. - // It may be the case that |parent| distributes its children - // but the child does not match any insertion points, thus - // the flattened tree parent is nullptr. - nsTArray* destInsertionPoints = GetExistingDestInsertionPoints(); - parent = destInsertionPoints && !destInsertionPoints->IsEmpty() ? - destInsertionPoints->LastElement()->GetParent() : nullptr; - } else if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) { + return GetFlattenedTreeParentForMaybeAssignedNode(); + } + + if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) { nsIContent* insertionParent = GetXBLInsertionParent(); if (insertionParent) { parent = insertionParent; @@ -890,42 +902,10 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) } } - nsIContent* parent = GetParent(); - - // Web components have a special event chain that need to account - // for destination insertion points where nodes have been distributed. - nsTArray* destPoints = GetExistingDestInsertionPoints(); - if (destPoints && !destPoints->IsEmpty()) { - // Push destination insertion points to aVisitor.mDestInsertionPoints. - for (uint32_t i = 0; i < destPoints->Length(); i++) { - nsIContent* point = destPoints->ElementAt(i); - aVisitor.mDestInsertionPoints.AppendElement(point); - } - } - - ShadowRoot* thisShadowRoot = ShadowRoot::FromNode(this); - if (thisShadowRoot) { - if (!aVisitor.mEvent->mFlags.mComposed) { - // If we do stop propagation, we still want to propagate - // the event to chrome (nsPIDOMWindow::GetParentTarget()). - // The load event is special in that we don't ever propagate it - // to chrome. - nsCOMPtr win = OwnerDoc()->GetWindow(); - EventTarget* parentTarget = win && aVisitor.mEvent->mMessage != eLoad - ? win->GetParentTarget() : nullptr; - - aVisitor.mParentTarget = parentTarget; - return NS_OK; - } - - if (!aVisitor.mDestInsertionPoints.IsEmpty()) { - parent = aVisitor.mDestInsertionPoints.LastElement(); - aVisitor.mDestInsertionPoints.SetLength( - aVisitor.mDestInsertionPoints.Length() - 1); - } else { - parent = thisShadowRoot->GetHost(); - } - } + // Event parent is the assigned slot, if node is assigned, or node's parent + // otherwise. + HTMLSlotElement* slot = GetAssignedSlot(); + nsIContent* parent = slot ? slot : GetParent(); // Event may need to be retargeted if this is the root of a native // anonymous content subtree or event is dispatched somewhere inside XBL. -- cgit v1.2.3 From 7e506bd98dab604062bfe12a44c096eb287721bf Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 07:30:43 -0400 Subject: Bug 1412775 - Implement Event.composedPath Tag #1375 --- dom/base/FragmentOrElement.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index ecb18798f..5b2fabd8d 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -813,6 +813,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) // Don't propagate mouseover and mouseout events when mouse is moving // inside chrome access only content. bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree(); + aVisitor.mRootOfClosedTree = isAnonForEvents; if ((aVisitor.mEvent->mMessage == eMouseOver || aVisitor.mEvent->mMessage == eMouseOut || aVisitor.mEvent->mMessage == ePointerOver || @@ -834,7 +835,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) nsIContent* adjustedTarget = Event::GetShadowRelatedTarget(this, relatedTarget); if (this == adjustedTarget) { - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); aVisitor.mCanHandle = false; return NS_OK; } @@ -891,7 +892,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) originalTarget->FindFirstNonChromeOnlyAccessContent()) ? "" : "Wrong event propagation!?!\n"); #endif - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); // Event should not propagate to non-anon content. aVisitor.mCanHandle = isAnonForEvents; return NS_OK; @@ -943,11 +944,17 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) if (!aVisitor.mEvent->mFlags.mComposedInNativeAnonymousContent && IsRootOfNativeAnonymousSubtree() && OwnerDoc() && OwnerDoc()->GetWindow()) { - aVisitor.mParentTarget = OwnerDoc()->GetWindow()->GetParentTarget(); + aVisitor.SetParentTarget(OwnerDoc()->GetWindow()->GetParentTarget(), true); } else if (parent) { - aVisitor.mParentTarget = parent; + aVisitor.SetParentTarget(parent, false); + if (slot) { + ShadowRoot* root = slot->GetContainingShadow(); + if (root && root->IsClosed()) { + aVisitor.mParentIsSlotInClosedTree = true; + } + } } else { - aVisitor.mParentTarget = GetComposedDoc(); + aVisitor.SetParentTarget(GetComposedDoc(), false); } return NS_OK; } -- cgit v1.2.3 From f164962a3dc53f4823dfff6c77e7972c72d4c61f Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 07:34:35 -0400 Subject: Bug 1425441 - Move relatedTarget to WidgetEvent Tag #1375 --- dom/base/FragmentOrElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 5b2fabd8d..676665c09 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -825,7 +825,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) ((this == aVisitor.mEvent->mOriginalTarget && !ChromeOnlyAccess()) || isAnonForEvents || GetShadowRoot())) { nsCOMPtr relatedTarget = - do_QueryInterface(aVisitor.mEvent->AsMouseEvent()->relatedTarget); + do_QueryInterface(aVisitor.mEvent->AsMouseEvent()->mRelatedTarget); if (relatedTarget && relatedTarget->OwnerDoc() == OwnerDoc()) { -- cgit v1.2.3 From 53df3a74f46fa6b5d3778f9635a1afb7522c345f Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 07:37:07 -0400 Subject: Bug 1426503 - Remove DestInsertionPoints stuff Tag #1375 --- dom/base/FragmentOrElement.cpp | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'dom/base/FragmentOrElement.cpp') diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 676665c09..6fbe04d25 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -1131,23 +1131,6 @@ FragmentOrElement::SetShadowRoot(ShadowRoot* aShadowRoot) slots->mShadowRoot = aShadowRoot; } -nsTArray& -FragmentOrElement::DestInsertionPoints() -{ - nsExtendedDOMSlots* slots = ExtendedDOMSlots(); - return slots->mDestInsertionPoints; -} - -nsTArray* -FragmentOrElement::GetExistingDestInsertionPoints() const -{ - nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); - if (slots) { - return &slots->mDestInsertionPoints; - } - return nullptr; -} - HTMLSlotElement* FragmentOrElement::GetAssignedSlot() const { -- cgit v1.2.3