Repository: flex-asjs
Updated Branches:
  refs/heads/develop 8616f4ebc -> 572b371ed


Observed drastic reduction of memory usage of XML objects of close to 50% 
(~43,000 XML objects ~37MB down to 20MB)
Still opportunity to optimize _attributes
Worth looking into default value for _nodeKind
Currently there’s no way to garbage-collect unused QNames due to references 
for QName re-usage. The tradeoff seems to be worthwhile.


Project: http://git-wip-us.apache.org/repos/asf/flex-asjs/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-asjs/commit/572b371e
Tree: http://git-wip-us.apache.org/repos/asf/flex-asjs/tree/572b371e
Diff: http://git-wip-us.apache.org/repos/asf/flex-asjs/diff/572b371e

Branch: refs/heads/develop
Commit: 572b371ed1530411100a8643b8aaea92e91d3c5a
Parents: 8616f4e
Author: Harbs <[email protected]>
Authored: Tue Sep 19 00:55:14 2017 +0300
Committer: Harbs <[email protected]>
Committed: Tue Sep 19 00:55:14 2017 +0300

----------------------------------------------------------------------
 frameworks/projects/XML/src/main/flex/XML.as | 285 +++++++++++++++-------
 1 file changed, 198 insertions(+), 87 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/572b371e/frameworks/projects/XML/src/main/flex/XML.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/XML/src/main/flex/XML.as 
b/frameworks/projects/XML/src/main/flex/XML.as
index fff4cfa..4fd596b 100644
--- a/frameworks/projects/XML/src/main/flex/XML.as
+++ b/frameworks/projects/XML/src/main/flex/XML.as
@@ -23,6 +23,7 @@ package
        {
                import org.apache.flex.debugging.assert;
                import org.apache.flex.debugging.assertType;
+               import org.apache.flex.utils.ObjectMap;
                /*
                 * Dealing with namespaces:
                 * If the name is qualified, it has a prefix. Otherwise, the 
prefix is null.
@@ -30,6 +31,32 @@ package
                 * the prefix together with the namespaceURI form a QName
                */
 
+               /**
+                * Memory optimization.
+                * Creating a new QName for each XML instance significantly 
adds memory usage.
+                * The XML Qname can be a significant percentage of an XML 
object size.
+                * By retaining a lookup of QNames and reusing QName objects, 
we can save quite a bit of memory.
+                */
+               static private var _nameMap:Object = {};
+               static private function 
getQName(localName:String,prefix:String,uri:String,isAttribute:Boolean):QName{
+                       localName = localName || "";
+                       prefix = prefix || "";
+                       uri = uri || "";
+                       var key:String = localName + ":" + prefix + ":" + uri + 
":" + isAttribute;
+                       var qname:QName = _nameMap[key];
+                       if(!qname){
+                               qname = new QName();
+                               if(prefix)
+                                       qname.prefix = prefix;
+                               if(uri)
+                                       qname.uri = uri;
+                               if(localName)
+                                       qname.localName = localName;
+                               qname.isAttribute = isAttribute;
+                               _nameMap[key] = qname;
+                       }
+                       return qname;
+               }
                static private var defaultNamespace:Namespace;
 
                static public function setDefaultNamespace(ns:*):void
@@ -37,7 +64,7 @@ package
                        if(!ns)
                                defaultNamespace = null;
                        else
-                               ns = new Namespace(ns);
+                               defaultNamespace = new Namespace(ns);
                }
 
                /**
@@ -184,8 +211,7 @@ package
                        var xml:XML;
                        var i:int;
                        var data:* = node.nodeValue;
-                       var qname:QName = new 
QName(node.namespaceURI,node.nodeName);
-                       qname.prefix = node.prefix;
+                       var qname:QName = getQName(node.nodeName, node.prefix, 
node.namespaceURI,false);
                        switch(node.nodeType)
                        {
                                case 1:
@@ -314,7 +340,7 @@ package
                public function XML(xml:* = null)
                {
                        // _origStr = xml;
-                       _children = [];
+                       // _children = [];
                        if(xml)
                        {
                                var xmlStr:String = "" + xml;
@@ -374,10 +400,11 @@ package
                                {
                                        _version = doc.xmlVersion;
                                        _encoding = doc.xmlEncoding;
-                                       _name = new QName();
-                                       _name.prefix = node.prefix;
-                                       _name.uri = node.namespaceURI;
-                                       _name.localName = node.localName;
+                                       _name = 
getQName(node.localName,node.prefix,node.namespaceURI,false);
+                                       // _name = new QName();
+                                       // _name.prefix = node.prefix;
+                                       // _name.uri = node.namespaceURI;
+                                       // _name.localName = node.localName;
                                        iterateElement(node,this);
                                }
                                else
@@ -401,7 +428,17 @@ package
                private var _version:String;
                private var _encoding:String;
                private var _appliedNamespace:Namespace;
-               private var _namespaces:Array = [];
+               /**
+                * Memory optimization: Don't create the array unless needed.
+                */
+               private var _namespaces:Array;
+               private function getNamespaces():Array
+               {
+                       if(!_namespaces)
+                               _namespaces = [];
+                       
+                       return _namespaces;
+               }
                private var _origStr:String;
 
 
