Bug 950436 - Store ImageValues that resulted from re-parsing a nsCSSValueTokenStream on that object. r=dbaron

This commit is contained in:
Cameron McCormack 2014-03-18 20:11:14 +11:00
parent 9d5f2b19f0
commit d36b03a216
7 changed files with 70 additions and 8 deletions

View File

@ -0,0 +1,5 @@
<!DOCTYPE html>
<style>
body { background-image: url(950436-1.png); }
</style>
<body>

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<style>
/* It's important here to reference an image that has not previously been loaded
during the reftest run. So don't use 950436-1.png in any other test. */
body { var-a: url(950436-1.png); background-image: var(a); }
</style>
<body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

View File

@ -1793,6 +1793,7 @@ fuzzy-if(OSX==10.6,2,30) skip-if(B2G&&browserIsRemote) == 933264-1.html 933264-1
== 953334-win32-clipping.html 953334-win32-clipping-ref.html
== 956513-1.svg 956513-1-ref.svg
== 944291-1.html 944291-1-ref.html
== 950436-1.html 950436-1-ref.html
== 957770-1.svg 957770-1-ref.svg
== 960277-1.html 960277-1-ref.html
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,10) == 966992-1.html 966992-1-ref.html

View File

@ -48,19 +48,27 @@ ShouldIgnoreColors(nsRuleData *aRuleData)
* Image sources are specified by |url()| or |-moz-image-rect()| function.
*/
static void
TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument)
TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument,
nsCSSValueTokenStream* aTokenStream)
{
MOZ_ASSERT(aDocument);
if (aValue.GetUnit() == eCSSUnit_URL) {
aValue.StartImageLoad(aDocument);
if (aTokenStream) {
aTokenStream->mImageValues.PutEntry(aValue.GetImageStructValue());
}
}
else if (aValue.GetUnit() == eCSSUnit_Image) {
// If we already have a request, see if this document needs to clone it.
imgIRequest* request = aValue.GetImageValue(nullptr);
if (request) {
aDocument->StyleImageLoader()->MaybeRegisterCSSImage(aValue.GetImageStructValue());
mozilla::css::ImageValue* imageValue = aValue.GetImageStructValue();
aDocument->StyleImageLoader()->MaybeRegisterCSSImage(imageValue);
if (aTokenStream) {
aTokenStream->mImageValues.PutEntry(imageValue);
}
}
}
else if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
@ -68,25 +76,27 @@ TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument)
NS_ABORT_IF_FALSE(arguments->Count() == 6, "unexpected num of arguments");
const nsCSSValue& image = arguments->Item(1);
TryToStartImageLoadOnValue(image, aDocument);
TryToStartImageLoadOnValue(image, aDocument, aTokenStream);
}
}
static void
TryToStartImageLoad(const nsCSSValue& aValue, nsIDocument* aDocument,
nsCSSProperty aProperty)
nsCSSProperty aProperty,
nsCSSValueTokenStream* aTokenStream)
{
if (aValue.GetUnit() == eCSSUnit_List) {
for (const nsCSSValueList* l = aValue.GetListValue(); l; l = l->mNext) {
TryToStartImageLoad(l->mValue, aDocument, aProperty);
TryToStartImageLoad(l->mValue, aDocument, aProperty, aTokenStream);
}
} else if (nsCSSProps::PropHasFlags(aProperty,
CSS_PROPERTY_IMAGE_IS_IN_ARRAY_0)) {
if (aValue.GetUnit() == eCSSUnit_Array) {
TryToStartImageLoadOnValue(aValue.GetArrayValue()->Item(0), aDocument);
TryToStartImageLoadOnValue(aValue.GetArrayValue()->Item(0), aDocument,
aTokenStream);
}
} else {
TryToStartImageLoadOnValue(aValue, aDocument);
TryToStartImageLoadOnValue(aValue, aDocument, aTokenStream);
}
}
@ -111,9 +121,28 @@ MapSinglePropertyInto(nsCSSProperty aProp,
nsRuleData* aRuleData)
{
NS_ABORT_IF_FALSE(aValue->GetUnit() != eCSSUnit_Null, "oops");
// Although aTarget is the nsCSSValue we are going to write into,
// we also look at its value before writing into it. This is done
// when aTarget is a token stream value, which is the case when we
// have just re-parsed a property that had a variable reference (in
// nsCSSParser::ParsePropertyWithVariableReferences). TryToStartImageLoad
// then records any resulting ImageValue objects on the
// nsCSSValueTokenStream object we found on aTarget. See the comment
// above nsCSSValueTokenStream::mImageValues for why.
NS_ABORT_IF_FALSE(aTarget->GetUnit() == eCSSUnit_TokenStream ||
aTarget->GetUnit() == eCSSUnit_Null,
"aTarget must only be a token stream (when re-parsing "
"properties with variable references) or null");
nsCSSValueTokenStream* tokenStream =
aTarget->GetUnit() == eCSSUnit_TokenStream ?
aTarget->GetTokenStreamValue() :
nullptr;
if (ShouldStartImageLoads(aRuleData, aProp)) {
nsIDocument* doc = aRuleData->mPresContext->Document();
TryToStartImageLoad(*aValue, doc, aProp);
TryToStartImageLoad(*aValue, doc, aProp, tokenStream);
}
*aTarget = *aValue;
if (nsCSSProps::PropHasFlags(aProp,

View File

@ -1355,6 +1355,18 @@ struct nsCSSValueTokenStream {
uint32_t mLineNumber;
uint32_t mLineOffset;
// This table is used to hold a reference on to any ImageValue that results
// from re-parsing this token stream at computed value time. When properties
// like background-image contain a normal url(), the Declaration's data block
// will hold a reference to the ImageValue. When a token stream is used,
// the Declaration only holds on to this nsCSSValueTokenStream object, and
// the ImageValue would only exist for the duration of
// nsRuleNode::WalkRuleTree, in the AutoCSSValueArray. So instead when
// we re-parse a token stream and get an ImageValue, we record it in this
// table so that the Declaration can be the object that keeps holding
// a reference to it.
nsTHashtable<nsRefPtrHashKey<mozilla::css::ImageValue> > mImageValues;
private:
nsCSSValueTokenStream(const nsCSSValueTokenStream& aOther) MOZ_DELETE;
nsCSSValueTokenStream& operator=(const nsCSSValueTokenStream& aOther) MOZ_DELETE;

View File

@ -2073,6 +2073,14 @@ nsRuleNode::ResolveVariableReferences(const nsStyleStructID aSID,
&aContext->StyleVariables()->mVariables;
nsCSSValueTokenStream* tokenStream = value->GetTokenStreamValue();
// Note that ParsePropertyWithVariableReferences relies on the fact
// that the nsCSSValue in aRuleData for the property we are re-parsing
// is still the token stream value. When
// ParsePropertyWithVariableReferences calls
// nsCSSExpandedDataBlock::MapRuleInfoInto, that function will add
// the ImageValue that is created into the token stream object's
// mImageValues table; see the comment above mImageValues for why.
// XXX Should pass in sheet here (see bug 952338).
parser.ParsePropertyWithVariableReferences(
tokenStream->mPropertyID, tokenStream->mShorthandPropertyID,