Bug 1365092 - Moves side effects of HTMLAnchorElement's SetAttr, UnsetAttr, and ParseAttribute functions to the corresponding BeforeSetAttr and AfterSetAttr functions
This is necessary to facilitate the transition to cloning attributes instead of reparsing them.
MozReview-Commit-ID: 2SZcYqWGJF6
--- a/dom/html/HTMLAnchorElement.cpp
+++ b/dom/html/HTMLAnchorElement.cpp
@@ -9,16 +9,17 @@
#include "mozilla/dom/HTMLAnchorElementBinding.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventStates.h"
#include "mozilla/MemoryReporting.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsGkAtoms.h"
#include "nsHTMLDNSPrefetch.h"
+#include "nsAttrValueOrString.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsIURI.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Anchor)
namespace mozilla {
@@ -360,94 +361,75 @@ HTMLAnchorElement::GetHrefURI() const
if (uri) {
return uri.forget();
}
return GetHrefURIForAnchors();
}
nsresult
-HTMLAnchorElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- nsIAtom* aPrefix, const nsAString& aValue,
- bool aNotify)
+HTMLAnchorElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
+ const nsAttrValueOrString* aValue,
+ bool aNotify)
{
- bool reset = false;
- if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
- // If we do not have a cached URI, we have some value here so we must reset
- // our link state after calling the parent.
- if (!Link::HasCachedURI()) {
- reset = true;
- }
- // However, if we have a cached URI, we'll want to see if the value changed.
- else {
- nsAutoString val;
- GetHref(val);
- if (!val.Equals(aValue)) {
+ if (aNamespaceID == kNameSpaceID_None) {
+ if (aName == nsGkAtoms::href) {
+ bool reset = false;
+ if (!aValue) {
reset = true;
+ } else {
+ // If we do not have a cached URI, we have some value here so we must
+ // reset our link state after calling the parent.
+ if (!Link::HasCachedURI()) {
+ reset = true;
+ }
+ // However, if we have a cached URI, we'll want to see if the value
+ // changed.
+ else {
+ const nsAttrValue* oldValue =
+ mAttrsAndChildren.GetAttr(nsGkAtoms::href);
+ if (!aValue->EqualsAsStrings(*oldValue)) {
+ reset = true;
+ }
+ }
}
- }
- if (reset) {
- CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
- HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
+ if (reset) {
+ CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
+ HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
+ }
}
}
- nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
- aValue, aNotify);
-
- // The ordering of the parent class's SetAttr call and Link::ResetLinkState
- // is important here! The attribute is not set until SetAttr returns, and
- // we will need the updated attribute value because notifying the document
- // that content states have changed will call IntrinsicState, which will try
- // to get updated information about the visitedness from Link.
- if (reset) {
- Link::ResetLinkState(!!aNotify, true);
- if (IsInComposedDoc()) {
- TryDNSPrefetch();
- }
- }
-
- return rv;
+ return nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, aValue,
+ aNotify);
}
nsresult
-HTMLAnchorElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
- bool aNotify)
+HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
- bool href =
- (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID);
-
- if (href) {
- CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
- HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
+ if (aNamespaceID == kNameSpaceID_None) {
+ if (aName == nsGkAtoms::href) {
+ if (aValue) {
+ if (!Link::HasCachedURI() || !aOldValue ||
+ !aValue->Equals(*aOldValue)) {
+ Link::ResetLinkState(!!aNotify, true);
+ if (IsInComposedDoc()) {
+ TryDNSPrefetch();
+ }
+ }
+ } else {
+ Link::ResetLinkState(!!aNotify, false);
+ }
+ }
}
- nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
- aNotify);
-
- // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState
- // is important here! The attribute is not unset until UnsetAttr returns, and
- // we will need the updated attribute value because notifying the document
- // that content states have changed will call IntrinsicState, which will try
- // to get updated information about the visitedness from Link.
- if (href) {
- Link::ResetLinkState(!!aNotify, false);
- }
-
- return rv;
-}
-
-bool
-HTMLAnchorElement::ParseAttribute(int32_t aNamespaceID,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- nsAttrValue& aResult)
-{
- return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
- aResult);
+ return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName,
+ aValue, aOldValue, aNotify);
}
EventStates
HTMLAnchorElement::IntrinsicState() const
{
return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
}
--- a/dom/html/HTMLAnchorElement.h
+++ b/dom/html/HTMLAnchorElement.h
@@ -61,30 +61,23 @@ public:
virtual nsresult GetEventTargetParent(
EventChainPreVisitor& aVisitor) override;
virtual nsresult PostHandleEvent(
EventChainPostVisitor& aVisitor) override;
virtual bool IsLink(nsIURI** aURI) const override;
virtual void GetLinkTarget(nsAString& aTarget) override;
virtual already_AddRefed<nsIURI> GetHrefURI() const override;
- nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- const nsAString& aValue, bool aNotify)
- {
- return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
- }
- virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
- nsIAtom* aPrefix, const nsAString& aValue,
- bool aNotify) override;
- virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
- bool aNotify) override;
- virtual bool ParseAttribute(int32_t aNamespaceID,
- nsIAtom* aAttribute,
- const nsAString& aValue,
- nsAttrValue& aResult) override;
+ virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
+ const nsAttrValueOrString* aValue,
+ bool aNotify) override;
+ virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue,
+ bool aNotify) override;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
bool aPreallocateChildren) const override;
virtual EventStates IntrinsicState() const override;
virtual void OnDNSPrefetchDeferred() override;
virtual void OnDNSPrefetchRequested() override;