Bug 1874040 - Simplify dir=auto implementation. r=smaug

Make sure to do no work on insertions if the dir=auto element has
already the right strong directionality, but record that the node might
be the one impacting the dir=auto resolution.

Also get some node flags back.

Differential Revision: https://phabricator.services.mozilla.com/D202071
This commit is contained in:
Emilio Cobos Álvarez 2024-02-21 12:23:48 +00:00
parent b1eb6f63e8
commit a29d2e78b4
11 changed files with 208 additions and 634 deletions

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ class nsTextNode;
namespace mozilla::dom {
class Element;
class HTMLSlotElement;
struct UnbindContext;
} // namespace mozilla::dom
namespace mozilla {
@ -133,10 +134,8 @@ void SetDirectionFromNewTextNode(nsTextNode* aTextNode);
/**
* When a text node is removed from a document, find any ancestors whose
* directionality it determined and redetermine their directionality
*
* @param aTextNode the text node
*/
void ResetDirectionSetByTextNode(nsTextNode* aTextNode);
void ResetDirectionSetByTextNode(nsTextNode*, dom::UnbindContext&);
/**
* Set the directionality of an element according to the directionality of the

View File

@ -3436,14 +3436,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);

View File

@ -1111,8 +1111,6 @@ class Element : public FragmentOrElement {
return FindAttributeDependence(aAttribute, aMaps, N);
}
static nsStaticAtom* const* HTMLSVGPropertiesToTraverseAndUnlink();
MOZ_CAN_RUN_SCRIPT virtual void HandleInvokeInternal(nsAtom* aAction,
ErrorResult& aRv) {}

View File

@ -1327,14 +1327,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
Element* elem = tmp->AsElement();
elem->UnlinkIntersectionObservers();
}
if (tmp->IsHTMLElement() || tmp->IsSVGElement()) {
nsStaticAtom* const* props =
Element::HTMLSVGPropertiesToTraverseAndUnlink();
for (uint32_t i = 0; props[i]; ++i) {
tmp->RemoveProperty(props[i]);
}
}
}
// Unlink child content (and unbind our subtree).
@ -1805,15 +1797,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
}
}
}
if (tmp->IsHTMLElement() || tmp->IsSVGElement()) {
nsStaticAtom* const* props =
Element::HTMLSVGPropertiesToTraverseAndUnlink();
for (uint32_t i = 0; props[i]; ++i) {
nsISupports* property =
static_cast<nsISupports*>(tmp->GetProperty(props[i]));
cb.NoteXPCOMChild(property);
}
}
}
if (tmp->IsElement()) {
Element* element = tmp->AsElement();

View File

@ -19,11 +19,15 @@ struct MOZ_STACK_CLASS UnbindContext final {
nsINode& Root() const { return mRoot; }
// Whether we're the root of the subtree being unbound.
bool IsUnbindRoot(const nsINode* aNode) const { return &mRoot == aNode; }
// The parent node of the subtree we're unbinding from.
nsINode* GetOriginalSubtreeParent() const { return mOriginalParent; }
explicit UnbindContext(nsINode& aRoot) : mRoot(aRoot) {}
explicit UnbindContext(nsINode& aRoot)
: mRoot(aRoot), mOriginalParent(aRoot.GetParentNode()) {}
private:
nsINode& mRoot;
nsINode* const mOriginalParent;
};
} // namespace mozilla::dom

View File

@ -1895,13 +1895,9 @@ class nsINode : public mozilla::dom::EventTarget {
// flags, because we can't use those to distinguish
// <bdi dir="some-invalid-value"> and <bdi dir="auto">.
NodeHasValidDirAttribute,
// Set if the node has dir=auto and has a property pointing to the text
// node that determines its direction
NodeHasDirAutoSet,
// Set if the node is a text node descendant of a node with dir=auto
// and has a TextNodeDirectionalityMap property listing the elements whose
// direction it determines.
NodeHasTextNodeDirectionalityMap,
// Set if this node, which must be a text node, might be responsible for
// setting the directionality of a dir="auto" ancestor.
NodeMaySetDirAuto,
// Set if a node in the node's parent chain has dir=auto.
NodeAncestorHasDirAuto,
// Set if the node is handling a click.
@ -2028,31 +2024,19 @@ class nsINode : public mozilla::dom::EventTarget {
void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
void SetHasDirAutoSet() {
MOZ_ASSERT(NodeType() != TEXT_NODE, "SetHasDirAutoSet on text node");
SetBoolFlag(NodeHasDirAutoSet);
void SetMaySetDirAuto() {
// FIXME(bug 1881225): dir=auto should probably work on CDATA too.
MOZ_ASSERT(NodeType() == TEXT_NODE);
SetBoolFlag(NodeMaySetDirAuto);
}
void ClearHasDirAutoSet() {
MOZ_ASSERT(NodeType() != TEXT_NODE, "ClearHasDirAutoSet on text node");
ClearBoolFlag(NodeHasDirAutoSet);
bool MaySetDirAuto() const {
MOZ_ASSERT(NodeType() == TEXT_NODE);
return GetBoolFlag(NodeMaySetDirAuto);
}
bool HasDirAutoSet() const { return GetBoolFlag(NodeHasDirAutoSet); }
void SetHasTextNodeDirectionalityMap() {
MOZ_ASSERT(NodeType() == TEXT_NODE,
"SetHasTextNodeDirectionalityMap on non-text node");
SetBoolFlag(NodeHasTextNodeDirectionalityMap);
void ClearMaySetDirAuto() {
MOZ_ASSERT(NodeType() == TEXT_NODE);
ClearBoolFlag(NodeMaySetDirAuto);
}
void ClearHasTextNodeDirectionalityMap() {
MOZ_ASSERT(NodeType() == TEXT_NODE,
"ClearHasTextNodeDirectionalityMap on non-text node");
ClearBoolFlag(NodeHasTextNodeDirectionalityMap);
}
bool HasTextNodeDirectionalityMap() const {
MOZ_ASSERT(NodeType() == TEXT_NODE,
"HasTextNodeDirectionalityMap on non-text node");
return GetBoolFlag(NodeHasTextNodeDirectionalityMap);
}
void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); }
void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); }
bool AncestorHasDirAuto() const {

View File

@ -43,13 +43,13 @@ class nsAttributeTextNode final : public nsTextNode,
NS_ASSERTION(mAttrName, "Must have attr name");
}
virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
virtual void UnbindFromTree(UnbindContext&) override;
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(UnbindContext&) override;
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
virtual already_AddRefed<CharacterData> CloneDataNode(
already_AddRefed<CharacterData> CloneDataNode(
mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const override {
RefPtr<nsAttributeTextNode> it =
new (aNodeInfo->NodeInfoManager()) nsAttributeTextNode(
@ -124,8 +124,8 @@ nsresult nsTextNode::BindToTree(BindContext& aContext, nsINode& aParent) {
}
void nsTextNode::UnbindFromTree(UnbindContext& aContext) {
ResetDirectionSetByTextNode(this);
CharacterData::UnbindFromTree(aContext);
ResetDirectionSetByTextNode(this, aContext);
}
#ifdef MOZ_DOM_LIST

View File

@ -8,9 +8,6 @@
[Non-HTML element text contents influence dir=auto]
expected: FAIL
[text changes apply to dir=auto on further ancestor after removing dir=auto from closer ancestor]
expected: FAIL
[directionality of bdi elements: dir=auto empty in rtl parent]
expected: FAIL

View File

@ -1,16 +1,10 @@
[dir-auto-dynamic-changes.window.html]
[dir=auto changes for content insertion and removal, in and out of document]
expected: FAIL
[dir=auto changes for slot reassignment]
expected: FAIL
[text changes affecting both slot and ancestor with dir=auto]
expected: FAIL
[dynamic changes to subtrees excluded as a result of the dir attribute]
expected: FAIL
[dynamic changes inside of non-HTML elements]
expected: FAIL

View File

@ -342,7 +342,6 @@ STATIC_ATOMS = [
Atom("difference", "difference"),
Atom("digit", "digit"),
Atom("dir", "dir"),
Atom("dirAutoSetBy", "dirAutoSetBy"),
Atom("directory", "directory"),
Atom("dirname", "dirname"),
Atom("disableOutputEscaping", "disable-output-escaping"),
@ -1236,7 +1235,6 @@ STATIC_ATOMS = [
Atom("textarea", "textarea"),
Atom("textbox", "textbox"),
Atom("textLink", "text-link"),
Atom("textNodeDirectionalityMap", "textNodeDirectionalityMap"),
Atom("textOverlay", "text-overlay"),
Atom("tfoot", "tfoot"),
Atom("th", "th"),