[ 
https://issues.apache.org/jira/browse/FLEX-34283?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14000438#comment-14000438
 ] 

Michael Labriola commented on FLEX-34283:
-----------------------------------------

The problem isn't XMLListCollection its XMLList. Its not a smart 
implementation. The commit you mention fixes another bug but at the expense of 
this one. I am not sure how we can fix this yet but trying. For reference, here 
is the root cause of the issue:

Since items added to an XMLList are passed "by reference," its state, including 
its parent node/place in an existing XML structure, are persisted. Hence, for 
example, when you create an XMLList out of the elements() of an existing XML 
object, they will still have a parent value pointing to that original XML 
object.

However, XMLLists also automatically parent new nodes that aren't parented. If 
you are *adding* a new node to an XMLList, here is the behavior:
*       If you add an XML node to an empty XMLList, it will not be (re)parented.
*       If you add an XML node that already has a parent to an XMLList, its 
parent property will be unaffected.
*       If you add an unparented XML node to an XMLList...
o       If added at index 0, it will take the parent of the subsequent XML node 
(ie: current index 0, which will become index 1).
o       If added at index > 0, it will take the parent of the previous XML node 
(ie: index - 1).

This entails a few things. Most noticeably, if your first node in an XMLList is 
unparented and you add an unparented node at index 0, it will remain unparented 
(because it takes the parent of the subsequent node, which is null).

The automatic parenting also occurs when *replacing* an existing node in an 
XMLList with a different one. Here is the behavior:
*       If you replace a node (original node) in an XMLList with another node 
(replacement node), the replacement node will also replace the original node in 
its parent XML structure as well.
*       If you replace a node (original node) in an XMLList with another node 
(replacement node), the replacement node's parent() function will return the 
value that was returned from the original node.
*       If you replace a node (original node) in an XMLList with another node 
(replacement node), the replacement node will still be a child of its previous 
parent.

The significant part of this is that, although an XML node can only have one 
parent() reference, it may exist in n children sets. Ie: The exact same XML 
node might be in numerous XML hierarchies, but will only reference the last 
parent assigned to it.


> XML item's parent null in item renderer when added to XMLListCollection
> -----------------------------------------------------------------------
>
>                 Key: FLEX-34283
>                 URL: https://issues.apache.org/jira/browse/FLEX-34283
>             Project: Apache Flex
>          Issue Type: Bug
>          Components: Spark: List
>    Affects Versions: Apache Flex 4.12.0
>            Reporter: Frédéric Monjo
>            Priority: Critical
>              Labels: collections, xml
>         Attachments: Tests.mxml
>
>
> Since 4.12, there seems to be a regression bug in XMLListCollection. The 
> scenario is:
> # The user selects an item in a list and clicks a button to create a copy of 
> this item below the selected one
> # Clone the item through {{item.copy()}}, make some modifications to this item
> # Add the item to the XMLListCollection using {{addItemAt}}, then call 
> {{refresh()}} on the collection
> # Inside some item renderers (not obviously the cloned one), XML item's 
> parent is null, and never get updated, which could cause runtime errors.
> Up to version 4.11, there has never been such problems. After a short 
> investigation, this problem may be caused by a change in {{XMLListAdapter}} 
> from [this 
> commit|https://github.com/apache/flex-sdk/commit/59dd2be7f6a9b0fda745249cf979adeac7f406b7].
>  
> Please find attached a sample program to reproduce the bug. Run the program, 
> select an item and click on the "Duplicate after" button. 
> When run in 4.11, you should see the following console trace :
> {code}
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="2"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> --------------------------------------------------
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="1+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="2"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> {code}
> Whereas when run in 4.12, you would get :
> {code}
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="2"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> --------------------------------------------------
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="1+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="2"/> --- is child of ---> null
> {code}
> Where you can see that the last item has lost his parent (note that it is not 
> the cloned item). You may try to clone several random items, and results get 
> even more confusing as you clone more items :
> {code}
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> <foo id="2"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="2"/></root>
> --------------------------------------------------
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="1+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="2"/></root>
> <foo id="2"/> --- is child of ---> null
> --------------------------------------------------
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/></root>
> <foo id="1+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/></root>
> <foo id="1++"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/></root>
> <foo id="2"/> --- is child of ---> null
> --------------------------------------------------
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/></root>
> <foo id="1+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/></root>
> <foo id="1++"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/></root>
> <foo id="2"/> --- is child of ---> null
> <foo id="2+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/></root>
> --------------------------------------------------
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/></root>
> <foo id="1+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/></root>
> <foo id="1++"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/></root>
> <foo id="2"/> --- is child of ---> null
> <foo id="2+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/></root>
> <foo id="2+"/> --- is child of ---> null
> --------------------------------------------------
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2++"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2++"/></root>
> <foo id="1+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2++"/></root>
> <foo id="1++"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2++"/></root>
> <foo id="2"/> --- is child of ---> null
> <foo id="2+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2++"/></root>
> <foo id="2+"/> --- is child of ---> null
> <foo id="2++"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2++"/></root>
> --------------------------------------------------
> <foo id="0"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2+"/><foo id="2++"/></root>
> <foo id="1"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2+"/><foo id="2++"/></root>
> <foo id="1+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2+"/><foo id="2++"/></root>
> <foo id="1++"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2+"/><foo id="2++"/></root>
> <foo id="2"/> --- is child of ---> null
> <foo id="2+"/> --- is child of ---> <root><foo id="0"/><foo id="1"/><foo 
> id="1+"/><foo id="1++"/><foo id="2"/><foo id="2+"/><foo id="2+"/><foo 
> id="2+"/><foo id="2++"/></root>
> <foo id="2+"/> --- is child of ---> null
> <foo id="2+"/> --- is child of ---> null
> <foo id="2++"/> --- is child of ---> null
> {code}



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to