msxml3: Properly update xmldoc refcounts on insertBefore().
insertBefore() is able to work on nodes from different documents, so on adding child or sibling it's possible that libxml2 switches doc pointer for a node, we need to update refcounts to cover that case.
This commit is contained in:
parent
d05435167a
commit
0f3c247e46
|
@ -295,6 +295,7 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
|
||||||
xmlNodePtr new_child_node;
|
xmlNodePtr new_child_node;
|
||||||
IXMLDOMNode *before = NULL;
|
IXMLDOMNode *before = NULL;
|
||||||
xmlnode *node_obj;
|
xmlnode *node_obj;
|
||||||
|
xmlDocPtr doc;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if(!new_child)
|
if(!new_child)
|
||||||
|
@ -336,7 +337,10 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
|
||||||
/* unlink from current parent first */
|
/* unlink from current parent first */
|
||||||
if(node_obj->parent)
|
if(node_obj->parent)
|
||||||
IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
|
IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
|
||||||
|
doc = new_child_node->doc;
|
||||||
|
xmldoc_add_ref(before_node_obj->node->doc);
|
||||||
xmlAddPrevSibling(before_node_obj->node, new_child_node);
|
xmlAddPrevSibling(before_node_obj->node, new_child_node);
|
||||||
|
xmldoc_release(doc);
|
||||||
node_obj->parent = This->parent;
|
node_obj->parent = This->parent;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -344,7 +348,10 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
|
||||||
/* unlink from current parent first */
|
/* unlink from current parent first */
|
||||||
if(node_obj->parent)
|
if(node_obj->parent)
|
||||||
IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
|
IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
|
||||||
|
doc = new_child_node->doc;
|
||||||
|
xmldoc_add_ref(This->node->doc);
|
||||||
xmlAddChild(This->node, new_child_node);
|
xmlAddChild(This->node, new_child_node);
|
||||||
|
xmldoc_release(doc);
|
||||||
node_obj->parent = This->iface;
|
node_obj->parent = This->iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2064,6 +2064,7 @@ static void test_refs(void)
|
||||||
doc = create_document(&IID_IXMLDOMDocument);
|
doc = create_document(&IID_IXMLDOMDocument);
|
||||||
if (!doc) return;
|
if (!doc) return;
|
||||||
|
|
||||||
|
EXPECT_REF(doc, 1);
|
||||||
ref = IXMLDOMDocument_Release(doc);
|
ref = IXMLDOMDocument_Release(doc);
|
||||||
ok( ref == 0, "ref %d\n", ref);
|
ok( ref == 0, "ref %d\n", ref);
|
||||||
|
|
||||||
|
@ -2076,6 +2077,7 @@ static void test_refs(void)
|
||||||
ok( b == VARIANT_TRUE, "failed to load XML string\n");
|
ok( b == VARIANT_TRUE, "failed to load XML string\n");
|
||||||
SysFreeString( str );
|
SysFreeString( str );
|
||||||
|
|
||||||
|
EXPECT_REF(doc, 1);
|
||||||
IXMLDOMDocument_AddRef( doc );
|
IXMLDOMDocument_AddRef( doc );
|
||||||
EXPECT_REF(doc, 2);
|
EXPECT_REF(doc, 2);
|
||||||
IXMLDOMDocument_AddRef( doc );
|
IXMLDOMDocument_AddRef( doc );
|
||||||
|
@ -2089,19 +2091,27 @@ static void test_refs(void)
|
||||||
ok( element != NULL, "should be an element\n");
|
ok( element != NULL, "should be an element\n");
|
||||||
|
|
||||||
EXPECT_REF(doc, 1);
|
EXPECT_REF(doc, 1);
|
||||||
|
todo_wine EXPECT_REF(element, 2);
|
||||||
|
|
||||||
|
IXMLDOMElement_AddRef(element);
|
||||||
|
todo_wine EXPECT_REF(element, 3);
|
||||||
|
IXMLDOMElement_Release(element);
|
||||||
|
|
||||||
r = IXMLDOMElement_get_childNodes( element, &node_list );
|
r = IXMLDOMElement_get_childNodes( element, &node_list );
|
||||||
ok( r == S_OK, "rets %08x\n", r);
|
ok( r == S_OK, "rets %08x\n", r);
|
||||||
|
|
||||||
|
todo_wine EXPECT_REF(element, 2);
|
||||||
EXPECT_REF(node_list, 1);
|
EXPECT_REF(node_list, 1);
|
||||||
|
|
||||||
IXMLDOMNodeList_get_item( node_list, 0, &node );
|
IXMLDOMNodeList_get_item( node_list, 0, &node );
|
||||||
ok( r == S_OK, "rets %08x\n", r);
|
ok( r == S_OK, "rets %08x\n", r);
|
||||||
|
EXPECT_REF(node_list, 1);
|
||||||
|
EXPECT_REF(node, 1);
|
||||||
|
|
||||||
IXMLDOMNodeList_get_item( node_list, 0, &node2 );
|
IXMLDOMNodeList_get_item( node_list, 0, &node2 );
|
||||||
ok( r == S_OK, "rets %08x\n", r);
|
ok( r == S_OK, "rets %08x\n", r);
|
||||||
|
EXPECT_REF(node_list, 1);
|
||||||
EXPECT_REF(node, 1);
|
EXPECT_REF(node2, 1);
|
||||||
|
|
||||||
ref = IXMLDOMNode_Release( node );
|
ref = IXMLDOMNode_Release( node );
|
||||||
ok( ref == 0, "ref %d\n", ref );
|
ok( ref == 0, "ref %d\n", ref );
|
||||||
|
@ -2121,18 +2131,22 @@ static void test_refs(void)
|
||||||
/* IUnknown must be unique however we obtain it */
|
/* IUnknown must be unique however we obtain it */
|
||||||
r = IXMLDOMElement_QueryInterface( element, &IID_IUnknown, (void**)&unk );
|
r = IXMLDOMElement_QueryInterface( element, &IID_IUnknown, (void**)&unk );
|
||||||
ok( r == S_OK, "rets %08x\n", r );
|
ok( r == S_OK, "rets %08x\n", r );
|
||||||
|
EXPECT_REF(element, 2);
|
||||||
r = IXMLDOMElement_QueryInterface( element, &IID_IXMLDOMNode, (void**)&node );
|
r = IXMLDOMElement_QueryInterface( element, &IID_IXMLDOMNode, (void**)&node );
|
||||||
ok( r == S_OK, "rets %08x\n", r );
|
ok( r == S_OK, "rets %08x\n", r );
|
||||||
|
todo_wine EXPECT_REF(element, 2);
|
||||||
r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (void**)&unk2 );
|
r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (void**)&unk2 );
|
||||||
ok( r == S_OK, "rets %08x\n", r );
|
ok( r == S_OK, "rets %08x\n", r );
|
||||||
|
todo_wine EXPECT_REF(element, 2);
|
||||||
ok( unk == unk2, "unk %p unk2 %p\n", unk, unk2 );
|
ok( unk == unk2, "unk %p unk2 %p\n", unk, unk2 );
|
||||||
|
todo_wine ok( element != (void*)node, "node %p element %p\n", node, element );
|
||||||
|
|
||||||
IUnknown_Release( unk2 );
|
IUnknown_Release( unk2 );
|
||||||
IUnknown_Release( unk );
|
IUnknown_Release( unk );
|
||||||
IXMLDOMNode_Release( node );
|
IXMLDOMNode_Release( node );
|
||||||
|
todo_wine EXPECT_REF(element, 2);
|
||||||
|
|
||||||
IXMLDOMElement_Release( element );
|
IXMLDOMElement_Release( element );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_create(void)
|
static void test_create(void)
|
||||||
|
@ -2156,6 +2170,8 @@ static void test_create(void)
|
||||||
doc = create_document(&IID_IXMLDOMDocument);
|
doc = create_document(&IID_IXMLDOMDocument);
|
||||||
if (!doc) return;
|
if (!doc) return;
|
||||||
|
|
||||||
|
EXPECT_REF(doc, 1);
|
||||||
|
|
||||||
/* types not supported for creation */
|
/* types not supported for creation */
|
||||||
V_VT(&var) = VT_I1;
|
V_VT(&var) = VT_I1;
|
||||||
V_I1(&var) = NODE_DOCUMENT;
|
V_I1(&var) = NODE_DOCUMENT;
|
||||||
|
@ -2452,9 +2468,12 @@ static void test_create(void)
|
||||||
V_I4(&var) = NODE_ELEMENT;
|
V_I4(&var) = NODE_ELEMENT;
|
||||||
r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
|
r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
|
||||||
ok( r == S_OK, "returns %08x\n", r );
|
ok( r == S_OK, "returns %08x\n", r );
|
||||||
|
|
||||||
|
EXPECT_REF(doc, 1);
|
||||||
r = IXMLDOMDocument_appendChild( doc, node, &root );
|
r = IXMLDOMDocument_appendChild( doc, node, &root );
|
||||||
ok( r == S_OK, "returns %08x\n", r );
|
ok( r == S_OK, "returns %08x\n", r );
|
||||||
ok( node == root, "%p %p\n", node, root );
|
ok( node == root, "%p %p\n", node, root );
|
||||||
|
EXPECT_REF(doc, 1);
|
||||||
|
|
||||||
EXPECT_REF(node, 2);
|
EXPECT_REF(node, 2);
|
||||||
|
|
||||||
|
@ -8250,7 +8269,45 @@ static void test_insertBefore(void)
|
||||||
SysFreeString(p);
|
SysFreeString(p);
|
||||||
|
|
||||||
IXMLDOMDocument_Release(doc);
|
IXMLDOMDocument_Release(doc);
|
||||||
free_bstrs();
|
}
|
||||||
|
|
||||||
|
static void test_appendChild(void)
|
||||||
|
{
|
||||||
|
IXMLDOMDocument *doc, *doc2;
|
||||||
|
IXMLDOMElement *elem, *elem2;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
doc = create_document(&IID_IXMLDOMDocument);
|
||||||
|
doc2 = create_document(&IID_IXMLDOMDocument);
|
||||||
|
|
||||||
|
hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem2"), &elem2);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
EXPECT_REF(doc, 1);
|
||||||
|
todo_wine EXPECT_REF(elem, 2);
|
||||||
|
EXPECT_REF(doc2, 1);
|
||||||
|
todo_wine EXPECT_REF(elem2, 2);
|
||||||
|
EXPECT_NO_CHILDREN(doc);
|
||||||
|
EXPECT_NO_CHILDREN(doc2);
|
||||||
|
|
||||||
|
/* append from another document */
|
||||||
|
hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, NULL);
|
||||||
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
|
|
||||||
|
EXPECT_REF(doc, 1);
|
||||||
|
todo_wine EXPECT_REF(elem, 2);
|
||||||
|
EXPECT_REF(doc2, 1);
|
||||||
|
todo_wine EXPECT_REF(elem2, 2);
|
||||||
|
EXPECT_NO_CHILDREN(doc);
|
||||||
|
EXPECT_CHILDREN(doc2);
|
||||||
|
|
||||||
|
IXMLDOMElement_Release(elem);
|
||||||
|
IXMLDOMElement_Release(elem2);
|
||||||
|
IXMLDOMDocument_Release(doc);
|
||||||
|
IXMLDOMDocument_Release(doc2);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(domdoc)
|
START_TEST(domdoc)
|
||||||
|
@ -8318,6 +8375,7 @@ START_TEST(domdoc)
|
||||||
test_put_nodeTypedValue();
|
test_put_nodeTypedValue();
|
||||||
test_get_xml();
|
test_get_xml();
|
||||||
test_insertBefore();
|
test_insertBefore();
|
||||||
|
test_appendChild();
|
||||||
test_xsltemplate();
|
test_xsltemplate();
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
|
|
Loading…
Reference in New Issue