summaryrefslogtreecommitdiffstats
path: root/dom/base/Element.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-04-16 19:59:10 -0400
committerMatt A. Tobin <email@mattatobin.com>2020-04-16 19:59:10 -0400
commit2f59167e65132fc652456ae8629c1246a9b4b2cb (patch)
treed6f5779a031f2c957612dd4f0dd0d6ee166f9a8b /dom/base/Element.cpp
parent4630e4abb531e416f8153846d422794de20261bd (diff)
downloadUXP-2f59167e65132fc652456ae8629c1246a9b4b2cb.tar
UXP-2f59167e65132fc652456ae8629c1246a9b4b2cb.tar.gz
UXP-2f59167e65132fc652456ae8629c1246a9b4b2cb.tar.lz
UXP-2f59167e65132fc652456ae8629c1246a9b4b2cb.tar.xz
UXP-2f59167e65132fc652456ae8629c1246a9b4b2cb.zip
Bug 656197 - Push state updates further out across beforesetattr/aftersetattr
* Remove the generic attr preparsing mechanism from BeforeSetAttr and just preparse class attributes directly in the one place that needs to do it * Move calls to BeforeSetAttr to after AttributeWillChange * Remove UpdateState calls in BeforeSetAttr * Move calls to AfterSetAttr to before UpdateState when manipulating attributes * Remove UpdateState calls from AfterSetAttr, since they are no longer needed there Tag #1375
Diffstat (limited to 'dom/base/Element.cpp')
-rw-r--r--dom/base/Element.cpp71
1 files changed, 30 insertions, 41 deletions
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 91a3b63d7..055746885 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -2461,6 +2461,9 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
uint8_t modType;
bool hasListeners;
+ // We don't want to spend time preparsing class attributes if the value is not
+ // changing, so just init our nsAttrValueOrString with aValue for the
+ // OnlyNotifySameValueSet call.
nsAttrValueOrString value(aValue);
nsAttrValue oldValue;
@@ -2469,25 +2472,30 @@ Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
return NS_OK;
}
- nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
- NS_ENSURE_SUCCESS(rv, rv);
- nsAttrValue* preparsedAttrValue = value.GetStoredAttrValue();
+ nsAttrValue attrValue;
+ nsAttrValue* preparsedAttrValue;
+ if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::_class) {
+ attrValue.ParseAtomArray(aValue);
+ value.ResetToAttrValue(attrValue);
+ preparsedAttrValue = &attrValue;
+ } else {
+ preparsedAttrValue = nullptr;
+ }
if (aNotify) {
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
preparsedAttrValue);
}
+ nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
+ NS_ENSURE_SUCCESS(rv, rv);
+
// Hold a script blocker while calling ParseAttribute since that can call
// out to id-observers
nsAutoScriptBlocker scriptBlocker;
- nsAttrValue attrValue;
- if (preparsedAttrValue) {
- attrValue.SwapValueWith(*preparsedAttrValue);
- }
- // Even the value was pre-parsed in BeforeSetAttr, we still need to call
- // ParseAttribute because it can have side effects.
+ // Even the value was pre-parsed, we still need to call ParseAttribute because
+ // it can have side effects.
if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
attrValue.SetTo(aValue);
}
@@ -2523,14 +2531,14 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
return NS_OK;
}
- nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
- NS_ENSURE_SUCCESS(rv, rv);
-
if (aNotify) {
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
&aParsedValue);
}
+ nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
+ NS_ENSURE_SUCCESS(rv, rv);
+
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
aParsedValue, modType, hasListeners, aNotify,
kCallAfterSetAttr);
@@ -2599,8 +2607,6 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
}
}
- UpdateState(aNotify);
-
if (CustomElementRegistry::IsCustomElementEnabled()) {
if (CustomElementData* data = GetCustomElementData()) {
if (CustomElementDefinition* definition =
@@ -2639,6 +2645,8 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
}
}
+ UpdateState(aNotify);
+
if (aNotify) {
// Don't pass aOldValue to AttributeChanged since it may not be reliable.
// Callers only compute aOldValue under certain conditions which may not
@@ -2674,25 +2682,6 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
return NS_OK;
}
-nsresult
-Element::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- nsAttrValueOrString* aValue, bool aNotify)
-{
- if (aNamespaceID == kNameSpaceID_None) {
- if (aName == nsGkAtoms::_class) {
- // aValue->GetAttrValue will only be non-null here when this is called
- // via Element::SetParsedAttr. This shouldn't happen for "class", but
- // this will handle it.
- if (aValue && !aValue->GetAttrValue()) {
- nsAttrValue attr;
- attr.ParseAtomArray(aValue->String());
- aValue->TakeParsedValue(attr);
- }
- }
- }
- return NS_OK;
-}
-
bool
Element::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
@@ -2809,9 +2798,6 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
return NS_OK;
}
- nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify);
- NS_ENSURE_SUCCESS(rv, rv);
-
nsIDocument *document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
@@ -2821,6 +2807,9 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nullptr);
}
+ nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify);
+ NS_ENSURE_SUCCESS(rv, rv);
+
bool hasMutationListeners = aNotify &&
nsContentUtils::HasMutationListeners(this,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
@@ -2869,8 +2858,6 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
}
- UpdateState(aNotify);
-
if (CustomElementRegistry::IsCustomElementEnabled()) {
if (CustomElementData* data = GetCustomElementData()) {
if (CustomElementDefinition* definition =
@@ -2897,6 +2884,11 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
}
+ rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ UpdateState(aNotify);
+
if (aNotify) {
// We can always pass oldValue here since there is no new value which could
// have corrupted it.
@@ -2904,9 +2896,6 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
nsIDOMMutationEvent::REMOVAL, &oldValue);
}
- rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
- NS_ENSURE_SUCCESS(rv, rv);
-
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
OnSetDirAttr(this, nullptr, hadValidDir, hadDirAuto, aNotify);
}