diff --git a/mozilla/layout/style/nsCSSDataBlock.cpp b/mozilla/layout/style/nsCSSDataBlock.cpp index d4ae1fb6067..988802e4ccb 100644 --- a/mozilla/layout/style/nsCSSDataBlock.cpp +++ b/mozilla/layout/style/nsCSSDataBlock.cpp @@ -646,35 +646,42 @@ nsCSSExpandedDataBlock::ComputeSize() PRUint32 increment = 0; switch (nsCSSProps::kTypeTable[iProp]) { case eCSSType_Value: { +#ifdef DEBUG nsCSSValue* val = NS_STATIC_CAST(nsCSSValue*, prop); - if (val->GetUnit() != eCSSUnit_Null) { - increment = CDBValueStorage_advance; - } + NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, + "null value while computing size"); +#endif + increment = CDBValueStorage_advance; } break; case eCSSType_Rect: { +#ifdef DEBUG nsCSSRect* val = NS_STATIC_CAST(nsCSSRect*, prop); - if (val->HasValue()) { - increment = CDBRectStorage_advance; - } + NS_ASSERTION(val->HasValue(), + "Valueless rect while computing size"); +#endif + increment = CDBRectStorage_advance; } break; case eCSSType_ValuePair: { +#ifdef DEBUG nsCSSValuePair* val = NS_STATIC_CAST(nsCSSValuePair*, prop); - if (val->mXValue.GetUnit() != eCSSUnit_Null || - val->mYValue.GetUnit() != eCSSUnit_Null) { - increment = CDBValuePairStorage_advance; - } + NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null || + val->mYValue.GetUnit() != eCSSUnit_Null, + "Valueless pair while computing size"); +#endif + increment = CDBValuePairStorage_advance; } break; case eCSSType_ValueList: case eCSSType_CounterData: case eCSSType_Quotes: case eCSSType_Shadow: { +#ifdef DEBUG void* val = *NS_STATIC_CAST(void**, prop); - if (val) { - increment = CDBPointerStorage_advance; - } + NS_ASSERTION(val, "Null pointer while computing size"); +#endif + increment = CDBPointerStorage_advance; } break; } if ((mPropertiesImportant[iHigh] & (1 << iLow)) == 0) @@ -732,7 +739,6 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock, NS_ASSERTION(0 <= iProp && iProp < eCSSProperty_COUNT_no_shorthands, "out of range"); void *prop = PropertyAt(iProp); - PRBool present = PR_FALSE; PRBool important = (mPropertiesImportant[iHigh] & (1 << iLow)) != 0; char *&cursor = important ? cursor_important : cursor_normal; @@ -741,42 +747,39 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock, switch (nsCSSProps::kTypeTable[iProp]) { case eCSSType_Value: { nsCSSValue* val = NS_STATIC_CAST(nsCSSValue*, prop); - if (val->GetUnit() != eCSSUnit_Null) { - CDBValueStorage *storage = - NS_REINTERPRET_CAST(CDBValueStorage*, cursor); - storage->property = iProp; - memcpy(&storage->value, val, sizeof(nsCSSValue)); - new (val) nsCSSValue(); - cursor += CDBValueStorage_advance; - present = PR_TRUE; - } + NS_ASSERTION(val->GetUnit() != eCSSUnit_Null, + "Null value while compressing"); + CDBValueStorage *storage = + NS_REINTERPRET_CAST(CDBValueStorage*, cursor); + storage->property = iProp; + memcpy(&storage->value, val, sizeof(nsCSSValue)); + new (val) nsCSSValue(); + cursor += CDBValueStorage_advance; } break; case eCSSType_Rect: { nsCSSRect* val = NS_STATIC_CAST(nsCSSRect*, prop); - if (val->HasValue()) { - CDBRectStorage *storage = - NS_REINTERPRET_CAST(CDBRectStorage*, cursor); - storage->property = iProp; - memcpy(&storage->value, val, sizeof(nsCSSRect)); - new (val) nsCSSRect(); - cursor += CDBRectStorage_advance; - present = PR_TRUE; - } + NS_ASSERTION(val->HasValue(), + "Valueless rect while compressing"); + CDBRectStorage *storage = + NS_REINTERPRET_CAST(CDBRectStorage*, cursor); + storage->property = iProp; + memcpy(&storage->value, val, sizeof(nsCSSRect)); + new (val) nsCSSRect(); + cursor += CDBRectStorage_advance; } break; case eCSSType_ValuePair: { nsCSSValuePair* val = NS_STATIC_CAST(nsCSSValuePair*, prop); - if (val->mXValue.GetUnit() != eCSSUnit_Null || - val->mYValue.GetUnit() != eCSSUnit_Null) { - CDBValuePairStorage *storage = - NS_REINTERPRET_CAST(CDBValuePairStorage*, cursor); - storage->property = iProp; - memcpy(&storage->value, val, sizeof(nsCSSValuePair)); - new (val) nsCSSValuePair(); - cursor += CDBValuePairStorage_advance; - present = PR_TRUE; - } + NS_ASSERTION(val->mXValue.GetUnit() != eCSSUnit_Null || + val->mYValue.GetUnit() != eCSSUnit_Null, + "Valueless pair while compressing"); + CDBValuePairStorage *storage = + NS_REINTERPRET_CAST(CDBValuePairStorage*, cursor); + storage->property = iProp; + memcpy(&storage->value, val, sizeof(nsCSSValuePair)); + new (val) nsCSSValuePair(); + cursor += CDBValuePairStorage_advance; } break; case eCSSType_ValueList: @@ -784,21 +787,17 @@ nsCSSExpandedDataBlock::Compress(nsCSSCompressedDataBlock **aNormalBlock, case eCSSType_Quotes: case eCSSType_Shadow: { void*& val = *NS_STATIC_CAST(void**, prop); - if (val) { - CDBPointerStorage *storage = - NS_REINTERPRET_CAST(CDBPointerStorage*, cursor); - storage->property = iProp; - storage->value = val; - val = nsnull; - cursor += CDBPointerStorage_advance; - present = PR_TRUE; - } + NS_ASSERTION(val, "Null pointer while compressing"); + CDBPointerStorage *storage = + NS_REINTERPRET_CAST(CDBPointerStorage*, cursor); + storage->property = iProp; + storage->value = val; + val = nsnull; + cursor += CDBPointerStorage_advance; } break; } - if (present) { - result->mStyleBits |= nsCachedStyleData::GetBitForSID( - nsCSSProps::kSIDTable[iProp]); - } + result->mStyleBits |= + nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]); } } diff --git a/mozilla/layout/style/nsCSSDataBlock.h b/mozilla/layout/style/nsCSSDataBlock.h index 2ddef369e66..11161d41272 100644 --- a/mozilla/layout/style/nsCSSDataBlock.h +++ b/mozilla/layout/style/nsCSSDataBlock.h @@ -212,11 +212,10 @@ private: (eCSSProperty_COUNT_no_shorthands + (kPropertiesSetChunkSize-1)) / kPropertiesSetChunkSize }; /* - * mPropertiesSet stores a bit for every property that may be - * present, to optimize compression of blocks with small numbers of - * properties (the norm). The code does not rely on it to be exact; - * it is allowable, although slower, if a bit is erroneously set - * even though the property is not present. + * mPropertiesSet stores a bit for every property that is present, + * to optimize compression of blocks with small numbers of + * properties (the norm) and to allow quickly checking whether a + * property is set in this block. */ property_set_type mPropertiesSet[kPropertiesSetChunkCount]; /* diff --git a/mozilla/layout/style/nsCSSDeclaration.h b/mozilla/layout/style/nsCSSDeclaration.h index adc189ca314..82616115a6f 100644 --- a/mozilla/layout/style/nsCSSDeclaration.h +++ b/mozilla/layout/style/nsCSSDeclaration.h @@ -136,6 +136,7 @@ public: mImportantData->Destroy(); mImportantData = nsnull; } + mOrder.Clear(); } #ifdef DEBUG diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp index 583aa70fc86..6f9f63cca3b 100644 --- a/mozilla/layout/style/nsCSSParser.cpp +++ b/mozilla/layout/style/nsCSSParser.cpp @@ -248,18 +248,23 @@ protected: PRBool ParseDeclaration(nsresult& aErrorCode, nsCSSDeclaration* aDeclaration, PRBool aCheckForBraces, + PRBool aMustCallValueAppended, PRBool* aChanged); // After a parse error parsing |aPropID|, clear the data in // |mTempData|. void ClearTempData(nsCSSProperty aPropID); // After a successful parse of |aPropID|, transfer data from // |mTempData| to |mData|. Set |*aChanged| to true if something - // changed, but leave it unmodified otherwise. + // changed, but leave it unmodified otherwise. If aMustCallValueAppended + // is false, will not call ValueAppended on aDeclaration if the property + // is already set in it. void TransferTempData(nsCSSDeclaration* aDeclaration, nsCSSProperty aPropID, PRBool aIsImportant, + PRBool aMustCallValueAppended, PRBool* aChanged); void DoTransferTempData(nsCSSDeclaration* aDeclaration, nsCSSProperty aPropID, PRBool aIsImportant, + PRBool aMustCallValueAppended, PRBool* aChanged); PRBool ParseProperty(nsresult& aErrorCode, nsCSSProperty aPropID); PRBool ParseSingleValueProperty(nsresult& aErrorCode, nsCSSValue& aValue, @@ -781,7 +786,10 @@ CSSParserImpl::ParseAndAppendDeclaration(const nsAString& aBuffer, } do { - if (!ParseDeclaration(errorCode, aDeclaration, PR_FALSE, aChanged)) { + // If we cleared the old decl, then we want to be calling + // ValueAppended as we parse. + if (!ParseDeclaration(errorCode, aDeclaration, PR_FALSE, + aClearOldDecl, aChanged)) { NS_ASSERTION(errorCode != nsresult(-1), "-1 is no longer used for EOF"); rv = errorCode; @@ -882,7 +890,7 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, aDeclaration->ExpandTo(&mData); nsresult result = NS_OK; if (ParseProperty(errorCode, aPropID)) { - TransferTempData(aDeclaration, aPropID, PR_FALSE, aChanged); + TransferTempData(aDeclaration, aPropID, PR_FALSE, PR_FALSE, aChanged); } else { NS_ConvertASCIItoUTF16 propName(nsCSSProps::GetStringValue(aPropID)); const PRUnichar *params[] = { @@ -2697,7 +2705,7 @@ CSSParserImpl::ParseDeclarationBlock(nsresult& aErrorCode, for (;;) { PRBool changed; if (!ParseDeclaration(aErrorCode, declaration, aCheckForBraces, - &changed)) { + PR_TRUE, &changed)) { if (!SkipDeclaration(aErrorCode, aCheckForBraces)) { break; } @@ -3075,6 +3083,7 @@ PRBool CSSParserImpl::ParseDeclaration(nsresult& aErrorCode, nsCSSDeclaration* aDeclaration, PRBool aCheckForBraces, + PRBool aMustCallValueAppended, PRBool* aChanged) { mTempData.AssertInitialState(); @@ -3148,7 +3157,8 @@ CSSParserImpl::ParseDeclaration(nsresult& aErrorCode, ClearTempData(propID); return PR_FALSE; } - TransferTempData(aDeclaration, propID, isImportant, aChanged); + TransferTempData(aDeclaration, propID, isImportant, + aMustCallValueAppended, aChanged); return PR_TRUE; } else { @@ -3193,12 +3203,14 @@ CSSParserImpl::ParseDeclaration(nsresult& aErrorCode, ClearTempData(propID); return PR_FALSE; } - TransferTempData(aDeclaration, propID, isImportant, aChanged); + TransferTempData(aDeclaration, propID, isImportant, + aMustCallValueAppended, aChanged); return PR_TRUE; } if (eCSSToken_Symbol == tk->mType) { if (';' == tk->mSymbol) { - TransferTempData(aDeclaration, propID, isImportant, aChanged); + TransferTempData(aDeclaration, propID, isImportant, + aMustCallValueAppended, aChanged); return PR_TRUE; } if (!aCheckForBraces) { @@ -3212,7 +3224,8 @@ CSSParserImpl::ParseDeclaration(nsresult& aErrorCode, } if ('}' == tk->mSymbol) { UngetToken(); - TransferTempData(aDeclaration, propID, isImportant, aChanged); + TransferTempData(aDeclaration, propID, isImportant, + aMustCallValueAppended, aChanged); return PR_TRUE; } } @@ -3242,14 +3255,17 @@ CSSParserImpl::ClearTempData(nsCSSProperty aPropID) void CSSParserImpl::TransferTempData(nsCSSDeclaration* aDeclaration, nsCSSProperty aPropID, PRBool aIsImportant, + PRBool aMustCallValueAppended, PRBool* aChanged) { if (nsCSSProps::IsShorthand(aPropID)) { CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID) { - DoTransferTempData(aDeclaration, *p, aIsImportant, aChanged); + DoTransferTempData(aDeclaration, *p, aIsImportant, + aMustCallValueAppended, aChanged); } } else { - DoTransferTempData(aDeclaration, aPropID, aIsImportant, aChanged); + DoTransferTempData(aDeclaration, aPropID, aIsImportant, + aMustCallValueAppended, aChanged); } mTempData.AssertInitialState(); } @@ -3260,6 +3276,7 @@ CSSParserImpl::TransferTempData(nsCSSDeclaration* aDeclaration, void CSSParserImpl::DoTransferTempData(nsCSSDeclaration* aDeclaration, nsCSSProperty aPropID, PRBool aIsImportant, + PRBool aMustCallValueAppended, PRBool* aChanged) { NS_ASSERTION(mTempData.HasPropertyBit(aPropID), "oops"); @@ -3273,11 +3290,14 @@ CSSParserImpl::DoTransferTempData(nsCSSDeclaration* aDeclaration, return; } } + + if (aMustCallValueAppended || !mData.HasPropertyBit(aPropID)) { + aDeclaration->ValueAppended(aPropID); + } + mData.SetPropertyBit(aPropID); mTempData.ClearPropertyBit(aPropID); - aDeclaration->ValueAppended(aPropID); - /* * Save needless copying and allocation by calling the destructor in * the destination, copying memory directly, and then using placement @@ -3294,6 +3314,12 @@ CSSParserImpl::DoTransferTempData(nsCSSDeclaration* aDeclaration, dest->~nsCSSValue(); memcpy(dest, source, sizeof(nsCSSValue)); new (source) nsCSSValue(); + if (dest->GetUnit() == eCSSUnit_Null) { + // Some of our property parsers actually want to _clear_ properties in + // mData (eg the "font" shorthand parser does for system fonts). We've + // cleared the data; now clear the bit too. + mData.ClearPropertyBit(aPropID); + } } break; case eCSSType_Rect: { @@ -5346,6 +5372,13 @@ PRBool CSSParserImpl::ParseFont(nsresult& aErrorCode) else { AppendValue(eCSSProperty_font_family, family); // keyword value overrides everything else nsCSSValue empty; + // XXXbz this is actually _clearing_ the values for the following + // properties in mTempData, but setting the bit for them. We need that + // because we want to clear out the values in mData when all is said + // and done. See the code in TransferTempData that handles this. The + // end result is that mData always has its property bits set like it + // should, but mTempData can, in fact, have bits set for properties + // that are not set... AppendValue(eCSSProperty_font_style, empty); AppendValue(eCSSProperty_font_variant, empty); AppendValue(eCSSProperty_font_weight, empty);