diff options
author | Matt A. Tobin <email@mattatobin.com> | 2020-04-16 19:59:10 -0400 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2020-04-16 19:59:10 -0400 |
commit | 2f59167e65132fc652456ae8629c1246a9b4b2cb (patch) | |
tree | d6f5779a031f2c957612dd4f0dd0d6ee166f9a8b /dom/base/Element.cpp | |
parent | 4630e4abb531e416f8153846d422794de20261bd (diff) | |
download | UXP-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.cpp | 71 |
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); } |