Fix for bug 603844 (Leak txUnknownHandler+ with transformToDocument(textnode)). r=sicking a=b:final

This commit is contained in:
Peter Van der Beken 2010-12-02 11:12:27 -05:00
Родитель c13f3e04fa
Коммит 6b75d0f84f
9 изменённых файлов: 94 добавлений и 85 удалений

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

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
function boom()
{
var frame = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
frame.onload = y;
frame.src = "data:text/plain,0";
document.body.appendChild(frame);
frameDoc = frame.contentDocument;
function y()
{
frameDoc.removeChild(frameDoc.documentElement);
var xp = new XSLTProcessor;
xp.importStylesheet(frameDoc);
try {
xp.transformToDocument(frameDoc.createTextNode('x'));
} catch(e) { }
document.documentElement.removeAttribute("class");
}
}
</script>
</head>
<body onload="boom();"></body>
</html>

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

@ -11,3 +11,4 @@ load 528488.xml
load 528963.xml load 528963.xml
load 545927.html load 545927.html
load 601543.html load 601543.html
load 603844.html

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

@ -359,122 +359,103 @@ txResultBuffer::addTransaction(txOutputTransaction* aTransaction)
return NS_OK; return NS_OK;
} }
struct Holder static nsresult
flushTransaction(txOutputTransaction* aTransaction,
txAXMLEventHandler* aHandler,
nsAFlatString::const_char_iterator& aIter)
{ {
txAXMLEventHandler** mHandler; switch (aTransaction->mType) {
nsresult mResult;
nsAFlatString::const_char_iterator mIter;
};
static PRBool
flushTransaction(txOutputTransaction* aElement, Holder* aData)
{
Holder* holder = aData;
txAXMLEventHandler* handler = *holder->mHandler;
txOutputTransaction* transaction = aElement;
nsresult rv;
switch (transaction->mType) {
case txOutputTransaction::eAttributeAtomTransaction: case txOutputTransaction::eAttributeAtomTransaction:
{ {
txAttributeAtomTransaction* transaction = txAttributeAtomTransaction* transaction =
static_cast<txAttributeAtomTransaction*>(aElement); static_cast<txAttributeAtomTransaction*>(aTransaction);
rv = handler->attribute(transaction->mPrefix, return aHandler->attribute(transaction->mPrefix,
transaction->mLocalName, transaction->mLocalName,
transaction->mLowercaseLocalName, transaction->mLowercaseLocalName,
transaction->mNsID, transaction->mNsID,
transaction->mValue); transaction->mValue);
break;
} }
case txOutputTransaction::eAttributeTransaction: case txOutputTransaction::eAttributeTransaction:
{ {
txAttributeTransaction* attrTransaction = txAttributeTransaction* attrTransaction =
static_cast<txAttributeTransaction*>(aElement); static_cast<txAttributeTransaction*>(aTransaction);
rv = handler->attribute(attrTransaction->mPrefix, return aHandler->attribute(attrTransaction->mPrefix,
attrTransaction->mLocalName, attrTransaction->mLocalName,
attrTransaction->mNsID, attrTransaction->mNsID,
attrTransaction->mValue); attrTransaction->mValue);
break;
} }
case txOutputTransaction::eCharacterTransaction: case txOutputTransaction::eCharacterTransaction:
case txOutputTransaction::eCharacterNoOETransaction: case txOutputTransaction::eCharacterNoOETransaction:
{ {
txCharacterTransaction* charTransaction = txCharacterTransaction* charTransaction =
static_cast<txCharacterTransaction*>(aElement); static_cast<txCharacterTransaction*>(aTransaction);
nsAFlatString::const_char_iterator& start = nsAFlatString::const_char_iterator& start = aIter;
holder->mIter;
nsAFlatString::const_char_iterator end = nsAFlatString::const_char_iterator end =
start + charTransaction->mLength; start + charTransaction->mLength;
rv = handler->characters(Substring(start, end), aIter = end;
transaction->mType == return aHandler->characters(Substring(start, end),
txOutputTransaction::eCharacterNoOETransaction); aTransaction->mType ==
start = end; txOutputTransaction::eCharacterNoOETransaction);
break;
} }
case txOutputTransaction::eCommentTransaction: case txOutputTransaction::eCommentTransaction:
{ {
txCommentTransaction* commentTransaction = txCommentTransaction* commentTransaction =
static_cast<txCommentTransaction*>(aElement); static_cast<txCommentTransaction*>(aTransaction);
rv = handler->comment(commentTransaction->mValue); return aHandler->comment(commentTransaction->mValue);
break;
} }
case txOutputTransaction::eEndElementTransaction: case txOutputTransaction::eEndElementTransaction:
{ {
rv = handler->endElement(); return aHandler->endElement();
break;
} }
case txOutputTransaction::ePITransaction: case txOutputTransaction::ePITransaction:
{ {
txPITransaction* piTransaction = txPITransaction* piTransaction =
static_cast<txPITransaction*>(aElement); static_cast<txPITransaction*>(aTransaction);
rv = handler->processingInstruction(piTransaction->mTarget, return aHandler->processingInstruction(piTransaction->mTarget,
piTransaction->mData); piTransaction->mData);
break;
} }
case txOutputTransaction::eStartDocumentTransaction: case txOutputTransaction::eStartDocumentTransaction:
{ {
rv = handler->startDocument(); return aHandler->startDocument();
break;
} }
case txOutputTransaction::eStartElementAtomTransaction: case txOutputTransaction::eStartElementAtomTransaction:
{ {
txStartElementAtomTransaction* transaction = txStartElementAtomTransaction* transaction =
static_cast<txStartElementAtomTransaction*>(aElement); static_cast<txStartElementAtomTransaction*>(aTransaction);
rv = handler->startElement(transaction->mPrefix, return aHandler->startElement(transaction->mPrefix,
transaction->mLocalName, transaction->mLocalName,
transaction->mLowercaseLocalName, transaction->mLowercaseLocalName,
transaction->mNsID); transaction->mNsID);
break;
} }
case txOutputTransaction::eStartElementTransaction: case txOutputTransaction::eStartElementTransaction:
{ {
txStartElementTransaction* transaction = txStartElementTransaction* transaction =
static_cast<txStartElementTransaction*>(aElement); static_cast<txStartElementTransaction*>(aTransaction);
rv = handler->startElement(transaction->mPrefix, return aHandler->startElement(transaction->mPrefix,
transaction->mLocalName, transaction->mLocalName,
transaction->mNsID); transaction->mNsID);
break; }
default:
{
NS_NOTREACHED("Unexpected transaction type");
} }
} }
holder->mResult = rv; return NS_ERROR_UNEXPECTED;
return NS_SUCCEEDED(rv);
} }
nsresult nsresult
txResultBuffer::flushToHandler(txAXMLEventHandler** aHandler) txResultBuffer::flushToHandler(txAXMLEventHandler* aHandler)
{ {
Holder data = { aHandler, NS_OK }; nsAFlatString::const_char_iterator iter;
mStringValue.BeginReading(data.mIter); mStringValue.BeginReading(iter);
for (PRUint32 i = 0, len = mTransactions.Length(); i < len; ++i) { for (PRUint32 i = 0, len = mTransactions.Length(); i < len; ++i) {
if (!flushTransaction(mTransactions[i], &data)) { nsresult rv = flushTransaction(mTransactions[i], aHandler, iter);
break; NS_ENSURE_SUCCESS(rv, rv);
}
} }
return data.mResult; return NS_OK;
} }
txOutputTransaction* txOutputTransaction*

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

