Bug 534566. Use separate nsPropertyTables for different categories so we don't pollute the property name list with unrelated names. r=sicking

This commit is contained in:
Robert O'Callahan 2010-04-23 14:41:38 +12:00
Родитель c29e28bbd0
Коммит 1cabbb443f
10 изменённых файлов: 137 добавлений и 177 удалений

Просмотреть файл

@ -816,7 +816,16 @@ public:
*/
virtual PRInt32 GetDefaultNamespaceID() const = 0;
nsPropertyTable* PropertyTable() { return &mPropertyTable; }
void DeleteAllProperties();
void DeleteAllPropertiesFor(nsINode* aNode);
nsPropertyTable* PropertyTable(PRUint16 aCategory) {
if (aCategory == 0)
return &mPropertyTable;
return GetExtraPropertyTable(aCategory);
}
PRUint32 GetPropertyTableCount()
{ return mExtraPropertyTables.Length() + 1; }
/**
* Sets the ID used to identify this part of the multipart document
@ -1356,6 +1365,8 @@ protected:
// want to expose to users of the nsIDocument API outside of Gecko.
}
nsPropertyTable* GetExtraPropertyTable(PRUint16 aCategory);
// Never ever call this. Only call GetInnerWindow!
virtual nsPIDOMWindow *GetInnerWindowInternal() = 0;
@ -1405,6 +1416,7 @@ protected:
// Table of element properties for this document.
nsPropertyTable mPropertyTable;
nsTArray<nsAutoPtr<nsPropertyTable> > mExtraPropertyTables;
// Compatibility mode
nsCompatibility mCompatMode;

Просмотреть файл

@ -249,6 +249,14 @@ private:
static PRUint32 sMutationCount;
};
// Categories of node properties
// 0 is global.
#define DOM_USER_DATA 1
#define DOM_USER_DATA_HANDLER 2
#ifdef MOZ_SMIL
#define SMIL_MAPPED_ATTR_ANIMVAL 3
#endif // MOZ_SMIL
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0xbc347b50, 0xa9b8, 0x419e, \

Просмотреть файл

@ -160,7 +160,7 @@ nsDOMAttribute::SetOwnerDocument(nsIDocument* aDocument)
nsIDocument *doc = GetOwnerDoc();
NS_ASSERTION(doc != aDocument, "bad call to nsDOMAttribute::SetOwnerDocument");
if (doc) {
doc->PropertyTable()->DeleteAllPropertiesFor(this);
doc->DeleteAllPropertiesFor(this);
}
nsCOMPtr<nsINodeInfo> newNodeInfo;

Просмотреть файл

@ -1786,6 +1786,32 @@ nsDocument::Init()
return NS_OK;
}
void
nsIDocument::DeleteAllProperties()
{
for (PRUint32 i = 0; i < GetPropertyTableCount(); ++i) {
PropertyTable(i)->DeleteAllProperties();
}
}
void
nsIDocument::DeleteAllPropertiesFor(nsINode* aNode)
{
for (PRUint32 i = 0; i < GetPropertyTableCount(); ++i) {
PropertyTable(i)->DeleteAllPropertiesFor(aNode);
}
}
nsPropertyTable*
nsIDocument::GetExtraPropertyTable(PRUint16 aCategory)
{
NS_ASSERTION(aCategory > 0, "Category 0 should have already been handled");
while (aCategory - 1 >= mExtraPropertyTables.Length()) {
mExtraPropertyTables.AppendElement(new nsPropertyTable());
}
return mExtraPropertyTables[aCategory - 1];
}
nsresult
nsDocument::AddXMLEventsContent(nsIContent *aXMLEventsElement)
{
@ -6120,35 +6146,40 @@ nsDocument::AdoptNode(nsIDOMNode *aAdoptedNode, nsIDOMNode **aResult)
BlastSubtreeToPieces(adoptedNode);
if (!sameDocument && oldDocument) {
PRUint32 i, count = nodesWithProperties.Count();
for (i = 0; i < count; ++i) {
// Remove all properties.
oldDocument->PropertyTable()->
DeleteAllPropertiesFor(nodesWithProperties[i]);
PRUint32 count = nodesWithProperties.Count();
for (PRUint32 j = 0; j < oldDocument->GetPropertyTableCount(); ++j) {
for (PRUint32 i = 0; i < count; ++i) {
// Remove all properties.
oldDocument->PropertyTable(j)->
DeleteAllPropertiesFor(nodesWithProperties[i]);
}
}
}
return rv;
}
PRUint32 i, count = nodesWithProperties.Count();
PRUint32 count = nodesWithProperties.Count();
if (!sameDocument && oldDocument) {
nsPropertyTable *oldTable = oldDocument->PropertyTable();
nsPropertyTable *newTable = PropertyTable();
for (i = 0; i < count; ++i) {
rv = oldTable->TransferOrDeleteAllPropertiesFor(nodesWithProperties[i],
newTable);
if (NS_FAILED(rv)) {
while (++i < count) {
for (PRUint32 j = 0; j < oldDocument->GetPropertyTableCount(); ++j) {
nsPropertyTable *oldTable = oldDocument->PropertyTable(j);
nsPropertyTable *newTable = PropertyTable(j);
for (PRUint32 i = 0; i < count; ++i) {
if (NS_SUCCEEDED(rv)) {
rv = oldTable->TransferOrDeleteAllPropertiesFor(nodesWithProperties[i],
newTable);
} else {
oldTable->DeleteAllPropertiesFor(nodesWithProperties[i]);
}
// Disconnect all nodes from their parents.
BlastSubtreeToPieces(adoptedNode);
return rv;
}
}
if (NS_FAILED(rv)) {
// Disconnect all nodes from their parents.
BlastSubtreeToPieces(adoptedNode);
return rv;
}
}
rv = nsNodeUtils::CallUserDataHandlers(nodesWithProperties, this,

Просмотреть файл

@ -209,8 +209,8 @@ nsINode::GetProperty(PRUint16 aCategory, nsIAtom *aPropertyName,
if (!doc)
return nsnull;
return doc->PropertyTable()->GetProperty(this, aCategory, aPropertyName,
aStatus);
return doc->PropertyTable(aCategory)->GetProperty(this, aPropertyName,
aStatus);
}
nsresult
@ -222,9 +222,9 @@ nsINode::SetProperty(PRUint16 aCategory, nsIAtom *aPropertyName, void *aValue,
if (!doc)
return NS_ERROR_FAILURE;
nsresult rv = doc->PropertyTable()->SetProperty(this, aCategory,
aPropertyName, aValue, aDtor,
nsnull, aTransfer, aOldValue);
nsresult rv = doc->PropertyTable(aCategory)->SetProperty(this,
aPropertyName, aValue, aDtor,
nsnull, aTransfer, aOldValue);
if (NS_SUCCEEDED(rv)) {
SetFlags(NODE_HAS_PROPERTIES);
}
@ -239,7 +239,7 @@ nsINode::DeleteProperty(PRUint16 aCategory, nsIAtom *aPropertyName)
if (!doc)
return nsnull;
return doc->PropertyTable()->DeleteProperty(this, aCategory, aPropertyName);
return doc->PropertyTable(aCategory)->DeleteProperty(this, aPropertyName);
}
void*
@ -250,8 +250,8 @@ nsINode::UnsetProperty(PRUint16 aCategory, nsIAtom *aPropertyName,
if (!doc)
return nsnull;
return doc->PropertyTable()->UnsetProperty(this, aCategory, aPropertyName,
aStatus);
return doc->PropertyTable(aCategory)->UnsetProperty(this, aPropertyName,
aStatus);
}
nsIEventListenerManager*

Просмотреть файл

@ -223,7 +223,7 @@ nsNodeUtils::LastRelease(nsINode* aNode)
// Delete all properties before tearing down the document. Some of the
// properties are bound to nsINode objects and the destructor functions of
// the properties may want to use the owner document of the nsINode.
static_cast<nsIDocument*>(aNode)->PropertyTable()->DeleteAllProperties();
static_cast<nsIDocument*>(aNode)->DeleteAllProperties();
}
else {
if (aNode->HasProperties()) {
@ -231,7 +231,7 @@ nsNodeUtils::LastRelease(nsINode* aNode)
// delete the document.
nsCOMPtr<nsIDocument> document = aNode->GetOwnerDoc();
if (document) {
document->PropertyTable()->DeleteAllPropertiesFor(aNode);
document->DeleteAllPropertiesFor(aNode);
}
}
@ -386,7 +386,7 @@ nsNodeUtils::CallUserDataHandlers(nsCOMArray<nsINode> &aNodesWithProperties,
"Expected aNodesWithProperties to contain original and "
"cloned nodes.");
nsPropertyTable *table = aOwnerDocument->PropertyTable();
nsPropertyTable *table = aOwnerDocument->PropertyTable(DOM_USER_DATA_HANDLER);
// Keep the document alive, just in case one of the handlers causes it to go
// away.
@ -408,8 +408,7 @@ nsNodeUtils::CallUserDataHandlers(nsCOMArray<nsINode> &aNodesWithProperties,
NS_ENSURE_SUCCESS(rv, rv);
}
table->Enumerate(nodeWithProperties, DOM_USER_DATA_HANDLER, CallHandler,
&handlerData);
table->Enumerate(nodeWithProperties, CallHandler, &handlerData);
}
return NS_OK;
@ -434,10 +433,8 @@ nsNodeUtils::TraverseUserData(nsINode* aNode,
return;
}
nsPropertyTable *table = ownerDoc->PropertyTable();
table->Enumerate(aNode, DOM_USER_DATA, NoteUserData, &aCb);
table->Enumerate(aNode, DOM_USER_DATA_HANDLER, NoteUserData, &aCb);
ownerDoc->PropertyTable(DOM_USER_DATA)->Enumerate(aNode, NoteUserData, &aCb);
ownerDoc->PropertyTable(DOM_USER_DATA_HANDLER)->Enumerate(aNode, NoteUserData, &aCb);
}
/* static */
@ -755,8 +752,7 @@ nsNodeUtils::UnlinkUserData(nsINode *aNode)
// delete the document.
nsCOMPtr<nsIDocument> document = aNode->GetOwnerDoc();
if (document) {
document->PropertyTable()->DeleteAllPropertiesFor(aNode, DOM_USER_DATA);
document->PropertyTable()->DeleteAllPropertiesFor(aNode,
DOM_USER_DATA_HANDLER);
document->PropertyTable(DOM_USER_DATA)->DeleteAllPropertiesFor(aNode);
document->PropertyTable(DOM_USER_DATA_HANDLER)->DeleteAllPropertiesFor(aNode);
}
}

