--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -803,16 +803,18 @@ public:
// together.
PRPackedBool mFixedPosIsAbsPos;
// A boolean to indicate whether we have a "pending" popupgroup. That is, we
// have already created the FrameConstructionItem for the root popupgroup but
// we have not yet created the relevant frame.
PRPackedBool mHavePendingPopupgroup;
+ nsCOMArray<nsIContent> mGeneratedTextNodesWithInitializer;
+
// Constructor
// Use the passed-in history state.
nsFrameConstructorState(nsIPresShell* aPresShell,
nsIFrame* aFixedContainingBlock,
nsIFrame* aAbsoluteContainingBlock,
nsIFrame* aFloatContainingBlock,
nsILayoutHistoryState* aHistoryState);
// Get the history state from the pres context's pres shell.
@@ -978,16 +980,20 @@ nsFrameConstructorState::~nsFrameConstru
// items whose containing block is outside the abs-pos frames.
MOZ_COUNT_DTOR(nsFrameConstructorState);
ProcessFrameInsertions(mFloatedItems, nsGkAtoms::floatList);
ProcessFrameInsertions(mAbsoluteItems, nsGkAtoms::absoluteList);
ProcessFrameInsertions(mFixedItems, nsGkAtoms::fixedList);
#ifdef MOZ_XUL
ProcessFrameInsertions(mPopupItems, nsGkAtoms::popupList);
#endif
+ for (PRInt32 i = mGeneratedTextNodesWithInitializer.Count() - 1; i >= 0; --i) {
+ mGeneratedTextNodesWithInitializer[i]->
+ DeleteProperty(nsGkAtoms::genConInitializerProperty);
+ }
}
static nsIFrame*
AdjustAbsoluteContainingBlock(nsIFrame* aContainingBlockIn)
{
if (!aContainingBlockIn) {
return nsnull;
}
@@ -1638,17 +1644,18 @@ DestroyGenConInitializer(void* aFrame
nsIAtom* aPropertyName,
void* aPropertyValue,
void* aDtorData)
{
delete static_cast<nsGenConInitializer*>(aPropertyValue);
}
already_AddRefed<nsIContent>
-nsCSSFrameConstructor::CreateGenConTextNode(const nsString& aString,
+nsCSSFrameConstructor::CreateGenConTextNode(nsFrameConstructorState& aState,
+ const nsString& aString,
nsCOMPtr<nsIDOMCharacterData>* aText,
nsGenConInitializer* aInitializer)
{
nsCOMPtr<nsIContent> content;
NS_NewTextNode(getter_AddRefs(content), mDocument->NodeInfoManager());
if (!content) {
// XXX The quotes/counters code doesn't like the text pointer
// being null in case of dynamic changes!
@@ -1657,22 +1664,24 @@ nsCSSFrameConstructor::CreateGenConTextN
}
content->SetText(aString, PR_FALSE);
if (aText) {
*aText = do_QueryInterface(content);
}
if (aInitializer) {
content->SetProperty(nsGkAtoms::genConInitializerProperty, aInitializer,
DestroyGenConInitializer);
+ aState.mGeneratedTextNodesWithInitializer.AppendObject(content);
}
return content.forget();
}
already_AddRefed<nsIContent>
-nsCSSFrameConstructor::CreateGeneratedContent(nsIContent* aParentContent,
+nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
+ nsIContent* aParentContent,
nsStyleContext* aStyleContext,
PRUint32 aContentIndex)
{
// Get the content value
const nsStyleContentData &data =
aStyleContext->GetStyleContent()->ContentAt(aContentIndex);
nsStyleContentType type = data.mType;
@@ -1693,18 +1702,19 @@ nsCSSFrameConstructor::CreateGeneratedCo
nsCOMPtr<nsIContent> content;
NS_NewGenConImageContent(getter_AddRefs(content), nodeInfo,
data.mContent.mImage);
return content.forget();
}
switch (type) {
case eStyleContentType_String:
- return CreateGenConTextNode(nsDependentString(data.mContent.mString), nsnull,
- nsnull);
+ return CreateGenConTextNode(aState,
+ nsDependentString(data.mContent.mString),
+ nsnull, nsnull);
case eStyleContentType_Attr:
{
nsCOMPtr<nsIAtom> attrName;
PRInt32 attrNameSpace = kNameSpaceID_None;
nsAutoString contentString(data.mContent.mString);
PRInt32 barIndex = contentString.FindChar('|'); // CSS namespace delimiter
if (-1 != barIndex) {
@@ -1744,17 +1754,18 @@ nsCSSFrameConstructor::CreateGeneratedCo
new nsCounterUseNode(counters, aContentIndex,
type == eStyleContentType_Counters);
if (!node)
return nsnull;
nsGenConInitializer* initializer =
new nsGenConInitializer(node, counterList,
&nsCSSFrameConstructor::CountersDirty);
- return CreateGenConTextNode(EmptyString(), &node->mText, initializer);
+ return CreateGenConTextNode(aState, EmptyString(), &node->mText,
+ initializer);
}
case eStyleContentType_Image:
NS_NOTREACHED("handled by if above");
return nsnull;
case eStyleContentType_OpenQuote:
case eStyleContentType_CloseQuote:
@@ -1764,17 +1775,18 @@ nsCSSFrameConstructor::CreateGeneratedCo
nsQuoteNode* node =
new nsQuoteNode(type, aContentIndex);
if (!node)
return nsnull;
nsGenConInitializer* initializer =
new nsGenConInitializer(node, &mQuoteList,
&nsCSSFrameConstructor::QuotesDirty);
- return CreateGenConTextNode(EmptyString(), &node->mText, initializer);
+ return CreateGenConTextNode(aState, EmptyString(), &node->mText,
+ initializer);
}
case eStyleContentType_AltContent:
{
// Use the "alt" attribute; if that fails and the node is an HTML
// <input>, try the value attribute and then fall back to some default
// localized text we have.
// XXX what if the 'alt' attribute is added later, how will we
@@ -1793,17 +1805,17 @@ nsCSSFrameConstructor::CreateGeneratedCo
NS_NewAttributeContent(mDocument->NodeInfoManager(),
kNameSpaceID_None, nsGkAtoms::value, getter_AddRefs(content));
return content.forget();
}
nsXPIDLString temp;
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
"Submit", temp);
- return CreateGenConTextNode(temp, nsnull, nsnull);
+ return CreateGenConTextNode(aState, temp, nsnull, nsnull);
}
break;
}
} // switch
return nsnull;
}
@@ -1861,17 +1873,18 @@ nsCSSFrameConstructor::CreateGeneratedCo
if (NS_FAILED(rv)) {
container->UnbindFromTree();
return;
}
PRUint32 contentCount = pseudoStyleContext->GetStyleContent()->ContentCount();
for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) {
nsCOMPtr<nsIContent> content =
- CreateGeneratedContent(aParentContent, pseudoStyleContext, contentIndex);
+ CreateGeneratedContent(aState, aParentContent, pseudoStyleContext,
+ contentIndex);
if (content) {
container->AppendChildTo(content, PR_FALSE);
}
}
AddFrameConstructionItemsInternal(aState, container, aParentFrame, elemName,
kNameSpaceID_None, -1, pseudoStyleContext,
ITEM_IS_GENERATED_CONTENT, aItems);
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -458,30 +458,32 @@ private:
nsCOMArray<nsIContent>& aGeneratedContent,
nsIContent** aNewContent,
nsIFrame** aNewFrame);
/**
* Create a text node containing the given string. If aText is non-null
* then we also set aText to the returned node.
*/
- already_AddRefed<nsIContent> CreateGenConTextNode(const nsString& aString,
+ already_AddRefed<nsIContent> CreateGenConTextNode(nsFrameConstructorState& aState,
+ const nsString& aString,
nsCOMPtr<nsIDOMCharacterData>* aText,
nsGenConInitializer* aInitializer);
/**
* Create a content node for the given generated content style.
* The caller takes care of making it SetNativeAnonymous, binding it
* to the document, and creating frames for it.
* @param aParentContent is the node that has the before/after style
* @param aStyleContext is the 'before' or 'after' pseudo-element
* style context
* @param aContentIndex is the index of the content item to create
*/
- already_AddRefed<nsIContent> CreateGeneratedContent(nsIContent* aParentContent,
+ already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState,
+ nsIContent* aParentContent,
nsStyleContext* aStyleContext,
PRUint32 aContentIndex);
// aFrame may be null; this method doesn't use it directly in any case.
void CreateGeneratedContentItem(nsFrameConstructorState& aState,
nsIFrame* aFrame,
nsIContent* aContent,
nsStyleContext* aStyleContext,