@ -55,12 +55,7 @@ public:
nsresult addTransaction(txOutputTransaction* aTransaction); nsresult addTransaction(txOutputTransaction* aTransaction);
/** nsresult flushToHandler(txAXMLEventHandler* aHandler);
* Flush the transactions to aHandler. Some handlers create a new handler
* and replace themselves with the new handler. The pointer that aHandler
* points to should be updated in that case.
*/
nsresult flushToHandler(txAXMLEventHandler** aHandler);
txOutputTransaction* getLastTransaction(); txOutputTransaction* getLastTransaction();

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

@ -88,10 +88,7 @@ convertRtfToNode(txIEvalContext *aContext, txResultTreeFragment *aRtf)
txOutputFormat format; txOutputFormat format;
txMozillaXMLOutput mozHandler(&format, domFragment, PR_TRUE); txMozillaXMLOutput mozHandler(&format, domFragment, PR_TRUE);
txAXMLEventHandler* handler = &mozHandler; rv = aRtf->flushToHandler(&mozHandler);
rv = aRtf->flushToHandler(&handler);
NS_ASSERTION(handler == &mozHandler,
"This handler shouldn't have been replaced!");
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = mozHandler.closePrevious(PR_TRUE); rv = mozHandler.closePrevious(PR_TRUE);

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

@ -432,7 +432,7 @@ txCopyOf::execute(txExecutionState& aEs)
txResultTreeFragment* rtf = txResultTreeFragment* rtf =
static_cast<txResultTreeFragment*> static_cast<txResultTreeFragment*>
(static_cast<txAExprResult*>(exprRes)); (static_cast<txAExprResult*>(exprRes));
return rtf->flushToHandler(&aEs.mResultHandler); return rtf->flushToHandler(aEs.mResultHandler);
} }
default: default:
{ {

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

@ -80,7 +80,7 @@ double txResultTreeFragment::numberValue()
return Double::toDouble(mBuffer->mStringValue); return Double::toDouble(mBuffer->mStringValue);
} }
nsresult txResultTreeFragment::flushToHandler(txAXMLEventHandler** aHandler) nsresult txResultTreeFragment::flushToHandler(txAXMLEventHandler* aHandler)
{ {
if (!mBuffer) { if (!mBuffer) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

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

@ -51,7 +51,7 @@ public:
TX_DECL_EXPRRESULT TX_DECL_EXPRRESULT
nsresult flushToHandler(txAXMLEventHandler** aHandler); nsresult flushToHandler(txAXMLEventHandler* aHandler);
void setNode(const txXPathNode* aNode) void setNode(const txXPathNode* aNode)
{ {

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

@ -147,14 +147,17 @@ nsresult txUnknownHandler::createHandlerAndFlush(PRBool aHTMLRoot,
format.mMethod = aHTMLRoot ? eHTMLOutput : eXMLOutput; format.mMethod = aHTMLRoot ? eHTMLOutput : eXMLOutput;
} }
txAXMLEventHandler *handler = nsnull; nsAutoPtr<txAXMLEventHandler> handler;
nsresult rv = mEs->mOutputHandlerFactory->createHandlerWith(&format, aName, nsresult rv = mEs->mOutputHandlerFactory->createHandlerWith(&format, aName,
aNsID, aNsID,
&handler); getter_Transfers(handler));
NS_ENSURE_SUCCESS(rv, rv);
rv = mBuffer->flushToHandler(handler);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mEs->mOutputHandler = handler; mEs->mOutputHandler = handler;
mEs->mResultHandler = handler; mEs->mResultHandler = handler.forget();
return mBuffer->flushToHandler(&handler); return NS_OK;
} }