summaryrefslogtreecommitdiffstats
path: root/dom/base/Element.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/Element.cpp')
-rw-r--r--dom/base/Element.cpp135
1 files changed, 89 insertions, 46 deletions
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<nsIScreen> 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<nsIScreenManager> 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<DOMRect> Element::GetBoundingClientRect() {
@@ -1722,8 +1713,7 @@ already_AddRefed<nsIHTMLCollection> 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<Element> 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<Element> attrEl = do_QueryReferent(weakAttrEl)) {
+ return attrEl;
+ }
+ }
+ return nullptr;
}
void Element::GetElementsWithGrid(nsTArray<RefPtr<Element>>& 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<nsINode> 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