From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- dom/base/Element.cpp | 135 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 46 deletions(-) (limited to 'dom/base/Element.cpp') diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index f653363f48..be31000278 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -54,7 +54,6 @@ #include "mozilla/PresShellForwards.h" #include "mozilla/ReflowOutput.h" #include "mozilla/RelativeTo.h" -#include "mozilla/ScrollOrigin.h" #include "mozilla/ScrollTypes.h" #include "mozilla/ServoStyleConsts.h" #include "mozilla/ServoStyleConstsInlines.h" @@ -106,6 +105,7 @@ #include "mozilla/dom/ScriptLoader.h" #include "mozilla/dom/ShadowRoot.h" #include "mozilla/dom/Text.h" +#include "mozilla/dom/UnbindContext.h" #include "mozilla/dom/WindowBinding.h" #include "mozilla/dom/XULCommandEvent.h" #include "mozilla/dom/nsCSPContext.h" @@ -113,6 +113,7 @@ #include "mozilla/gfx/BaseRect.h" #include "mozilla/gfx/BaseSize.h" #include "mozilla/gfx/Matrix.h" +#include "mozilla/widget/Screen.h" #include "nsAtom.h" #include "nsAttrName.h" #include "nsAttrValueInlines.h" @@ -161,7 +162,6 @@ #include "nsIInterfaceRequestor.h" #include "nsIMemoryReporter.h" #include "nsIPrincipal.h" -#include "nsIScreenManager.h" #include "nsIScriptError.h" #include "nsIScrollableFrame.h" #include "nsISpeculativeConnect.h" @@ -780,8 +780,6 @@ void Element::ScrollIntoView(const ScrollIntoViewOptions& aOptions) { return WhereToScroll::Center; case ScrollLogicalPosition::End: return WhereToScroll::End; - case ScrollLogicalPosition::EndGuard_: - MOZ_FALLTHROUGH_ASSERT("Unexpected block direction value"); case ScrollLogicalPosition::Nearest: break; } @@ -1048,20 +1046,13 @@ int32_t Element::ScreenY() { } already_AddRefed Element::GetScreen() { - nsIFrame* frame = GetPrimaryFrame(FlushType::Layout); - if (!frame) { - return nullptr; + // Flush layout to guarantee that frames are created if needed, and preserve + // behavior. + Unused << GetPrimaryFrame(FlushType::Frames); + if (nsIWidget* widget = nsContentUtils::WidgetForContent(this)) { + return widget->GetWidgetScreen(); } - nsCOMPtr screenMgr = - do_GetService("@mozilla.org/gfx/screenmanager;1"); - if (!screenMgr) { - return nullptr; - } - nsPresContext* pc = frame->PresContext(); - const CSSIntRect rect = frame->GetScreenRect(); - DesktopRect desktopRect = rect * pc->CSSToDevPixelScale() / - pc->DeviceContext()->GetDesktopToDeviceScale(); - return screenMgr->ScreenForRect(DesktopIntRect::Round(desktopRect)); + return nullptr; } already_AddRefed Element::GetBoundingClientRect() { @@ -1722,8 +1713,7 @@ already_AddRefed Element::GetElementsByClassName( } Element* Element::GetAttrAssociatedElement(nsAtom* aAttr) const { - const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots(); - if (slots) { + if (const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) { nsWeakPtr weakAttrEl = slots->mExplicitlySetAttrElements.Get(aAttr); if (nsCOMPtr attrEl = do_QueryReferent(weakAttrEl)) { // If reflectedTarget's explicitly set attr-element |attrEl| is @@ -1774,16 +1764,56 @@ void Element::ClearExplicitlySetAttrElement(nsAtom* aAttr) { } void Element::ExplicitlySetAttrElement(nsAtom* aAttr, Element* aElement) { +#ifdef ACCESSIBILITY + nsAccessibilityService* accService = GetAccService(); +#endif + // Accessibility requires that no other attribute changes occur between + // AttrElementWillChange and AttrElementChanged. Scripts could cause + // this, so don't let them run here. We do this even if accessibility isn't + // running so that the JS behavior is consistent regardless of accessibility. + // Otherwise, JS might be able to use this difference to determine whether + // accessibility is running, which would be a privacy concern. + nsAutoScriptBlocker scriptBlocker; if (aElement) { +#ifdef ACCESSIBILITY + if (accService) { + accService->NotifyAttrElementWillChange(this, aAttr); + } +#endif SetAttr(aAttr, EmptyString(), IgnoreErrors()); nsExtendedDOMSlots* slots = ExtendedDOMSlots(); slots->mExplicitlySetAttrElements.InsertOrUpdate( aAttr, do_GetWeakReference(aElement)); +#ifdef ACCESSIBILITY + if (accService) { + accService->NotifyAttrElementChanged(this, aAttr); + } +#endif return; } +#ifdef ACCESSIBILITY + if (accService) { + accService->NotifyAttrElementWillChange(this, aAttr); + } +#endif ClearExplicitlySetAttrElement(aAttr); UnsetAttr(aAttr, IgnoreErrors()); +#ifdef ACCESSIBILITY + if (accService) { + accService->NotifyAttrElementChanged(this, aAttr); + } +#endif +} + +Element* Element::GetExplicitlySetAttrElement(nsAtom* aAttr) const { + if (const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) { + nsWeakPtr weakAttrEl = slots->mExplicitlySetAttrElements.Get(aAttr); + if (nsCOMPtr attrEl = do_QueryReferent(weakAttrEl)) { + return attrEl; + } + } + return nullptr; } void Element::GetElementsWithGrid(nsTArray>& aElements) { @@ -1958,7 +1988,8 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) { return NS_OK; } -bool WillDetachFromShadowOnUnbind(const Element& aElement, bool aNullParent) { +static bool WillDetachFromShadowOnUnbind(const Element& aElement, + bool aNullParent) { // If our parent still is in a shadow tree by now, and we're not removing // ourselves from it, then we're still going to be in a shadow tree after // this. @@ -1966,12 +1997,14 @@ bool WillDetachFromShadowOnUnbind(const Element& aElement, bool aNullParent) { (aNullParent || !aElement.GetParent()->IsInShadowTree()); } -void Element::UnbindFromTree(bool aNullParent) { - HandleShadowDOMRelatedRemovalSteps(aNullParent); +void Element::UnbindFromTree(UnbindContext& aContext) { + const bool nullParent = aContext.IsUnbindRoot(this); + + HandleShadowDOMRelatedRemovalSteps(nullParent); if (HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) && !IsHTMLElement(nsGkAtoms::datalist)) { - if (aNullParent) { + if (nullParent) { UnsetFlags(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR); } else { nsIContent* parent = GetParent(); @@ -1983,7 +2016,7 @@ void Element::UnbindFromTree(bool aNullParent) { } const bool detachingFromShadow = - WillDetachFromShadowOnUnbind(*this, aNullParent); + WillDetachFromShadowOnUnbind(*this, nullParent); // Make sure to only remove from the ID table if our subtree root is actually // changing. if (IsInUncomposedDoc() || detachingFromShadow) { @@ -2033,7 +2066,7 @@ void Element::UnbindFromTree(bool aNullParent) { data->ClearAllAnimationCollections(); } - if (aNullParent) { + if (nullParent) { if (GetParent()) { RefPtr p; p.swap(mParent); @@ -2071,15 +2104,13 @@ void Element::UnbindFromTree(bool aNullParent) { ClearElementCreatedFromPrototypeAndHasUnmodifiedL10n(); } - if (aNullParent || !mParent->IsInShadowTree()) { + if (nullParent || !mParent->IsInShadowTree()) { UnsetFlags(NODE_IS_IN_SHADOW_TREE); // Begin keeping track of our subtree root. - SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot()); - } + SetSubtreeRootPointer(nullParent ? this : mParent->SubtreeRoot()); - if (nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) { - if (aNullParent || !mParent->IsInShadowTree()) { + if (nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) { slots->mContainingShadow = nullptr; } } @@ -2103,11 +2134,10 @@ void Element::UnbindFromTree(bool aNullParent) { } if (HasLastRememberedBSize() || HasLastRememberedISize()) { - // Need to remove the last remembered size at the next ResizeObserver - // opportunity, so observe the element. But if already observed, we still - // want the callback to be invoked even if the size was already 0x0, so - // unobserve it first. - document->UnobserveForLastRememberedSize(*this); + // Make sure the element is observed so that remembered sizes are kept + // until the next time "ResizeObserver events are determined and + // delivered". See "Disconnected element" tests from + // css/css-sizing/contain-intrinsic-size/auto-006.html document->ObserveForLastRememberedSize(*this); } } @@ -2121,9 +2151,7 @@ void Element::UnbindFromTree(bool aNullParent) { for (nsIContent* child = GetFirstChild(); child; child = child->GetNextSibling()) { - // Note that we pass false for aNullParent here, since we don't want - // the kids to forget us. - child->UnbindFromTree(false); + child->UnbindFromTree(aContext); } MutationObservers::NotifyParentChainChanged(this); @@ -2751,6 +2779,12 @@ bool Element::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, return true; } + if (aAttribute == nsGkAtoms::aria_activedescendant) { + // String in aria-activedescendant is an id, so store as an atom. + aResult.ParseAtom(aValue); + return true; + } + if (aAttribute == nsGkAtoms::id) { // Store id as an atom. id="" means that the element has no id, // not that it has an emptystring as the id. @@ -2805,6 +2839,8 @@ void Element::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName, if (ShadowRoot* shadow = GetParent()->GetShadowRoot()) { shadow->MaybeReassignContent(*this); } + } else if (aName == nsGkAtoms::aria_activedescendant) { + ClearExplicitlySetAttrElement(aName); } } } @@ -2856,6 +2892,11 @@ void Element::OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName, ElementCallbackType::eAttributeChanged, this, args, definition); } } + + if (aNamespaceID == kNameSpaceID_None && + aName == nsGkAtoms::aria_activedescendant) { + ClearExplicitlySetAttrElement(aName); + } } EventListenerManager* Element::GetEventListenerManagerForAttr(nsAtom* aAttrName, @@ -3397,14 +3438,6 @@ nsresult Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor) { void Element::GetLinkTarget(nsAString& aTarget) { aTarget.Truncate(); } -static nsStaticAtom* const sPropertiesToTraverseAndUnlink[] = { - nsGkAtoms::dirAutoSetBy, nullptr}; - -// static -nsStaticAtom* const* Element::HTMLSVGPropertiesToTraverseAndUnlink() { - return sPropertiesToTraverseAndUnlink; -} - nsresult Element::CopyInnerTo(Element* aDst, ReparseAttributes aReparse) { nsresult rv = aDst->mAttrs.EnsureCapacityToClone(mAttrs); NS_ENSURE_SUCCESS(rv, rv); @@ -5048,4 +5081,14 @@ void Element::SetHTMLUnsafe(const nsAString& aHTML) { nsContentUtils::SetHTMLUnsafe(this, this, aHTML); } +bool Element::BlockingContainsRender() const { + const nsAttrValue* attrValue = GetParsedAttr(nsGkAtoms::blocking); + if (!attrValue || !StaticPrefs::dom_element_blocking_enabled()) { + return false; + } + MOZ_ASSERT(attrValue->Type() == nsAttrValue::eAtomArray, + "Checking blocking attribute on element that doesn't parse it?"); + return attrValue->Contains(nsGkAtoms::render, eIgnoreCase); +} + } // namespace mozilla::dom -- cgit v1.2.3