Record detached document of a node and use that to fix memory leak.

This commit is contained in:
rfm 2024-12-19 10:26:19 +00:00
parent 3f27cb0d23
commit 0d010003f9
3 changed files with 40 additions and 18 deletions

View file

@ -183,7 +183,12 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
self = [self initWithKind: NSXMLDocumentKind options: 0];
if (self != nil)
{
[self setRootElement: (NSXMLNode*)element];
NS_DURING
[self setRootElement: (NSXMLNode*)element];
NS_HANDLER
RELEASE(self);
[localException raise];
NS_ENDHANDLER
}
return self;
}
@ -279,6 +284,11 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
// FIXME: Should we use addChild: here?
xmlDocSetRootElement(internal->node.doc, [root _node]);
if (root->detached)
{
xmlFreeDoc(root->detached);
root->detached = 0;
}
// Do our subNode housekeeping...
[self _addSubNode: root];

View file

@ -506,8 +506,8 @@ isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
xmlNodePtr theNode = internal->node.node;
xmlNodePtr children;
if ((theNode->type == XML_NAMESPACE_DECL) ||
(theNode->type == XML_ATTRIBUTE_NODE))
if ((theNode->type == XML_NAMESPACE_DECL)
|| (theNode->type == XML_ATTRIBUTE_NODE))
{
return NULL;
}
@ -629,6 +629,10 @@ isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
#else
xmlSetTreeDoc(childNode, parentNode->doc);
#endif
if (tmp == child->detached)
{
child->detached = 0;
}
xmlFreeDoc(tmp);
}
}
@ -1292,18 +1296,21 @@ execute_xpath(xmlNodePtr node, NSString *xpath_exp, NSDictionary *constants,
{
if (theNode->doc)
{
if (theNode->doc == detached)
{
return; // Already detached.
}
/* Create a private document and move the node over.
* This is needed so that the strings of the nodes subtree
* get stored in the dictionary of this new document.
*/
// FIXME: Should flag this doc so it wont get returned in
// the method rootDocument
xmlDocPtr tmp = xmlNewDoc((xmlChar *)"1.0");
detached = xmlNewDoc((xmlChar *)"1.0");
#if LIBXML_VERSION >= 20620
xmlDOMWrapAdoptNode(NULL, theNode->doc, theNode, tmp, NULL, 0);
xmlDOMWrapAdoptNode(NULL, theNode->doc, theNode, detached,
NULL, 0);
#else
xmlSetTreeDoc(theNode, tmp);
xmlSetTreeDoc(theNode, detached);
#endif
}
else
@ -1734,6 +1741,10 @@ execute_xpath(xmlNodePtr node, NSString *xpath_exp, NSDictionary *constants,
// but we don't want to return this.
return nil;
}
if (theNode->doc == detached)
{
return nil; // the document is private from when we detached
}
return
(NSXMLDocument *)[NSXMLNode _objectForNode: (xmlNodePtr)(theNode->doc)];

View file

@ -113,10 +113,10 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
#define GS_XMLNODETYPE \
union\
{\
xmlDoc *doc;\
xmlDtd *dtd;\
xmlEntity *entity;\
xmlNode *node;\
xmlDoc *doc;\
xmlDtd *dtd;\
xmlEntity *entity;\
xmlNode *node;\
}
#else
@ -135,7 +135,7 @@ union\
* The 'subNodes' array is used to retain the objects pointed to by subnodes.
*
* When we create an Objective-C object for a node we also create objects
* for all parents up to the root object. (Reusing existing once as we find
* for all parents up to the root object. (Reusing existing ones as we find
* them in the _private points of parent nodes)
* This adds the object to the subnode array of the parent object, retaining
* the object in this process.
@ -154,11 +154,12 @@ union\
* URI is probably not needed at all ... I'm not sure
*/
#define GS_NSXMLNode_IVARS \
NSUInteger kind; \
GS_XMLNODETYPE node; \
NSUInteger options; \
id objectValue; \
NSMutableArray *subNodes;
NSUInteger kind; \
GS_XMLNODETYPE node; \
NSUInteger options; \
id objectValue; \
NSMutableArray *subNodes; \
xmlDoc *detached;
/* When using the non-fragile ABI, the instance variables are exposed to the