@@ -432,10 +469,18 @@ package
                                _attributes.push(child);
 
                        }
-                       else
-                               _children.push(child);
+                       else                            
+                               getChildren().push(child);
+                       
                }
 
+               private function getChildren():Array
+               {
+                       if(!_children)
+                               _children = [];
+
+                       return _children;
+               }
 
                /**
                 * Adds a namespace to the set of in-scope namespaces for the 
XML object.
@@ -446,6 +491,7 @@ package
                 */
                public function addNamespace(ns:Namespace):XML
                {
+                       //TODO cached QNames will not work very well here.
                        /*
                                When the [[AddInScopeNamespace]] method of an 
XML object x is called with a namespace N, the following steps are taken:
                                1. If x.[[Class]] ∈ {"text", "comment", 
"processing-instruction", “attribute”}, return
@@ -471,23 +517,24 @@ package
                                return this;
                        var match:Namespace = null;
                        var i:int;
-                       for(i=0;i<_namespaces.length;i++)
+                       var nspaces:Array = getNamespaces();
+                       for(i=0;i<nspaces.length;i++)
                        {
-                               if(_namespaces[i].prefix == ns.prefix)
+                               if(nspaces[i].prefix == ns.prefix)
                                {
-                                       match = _namespaces[i];
+                                       match = nspaces[i];
                                        break;
                                }
                        }
                        if(match)
-                               _namespaces[i] = ns;
+                               nspaces[i] = ns;
                        else
-                               _namespaces.push(ns);
+                               nspaces.push(ns);
 
                        if(ns.prefix == name().prefix)
                                name().prefix = null;
-
-                       for(i=0;i<_attributes.length;i++)
+                       var len:int = attributeLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_attributes[i].name().prefix == ns.prefix)
                                        _attributes[i].name().prefix = null;
@@ -546,7 +593,7 @@ package
                        {
                                assertType(child,XML,"Type must be XML");
                                child.setParent(this);
-                               _children.push(child);
+                               getChildren().push(child);
                        }
                }
                
@@ -565,7 +612,8 @@ package
 
                        attributeName = toAttributeName(attributeName);
                        var list:XMLList = new XMLList();
-                       for(i=0;i<_attributes.length;i++)
+                       var len:int = attributeLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_attributes[i].name().matches(attributeName))
                                        list.append(_attributes[i]);
@@ -585,7 +633,8 @@ package
                {
                        var i:int;
                        var list:XMLList = new XMLList();
-                       for(i=0;i<_attributes.length;i++)
+                       var len:int = attributeLength();
+                       for(i=0;i<len;i++)
                                list.append(_attributes[i]);
 
                        list.targetObject = this;
@@ -620,6 +669,7 @@ package
                        6. Return list
                        */
                        var i:int;
+                       var len:int;
                        var list:XMLList = new XMLList();
                        if(parseInt(propertyName,10).toString() == propertyName)
                        {
@@ -632,7 +682,8 @@ package
                        propertyName = toXMLName(propertyName);
                        if(propertyName.isAttribute)
                        {
-                               for(i=0;i<_attributes.length;i++)
+                               len = attributeLength();
+                               for(i=0;i<len;i++)
                                {
                                        
if(propertyName.matches(_attributes[i].name()))
                                                list.append(_attributes[i]);
@@ -640,7 +691,8 @@ package
                        }
                        else
                        {
-                               for(i=0;i<_children.length;i++)
+                               len = childrenLength();
+                               for(i=0;i<len;i++)
                                {
                                        
if(propertyName.matches(_children[i].name()))
                                                list.append(_children[i]);
@@ -675,7 +727,8 @@ package
                {
                        var i:int;
                        var list:XMLList = new XMLList();
-                       for(i=0;i<_children.length;i++)
+                       var len:int = childrenLength();
+                       for(i=0;i<len;i++)
                                list.append(_children[i]);
 
                        list.targetObject = this;
@@ -692,7 +745,8 @@ package
                {
                        var i:int;
                        var list:XMLList = new XMLList();
-                       for(i=0;i<_children.length;i++)
+                       var len:int = childrenLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_children[i].nodeKind() == "comment")
                                        list.append(_children[i]);
@@ -765,15 +819,18 @@ package
                        xml.setNodeKind(_nodeKind);
                        xml.setName(name());
                        xml.setValue(_value);
-                       for(i=0;i<_namespaces.length;i++)
+                       var len:int;
+                       len = namespaceLength();
+                       for(i=0;i<len;i++)
                        {
                                xml.addNamespace(new Namespace(_namespaces[i]));
                        }
                        //parent should be null by default
-                       for(i=0;i<_attributes.length;i++)
+                       len = attributeLength();
+                       for(i=0;i<len;i++)
                                xml.addChildInternal(_attributes[i].copy());
-
-                       for(i=0;i<_children.length;i++)
+                       len = childrenLength();
+                       for(i=0;i<len;i++)
                                xml.addChildInternal(_children[i].copy());
                        
                        return xml;
@@ -783,7 +840,7 @@ package
                {
                        if(idx < 0)
                                return;
-                       if(idx >= _children.length)
+                       if(idx >= childrenLength())
                                return;
                        var child:XML = _children[idx];
                        child._parent = null;
@@ -815,19 +872,22 @@ package
                                5. Return list
                        */
                        var i:int;
+                       var len:int;
                        if(!name)
                                name = "*";
                        name = toXMLName(name);
                        var list:XMLList = new XMLList();
                        if(name.isAttribute)
                        {
-                               for(i=0;i<_attributes.length;i++)
+                               len = attributeLength();
+                               for(i=0;i<len;i++)
                                {
                                        if(name.matches(_attributes[i].name()))
                                                list.append(_attributes[i]);
                                }
                        }
-                       for(i=0;i<_children.length;i++)
+                       len = childrenLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_children[i].nodeKind() == "element")
                                {
@@ -854,7 +914,8 @@ package
                        name = toXMLName(name);
                        var i:int;
                        var list:XMLList = new XMLList();
-                       for(i=0;i<_children.length;i++)
+                       var len:int = childrenLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_children[i].nodeKind() == "element" && 
name.matches(_children[i].name()))
                                        list.append(_children[i]);
@@ -943,7 +1004,8 @@ package
                                name = new QName(nameOrXML);
                        }
                        var i:int;
-                       for(i=0;i<_attributes.length;i++)
+                       var len:int = attributeLength();
+                       for(i=0;i<len;i++)
                        {
                                if(name.matches(_attributes[i].name()))
                                {
@@ -997,12 +1059,27 @@ package
 
                public function getIndexOf(elem:XML):int
                {
-                       return _children.indexOf(elem);
+                       return _children ? _children.indexOf(elem) : -1;
+               }
+               private function childrenLength():int
+               {
+                       return _children ? _children.length : 0;
+               }
+               private function attributeLength():int
+               {
+                       return _attributes ? _attributes.length : 0;
+               }
+               private function namespaceLength():int
+               {
+                       return _namespaces ? _namespaces.length : 0;
                }
                
                private function getURI(prefix:String):String
                {
                        var i:int;
+                       if(!_namespaces)
+                               return "";
+
                        var namespaces:Array = 
getAncestorNamespaces(_namespaces);
                        for(i=0;i<namespaces.length;i++)
                        {
@@ -1049,7 +1126,8 @@ package
                        if(_nodeKind == "attribute" || _nodeKind == "comment" 
|| _nodeKind == "processing-instruction" || _nodeKind == "text")
                                return false;
                        var i:int;
-                       for(i=0;i<_children.length;i++)
+                       var len:int = childrenLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_children[i].nodeKind() == "element")
                                        return true;
@@ -1078,9 +1156,11 @@ package
                                return p == "0";
                        var name:QName = toXMLName(p);
                        var i:int;
+                       var len:int
                        if(name.isAttribute)
                        {
-                               for(i=0;i<_attributes.length;i++)
+                               len = attributeLength();
+                               for(i=0;i<len;i++)
                                {
                                        if(_attributes[i].name().matches(name))
                                                return true;
@@ -1088,7 +1168,8 @@ package
                        }
                        else
                        {
-                               for(i=0;i<_children.length;i++)
+                               len = childrenLength();
+                               for(i=0;i<len;i++)
                                {
                                        if(_children[i].nodeKind() != "element")
                                                continue;
@@ -1117,7 +1198,8 @@ package
                        if(_nodeKind == "comment" || _nodeKind == 
"processing-instruction")
                                return false;
                        var i:int;
-                       for(i=0;i<_children.length;i++)
+                       var len:int = childrenLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_children[i].nodeKind() == "element")
                                        return false;
@@ -1133,7 +1215,7 @@ package
                 */
                public function inScopeNamespaces():Array
                {
-                       return _namespaces.slice();
+                       return _namespaces ? _namespaces.slice() : [];
                }
                
                private function insertChildAt(child:XML,idx:int):void{
@@ -1164,7 +1246,8 @@ package
                        if(parent)
                                parent.removeChild(child);
                        child.setParent(this);
-                       _children.splice(idx,0,child);
+
+                       getChildren().splice(idx,0,child);
                }
                /**
                 * Inserts the given child2 parameter after the child1 
parameter in this XML object and returns the resulting object.
@@ -1194,7 +1277,7 @@ package
                                insertChildAt(child2,0);
                                return child2;
                        }
-                       var idx:int = _children.indexOf(child1);
+                       var idx:int = getIndexOf(child1);
                        if(idx >= 0)
                        {
                                insertChildAt(child2,idx+1);
@@ -1229,10 +1312,11 @@ package
                                return null;
                        if(!child1)
                        {
-                               insertChildAt(child2,_children.length);
+                               var len:int = childrenLength();
+                               insertChildAt(child2,len);
                                return child2;
                        }
-                       var idx:int = _children.indexOf(child1);
+                       var idx:int = getIndexOf(child1);
                        if(idx >= 0)
                        {
                                insertChildAt(child2,idx);
@@ -1273,7 +1357,7 @@ package
                public function name():Object
                {
                        if(!_name)
-                               _name = new QName();
+                               _name = getQName("","","",false);
                        return _name;
                }
                
@@ -1306,7 +1390,8 @@ package
                        var i:int;
                        if(prefix)
                        {
-                               for(i=0;i<_namespaces.length;i++)
+                               var len:int = namespaceLength();
+                               for(i=0;i<len;i++)
                                {
                                        if(_namespaces[i].prefix == prefix)
                                                return _namespaces[i];
@@ -1354,7 +1439,7 @@ package
                        var retVal:Array = [];
                        if(_nodeKind == "text" || _nodeKind == "comment" || 
_nodeKind == "processing-instruction" || _nodeKind ==  "attribute")
                                return retVal;
-                       var declaredNS:Array = _namespaces.slice();
+                       var declaredNS:Array = _namespaces ? 
_namespaces.slice() : [];
                        var parent:XML = _parent;
                        while(parent)
                        {
@@ -1399,7 +1484,7 @@ package
                 */
                public function normalize():XML
                {
-                       var len:int = _children.length-1;
+                       var len:int = childrenLength() - 1;
                        var lastChild:XML;
                        for(var i:int=len;i>=0;i--)
                        {
@@ -1482,7 +1567,7 @@ package
                        {
                                assertType(child,XML,"Type must be XML");
                                child.setParent(this);
-                               _children.unshift(child);
+                               getChildren().unshift(child);
                        }
                }
 
@@ -1498,7 +1583,8 @@ package
                {
                        var i:int;
                        var list:XMLList = new XMLList();
-                       for(i=0;i<_children.length;i++)
+                       var len:int = childrenLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_children[i].nodeKind() == 
"processing-instruction")
                                        list.append(_children[i]);
@@ -1548,9 +1634,8 @@ package
                        
                        if(child.nodeKind() == "attribute")
                        {
-                               if(!_attributes)
-                                       return false;
-                               for(i=0;i<_attributes.length;i++)
+                               var len:int = attributeLength();
+                               for(i=0;i<len;i++)
                                {
                                        if(child.equals(_attributes[i]))
                                        {
@@ -1562,7 +1647,7 @@ package
                                }
                                return false;
                        }
-                       var idx:int = _children.indexOf(child);
+                       var idx:int = getIndexOf(child);
                        if(idx < 0)
                                return false;
                        removed = _children.splice(idx,1);
@@ -1572,15 +1657,14 @@ package
                private function removeChildByName(name:*):Boolean
                {
                        var i:int;
+                       var len:int;
                        name = toXMLName(name);
                        var child:XML = null;
                        var removedItem:Boolean = false;
                        if(name.isAttribute)
                        {
-                               if(!_attributes)
-                                       return false;
-
-                               for(i=_attributes.length-1;i>=0;i--)
+                               len = attributeLength() -1;
+                               for(i=len;i>=0;i--)
                                {
                                        if(_attributes[i].name().matches(name))
                                        {
@@ -1593,9 +1677,8 @@ package
                                return removedItem;
                        }
                        //QUESTION am I handling non-elements correctly?
-                       if(!_children)
-                               return false;
-                       for(i=_children.length-1;i>=0;i--)
+                       len = childrenLength() - 1;
+                       for(i=len;i>=0;i--)
                        {
                                if(_children[i].name().matches(name))
                                {
@@ -1659,27 +1742,32 @@ package
                                9. Return x
                        */
                        var i:int;
+                       var len:int;
                        if(_nodeKind == "text" || _nodeKind == "comment" || 
_nodeKind == "processing-instruction" || _nodeKind == "attribute")
                                return this;
                        if(!(ns is Namespace))
                                ns = new Namespace(ns);
                        if(ns == name().getNamespace(_namespaces))
                                return this;
-                       for(i=0;i<_attributes.length;i++)
+                       len = attributeLength();
+                       for(i=0;i<len;i++)
                        {
                                if(ns == 
_attributes[i].name().getNamespace(_namespaces))
                                        return this;
                        }
                        
                        //
-                       for(i=_namespaces.length-1;i>=0;i--)
+                       
+                       len = namespaceLength();
+                       for(i=len-1;i>=0;i--)
                        {
                                if(_namespaces[i].uri == ns.uri && 
_namespaces[i].prefix == ns.prefix)
                                        _namespaces.splice(i,1);
                                else if(ns.prefix == null && _namespaces[i].uri 
== ns.uri)
                                        _namespaces.splice(i,1);
                        }
-                       for(i=0;i<_children.length;i++)
+                       len = childrenLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_children[i].nodeKind() == "element")
                                        _children[i].removeNamespace(ns);
@@ -1759,10 +1847,14 @@ package
                                  d. Let the value of property P of x be t
                                8. Return
                        */
+                       var len:int;
                        if(_nodeKind == "text" || _nodeKind == "comment" || 
_nodeKind == "processing-instruction" || _nodeKind ==  "attribute")
                                return;
-                       if(idx > _children.length)
-                               idx = _children.length;
+                       len = childrenLength();
+                       if(idx > len)
+                               idx = len;
+                       // make sure _children exist
+                       getChildren();
                        if(v is XML && v.nodeKind() != "attribute")
                        {
                                if(v.nodeKind() == "element" && (v==this || 
isAncestor(v)) )
@@ -1778,7 +1870,7 @@ package
                                if(_children[idx])
                                        _children[idx]._parent = null;
 
-                               var len:int = v.length();
+                               len = v.length();
                                v[0].setParent(this);
                                _children[idx] = v[0];
                                var listIdx:int = 1;
@@ -1818,7 +1910,8 @@ package
                        {
                                if(attr.nodeKind() == "attribute")
                                {
-                                       for(i=0;i<_attributes.length;i++)
+                                       var len:int = attributeLength();
+                                       for(i=0;i<len;i++)
                                        {
                                                
if(_attributes[i].name().equals(attr.name()))
                                                {
@@ -1852,7 +1945,8 @@ package
                                attrXML.setNodeKind("attribute");
                                attrXML.setName(toAttributeName(attr));
                                attrXML.setValue(value);
-                               for(i=0;i<_attributes.length;i++)
+                               len = attributeLength();
+                               for(i=0;i<len;i++)
                                {
                                        
if(_attributes[i].name().equals(attrXML.name()))
                                        {
@@ -1945,7 +2039,7 @@ package
                        var chld:XML;
                        var retVal:Object = elements;
 
-                       // I'm not wure that this a strict interpretation of 
the spec but I think this does the "right thing".
+                       // I'm not sure that this a strict interpretation of 
the spec but I think this does the "right thing".
                        var childType:String = typeof elements;
                        if(childType != "object")
                        {
@@ -1975,7 +2069,7 @@ package
                                        // remove the children
                                        // adjust the childIndexes
                                }
-                               var curChild:XML = _children[childIdx];
+                               var curChild:XML = getChildren()[childIdx];
                                // Now add them in.
                                len = elements.length();
                                for(i=0;i<len;i++)
@@ -2012,6 +2106,7 @@ package
                        var i:int;
                        var len:int;
                        var chld:XML;
+
                        if(value is XML)
                        {
                                var list:XMLList = new XMLList();
@@ -2034,7 +2129,7 @@ package
                                        // remove the children
                                        // adjust the childIndexes
                                }
-                               var curChild:XML = _children[childIdx];
+                               var curChild:XML = getChildren()[childIdx];
                                // Now add them in.
                                len = value.length();
                                for(i=0;i<len;i++)
@@ -2066,7 +2161,8 @@ package
                        if(!_name)
                                _name = new QName();
 
-                       _name.localName = name;
+                       _name = 
getQName(name,_name.prefix,_name.uri,_name.isAttribute)
+                       // _name.localName = name;
                }
                
                /**
@@ -2077,10 +2173,13 @@ package
                 */
                public function setName(name:*):void
                {
+                       var nameRef:QName;
                        if(name is QName)
-                               _name = name;
+                               nameRef = name;
                        else
-                               _name = new QName(name);
+                               nameRef = new QName(name);
+                       
+                       _name = 
getQName(nameRef.localName,nameRef.prefix,nameRef.uri,nameRef.isAttribute);
                }
                
                /**
@@ -2094,15 +2193,18 @@ package
                        if(_nodeKind == "text" || _nodeKind == "comment" || 
_nodeKind == "processing-instruction")
                                return;
                        var ns2:Namespace = new Namespace(ns);
-                       _name = new QName(ns2,name());
-
+                       var nameRef:QName = new QName(ns2,name());
+                       
                        if(_nodeKind == "attribute")
                        {
-                               _name.isAttribute = true;
+                               nameRef.isAttribute = true;
                                if(_parent == null)
                                        return;
                                _parent.addNamespace(ns2);
                        }
+
+                       _name = 
getQName(nameRef.localName,nameRef.prefix,nameRef.uri,nameRef.isAttribute);
+
                        if(_nodeKind == "element")
                                addNamespace(ns2);
                }
@@ -2113,7 +2215,9 @@ package
                 */
                public function setNodeKind(value:String):void
                {
-                       _nodeKind = value;
+                       // memory optimization. The default on the prototype is 
"element" and using the prototype saves memory
+                       if(_nodeKind != value)
+                               _nodeKind = value;
                }
                
                public function setParent(parent:XML):void
@@ -2151,7 +2255,8 @@ package
                {
                        var list:XMLList = new XMLList();
                        var i:int;
-                       for(i=0;i<_children.length;i++)
+                       var len:int = childrenLength();
+                       for(i=0;i<len;i++)
                        {
                                if(_children[i].nodeKind() == "text")
                                        list.append(_children[i]);
@@ -2193,7 +2298,8 @@ package
                        if(this.hasSimpleContent())
                        {
                                var s:String = "";
-                               for(i=0;i<_children.length;i++)
+                               var len:int = childrenLength();
+                               for(i=0;i<len;i++)
                                {
                                        if(_children[i].nodeKind() == "comment" 
|| _children[i].nodeKind() == "processing-instruction")
                                                continue;
@@ -2354,6 +2460,7 @@ package
                                NOTE Implementations may also preserve 
insignificant whitespace (e.g., inside and between element tags) and attribute 
quoting conventions in ToXMLString().                     
                        */
                        var i:int;
+                       var len:int;
                        var ns:Namespace;
                        var strArr:Array = [];
                        indentLevel = isNaN(indentLevel) ? 0 : indentLevel;
@@ -2387,13 +2494,15 @@ package
                                ancestors = [];
 
                        var declarations:Array = [];
-                       for(i=0;i<_namespaces.length;i++)
+                       len = namespaceLength();
+                       for(i=0;i<len;i++)
                        {
                                if(!namespaceInArray(_namespaces[i],ancestors))
                                        declarations.push(new 
Namespace(_namespaces[i]));
                        }
                        //11
-                       for(i=0;i<_attributes.length;i++)
+                       len = attributeLength();
+                       for(i=0;i<len;i++)
                        {
                                ns = new 
Namespace(_attributes[i].name().getNamespace(ancestors.concat(declarations)));
                                if(ns.prefix === null)
@@ -2434,7 +2543,8 @@ package
                                        strArr.push('"');
                                }
                        }
-                       for(i=0;i<_attributes.length;i++)
+                       len = attributeLength();
+                       for(i=0;i<len;i++)
                        {
                                strArr.push(" ");
                                // the following seems to be the spec, but it 
does not make sense to me.
@@ -2452,19 +2562,20 @@ package
                                strArr.push('"');
                        }
                        // now write elements or close the tag if none exist
-                       if(_children.length == 0)
+                       len = childrenLength();
+                       if(len == 0)
                        {
                                strArr.push("/>");
                                return strArr.join("");
                        }
                        strArr.push(">");
-                       var indentChildren:Boolean = _children.length > 1 || 
(_children.length == 1 && _children[0].nodeKind() != "text");
+                       var indentChildren:Boolean = len > 1 || (len == 1 && 
_children[0].nodeKind() != "text");
                        var nextIndentLevel:int;
                        if(XML.prettyPrinting && indentChildren)
                                nextIndentLevel = indentLevel + prettyIndent;
                        else
                                nextIndentLevel = 0;
-                       for(i=0;i<_children.length;i++)
+                       for(i=0;i<len;i++)
                        {
                                //
                                if(XML.prettyPrinting && indentChildren)

Reply via email to