зеркало из https://github.com/mozilla/pjs.git
Part of the fix for bug 193678 (support exslt:common - allow txXPathNode to hold a strong ref to its root). r/sr=sicking.
This commit is contained in:
Родитель
ba5ddaa8d2
Коммит
46ea975af9
|
@ -86,16 +86,13 @@ txXPathTreeWalker::moveToRoot()
|
|||
mPosition.mNode = root;
|
||||
}
|
||||
else {
|
||||
nsINode *parent, *current = mPosition.mNode;
|
||||
while ((parent = current->GetNodeParent())) {
|
||||
current = parent;
|
||||
}
|
||||
nsINode *rootNode = mPosition.Root();
|
||||
|
||||
NS_ASSERTION(current->IsNodeOfType(nsINode::eCONTENT),
|
||||
NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
|
||||
"root of subtree wasn't an nsIContent");
|
||||
|
||||
mPosition.mIndex = txXPathNode::eContent;
|
||||
mPosition.mNode = current;
|
||||
mPosition.mNode = rootNode;
|
||||
}
|
||||
|
||||
mCurrentIndex = kUnknownIndex;
|
||||
|
@ -123,16 +120,13 @@ txXPathTreeWalker::moveToElementById(const nsAString& aID)
|
|||
}
|
||||
else {
|
||||
// We're in a disconnected subtree, search only that subtree.
|
||||
nsINode *parent, *current = mPosition.mNode;
|
||||
while ((parent = current->GetNodeParent())) {
|
||||
current = parent;
|
||||
}
|
||||
nsINode *rootNode = mPosition.Root();
|
||||
|
||||
NS_ASSERTION(current->IsNodeOfType(nsINode::eCONTENT),
|
||||
NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
|
||||
"root of subtree wasn't an nsIContent");
|
||||
|
||||
content = nsContentUtils::MatchElementId(
|
||||
NS_STATIC_CAST(nsIContent*, current), aID);
|
||||
NS_STATIC_CAST(nsIContent*, rootNode), aID);
|
||||
}
|
||||
|
||||
if (!content) {
|
||||
|
@ -350,17 +344,6 @@ txXPathTreeWalker::moveToSibling(PRInt32 aDir)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
txXPathNode::txXPathNode(const txXPathNode& aNode) : mIndex(aNode.mIndex),
|
||||
mNode(aNode.mNode)
|
||||
{
|
||||
}
|
||||
|
||||
PRBool
|
||||
txXPathNode::operator==(const txXPathNode& aNode) const
|
||||
{
|
||||
return mIndex == aNode.mIndex && mNode == aNode.mNode;
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRBool
|
||||
txXPathNodeUtils::getAttr(const txXPathNode& aNode, nsIAtom* aLocalName,
|
||||
|
@ -695,7 +678,6 @@ txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
|
|||
nsINode* node = aNode.mNode;
|
||||
nsINode* otherNode = aOtherNode.mNode;
|
||||
nsINode* parent, *otherParent;
|
||||
PRInt32 index, otherIndex;
|
||||
while (node && otherNode) {
|
||||
parent = node->GetNodeParent();
|
||||
otherParent = otherNode->GetNodeParent();
|
||||
|
@ -764,7 +746,7 @@ txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
|
|||
|
||||
/* static */
|
||||
txXPathNode*
|
||||
txXPathNativeNode::createXPathNode(nsIDOMNode* aNode)
|
||||
txXPathNativeNode::createXPathNode(nsIDOMNode* aNode, PRBool aKeepRootAlive)
|
||||
{
|
||||
PRUint16 nodeType;
|
||||
aNode->GetNodeType(&nodeType);
|
||||
|
@ -779,11 +761,13 @@ txXPathNativeNode::createXPathNode(nsIDOMNode* aNode)
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(parent) : nsnull;
|
||||
|
||||
PRUint32 i, total = parent->GetAttrCount();
|
||||
for (i = 0; i < total; ++i) {
|
||||
const nsAttrName* name = parent->GetAttrNameAt(i);
|
||||
if (nodeInfo->Equals(name->LocalName(), name->NamespaceID())) {
|
||||
return new txXPathNode(parent, i);
|
||||
return new txXPathNode(parent, i, root);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -792,13 +776,21 @@ txXPathNativeNode::createXPathNode(nsIDOMNode* aNode)
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
|
||||
PRUint32 index;
|
||||
nsINode* root = aKeepRootAlive ? node : nsnull;
|
||||
|
||||
if (nodeType == nsIDOMNode::DOCUMENT_NODE) {
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(aNode);
|
||||
return new txXPathNode(document);
|
||||
index = txXPathNode::eDocument;
|
||||
}
|
||||
else {
|
||||
index = txXPathNode::eContent;
|
||||
if (root) {
|
||||
root = txXPathNode::RootOf(root);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
return new txXPathNode(content);
|
||||
return new txXPathNode(node, index, root);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -45,6 +45,24 @@
|
|||
* Implementation of an XPath nodeset
|
||||
*/
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
#define LOG_CHUNK_MOVE(_start, _new_start, _count) \
|
||||
{ \
|
||||
txXPathNode *start = NS_CONST_CAST(txXPathNode*, _start); \
|
||||
while (start < _start + _count) { \
|
||||
NS_LogDtor(start, "txXPathNode", sizeof(*start)); \
|
||||
++start; \
|
||||
} \
|
||||
start = NS_CONST_CAST(txXPathNode*, _new_start); \
|
||||
while (start < _new_start + _count) { \
|
||||
NS_LogCtor(start, "txXPathNode", sizeof(*start)); \
|
||||
++start; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LOG_CHUNK_MOVE(_start, _new_start, _count)
|
||||
#endif
|
||||
|
||||
static const PRInt32 kTxNodeSetMinSize = 4;
|
||||
static const PRInt32 kTxNodeSetGrowFactor = 2;
|
||||
|
||||
|
@ -96,10 +114,7 @@ txNodeSet::~txNodeSet()
|
|||
delete [] mMarks;
|
||||
|
||||
if (mStartBuffer) {
|
||||
while (mStart < mEnd) {
|
||||
mStart->~txXPathNode();
|
||||
++mStart;
|
||||
}
|
||||
destroyElements(mStart, mEnd);
|
||||
|
||||
nsMemory::Free(mStartBuffer);
|
||||
}
|
||||
|
@ -131,6 +146,7 @@ nsresult txNodeSet::add(const txXPathNode& aNode)
|
|||
pos = mStart + offset;
|
||||
|
||||
if (moveSize > 0) {
|
||||
LOG_CHUNK_MOVE(pos, pos + 1, moveSize);
|
||||
memmove(pos + 1, pos, moveSize * sizeof(txXPathNode));
|
||||
}
|
||||
|
||||
|
@ -142,13 +158,13 @@ nsresult txNodeSet::add(const txXPathNode& aNode)
|
|||
|
||||
nsresult txNodeSet::add(const txNodeSet& aNodes)
|
||||
{
|
||||
return add(aNodes, copyElements);
|
||||
return add(aNodes, copyElements, nsnull);
|
||||
}
|
||||
|
||||
nsresult txNodeSet::addAndTransfer(txNodeSet* aNodes)
|
||||
{
|
||||
// failure is out-of-memory, transfer didn't happen
|
||||
nsresult rv = add(*aNodes, transferElements);
|
||||
nsresult rv = add(*aNodes, transferElements, destroyElements);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef TX_DONT_RECYCLE_BUFFER
|
||||
|
@ -203,7 +219,8 @@ nsresult txNodeSet::addAndTransfer(txNodeSet* aNodes)
|
|||
* check for sequences of duplicate nodes, which can be optimized.
|
||||
*
|
||||
*/
|
||||
nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer)
|
||||
nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer,
|
||||
destroyOp aDestroy)
|
||||
{
|
||||
NS_ASSERTION(mDirection == kForward,
|
||||
"only append(aNode) is supported on reversed nodesets");
|
||||
|
@ -244,6 +261,7 @@ nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer)
|
|||
pos = findPosition(thisPos[-1], aNodes.mStart, otherPos, dupe);
|
||||
|
||||
if (dupe) {
|
||||
const txXPathNode *deletePos = thisPos;
|
||||
--thisPos; // this is already added
|
||||
// check dupe sequence
|
||||
while (thisPos > mStart && pos > aNodes.mStart &&
|
||||
|
@ -251,6 +269,10 @@ nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer)
|
|||
--thisPos;
|
||||
--pos;
|
||||
}
|
||||
|
||||
if (aDestroy) {
|
||||
aDestroy(thisPos, deletePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -271,6 +293,7 @@ nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer)
|
|||
pos = findPosition(otherPos[-1], mStart, thisPos, dupe);
|
||||
|
||||
if (dupe) {
|
||||
const txXPathNode *deletePos = otherPos;
|
||||
--otherPos; // this is already added
|
||||
// check dupe sequence
|
||||
while (otherPos > aNodes.mStart && pos > mStart &&
|
||||
|
@ -278,6 +301,10 @@ nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer)
|
|||
--otherPos;
|
||||
--pos;
|
||||
}
|
||||
|
||||
if (aDestroy) {
|
||||
aDestroy(otherPos, deletePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -289,6 +316,7 @@ nsresult txNodeSet::add(const txNodeSet& aNodes, transferOp aTransfer)
|
|||
count = thisPos - pos;
|
||||
if (count > 0) {
|
||||
insertPos -= count;
|
||||
LOG_CHUNK_MOVE(pos, insertPos, count);
|
||||
memmove(insertPos, pos, count * sizeof(txXPathNode));
|
||||
thisPos -= count;
|
||||
}
|
||||
|
@ -396,6 +424,7 @@ txNodeSet::sweep()
|
|||
}
|
||||
// move chunk
|
||||
if (chunk > 0) {
|
||||
LOG_CHUNK_MOVE(mStart + pos - chunk, insertion, chunk);
|
||||
memmove(insertion, mStart + pos - chunk,
|
||||
chunk * sizeof(txXPathNode));
|
||||
insertion += chunk;
|
||||
|
@ -412,10 +441,7 @@ txNodeSet::sweep()
|
|||
void
|
||||
txNodeSet::clear()
|
||||
{
|
||||
while (mStart < mEnd) {
|
||||
mStart->~txXPathNode();
|
||||
++mStart;
|
||||
}
|
||||
destroyElements(mStart, mEnd);
|
||||
#ifdef TX_DONT_RECYCLE_BUFFER
|
||||
if (mStartBuffer) {
|
||||
nsMemory::Free(mStartBuffer);
|
||||
|
@ -517,6 +543,7 @@ PRBool txNodeSet::ensureGrowSize(PRInt32 aSize)
|
|||
if (mDirection == kReversed) {
|
||||
dest = mEndBuffer - oldSize;
|
||||
}
|
||||
LOG_CHUNK_MOVE(mStart, dest, oldSize);
|
||||
memmove(dest, mStart, oldSize * sizeof(txXPathNode));
|
||||
mStart = dest;
|
||||
mEnd = dest + oldSize;
|
||||
|
@ -545,6 +572,7 @@ PRBool txNodeSet::ensureGrowSize(PRInt32 aSize)
|
|||
}
|
||||
|
||||
if (oldSize > 0) {
|
||||
LOG_CHUNK_MOVE(mStart, dest, oldSize);
|
||||
memcpy(dest, mStart, oldSize * sizeof(txXPathNode));
|
||||
}
|
||||
|
||||
|
@ -623,5 +651,6 @@ void
|
|||
txNodeSet::transferElements(txXPathNode* aDest,
|
||||
const txXPathNode* aStart, const txXPathNode* aEnd)
|
||||
{
|
||||
LOG_CHUNK_MOVE(aStart, aDest, (aEnd - aStart));
|
||||
memcpy(aDest, aStart, (aEnd - aStart) * sizeof(txXPathNode));
|
||||
}
|
||||
|
|
|
@ -227,10 +227,21 @@ private:
|
|||
const txXPathNode* aEnd);
|
||||
static void transferElements(txXPathNode* aDest, const txXPathNode* aStart,
|
||||
const txXPathNode* aEnd);
|
||||
static void destroyElements(const txXPathNode* aStart,
|
||||
const txXPathNode* aEnd)
|
||||
{
|
||||
while (aStart < aEnd) {
|
||||
aStart->~txXPathNode();
|
||||
++aStart;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*transferOp) (txXPathNode* aDest, const txXPathNode* aStart,
|
||||
const txXPathNode* aEnd);
|
||||
nsresult add(const txNodeSet& aNodes, transferOp aTransfer);
|
||||
typedef void (*destroyOp) (const txXPathNode* aStart,
|
||||
const txXPathNode* aEnd);
|
||||
nsresult add(const txNodeSet& aNodes, transferOp aTransfer,
|
||||
destroyOp aDestroy);
|
||||
|
||||
txXPathNode *mStart, *mEnd, *mStartBuffer, *mEndBuffer;
|
||||
PRInt32 mDirection;
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
{
|
||||
return !(*this == aNode);
|
||||
}
|
||||
~txXPathNode();
|
||||
|
||||
private:
|
||||
friend class txNodeSet;
|
||||
|
@ -71,24 +72,48 @@ private:
|
|||
friend class txXPathNodeUtils;
|
||||
friend class txXPathTreeWalker;
|
||||
|
||||
txXPathNode(const txXPathNode& aNode);
|
||||
|
||||
#ifdef TX_EXE
|
||||
txXPathNode(NodeDefinition* aNode) : mInner(aNode)
|
||||
{
|
||||
}
|
||||
txXPathNode(const txXPathNode& aNode);
|
||||
|
||||
NodeDefinition* mInner;
|
||||
#else
|
||||
txXPathNode(nsIDocument* aDocument) : mNode(aDocument),
|
||||
mRefCountRoot(0),
|
||||
mIndex(eDocument)
|
||||
{
|
||||
MOZ_COUNT_CTOR(txXPathNode);
|
||||
}
|
||||
txXPathNode(nsIContent* aContent, PRUint32 aIndex = eContent)
|
||||
: mNode(aContent),
|
||||
txXPathNode(nsINode *aNode, PRUint32 aIndex, nsINode *aRoot)
|
||||
: mNode(aNode),
|
||||
mRefCountRoot(aRoot ? 1 : 0),
|
||||
mIndex(aIndex)
|
||||
{
|
||||
MOZ_COUNT_CTOR(txXPathNode);
|
||||
if (aRoot) {
|
||||
NS_ADDREF(aRoot);
|
||||
}
|
||||
}
|
||||
|
||||
static nsINode *RootOf(nsINode *aNode)
|
||||
{
|
||||
nsINode *ancestor, *root = aNode;
|
||||
while ((ancestor = root->GetNodeParent())) {
|
||||
root = ancestor;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
nsINode *Root() const
|
||||
{
|
||||
return RootOf(mNode);
|
||||
}
|
||||
nsINode *GetRootToAddRef() const
|
||||
{
|
||||
return mRefCountRoot ? Root() : nsnull;
|
||||
}
|
||||
txXPathNode(const txXPathNode& aNode);
|
||||
|
||||
PRBool isDocument() const
|
||||
{
|
||||
|
@ -116,11 +141,13 @@ private:
|
|||
|
||||
enum PositionType
|
||||
{
|
||||
eDocument = (PRUint32)-2,
|
||||
eContent = (PRUint32)-1
|
||||
eDocument = (1 << 30),
|
||||
eContent = eDocument - 1
|
||||
};
|
||||
|
||||
nsINode* mNode;
|
||||
PRUint32 mIndex;
|
||||
PRUint32 mRefCountRoot : 1;
|
||||
PRUint32 mIndex : 31;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -157,4 +184,47 @@ txNamespaceManager::getNamespaceURI(const PRInt32 aID, nsAString& aResult)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef TX_EXE
|
||||
inline
|
||||
txXPathNode::txXPathNode(const txXPathNode& aNode)
|
||||
: mInner(aNode.mInner)
|
||||
{
|
||||
}
|
||||
#else
|
||||
inline
|
||||
txXPathNode::txXPathNode(const txXPathNode& aNode)
|
||||
: mNode(aNode.mNode),
|
||||
mRefCountRoot(aNode.mRefCountRoot),
|
||||
mIndex(aNode.mIndex)
|
||||
{
|
||||
MOZ_COUNT_CTOR(txXPathNode);
|
||||
if (mRefCountRoot) {
|
||||
NS_ADDREF(Root());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline
|
||||
txXPathNode::~txXPathNode()
|
||||
{
|
||||
#ifdef TX_EXE
|
||||
#else
|
||||
MOZ_COUNT_DTOR(txXPathNode);
|
||||
if (mRefCountRoot) {
|
||||
nsINode *root = Root();
|
||||
NS_RELEASE(root);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline PRBool
|
||||
txXPathNode::operator==(const txXPathNode& aNode) const
|
||||
{
|
||||
#ifdef TX_EXE
|
||||
return (mInner == aNode.mInner);
|
||||
#else
|
||||
return mIndex == aNode.mIndex && mNode == aNode.mNode;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* txXPathNode_h__ */
|
||||
|
|
|
@ -160,7 +160,8 @@ public:
|
|||
class txXPathNativeNode
|
||||
{
|
||||
public:
|
||||
static txXPathNode* createXPathNode(nsIDOMNode* aNode);
|
||||
static txXPathNode* createXPathNode(nsIDOMNode* aNode,
|
||||
PRBool aKeepRootAlive = PR_FALSE);
|
||||
static txXPathNode* createXPathNode(nsIDOMDocument* aDocument);
|
||||
static nsresult getNode(const txXPathNode& aNode, nsIDOMNode** aResult);
|
||||
static nsIContent* getContent(const txXPathNode& aNode);
|
||||
|
@ -215,8 +216,22 @@ txXPathTreeWalker::moveTo(const txXPathTreeWalker& aWalker)
|
|||
#ifdef TX_EXE
|
||||
mPosition.mInner = aWalker.mPosition.mInner;
|
||||
#else
|
||||
nsINode *root = nsnull;
|
||||
if (mPosition.mRefCountRoot) {
|
||||
root = mPosition.Root();
|
||||
}
|
||||
mPosition.mIndex = aWalker.mPosition.mIndex;
|
||||
mPosition.mRefCountRoot = aWalker.mPosition.mRefCountRoot;
|
||||
mPosition.mNode = aWalker.mPosition.mNode;
|
||||
nsINode *newRoot = nsnull;
|
||||
if (mPosition.mRefCountRoot) {
|
||||
newRoot = mPosition.Root();
|
||||
}
|
||||
if (root != newRoot) {
|
||||
NS_IF_ADDREF(newRoot);
|
||||
NS_IF_RELEASE(root);
|
||||
}
|
||||
|
||||
mCurrentIndex = aWalker.mCurrentIndex;
|
||||
mDescendants.Clear();
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче