зеркало из https://github.com/mozilla/pjs.git
[XForms] NPOTDB insert cant handle empty target nodeset. Bug 389016, r=olli+aaronr
This commit is contained in:
Родитель
6285661069
Коммит
a5a6a473b5
|
@ -77,6 +77,12 @@ class nsXFormsInsertDeleteElement : public nsXFormsActionModuleBase
|
||||||
private:
|
private:
|
||||||
PRBool mIsInsert;
|
PRBool mIsInsert;
|
||||||
|
|
||||||
|
enum Location {
|
||||||
|
eLocation_After,
|
||||||
|
eLocation_Before,
|
||||||
|
eLocation_FirstChild,
|
||||||
|
};
|
||||||
|
|
||||||
/** Get the first node of a given type in aNodes.
|
/** Get the first node of a given type in aNodes.
|
||||||
*
|
*
|
||||||
* @param aNodes array of nodes
|
* @param aNodes array of nodes
|
||||||
|
@ -92,12 +98,12 @@ private:
|
||||||
*
|
*
|
||||||
* @param aTargetNode target location node
|
* @param aTargetNode target location node
|
||||||
* @param aNewNode node to insert
|
* @param aNewNode node to insert
|
||||||
* @param aInsertAfter insert before or after target?
|
* @param aLocation insert location relative to target
|
||||||
*
|
*
|
||||||
* @return aResult result node
|
* @return aResult result node
|
||||||
*/
|
*/
|
||||||
nsresult InsertNode(nsIDOMNode *aTargetNode, nsIDOMNode *aNewNode,
|
nsresult InsertNode(nsIDOMNode *aTargetNode, nsIDOMNode *aNewNode,
|
||||||
PRBool aInsertAfter, nsIDOMNode **aResNode);
|
Location aLocation, nsIDOMNode **aResNode);
|
||||||
|
|
||||||
nsresult RefreshRepeats(nsCOMArray<nsIDOMNode> *aNodes);
|
nsresult RefreshRepeats(nsCOMArray<nsIDOMNode> *aNodes);
|
||||||
|
|
||||||
|
@ -463,15 +469,24 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
|
||||||
// the first attribute of the insert location node. If the cloned node is
|
// the first attribute of the insert location node. If the cloned node is
|
||||||
// not an attribute, then the target location is before the first child
|
// not an attribute, then the target location is before the first child
|
||||||
// of the insert location node.
|
// of the insert location node.
|
||||||
if (!nodeset ||
|
if ((!nodeset || nodesetSize < 1) ||
|
||||||
(nodeset && nodesetSize > 1 && newNodeType != locationNodeType)) {
|
(nodeset && nodesetSize > 1 && newNodeType != locationNodeType)) {
|
||||||
|
Location location = eLocation_Before;
|
||||||
if (newNodeType != nsIDOMNode::ATTRIBUTE_NODE) {
|
if (newNodeType != nsIDOMNode::ATTRIBUTE_NODE) {
|
||||||
// target location is before first child of location node.
|
// Target location is before the first child of location node. If the
|
||||||
|
// location node is empty (has no children), it remains the location
|
||||||
|
// node and the new node will become the first child of the location
|
||||||
|
// node.
|
||||||
nsCOMPtr<nsIDOMNode> targetNode;
|
nsCOMPtr<nsIDOMNode> targetNode;
|
||||||
locationNode->GetFirstChild(getter_AddRefs(targetNode));
|
locationNode->GetFirstChild(getter_AddRefs(targetNode));
|
||||||
locationNode.swap(targetNode);
|
if (targetNode) {
|
||||||
|
locationNode.swap(targetNode);
|
||||||
|
} else {
|
||||||
|
// New node will become first child of locationNode.
|
||||||
|
location = eLocation_FirstChild;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
InsertNode(locationNode, newNode, PR_FALSE, getter_AddRefs(resNode));
|
InsertNode(locationNode, newNode, location, getter_AddRefs(resNode));
|
||||||
} else {
|
} else {
|
||||||
// Step 6c - If insert location node is the root element of an
|
// Step 6c - If insert location node is the root element of an
|
||||||
// instance, then that instance root element location is the target
|
// instance, then that instance root element location is the target
|
||||||
|
@ -512,7 +527,9 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InsertNode(locationNode, newNode, insertAfter, getter_AddRefs(resNode));
|
InsertNode(locationNode, newNode,
|
||||||
|
insertAfter ? eLocation_After: eLocation_Before,
|
||||||
|
getter_AddRefs(resNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,20 +576,35 @@ nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent,
|
||||||
while ((deleteIndex < deleteCount) && locationNode) {
|
while ((deleteIndex < deleteCount) && locationNode) {
|
||||||
// Delete the node(s) unless the delete location is the root document
|
// Delete the node(s) unless the delete location is the root document
|
||||||
// element of an instance.
|
// element of an instance.
|
||||||
if (!SameCOMIdentity(locationNode, locationDocElement)) {
|
PRUint16 locationNodeType;
|
||||||
locationNode->GetParentNode(getter_AddRefs(parentNode));
|
locationNode->GetNodeType(&locationNodeType);
|
||||||
NS_ENSURE_STATE(parentNode);
|
if (locationNodeType == nsIDOMNode::ATTRIBUTE_NODE) {
|
||||||
|
nsCOMPtr<nsIDOMElement> ownerElement;
|
||||||
|
nsCOMPtr<nsIDOMAttr> attrNode(do_QueryInterface(locationNode));
|
||||||
|
attrNode->GetOwnerElement(getter_AddRefs(ownerElement));
|
||||||
|
NS_ENSURE_STATE(ownerElement);
|
||||||
|
|
||||||
rv = parentNode->RemoveChild(locationNode, getter_AddRefs(resNode));
|
nsCOMPtr<nsIDOMAttr> resAttr;
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
ownerElement->RemoveAttributeNode(attrNode, getter_AddRefs(resAttr));
|
||||||
|
resNode = locationNode;
|
||||||
// Get the next node in the node-set.
|
|
||||||
++deleteIndex;
|
|
||||||
nodeset->SnapshotItem(deleteIndex, getter_AddRefs(locationNode));
|
|
||||||
|
|
||||||
// Deleted at least one node so delete will not terminate.
|
// Deleted at least one node so delete will not terminate.
|
||||||
didDelete = PR_TRUE;
|
didDelete = PR_TRUE;
|
||||||
|
} else {
|
||||||
|
if (!SameCOMIdentity(locationNode, locationDocElement)) {
|
||||||
|
locationNode->GetParentNode(getter_AddRefs(parentNode));
|
||||||
|
NS_ENSURE_STATE(parentNode);
|
||||||
|
|
||||||
|
rv = parentNode->RemoveChild(locationNode, getter_AddRefs(resNode));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Deleted at least one node so delete will not terminate.
|
||||||
|
didDelete = PR_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// Get the next node in the node-set.
|
||||||
|
++deleteIndex;
|
||||||
|
nodeset->SnapshotItem(deleteIndex, getter_AddRefs(locationNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The delete action is terminated with no effect if no node is deleted.
|
// The delete action is terminated with no effect if no node is deleted.
|
||||||
|
@ -631,7 +663,7 @@ nsXFormsInsertDeleteElement::GetFirstNodeOfType(nsCOMArray<nsIDOMNode> *aNodes,
|
||||||
nsresult
|
nsresult
|
||||||
nsXFormsInsertDeleteElement::InsertNode(nsIDOMNode *aTargetNode,
|
nsXFormsInsertDeleteElement::InsertNode(nsIDOMNode *aTargetNode,
|
||||||
nsIDOMNode *aNewNode,
|
nsIDOMNode *aNewNode,
|
||||||
PRBool aInsertAfter,
|
Location aLocation,
|
||||||
nsIDOMNode **aResNode)
|
nsIDOMNode **aResNode)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG(aTargetNode);
|
NS_ENSURE_ARG(aTargetNode);
|
||||||
|
@ -657,16 +689,17 @@ nsXFormsInsertDeleteElement::InsertNode(nsIDOMNode *aTargetNode,
|
||||||
// Can add an attribute to an element node or the owning element
|
// Can add an attribute to an element node or the owning element
|
||||||
// of an attribute node.
|
// of an attribute node.
|
||||||
nsCOMPtr<nsIDOMElement> ownerElement;
|
nsCOMPtr<nsIDOMElement> ownerElement;
|
||||||
nsCOMPtr<nsIDOMAttr> attrNode(do_QueryInterface(aNewNode));
|
|
||||||
|
|
||||||
if (targetNodeType == nsIDOMNode::ELEMENT_NODE) {
|
if (targetNodeType == nsIDOMNode::ELEMENT_NODE) {
|
||||||
ownerElement = do_QueryInterface(aTargetNode);
|
ownerElement = do_QueryInterface(aTargetNode);
|
||||||
} else if (targetNodeType == nsIDOMNode::ATTRIBUTE_NODE) {
|
} else if (targetNodeType == nsIDOMNode::ATTRIBUTE_NODE) {
|
||||||
attrNode->GetOwnerElement(getter_AddRefs(ownerElement));
|
nsCOMPtr<nsIDOMAttr> targetAttrNode(do_QueryInterface(aTargetNode));
|
||||||
|
targetAttrNode->GetOwnerElement(getter_AddRefs(ownerElement));
|
||||||
}
|
}
|
||||||
NS_ENSURE_STATE(ownerElement);
|
NS_ENSURE_STATE(ownerElement);
|
||||||
|
|
||||||
// Check for a duplicate attribute.
|
// Check for a duplicate attribute.
|
||||||
|
nsCOMPtr<nsIDOMAttr> attrNode(do_QueryInterface(aNewNode));
|
||||||
nsAutoString attrName, attrValue;
|
nsAutoString attrName, attrValue;
|
||||||
attrNode->GetName(attrName);
|
attrNode->GetName(attrName);
|
||||||
attrNode->GetValue(attrValue);
|
attrNode->GetValue(attrValue);
|
||||||
|
@ -681,18 +714,18 @@ nsXFormsInsertDeleteElement::InsertNode(nsIDOMNode *aTargetNode,
|
||||||
resNode.swap(*aResNode);
|
resNode.swap(*aResNode);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// New node is not an attribute so it can only be inserted to an
|
// New node will be inserted at location aLocation.
|
||||||
// element node.
|
nsCOMPtr<nsIDOMNode> targetNode = aTargetNode;
|
||||||
if (targetNodeType == nsIDOMNode::ELEMENT_NODE) {
|
|
||||||
// New node will be inserted either before or after targetNode.
|
|
||||||
nsCOMPtr<nsIDOMNode> targetNode;
|
|
||||||
targetNode = aTargetNode;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNode> parentNode;
|
nsCOMPtr<nsIDOMNode> parentNode;
|
||||||
targetNode->GetParentNode(getter_AddRefs(parentNode));
|
targetNode->GetParentNode(getter_AddRefs(parentNode));
|
||||||
NS_ENSURE_STATE(parentNode);
|
NS_ENSURE_STATE(parentNode);
|
||||||
|
|
||||||
if (aInsertAfter) {
|
if (aLocation == eLocation_FirstChild) {
|
||||||
|
aTargetNode->AppendChild(aNewNode, getter_AddRefs(resNode));
|
||||||
|
resNode.swap(*aResNode);
|
||||||
|
} else {
|
||||||
|
if (aLocation == eLocation_After) {
|
||||||
// If we're at the end of the nodeset, this returns nsnull, which is
|
// If we're at the end of the nodeset, this returns nsnull, which is
|
||||||
// fine, because InsertBefore then inserts at the end of the nodeset.
|
// fine, because InsertBefore then inserts at the end of the nodeset.
|
||||||
aTargetNode->GetNextSibling(getter_AddRefs(targetNode));
|
aTargetNode->GetNextSibling(getter_AddRefs(targetNode));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче