Take advantage of fix for bug 60683 (thanks bz) in ChangeCSSInlineStyleTxn and then reduce a lot the size of the transaction, keeping only property values instead of a whole style attribute ; major memory impact in CSS mode; b=162473, r=brade, sr=kin
This commit is contained in:
Родитель
ed3bf522d6
Коммит
6d9ec3b18b
|
@ -165,10 +165,10 @@ NS_IMETHODIMP ChangeCSSInlineStyleTxn::Init(nsIEditor *aEditor,
|
||||||
NS_ADDREF(mProperty);
|
NS_ADDREF(mProperty);
|
||||||
mValue.Assign(aValue);
|
mValue.Assign(aValue);
|
||||||
mRemoveProperty = aRemoveProperty;
|
mRemoveProperty = aRemoveProperty;
|
||||||
mPropertyWasSet = PR_FALSE;
|
|
||||||
mUndoAttributeWasSet = PR_FALSE;
|
mUndoAttributeWasSet = PR_FALSE;
|
||||||
mRedoAttributeWasSet = PR_FALSE;
|
mRedoAttributeWasSet = PR_FALSE;
|
||||||
mUndoValue.SetLength(0);
|
mUndoValue.SetLength(0);
|
||||||
|
mRedoValue.SetLength(0);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,160 +177,139 @@ NS_IMETHODIMP ChangeCSSInlineStyleTxn::DoTransaction(void)
|
||||||
NS_ASSERTION(mEditor && mElement, "bad state");
|
NS_ASSERTION(mEditor && mElement, "bad state");
|
||||||
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
|
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
|
||||||
|
|
||||||
nsresult result=NS_OK;
|
nsresult result = NS_OK;
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||||
PRUint32 length = 0;
|
|
||||||
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
|
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
|
||||||
if (!inlineStyles) return NS_ERROR_NULL_POINTER;
|
if (!inlineStyles) return NS_ERROR_NULL_POINTER;
|
||||||
result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
|
result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
|
||||||
if (NS_FAILED(result)) return result;
|
if (NS_FAILED(result)) return result;
|
||||||
if (!cssDecl) return NS_ERROR_NULL_POINTER;
|
if (!cssDecl) return NS_ERROR_NULL_POINTER;
|
||||||
result = cssDecl->GetLength(&length);
|
|
||||||
if (NS_FAILED(result)) return result;
|
|
||||||
|
|
||||||
nsAutoString newDeclString, propertyNameString, undoString, redoString;
|
nsAutoString propertyNameString;
|
||||||
mProperty->ToString(propertyNameString);
|
mProperty->ToString(propertyNameString);
|
||||||
|
|
||||||
mPropertyWasSet = PR_FALSE;
|
|
||||||
// does this property accept more than 1 value ?
|
// does this property accept more than 1 value ?
|
||||||
|
// we need to know that because of bug 62682
|
||||||
PRBool multiple = AcceptsMoreThanOneValue(mProperty);
|
PRBool multiple = AcceptsMoreThanOneValue(mProperty);
|
||||||
|
|
||||||
nsAutoString styleAttr(NS_LITERAL_STRING("style"));
|
nsAutoString styleAttr(NS_LITERAL_STRING("style"));
|
||||||
|
|
||||||
result = mEditor->GetAttributeValue(mElement, styleAttr, mUndoValue, &mUndoAttributeWasSet);
|
result = mElement->HasAttribute(styleAttr, &mUndoAttributeWasSet);
|
||||||
if (NS_FAILED(result)) return result;
|
if (NS_FAILED(result)) return result;
|
||||||
|
|
||||||
if (0 == length && !mRemoveProperty && mUndoAttributeWasSet) {
|
nsAutoString values;
|
||||||
// dirty case, the style engine did not have the time to parse the style attribute
|
result = cssDecl->GetPropertyValue(propertyNameString, values);
|
||||||
newDeclString.Append(mUndoValue + NS_LITERAL_STRING(" "));
|
if (NS_FAILED(result)) return result;
|
||||||
AppendDeclaration(newDeclString, propertyNameString, mValue);
|
mUndoValue.Assign(values);
|
||||||
result = mElement->SetAttribute(styleAttr, newDeclString);
|
|
||||||
}
|
if (mRemoveProperty) {
|
||||||
else if (0 == length) {
|
nsAutoString returnString;
|
||||||
if (mRemoveProperty) {
|
if (multiple) {
|
||||||
// there is no style attribute or it is empty and we want to remove something
|
// the property can have more than one value, let's remove only
|
||||||
// so it is an early way out
|
// the value we have to remove and not the others
|
||||||
result = mElement->RemoveAttribute(styleAttr);
|
|
||||||
}
|
// the 2 lines below are a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
|
||||||
else {
|
// is not yet implemented (bug 62682)
|
||||||
// the style attribute is empty or absent and we want to add a property
|
RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
|
||||||
// let's do it...
|
RemoveValueFromListOfValues(values, mValue);
|
||||||
AppendDeclaration(newDeclString, propertyNameString, mValue);
|
if (values.IsEmpty()) {
|
||||||
result = mElement->SetAttribute(styleAttr, newDeclString);
|
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||||
}
|
if (NS_FAILED(result)) return result;
|
||||||
}
|
|
||||||
else if (mRemoveProperty && (1 == length)) {
|
|
||||||
// let's deal with a special case : we want to remove a property from the
|
|
||||||
// style attribute and it contains only one declaration...
|
|
||||||
// if it is the one we look for, let's remove the attribute ! Otherwise,
|
|
||||||
// do nothing.
|
|
||||||
nsAutoString itemPropertyNameString;
|
|
||||||
cssDecl->Item(0, itemPropertyNameString);
|
|
||||||
PRBool thisOne = propertyNameString.Equals(itemPropertyNameString, nsCaseInsensitiveStringComparator());
|
|
||||||
if (thisOne) {
|
|
||||||
mPropertyWasSet = PR_TRUE;
|
|
||||||
if (multiple) {
|
|
||||||
// the property accepts more than one value...
|
|
||||||
// cssDecl->GetPropertyValue(propertyNameString, mUndoValue);
|
|
||||||
nsAutoString values;
|
|
||||||
cssDecl->GetPropertyValue(propertyNameString, values);
|
|
||||||
RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
|
|
||||||
RemoveValueFromListOfValues(values, mValue);
|
|
||||||
if (0 != values.Length()) {
|
|
||||||
AppendDeclaration(newDeclString, propertyNameString, values);
|
|
||||||
}
|
|
||||||
result = mElement->SetAttribute(styleAttr, newDeclString);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = mElement->RemoveAttribute(styleAttr);
|
nsAutoString priority;
|
||||||
|
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||||
|
if (NS_FAILED(result)) return result;
|
||||||
|
result = cssDecl->SetProperty(propertyNameString, values,
|
||||||
|
priority);
|
||||||
|
if (NS_FAILED(result)) return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||||
|
if (NS_FAILED(result)) return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// general case, we are going to browse all the CSS declarations in the
|
nsAutoString priority;
|
||||||
// style attribute, and, if needed, remove or rewrite the one we want
|
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||||
PRUint32 index;
|
if (NS_FAILED(result)) return result;
|
||||||
nsAutoString itemPropertyNameString;
|
if (multiple) {
|
||||||
for (index = 0 ; index < length; index++) {
|
// the property can have more than one value, let's add
|
||||||
cssDecl->Item(index, itemPropertyNameString);
|
// the value we have to add to the others
|
||||||
PRBool thisOne = propertyNameString.Equals(itemPropertyNameString, nsCaseInsensitiveStringComparator());
|
|
||||||
if (thisOne) {
|
// the line below is a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
|
||||||
// we have found the property we are looking for...
|
// is not yet implemented (bug 62682)
|
||||||
// if we have to remove it, do nothing or remove only the corresponding value
|
AddValueToMultivalueProperty(values, mValue);
|
||||||
// if we have to change it, do it below
|
|
||||||
if (mRemoveProperty) {
|
|
||||||
if (multiple) {
|
|
||||||
nsAutoString values;
|
|
||||||
cssDecl->GetPropertyValue(propertyNameString, values);
|
|
||||||
RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
|
|
||||||
RemoveValueFromListOfValues(values, mValue);
|
|
||||||
if (0 != values.Length()) {
|
|
||||||
AppendDeclaration(newDeclString, propertyNameString, values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newDeclString.Append(propertyNameString + NS_LITERAL_STRING(": "));
|
|
||||||
if (multiple) {
|
|
||||||
nsAutoString values;
|
|
||||||
cssDecl->GetPropertyValue(propertyNameString, values);
|
|
||||||
AddValueToMultivalueProperty(values, mValue);
|
|
||||||
newDeclString.Append(values);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newDeclString.Append(mValue);
|
|
||||||
}
|
|
||||||
newDeclString.Append(NS_LITERAL_STRING("; "));
|
|
||||||
}
|
|
||||||
mPropertyWasSet = PR_TRUE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// this is not the property we are looking for, let's recreate the declaration
|
|
||||||
nsAutoString stringValue;
|
|
||||||
cssDecl->GetPropertyValue(itemPropertyNameString, stringValue);
|
|
||||||
AppendDeclaration(newDeclString, itemPropertyNameString, stringValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// if we DON'T have to remove the property, ie if we have to change or set it,
|
else
|
||||||
// did we find it earlier ? If not, let's set it now...
|
values.Assign(mValue);
|
||||||
if (!mRemoveProperty && !mPropertyWasSet) {
|
result = cssDecl->SetProperty(propertyNameString, values,
|
||||||
AppendDeclaration(newDeclString, propertyNameString, mValue);
|
priority);
|
||||||
}
|
if (NS_FAILED(result)) return result;
|
||||||
result = mElement->SetAttribute(styleAttr, newDeclString);
|
|
||||||
}
|
}
|
||||||
result = mEditor->GetAttributeValue(mElement, styleAttr, mRedoValue, &mRedoAttributeWasSet);
|
|
||||||
|
// let's be sure we don't keep an empty style attribute
|
||||||
|
PRUint32 length;
|
||||||
|
result = cssDecl->GetLength(&length);
|
||||||
|
if (NS_FAILED(result)) return result;
|
||||||
|
if (!length) {
|
||||||
|
result = mElement->RemoveAttribute(styleAttr);
|
||||||
|
if (NS_FAILED(result)) return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mRedoAttributeWasSet = PR_TRUE;
|
||||||
|
|
||||||
|
return cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult ChangeCSSInlineStyleTxn::SetStyle(PRBool aAttributeWasSet,
|
||||||
|
nsAString & aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mEditor && mElement, "bad state");
|
||||||
|
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
|
||||||
|
|
||||||
|
nsresult result = NS_OK;
|
||||||
|
if (aAttributeWasSet) {
|
||||||
|
// the style attribute was set and not empty, let's recreate the declaration
|
||||||
|
nsAutoString propertyNameString;
|
||||||
|
mProperty->ToString(propertyNameString);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||||
|
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
|
||||||
|
if (!inlineStyles) return NS_ERROR_NULL_POINTER;
|
||||||
|
result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
|
||||||
|
if (NS_FAILED(result)) return result;
|
||||||
|
if (!cssDecl) return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
|
if (aValue.IsEmpty()) {
|
||||||
|
// an empty value means we have to remove the property
|
||||||
|
nsAutoString returnString;
|
||||||
|
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// let's recreate the declaration as it was
|
||||||
|
nsAutoString priority;
|
||||||
|
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||||
|
if (NS_FAILED(result)) return result;
|
||||||
|
result = cssDecl->SetProperty(propertyNameString, aValue, priority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// to undo a transaction, just reset the style attribute to its former value...
|
|
||||||
NS_IMETHODIMP ChangeCSSInlineStyleTxn::UndoTransaction(void)
|
NS_IMETHODIMP ChangeCSSInlineStyleTxn::UndoTransaction(void)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mEditor && mElement, "bad state");
|
return SetStyle(mUndoAttributeWasSet, mUndoValue);
|
||||||
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
|
|
||||||
|
|
||||||
nsresult result=NS_OK;
|
|
||||||
if (PR_TRUE == mUndoAttributeWasSet)
|
|
||||||
result = mElement->SetAttribute(NS_LITERAL_STRING("style"), mUndoValue);
|
|
||||||
else
|
|
||||||
result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// to redo a transaction, just set again the style attribute
|
|
||||||
NS_IMETHODIMP ChangeCSSInlineStyleTxn::RedoTransaction(void)
|
NS_IMETHODIMP ChangeCSSInlineStyleTxn::RedoTransaction(void)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(mEditor && mElement, "bad state");
|
return SetStyle(mRedoAttributeWasSet, mRedoValue);
|
||||||
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
|
|
||||||
|
|
||||||
nsresult result=NS_OK;
|
|
||||||
if (PR_TRUE == mRedoAttributeWasSet)
|
|
||||||
result = mElement->SetAttribute(NS_LITERAL_STRING("style"), mRedoValue);
|
|
||||||
else
|
|
||||||
result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP ChangeCSSInlineStyleTxn::Merge(nsITransaction *aTransaction, PRBool *aDidMerge)
|
NS_IMETHODIMP ChangeCSSInlineStyleTxn::Merge(nsITransaction *aTransaction, PRBool *aDidMerge)
|
||||||
|
|
|
@ -117,6 +117,13 @@ private:
|
||||||
const nsAString & aProperty,
|
const nsAString & aProperty,
|
||||||
const nsAString & aValues);
|
const nsAString & aValues);
|
||||||
|
|
||||||
|
/** If the boolean is true and if the value is not the empty string,
|
||||||
|
* set the property in the transaction to that value; if the value
|
||||||
|
* is empty, remove the property from element's styles. If the boolean
|
||||||
|
* is false, just remove the style attribute.
|
||||||
|
*/
|
||||||
|
nsresult SetStyle(PRBool aAttributeWasSet, nsAString & aValue);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NS_IMETHOD DoTransaction(void);
|
NS_IMETHOD DoTransaction(void);
|
||||||
|
@ -143,16 +150,15 @@ protected:
|
||||||
/** the value to set the property to (ignored if mRemoveProperty==PR_TRUE) */
|
/** the value to set the property to (ignored if mRemoveProperty==PR_TRUE) */
|
||||||
nsString mValue;
|
nsString mValue;
|
||||||
|
|
||||||
/** the value to set the attribute to for undo */
|
/** the value to set the property to for undo */
|
||||||
nsString mUndoValue;
|
nsString mUndoValue;
|
||||||
|
/** true if the style attribute was present and not empty before DoTransaction */
|
||||||
PRBool mUndoAttributeWasSet;
|
PRBool mUndoAttributeWasSet;
|
||||||
/** the value to set the attribute to for redo */
|
/** the value to set the property to for redo */
|
||||||
nsString mRedoValue;
|
nsString mRedoValue;
|
||||||
|
/** true if the style attribute is present and not empty after DoTransaction */
|
||||||
PRBool mRedoAttributeWasSet;
|
PRBool mRedoAttributeWasSet;
|
||||||
|
|
||||||
/** PR_TRUE if the mProperty was explicitely set on mElement at the time of execution */
|
|
||||||
PRBool mPropertyWasSet;
|
|
||||||
|
|
||||||
/** PR_TRUE if the operation is to remove mProperty from mElement */
|
/** PR_TRUE if the operation is to remove mProperty from mElement */
|
||||||
PRBool mRemoveProperty;
|
PRBool mRemoveProperty;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче