Bug 1294299 part 10 - Implement DeclarationBlock.EnsureMutable. r=heycam
MozReview-Commit-ID: KpaypyY5moC
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -1808,29 +1808,16 @@ Declaration::GetNthProperty(uint32_t aIn
void
Declaration::InitializeEmpty()
{
MOZ_ASSERT(!mData && !mImportantData, "already initialized");
mData = nsCSSCompressedDataBlock::CreateEmptyBlock();
}
-already_AddRefed<Declaration>
-Declaration::EnsureMutable()
-{
- MOZ_ASSERT(mData, "should only be called when not expanded");
- RefPtr<Declaration> result;
- if (!IsMutable()) {
- result = new Declaration(*this);
- } else {
- result = this;
- }
- return result.forget();
-}
-
size_t
Declaration::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
n += mOrder.ShallowSizeOfExcludingThis(aMallocSizeOf);
n += mData ? mData ->SizeOfIncludingThis(aMallocSizeOf) : 0;
n += mImportantData ? mImportantData->SizeOfIncludingThis(aMallocSizeOf) : 0;
if (mVariables) {
--- a/layout/style/Declaration.h
+++ b/layout/style/Declaration.h
@@ -183,16 +183,20 @@ public:
// Returns whether we actually had a property at aIndex
bool GetNthProperty(uint32_t aIndex, nsAString& aReturn) const;
void ToString(nsAString& aString) const;
nsCSSCompressedDataBlock* GetNormalBlock() const { return mData; }
nsCSSCompressedDataBlock* GetImportantBlock() const { return mImportantData; }
+ void AssertNotExpanded() const {
+ MOZ_ASSERT(mData, "should only be called when not expanded");
+ }
+
/**
* Initialize this declaration as holding no data. Cannot fail.
*/
void InitializeEmpty();
/**
* Transfer all of the state from |aExpandedData| into this declaration.
* After calling, |aExpandedData| should be in its initial state.
@@ -218,17 +222,17 @@ public:
AssertMutable();
aExpandedData->AssertInitialState();
MOZ_ASSERT(mData, "oops");
aExpandedData->Expand(mData.forget(), mImportantData.forget());
}
void MapImportantRuleInfoInto(nsRuleData *aRuleData) const {
- MOZ_ASSERT(mData, "called while expanded");
+ AssertNotExpanded();
MOZ_ASSERT(mImportantData || mImportantVariables,
"must have important data or variables");
if (mImportantData) {
mImportantData->MapRuleInfoInto(aRuleData);
}
if (mImportantVariables) {
mImportantVariables->MapRuleInfoInto(aRuleData);
}
@@ -246,17 +250,17 @@ public:
* |aFromBlock|. |aChanged| is set to true if the declaration
* changed as a result of the call, and to false otherwise.
*/
bool TryReplaceValue(nsCSSPropertyID aProperty, bool aIsImportant,
nsCSSExpandedDataBlock& aFromBlock,
bool* aChanged)
{
AssertMutable();
- MOZ_ASSERT(mData, "called while expanded");
+ AssertNotExpanded();
if (nsCSSProps::IsShorthand(aProperty)) {
*aChanged = false;
return false;
}
nsCSSCompressedDataBlock *block = aIsImportant ? mImportantData : mData;
// mImportantData might be null
if (!block) {
@@ -276,21 +280,16 @@ public:
}
bool HasNonImportantValueFor(nsCSSPropertyID aProperty) const {
MOZ_ASSERT(!nsCSSProps::IsShorthand(aProperty), "must be longhand");
return !!mData->ValueFor(aProperty);
}
/**
- * Copy |this|, if necessary to ensure that it can be modified.
- */
- already_AddRefed<Declaration> EnsureMutable();
-
- /**
* Clear the data, in preparation for its replacement with entirely
* new data by a call to |CompressFrom|.
*/
void ClearData() {
AssertMutable();
mData = nullptr;
mImportantData = nullptr;
mVariables = nullptr;
--- a/layout/style/DeclarationBlock.h
+++ b/layout/style/DeclarationBlock.h
@@ -58,16 +58,21 @@ public:
}
/**
* Mark this declaration as unmodifiable. It's 'const' so it can
* be called from ToString.
*/
void SetImmutable() const { mImmutable = true; }
+ /**
+ * Copy |this|, if necessary to ensure that it can be modified.
+ */
+ inline already_AddRefed<DeclarationBlock> EnsureMutable();
+
void SetOwningRule(css::Rule* aRule) {
MOZ_ASSERT(!mContainer.mOwningRule || !aRule,
"should never overwrite one rule with another");
mContainer.mOwningRule = aRule;
}
css::Rule* GetOwningRule() const {
if (mContainer.mRaw & 0x1) {
--- a/layout/style/DeclarationBlockInlines.h
+++ b/layout/style/DeclarationBlockInlines.h
@@ -33,16 +33,30 @@ DeclarationBlock::Clone() const
if (IsGecko()) {
result = new css::Declaration(*AsGecko());
} else {
result = new ServoDeclarationBlock(*AsServo());
}
return result.forget();
}
+already_AddRefed<DeclarationBlock>
+DeclarationBlock::EnsureMutable()
+{
+#ifdef DEBUG
+ if (IsGecko()) {
+ AsGecko()->AssertNotExpanded();
+ }
+#endif
+ if (!IsMutable()) {
+ return Clone();
+ }
+ return do_AddRef(this);
+}
+
void
DeclarationBlock::ToString(nsAString& aString) const
{
MOZ_STYLO_FORWARD(ToString, (aString))
}
uint32_t
DeclarationBlock::Count() const
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -274,121 +274,120 @@ nsDOMCSSDeclaration::GetCSSParsingEnviro
aCSSParseEnv.mCSSLoader = document ? document->CSSLoader() : nullptr;
}
nsresult
nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSPropertyID aPropID,
const nsAString& aPropValue,
bool aIsImportant)
{
- css::Declaration* olddecl = GetCSSDeclaration(eOperation_Modify)->AsGecko();
+ DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_Modify);
if (!olddecl) {
return NS_ERROR_NOT_AVAILABLE;
}
CSSParsingEnvironment env;
GetCSSParsingEnvironment(env);
if (!env.mPrincipal) {
return NS_ERROR_NOT_AVAILABLE;
}
// For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
// Attribute setting code, which leads in turn to BeginUpdate. We
// need to start the update now so that the old rule doesn't get used
// between when we mutate the declaration and when we set the new
// rule (see stack in bug 209575).
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
- RefPtr<css::Declaration> decl = olddecl->EnsureMutable();
+ RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
nsCSSParser cssParser(env.mCSSLoader);
bool changed;
- cssParser.ParseProperty(aPropID, aPropValue, env.mSheetURI, env.mBaseURI,
- env.mPrincipal, decl, &changed, aIsImportant);
+ cssParser.ParseProperty(aPropID, aPropValue,
+ env.mSheetURI, env.mBaseURI, env.mPrincipal,
+ decl->AsGecko(), &changed, aIsImportant);
if (!changed) {
// Parsing failed -- but we don't throw an exception for that.
return NS_OK;
}
return SetCSSDeclaration(decl);
}
nsresult
nsDOMCSSDeclaration::ParseCustomPropertyValue(const nsAString& aPropertyName,
const nsAString& aPropValue,
bool aIsImportant)
{
MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName));
- css::Declaration* olddecl = GetCSSDeclaration(eOperation_Modify)->AsGecko();
+ DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_Modify);
if (!olddecl) {
return NS_ERROR_NOT_AVAILABLE;
}
CSSParsingEnvironment env;
GetCSSParsingEnvironment(env);
if (!env.mPrincipal) {
return NS_ERROR_NOT_AVAILABLE;
}
// For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
// Attribute setting code, which leads in turn to BeginUpdate. We
// need to start the update now so that the old rule doesn't get used
// between when we mutate the declaration and when we set the new
// rule (see stack in bug 209575).
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
- RefPtr<css::Declaration> decl = olddecl->EnsureMutable();
+ RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
nsCSSParser cssParser(env.mCSSLoader);
bool changed;
cssParser.ParseVariable(Substring(aPropertyName,
CSS_CUSTOM_NAME_PREFIX_LENGTH),
aPropValue, env.mSheetURI,
- env.mBaseURI, env.mPrincipal, decl,
+ env.mBaseURI, env.mPrincipal, decl->AsGecko(),
&changed, aIsImportant);
if (!changed) {
// Parsing failed -- but we don't throw an exception for that.
return NS_OK;
}
return SetCSSDeclaration(decl);
}
nsresult
nsDOMCSSDeclaration::RemovePropertyInternal(nsCSSPropertyID aPropID)
{
- css::Declaration* olddecl =
- GetCSSDeclaration(eOperation_RemoveProperty)->AsGecko();
+ DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_RemoveProperty);
if (!olddecl) {
return NS_OK; // no decl, so nothing to remove
}
// For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
// Attribute setting code, which leads in turn to BeginUpdate. We
// need to start the update now so that the old rule doesn't get used
// between when we mutate the declaration and when we set the new
// rule (see stack in bug 209575).
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
- RefPtr<css::Declaration> decl = olddecl->EnsureMutable();
- decl->RemovePropertyByID(aPropID);
+ RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
+ decl->AsGecko()->RemovePropertyByID(aPropID);
return SetCSSDeclaration(decl);
}
nsresult
nsDOMCSSDeclaration::RemovePropertyInternal(const nsAString& aPropertyName)
{
- css::Declaration* olddecl =
- GetCSSDeclaration(eOperation_RemoveProperty)->AsGecko();
+ DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_RemoveProperty);
if (!olddecl) {
return NS_OK; // no decl, so nothing to remove
}
// For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
// Attribute setting code, which leads in turn to BeginUpdate. We
// need to start the update now so that the old rule doesn't get used
// between when we mutate the declaration and when we set the new
// rule (see stack in bug 209575).
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
- RefPtr<css::Declaration> decl = olddecl->EnsureMutable();
- decl->RemoveProperty(aPropertyName);
+ RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
+ decl->AsGecko()->RemoveProperty(aPropertyName);
return SetCSSDeclaration(decl);
}