Bug 773296 - Part 10: Add a new eCSSUnit_TokenStream type for storing unparsed CSS values. p=ebassi,heycam r=dbaron

Patch co-authored by Emmanuele Bassi <ebassi@gmail.com>

This adds a new nsCSSValue unit type to represent an unparsed
stream of CSS tokens as a specified value.  This is what properties
that have a variable reference get as their specified value.

On the nsCSSValueTokenStream object that is used when mUnit ==
eCSSUnit_TokenStream, we store two property IDs: first, the property
ID for the longhand that this token stream value is the value for.  We
pass this back in to nsCSSParser::ParseProperty at computed value time,
when we need to re-parse the property.  Second is the shorthand property
ID, if we used a variable reference in a shorthand.  In such a case, we
store the token stream value for each of the corresponding longhand
properties.  This is because shorthands don't actually get any storage
in an nsRuleData, and because any of the longhands might be overwritten
by subsequent declarations, we need to keep the token stream somewhere.

We also store other information on the nsCSSValueTokenStream required by
the CSS parser (base URI, etc.).
This commit is contained in:
Cameron McCormack 2013-12-12 13:09:42 +11:00
parent 6c08a4ff75
commit bcfb74f5f8
2 changed files with 134 additions and 0 deletions

View File

@ -96,6 +96,13 @@ nsCSSValue::nsCSSValue(nsCSSValueGradient* aValue)
mValue.mGradient->AddRef();
}
nsCSSValue::nsCSSValue(nsCSSValueTokenStream* aValue)
: mUnit(eCSSUnit_TokenStream)
{
mValue.mTokenStream = aValue;
mValue.mTokenStream->AddRef();
}
nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
: mUnit(aCopy.mUnit)
{
@ -132,6 +139,10 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
mValue.mGradient = aCopy.mValue.mGradient;
mValue.mGradient->AddRef();
}
else if (eCSSUnit_TokenStream == mUnit) {
mValue.mTokenStream = aCopy.mValue.mTokenStream;
mValue.mTokenStream->AddRef();
}
else if (eCSSUnit_Pair == mUnit) {
mValue.mPair = aCopy.mValue.mPair;
mValue.mPair->AddRef();
@ -206,6 +217,9 @@ bool nsCSSValue::operator==(const nsCSSValue& aOther) const
else if (eCSSUnit_Gradient == mUnit) {
return *mValue.mGradient == *aOther.mValue.mGradient;
}
else if (eCSSUnit_TokenStream == mUnit) {
return *mValue.mTokenStream == *aOther.mValue.mTokenStream;
}
else if (eCSSUnit_Pair == mUnit) {
return *mValue.mPair == *aOther.mValue.mPair;
}
@ -291,6 +305,8 @@ void nsCSSValue::DoReset()
mValue.mImage->Release();
} else if (eCSSUnit_Gradient == mUnit) {
mValue.mGradient->Release();
} else if (eCSSUnit_TokenStream == mUnit) {
mValue.mTokenStream->Release();
} else if (eCSSUnit_Pair == mUnit) {
mValue.mPair->Release();
} else if (eCSSUnit_Triplet == mUnit) {
@ -388,6 +404,14 @@ void nsCSSValue::SetGradientValue(nsCSSValueGradient* aValue)
mValue.mGradient->AddRef();
}
void nsCSSValue::SetTokenStreamValue(nsCSSValueTokenStream* aValue)
{
Reset();
mUnit = eCSSUnit_TokenStream;
mValue.mTokenStream = aValue;
mValue.mTokenStream->AddRef();
}
void nsCSSValue::SetPairValue(const nsCSSValuePair* aValue)
{
// pairs should not be used for null/inherit/initial values
@ -1137,6 +1161,15 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
}
aResult.AppendLiteral(")");
} else if (eCSSUnit_TokenStream == unit) {
nsCSSProperty shorthand = mValue.mTokenStream->mShorthandPropertyID;
if (shorthand == eCSSProperty_UNKNOWN ||
nsCSSProps::PropHasFlags(shorthand, CSS_PROPERTY_IS_ALIAS)) {
// We treat serialization of aliases like '-moz-transform' as a special
// case, since it really wants to be serialized as if it were a longhand
// even though it is implemented as a shorthand.
aResult.Append(mValue.mTokenStream->mTokenStream);
}
} else if (eCSSUnit_Pair == unit) {
if (eCSSProperty_font_variant_alternates == aProperty) {
int32_t intValue = GetPairValue().mXValue.GetIntValue();
@ -1219,6 +1252,7 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
case eCSSUnit_Percent: aResult.Append(PRUnichar('%')); break;
case eCSSUnit_Number: break;
case eCSSUnit_Gradient: break;
case eCSSUnit_TokenStream: break;
case eCSSUnit_Pair: break;
case eCSSUnit_Triplet: break;
case eCSSUnit_Rect: break;
@ -1321,6 +1355,11 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
n += mValue.mGradient->SizeOfIncludingThis(aMallocSizeOf);
break;
// TokenStream
case eCSSUnit_TokenStream:
n += mValue.mTokenStream->SizeOfIncludingThis(aMallocSizeOf);
break;
// Pair
case eCSSUnit_Pair:
n += mValue.mPair->SizeOfIncludingThis(aMallocSizeOf);
@ -1929,6 +1968,28 @@ nsCSSValueGradient::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) con
return n;
}
// --- nsCSSValueTokenStream ------------
nsCSSValueTokenStream::nsCSSValueTokenStream()
: mPropertyID(eCSSProperty_UNKNOWN)
, mShorthandPropertyID(eCSSProperty_UNKNOWN)
{
MOZ_COUNT_CTOR(nsCSSValueTokenStream);
}
nsCSSValueTokenStream::~nsCSSValueTokenStream()
{
MOZ_COUNT_DTOR(nsCSSValueTokenStream);
}
size_t
nsCSSValueTokenStream::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
n += mTokenStream.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
return n;
}
// --- nsCSSCornerSizes -----------------
nsCSSCornerSizes::nsCSSCornerSizes(void)