Просмотреть файл

@ -66,8 +66,7 @@ struct PropertyListMapEntry : public PLDHashEntryHdr {
class nsPropertyTable::PropertyList {
public:
PropertyList(PRUint16 aCategory,
nsIAtom* aName,
PropertyList(nsIAtom* aName,
NSPropertyDtorFunc aDtorFunc,
void* aDtorData,
PRBool aTransfer) NS_HIDDEN;
@ -80,16 +79,15 @@ public:
// Destroy all remaining properties (without removing them)
NS_HIDDEN_(void) Destroy();
NS_HIDDEN_(PRBool) Equals(PRUint16 aCategory, nsIAtom *aPropertyName)
NS_HIDDEN_(PRBool) Equals(nsIAtom *aPropertyName)
{
return mCategory == aCategory && mName == aPropertyName;
return mName == aPropertyName;
}
nsCOMPtr<nsIAtom> mName; // property name
PLDHashTable mObjectValueMap; // map of object/value pairs
NSPropertyDtorFunc mDtorFunc; // property specific value dtor function
void* mDtorData; // pointer to pass to dtor
PRUint16 mCategory; // category
PRPackedBool mTransfer; // whether to transfer in
// TransferOrDeleteAllPropertiesFor
@ -116,16 +114,6 @@ nsPropertyTable::DeleteAllPropertiesFor(nsPropertyOwner aObject)
}
}
void
nsPropertyTable::DeleteAllPropertiesFor(nsPropertyOwner aObject,
PRUint16 aCategory)
{
for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
if (prop->mCategory == aCategory)
prop->DeletePropertyFor(aObject);
}
}
nsresult
nsPropertyTable::TransferOrDeleteAllPropertiesFor(nsPropertyOwner aObject,
nsPropertyTable *aOtherTable)
@ -137,7 +125,7 @@ nsPropertyTable::TransferOrDeleteAllPropertiesFor(nsPropertyOwner aObject,
(PL_DHashTableOperate(&prop->mObjectValueMap, aObject,
PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
rv = aOtherTable->SetProperty(aObject, prop->mCategory, prop->mName,
rv = aOtherTable->SetProperty(aObject, prop->mName,
entry->value, prop->mDtorFunc,
prop->mDtorData, prop->mTransfer);
if (NS_FAILED(rv)) {
@ -159,26 +147,22 @@ nsPropertyTable::TransferOrDeleteAllPropertiesFor(nsPropertyOwner aObject,
}
void
nsPropertyTable::Enumerate(nsPropertyOwner aObject, PRUint16 aCategory,
nsPropertyTable::Enumerate(nsPropertyOwner aObject,
NSPropertyFunc aCallback, void *aData)
{
PropertyList* prop;
for (prop = mPropertyList; prop; prop = prop->mNext) {
if (prop->mCategory == aCategory) {
PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
(PL_DHashTableOperate(&prop->mObjectValueMap, aObject,
PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
aCallback(const_cast<void*>(aObject.get()), prop->mName, entry->value,
aData);
}
PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
(PL_DHashTableOperate(&prop->mObjectValueMap, aObject, PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
aCallback(const_cast<void*>(aObject.get()), prop->mName, entry->value,
aData);
}
}
}
void*
nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName,
PRBool aRemove,
nsresult *aResult)
@ -187,7 +171,7 @@ nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
nsresult rv = NS_PROPTABLE_PROP_NOT_THERE;
void *propValue = nsnull;
PropertyList* propertyList = GetPropertyListFor(aCategory, aPropertyName);
PropertyList* propertyList = GetPropertyListFor(aPropertyName);
if (propertyList) {
PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
(PL_DHashTableOperate(&propertyList->mObjectValueMap, aObject,
@ -210,7 +194,6 @@ nsPropertyTable::GetPropertyInternal(nsPropertyOwner aObject,
nsresult
nsPropertyTable::SetPropertyInternal(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName,
void *aPropertyValue,
NSPropertyDtorFunc aPropDtorFunc,
@ -220,7 +203,7 @@ nsPropertyTable::SetPropertyInternal(nsPropertyOwner aObject,
{
NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
PropertyList* propertyList = GetPropertyListFor(aCategory, aPropertyName);
PropertyList* propertyList = GetPropertyListFor(aPropertyName);
if (propertyList) {
// Make sure the dtor function and data and the transfer flag match
@ -232,7 +215,7 @@ nsPropertyTable::SetPropertyInternal(nsPropertyOwner aObject,
}
} else {
propertyList = new PropertyList(aCategory, aPropertyName, aPropDtorFunc,
propertyList = new PropertyList(aPropertyName, aPropDtorFunc,
aPropDtorData, aTransfer);
if (!propertyList || !propertyList->mObjectValueMap.ops) {
delete propertyList;
@ -271,12 +254,11 @@ nsPropertyTable::SetPropertyInternal(nsPropertyOwner aObject,
nsresult
nsPropertyTable::DeleteProperty(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName)
{
NS_PRECONDITION(aPropertyName && aObject, "unexpected null param");
PropertyList* propertyList = GetPropertyListFor(aCategory, aPropertyName);
PropertyList* propertyList = GetPropertyListFor(aPropertyName);
if (propertyList) {
if (propertyList->DeletePropertyFor(aObject))
return NS_OK;
@ -286,13 +268,12 @@ nsPropertyTable::DeleteProperty(nsPropertyOwner aObject,
}
nsPropertyTable::PropertyList*
nsPropertyTable::GetPropertyListFor(PRUint16 aCategory,
nsIAtom* aPropertyName) const
nsPropertyTable::GetPropertyListFor(nsIAtom* aPropertyName) const
{
PropertyList* result;
for (result = mPropertyList; result; result = result->mNext) {
if (result->Equals(aCategory, aPropertyName)) {
if (result->Equals(aPropertyName)) {
break;
}
}
@ -302,15 +283,13 @@ nsPropertyTable::GetPropertyListFor(PRUint16 aCategory,
//----------------------------------------------------------------------
nsPropertyTable::PropertyList::PropertyList(PRUint16 aCategory,
nsIAtom *aName,
nsPropertyTable::PropertyList::PropertyList(nsIAtom *aName,
NSPropertyDtorFunc aDtorFunc,
void *aDtorData,
PRBool aTransfer)
: mName(aName),
mDtorFunc(aDtorFunc),
mDtorData(aDtorData),
mCategory(aCategory),
mTransfer(aTransfer),
mNext(nsnull)
{

Просмотреть файл

@ -94,14 +94,6 @@ private:
const void* mObject;
};
// Categories of properties
// 0 is global.
#define DOM_USER_DATA 1
#define DOM_USER_DATA_HANDLER 2
#ifdef MOZ_SMIL
#define SMIL_MAPPED_ATTR_ANIMVAL 3
#endif // MOZ_SMIL
class nsPropertyTable
{
public:
@ -113,20 +105,11 @@ class nsPropertyTable
nsIAtom *aPropertyName,
nsresult *aResult = nsnull)
{
return GetPropertyInternal(aObject, 0, aPropertyName, PR_FALSE, aResult);
}
void* GetProperty(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName,
nsresult *aResult = nsnull)
{
return GetPropertyInternal(aObject, aCategory, aPropertyName, PR_FALSE,
aResult);
return GetPropertyInternal(aObject, aPropertyName, PR_FALSE, aResult);
}
/**
* Set the value of the property |aPropertyName| in the global category to
* Set the value of the property |aPropertyName| to
* |aPropertyValue| for node |aObject|. |aDtor| is a destructor for the
* property value to be called if the property is removed. It can be null
* if no destructor is required. |aDtorData| is an optional pointer to an
@ -150,57 +133,15 @@ class nsPropertyTable
PRBool aTransfer = PR_FALSE,
void **aOldValue = nsnull)
{
return SetPropertyInternal(aObject, 0, aPropertyName, aPropertyValue,
return SetPropertyInternal(aObject, aPropertyName, aPropertyValue,
aDtor, aDtorData, aTransfer, aOldValue);
}
/**
* Set the value of the property |aPropertyName| in the category |aCategory|
* to |aPropertyValue| for node |aObject|. |aDtor| is a destructor for the
* property value to be called if the property is removed. It can be null
* if no destructor is required. |aDtorData| is an optional pointer to an
* opaque context to be passed to the property destructor. Note that the
* destructor is global for each property name regardless of node; it is an
* error to set a given property with a different destructor than was used
* before (this will return NS_ERROR_INVALID_ARG). If aOldValue is non-null
* it will contain the old value after the function returns (the destructor
* for the old value will not be run in that case). If aTransfer is PR_TRUE
* the property will be transfered to the new table when the property table
* for |aObject| changes (currently the tables for nodes are owned by their
* ownerDocument, so if the ownerDocument for a node changes, its property
* table changes too). If |aTransfer| is PR_FALSE the property will just be
* deleted instead.
*/
NS_HIDDEN_(nsresult) SetProperty(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName,
void *aPropertyValue,
NSPropertyDtorFunc aDtor,
void *aDtorData,
PRBool aTransfer = PR_FALSE,
void **aOldValue = nsnull)
{
return SetPropertyInternal(aObject, aCategory, aPropertyName,
aPropertyValue, aDtor, aDtorData, aTransfer,
aOldValue);
}
/**
* Delete the property |aPropertyName| in the global category for object
* |aObject|. The property's destructor function will be called.
*/
NS_HIDDEN_(nsresult) DeleteProperty(nsPropertyOwner aObject,
nsIAtom *aPropertyName)
{
return DeleteProperty(aObject, 0, aPropertyName);
}
/**
* Delete the property |aPropertyName| in category |aCategory| for object
* |aObject|. The property's destructor function will be called.
*/
NS_HIDDEN_(nsresult) DeleteProperty(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName);
/**
@ -212,21 +153,7 @@ class nsPropertyTable
nsIAtom *aPropertyName,
nsresult *aStatus = nsnull)
{
return GetPropertyInternal(aObject, 0, aPropertyName, PR_TRUE, aStatus);
}
/**
* Unset the property |aPropertyName| in category |aCategory| for object
* |aObject|, but do not call the property's destructor function. The
* property value is returned.
*/
void* UnsetProperty(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName,
nsresult *aStatus = nsnull)
{
return GetPropertyInternal(aObject, aCategory, aPropertyName, PR_TRUE,
aStatus);
return GetPropertyInternal(aObject, aPropertyName, PR_TRUE, aStatus);
}
/**
@ -235,13 +162,6 @@ class nsPropertyTable
*/
NS_HIDDEN_(void) DeleteAllPropertiesFor(nsPropertyOwner aObject);
/**
* Deletes all of the properties in category |aCategory| for object |aObject|,
* calling the destructor function for each property.
*/
NS_HIDDEN_(void) DeleteAllPropertiesFor(nsPropertyOwner aObject,
PRUint16 aCategory);
/**
* Transfers all properties for object |aObject| that were set with the
* |aTransfer| argument as PR_TRUE to |aTable|. Deletes the other properties
@ -254,11 +174,11 @@ class nsPropertyTable
nsPropertyTable *aOtherTable);
/**
* Enumerate the properties in category |aCategory| for object |aObject|.
* Enumerate the properties for object |aObject|.
* For every property |aCallback| will be called with as arguments |aObject|,
* the property name, the property value and |aData|.
*/
NS_HIDDEN_(void) Enumerate(nsPropertyOwner aObject, PRUint16 aCategory,
NS_HIDDEN_(void) Enumerate(nsPropertyOwner aObject,
NSPropertyFunc aCallback, void *aData);
/**
@ -267,6 +187,7 @@ class nsPropertyTable
*/
NS_HIDDEN_(void) DeleteAllProperties();
nsPropertyTable() : mPropertyList(nsnull) {}
~nsPropertyTable() {
DeleteAllProperties();
}
@ -283,15 +204,12 @@ class nsPropertyTable
private:
NS_HIDDEN_(void) DestroyPropertyList();
NS_HIDDEN_(PropertyList*) GetPropertyListFor(PRUint16 aCategory,
nsIAtom *aPropertyName) const;
NS_HIDDEN_(PropertyList*) GetPropertyListFor(nsIAtom *aPropertyName) const;
NS_HIDDEN_(void*) GetPropertyInternal(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName,
PRBool aRemove,
nsresult *aStatus);
NS_HIDDEN_(nsresult) SetPropertyInternal(nsPropertyOwner aObject,
PRUint16 aCategory,
nsIAtom *aPropertyName,
void *aPropertyValue,
NSPropertyDtorFunc aDtor,

Просмотреть файл

@ -1250,9 +1250,8 @@ nsSVGElement::UpdateAnimatedContentStyleRule()
MappedAttrParser mappedAttrParser(doc->CSSLoader(), doc->GetDocumentURI(),
GetBaseURI(), NodePrincipal());
doc->PropertyTable()->Enumerate(this, SMIL_MAPPED_ATTR_ANIMVAL,
ParseMappedAttrAnimValueCallback,
&mappedAttrParser);
doc->PropertyTable(SMIL_MAPPED_ATTR_ANIMVAL)->
Enumerate(this, ParseMappedAttrAnimValueCallback, &mappedAttrParser);
nsRefPtr<nsICSSStyleRule>
animContentStyleRule(mappedAttrParser.CreateStyleRule());

Просмотреть файл

@ -1620,9 +1620,13 @@ SortBlitRectsForCopy(nsIntPoint aPixDelta, nsTArray<nsIntRect>* aRects)
}
static PRBool
CanScrollWithBlitting(nsIFrame* aFrame)
CanScrollWithBlitting(nsIFrame* aFrame, nsIFrame* aDisplayRoot, nsRect* aClippedScrollPort)
{
for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
nsPoint offset(0, 0);
*aClippedScrollPort = nsRect(nsPoint(0, 0), aFrame->GetSize());
for (nsIFrame* f = aFrame; f;
f = nsLayoutUtils::GetCrossDocParentFrame(f, &offset)) {
if (f->GetStyleDisplay()->HasTransform()) {
return PR_FALSE;
}
@ -1632,6 +1636,18 @@ CanScrollWithBlitting(nsIFrame* aFrame)
return PR_FALSE;
}
#endif
nsIScrollableFrame* sf = do_QueryFrame(f);
if (sf) {
// Note that this will always happen on the first iteration of the loop,
// ensuring that we clip to our own scrollframe's scrollport
aClippedScrollPort->IntersectRect(*aClippedScrollPort,
sf->GetScrollPortRect() - offset);
}
offset += f->GetPosition();
if (f == aDisplayRoot)
break;
}
return PR_TRUE;
}
@ -1658,9 +1674,11 @@ void nsGfxScrollFrameInner::ScrollVisual(nsIntPoint aPixDelta)
rootPresContext->GetPluginGeometryUpdates(mOuter, &configurations);
}
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(mOuter);
nsRect clippedScrollPort;
if (!nearestWidget ||
nearestWidget->GetTransparencyMode() == eTransparencyTransparent ||
!CanScrollWithBlitting(mOuter)) {
!CanScrollWithBlitting(mOuter, displayRoot, &clippedScrollPort)) {
// Just invalidate the frame and adjust child widgets
// Recall that our widget's origin is at our bounds' top-left
if (nearestWidget) {
@ -1672,7 +1690,6 @@ void nsGfxScrollFrameInner::ScrollVisual(nsIntPoint aPixDelta)
mOuter->InvalidateWithFlags(mScrollPort,
nsIFrame::INVALIDATE_REASON_SCROLL_REPAINT);
} else {
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(mOuter);
nsRegion blitRegion;
nsRegion repaintRegion;
nsPresContext* presContext = mOuter->PresContext();
@ -1681,7 +1698,7 @@ void nsGfxScrollFrameInner::ScrollVisual(nsIntPoint aPixDelta)
nsPoint offsetToDisplayRoot = mOuter->GetOffsetTo(displayRoot);
nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
nsRect scrollPort =
(mScrollPort + offsetToDisplayRoot).ToNearestPixels(appUnitsPerDevPixel).
(clippedScrollPort + offsetToDisplayRoot).ToNearestPixels(appUnitsPerDevPixel).
ToAppUnits(appUnitsPerDevPixel);
nsresult rv =
nsLayoutUtils::ComputeRepaintRegionForCopy(displayRoot, mScrolledFrame,