View File

@ -12,6 +12,8 @@
#include "mozilla/FloatingPoint.h"
#include "mozilla/MemoryReporting.h"
#include "nsIPrincipal.h"
#include "nsIURI.h"
#include "nsCOMPtr.h"
#include "nsCRTGlue.h"
#include "nsCSSKeywords.h"
@ -187,6 +189,7 @@ enum nsCSSUnit {
eCSSUnit_URL = 40, // (nsCSSValue::URL*) value
eCSSUnit_Image = 41, // (nsCSSValue::Image*) value
eCSSUnit_Gradient = 42, // (nsCSSValueGradient*) value
eCSSUnit_TokenStream = 43, // (nsCSSValueTokenStream*) value
eCSSUnit_Pair = 50, // (nsCSSValuePair*) pair of values
eCSSUnit_Triplet = 51, // (nsCSSValueTriplet*) triplet of values
@ -249,6 +252,7 @@ enum nsCSSUnit {
struct nsCSSValueGradient;
struct nsCSSValuePair;
struct nsCSSValuePair_heap;
struct nsCSSValueTokenStream;
struct nsCSSRect;
struct nsCSSRect_heap;
struct nsCSSValueList;
@ -281,6 +285,7 @@ public:
explicit nsCSSValue(mozilla::css::URLValue* aValue);
explicit nsCSSValue(mozilla::css::ImageValue* aValue);
explicit nsCSSValue(nsCSSValueGradient* aValue);
explicit nsCSSValue(nsCSSValueTokenStream* aValue);
nsCSSValue(const nsCSSValue& aCopy);
~nsCSSValue() { Reset(); }
@ -419,6 +424,12 @@ public:
return mValue.mGradient;
}
nsCSSValueTokenStream* GetTokenStreamValue() const
{
NS_ABORT_IF_FALSE(mUnit == eCSSUnit_TokenStream, "not a token stream value");
return mValue.mTokenStream;
}
// bodies of these are below
inline nsCSSValuePair& GetPairValue();
inline const nsCSSValuePair& GetPairValue() const;
@ -484,6 +495,7 @@ public:
void SetURLValue(mozilla::css::URLValue* aURI);
void SetImageValue(mozilla::css::ImageValue* aImage);
void SetGradientValue(nsCSSValueGradient* aGradient);
void SetTokenStreamValue(nsCSSValueTokenStream* aTokenStream);
void SetPairValue(const nsCSSValuePair* aPair);
void SetPairValue(const nsCSSValue& xValue, const nsCSSValue& yValue);
void SetDependentListValue(nsCSSValueList* aList);
@ -539,6 +551,7 @@ protected:
mozilla::css::URLValue* mURL;
mozilla::css::ImageValue* mImage;
nsCSSValueGradient* mGradient;
nsCSSValueTokenStream* mTokenStream;
nsCSSValuePair_heap* mPair;
nsCSSRect_heap* mRect;
nsCSSValueTriplet_heap* mTriplet;
@ -1130,6 +1143,66 @@ private:
nsCSSValueGradient& operator=(const nsCSSValueGradient& aOther) MOZ_DELETE;
};
struct nsCSSValueTokenStream {
nsCSSValueTokenStream();
~nsCSSValueTokenStream();
bool operator==(const nsCSSValueTokenStream& aOther) const
{
bool eq;
return mPropertyID == aOther.mPropertyID &&
mShorthandPropertyID == aOther.mShorthandPropertyID &&
mTokenStream.Equals(aOther.mTokenStream) &&
(mBaseURI == aOther.mBaseURI ||
(mBaseURI && aOther.mBaseURI &&
NS_SUCCEEDED(mBaseURI->Equals(aOther.mBaseURI, &eq)) &&
eq)) &&
(mSheetURI == aOther.mSheetURI ||
(mSheetURI && aOther.mSheetURI &&
NS_SUCCEEDED(mSheetURI->Equals(aOther.mSheetURI, &eq)) &&
eq)) &&
(mSheetPrincipal == aOther.mSheetPrincipal ||
(mSheetPrincipal && aOther.mSheetPrincipal &&
NS_SUCCEEDED(mSheetPrincipal->Equals(aOther.mSheetPrincipal,
&eq)) &&
eq));
}
bool operator!=(const nsCSSValueTokenStream& aOther) const
{
return !(*this == aOther);
}
NS_INLINE_DECL_REFCOUNTING(nsCSSValueTokenStream)
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
// The property that has mTokenStream as its unparsed specified value.
// When a variable reference is used in a shorthand property, a
// TokenStream value is stored as the specified value for each of its
// component longhand properties.
nsCSSProperty mPropertyID;
// The shorthand property that had a value with a variable reference,
// which caused the longhand property identified by mPropertyID to have
// a TokenStream value.
nsCSSProperty mShorthandPropertyID;
// The unparsed CSS corresponding to the specified value of the property.
// When the value of a shorthand property has a variable reference, the
// same mTokenStream value is used on each of the nsCSSValueTokenStream
// objects that will be set by parsing the shorthand.
nsString mTokenStream;
nsCOMPtr<nsIURI> mBaseURI;
nsCOMPtr<nsIURI> mSheetURI;
nsCOMPtr<nsIPrincipal> mSheetPrincipal;
private:
nsCSSValueTokenStream(const nsCSSValueTokenStream& aOther) MOZ_DELETE;
nsCSSValueTokenStream& operator=(const nsCSSValueTokenStream& aOther) MOZ_DELETE;
};
struct nsCSSCornerSizes {
nsCSSCornerSizes(void);
nsCSSCornerSizes(const nsCSSCornerSizes& aCopy);