[Laszlo-checkins] r10258 - openlaszlo/trunk/WEB-INF/lps/lfc/data

bargull@openlaszlo.org bargull at openlaszlo.org
Tue Jul 8 11:14:26 PDT 2008


Author: bargull
Date: 2008-07-08 11:14:22 -0700 (Tue, 08 Jul 2008)
New Revision: 10258

Modified:
   openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataElement.lzs
   openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataNode.lzs
   openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataText.lzs
Log:
Change 20080702-bargull-jQa by bargull at dell--p4--2-53 on 2008-07-02 23:41:28
    in /home/Admin/src/svn/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary: enhance dom-compatibility

New Features:

Bugs Fixed: LPP-4774

Technical Reviewer: hminsky
QA Reviewer: promanik
Doc Reviewer: (pending)

Documentation:

Release Notes:

Details:
Changes for insertBefore, replaceChild, appendChild, setChildNodes:
handle case where referenced datanode is still attached to another parent-node 
-> first remove from former parent and then attach to new parent-node.
Additionally added more type declarations for base data classes, added public modifier to methods, 
and moved "serialize" and "cloneNode" declaration to LzDataNodeMixin for a more consistent API.
    

Tests:
alldata passes, compile swf9, testcase from bugreport



Modified: openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataElement.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataElement.lzs	2008-07-08 17:50:16 UTC (rev 10257)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataElement.lzs	2008-07-08 18:14:22 UTC (rev 10258)
@@ -22,71 +22,75 @@
    * @devnote These are the setters that this trait creates
    */
   /** @access private */
-  function $lzc$set_attributes(v) { this.setAttrs(v); }
+  function $lzc$set_attributes(v:Object) :void { this.setAttrs(v); }
   /** @access private */
-  function $lzc$set_childNodes(v) { this.setChildNodes(v); }
+  function $lzc$set_childNodes(v:Array) :void { this.setChildNodes(v); }
   /** @access private */
-  function $lzc$set_nodeName(v) { this.setNodeName(v); }
+  function $lzc$set_nodeName(v:String) :void { this.setNodeName(v); }
   /** @access private */
-  function $lzc$set_ownerDocument(v) { this.setOwnerDocument(v); }
+  function $lzc$set_ownerDocument(v:*) :void { this.setOwnerDocument(v); }
 
-/** @lzxtype event */
-var onDocumentChange = LzDeclaredEvent;
-/** @lzxtype event */
-var onparentNode = LzDeclaredEvent;
-/** @lzxtype event */
-var onchildNode = LzDeclaredEvent;
-/** @lzxtype event */
-var onchildNodes = LzDeclaredEvent;
-/** @lzxtype event */
-var onattributes = LzDeclaredEvent;
-/** @lzxtype event */
-var onnodeName = LzDeclaredEvent;
 
 /** @access private */
-//var __LZo = -1;
+var __LZchangeQ :Array = null;
 /** @access private */
-//var __LZcoDirty = true;
-/** @access private */
-var __LZchangeQ = null;
-/** @access private */
-var __LZlocker = null;
+var __LZlocker :LzDatapath = null;
 
 /** The name of this node.
   * @type String
   */
-var nodeName:* = null;
+var nodeName:String = null;
 
 /** The dictionary of attributes for this node.
   * @type Object
   */
-var attributes:* = null;
+var attributes:Object = null;
 
 
 /** Inserts the given LzDataNodeMixin before another node in this node's childNodes
   * @param LzDataNodeMixin newChild: the LzDataNodeMixin to insert
   * @param LzDataNodeMixin refChild: the LzDataNodeMixin to insert newChild before
-  * @return LzDataElement: The new child, or null if the refChild wasn't found
+  * @return LzDataNodeMixin: The new child, or null if the refChild wasn't found
   */
-function insertBefore (newChild, refChild){
-    this.__LZcoDirty = true;
-
-    for ( var i = 0; i < this.childNodes.length; i++ ){
-        if ( this.childNodes[ i ] == refChild ){
-            this.childNodes.splice( i , 0 , newChild );
+public function insertBefore (newChild, refChild){
+    if (newChild == null) {
+        return null;
+    } else if (refChild == null) {
+        return this.appendChild(newChild);
+    } /* else if (newChild === this) {
+        //raise DOMException "HIERARCHY_REQUEST_ERR"
+        return null;
+    } */ else {
+        var off:int = this.__LZgetCO(refChild);
+        if (off >= 0) {
+            var samenode:Boolean = (newChild === refChild);
+            if (newChild.parentNode != null) {
+                if (newChild.parentNode === this) {
+                    if (! samenode) {
+                        this.__LZremoveChild( newChild );
+                    }
+                } else {
+                    newChild.parentNode.removeChild( newChild );
+                }
+            }
+            
+            if (! samenode) {
+                this.__LZcoDirty = true;
+                this.childNodes.splice( off, 0, newChild );
+            }
+            
             newChild.setOwnerDocument( this.ownerDocument );
-
             newChild.parentNode = this;
             if (newChild.onparentNode.ready) newChild.onparentNode.sendEvent( this );
             if (this.onchildNodes.ready) this.onchildNodes.sendEvent( newChild );
-            this.ownerDocument.handleDocumentChange( "insertBefore" , 
-                                                     this, 0 );
+            this.ownerDocument.handleDocumentChange( "insertBefore", this, 0 );
+            
             return newChild;
         }
+        
+        //raise DOMException "NOT_FOUND_ERR"
+        return null;
     }
-
-    //raise exception
-    return null;
 }
 
 
@@ -94,26 +98,50 @@
   * Replaces a given LzDataNodeMixin in this node's childNodes with a new one.
   * @param LzDataNodeMixin newChild: the LzDataNodeMixin to add
   * @param LzDataNodeMixin oldChild: the LzDataNodeMixin to be replaced by the newChild
-  * @return LzDataElement: The new child, or null if the oldChild wasn't found
+  * @return LzDataNodeMixin: The new child, or null if the oldChild wasn't found
+  * @dev-note: DOM-Spec (Level2, Level3) says we need to return the oldChild instead of the newChild
   */
-function replaceChild (newChild, oldChild){
-
-    this.__LZcoDirty = true;
-    for ( var i = 0; i < this.childNodes.length; i++ ){
-        if ( this.childNodes[ i ] == oldChild ){
-            this.childNodes[ i ] = newChild;
-
+public function replaceChild (newChild, oldChild){
+    if (newChild == null) {
+        return null;
+    } /* else if (newChild === this) {
+        //raise DOMException "HIERARCHY_REQUEST_ERR"
+        return null;
+    } */ else {
+        var off:int = this.__LZgetCO(oldChild);
+        if (off >= 0) {
+            var samenode:Boolean = (newChild === oldChild);
+            if (newChild.parentNode != null) {
+                if (newChild.parentNode === this) {
+                    if (! samenode) {
+                        this.__LZremoveChild( newChild );
+                    }
+                } else {
+                    newChild.parentNode.removeChild( newChild );
+                }
+            }
+            
+            if (! samenode) {
+                //TODO [20080702 anba] this breaks smoke-check!
+                // oldChild.parentNode = null;
+                // oldChild.setOwnerDocument( null );
+                //adjust node-offset
+                newChild.__LZo = off;
+                this.childNodes[ off ] = newChild;
+            }
+            
             newChild.setOwnerDocument( this.ownerDocument );
-
             newChild.parentNode = this;
             if (newChild.onparentNode.ready) newChild.onparentNode.sendEvent( this );
             if (this.onchildNodes.ready) this.onchildNodes.sendEvent( newChild );
-            this.ownerDocument.handleDocumentChange( "childNodes" , this , 0, newChild );
+            this.ownerDocument.handleDocumentChange( "childNodes", this, 0, newChild );
+            
             return newChild;
         }
+        
+        //raise DOMException "NOT_FOUND_ERR"
+        return null;
     }
-    //raise exception
-    return null;
 }
 
 /**
@@ -121,19 +149,24 @@
   * @param LzDataNodeMixin oldChild: The LzDataNodeMixin to remove
   * @return LzDataNodeMixin: The removed child, or null if the oldChild was not found
   */
-function removeChild (oldChild){
-    var reval = null;
-    this.__LZcoDirty = true;
-    for ( var i = 0; i < this.childNodes.length; i++ ){
-        if ( this.childNodes[ i ] == oldChild ){
-            this.childNodes.splice( i , 1 );
-            if (this.onchildNodes.ready) this.onchildNodes.sendEvent( oldChild );
-            reval = oldChild;
-            this.ownerDocument.handleDocumentChange("removeChild", this, 0, oldChild);
-        }
+public function removeChild (oldChild){
+    var off:int = this.__LZgetCO(oldChild);
+    if (off >= 0) {
+        //TODO [20080702 anba] this breaks smoke-check!
+        // oldChild.parentNode = null;
+        // oldChild.setOwnerDocument( null );
+        
+        this.__LZcoDirty = true;
+        this.childNodes.splice( off, 1 );
+        
+        if (this.onchildNodes.ready) this.onchildNodes.sendEvent( oldChild );
+        this.ownerDocument.handleDocumentChange("removeChild", this, 0, oldChild);
+        
+        return oldChild;
     }
-    //raise exception if not found
-    return reval;
+    
+    //raise DOMException "NOT_FOUND_ERR"
+    return null;
 }
 
 /**
@@ -141,46 +174,58 @@
   * @param LzDataNodeMixin newChild: The LzDataNodeMixin to add.
   * @return LzDataNodeMixin: The newChild.
   */
-function appendChild (newChild){
-    if ( this.childNodes ){
-        this.childNodes.push( newChild );
-    } else {
-        this.childNodes = [ newChild ];
+public function appendChild (newChild){
+    if (newChild == null) {
+        return null;
+    } /* else if (newChild === this) {
+        //raise DOMException "HIERARCHY_REQUEST_ERR"
+        return null;
+    } */ else {
+        if (newChild.parentNode != null) {
+            if (newChild.parentNode === this) {
+                this.__LZcoDirty = true;
+                this.__LZremoveChild( newChild );
+            } else {
+                newChild.parentNode.removeChild( newChild );
+            }
+        }
+        
+        if (this.childNodes) {
+            this.childNodes.push( newChild );
+        } else {
+            this.childNodes = [newChild];
+        }
+        
+        //instead of marking dirty, this is easy
+        newChild.__LZo = this.childNodes.length - 1;
+        
+        newChild.setOwnerDocument( this.ownerDocument );
+        newChild.parentNode = this;
+        if (newChild.onparentNode.ready) newChild.onparentNode.sendEvent( this );
+        if (this.onchildNodes.ready) this.onchildNodes.sendEvent( newChild );
+        this.ownerDocument.handleDocumentChange( "appendChild", this, 0, newChild );
+        
+        return newChild;
     }
-
-    newChild.setOwnerDocument( this.ownerDocument );
-
-    newChild.parentNode = this;
-    if (newChild.onparentNode.ready) newChild.onparentNode.sendEvent( this );
-
-    //instead of marking dirty, this is easy
-    newChild.__LZo = this.childNodes.length -1;
-
-    if (this.onchildNodes.ready) this.onchildNodes.sendEvent( newChild );
-    this.ownerDocument.handleDocumentChange( "appendChild" , this , 0, newChild );
-    return newChild;
 }
 
 /**
   * Tests whether or not this node has child nodes.
   * @return Boolean: If true, this node has child nodes.
   */
-function hasChildNodes (){
+public function hasChildNodes () :Boolean {
     return this.childNodes.length > 0;
 }
 
 /**
-  * Returns a copy of this node.
-  * @param Boolean deep: If true, the children of this node will be part of the
-  * new node
-  * @return LzDataNodeMixin: A copy of this node.
+  * @access private
   */
-function cloneNode ( deep=false ){
-    var n = new LzDataElement(this.nodeName);
+override public function cloneNode ( deep:Boolean = false ) :LzDataNodeMixin {
+    var n:LzDataElement = new LzDataElement(this.nodeName);
     n.setAttrs( this.attributes );
     if ( deep ){
-        for ( var i = 0 ; i < this.childNodes.length; i++ ){
-            n.appendChild ( this.childNodes[ i ].cloneNode( true ) );
+        for ( var i:int = 0 ; i < this.childNodes.length; i++ ){
+            n.appendChild( this.childNodes[ i ].cloneNode( true ) );
         }
     }
 
@@ -192,11 +237,11 @@
   * @param String name: The name of the attribute whose value to return
   * @return String: The value for the given attribute
   */
-function getAttr (name){
+public function getAttr (name:String) :String {
     if (this.attributes) return this.attributes[ name ];
 }
 /** @access private */
-function $lzc$getAttr_dependencies (who , self){
+function $lzc$getAttr_dependencies (who , self) :Array {
     return [ self, 'attributes' ];
 }
 
@@ -205,13 +250,13 @@
   * @param String name: The name of the attribute to set.
   * @param String value: The value for the attribute.
   */
-function setAttr (name, value){
+public function setAttr (name:String, value:String) :String {
     if ( ! this.attributes ) {
       this.attributes = {};
     }
     this.attributes[ name ] = value;
     if (this.onattributes.ready) this.onattributes.sendEvent( name );
-    this.ownerDocument.handleDocumentChange( "attributes" , this , 1, {name: name, value: value, type: 'set'});
+    this.ownerDocument.handleDocumentChange( "attributes" , this, 1, {name: name, value: value, type: 'set'});
     return value;
 }
 
@@ -219,11 +264,11 @@
   * Removes the named attribute
   * @param String name: The name of the attribute to remove.
   */
-function removeAttr (name){
-    var v = this.attributes[ name ];
+public function removeAttr (name:String) :String {
+    var v:String = this.attributes[ name ];
     delete this.attributes[ name ];
     if (this.onattributes.ready) this.onattributes.sendEvent( name );
-    this.ownerDocument.handleDocumentChange( "attributes" , this , 1, {name: name, value: v, type: 'remove'});
+    this.ownerDocument.handleDocumentChange( "attributes", this, 1, {name: name, value: v, type: 'remove'});
     return v;
 }
 
@@ -246,11 +291,11 @@
   * @param String name: The name of the attribute to test
   * @return Boolean: If true, the named attribute is present.
   */
-function hasAttr (name){
+public function hasAttr (name:String) :Boolean {
     return this.attributes[ name ] != null;
 }
 /** @access private */
-function $lzc$hasAttr_dependencies (who , self){
+function $lzc$hasAttr_dependencies (who , self) :Array {
     return [ self, 'attributes' ];
 }
 
@@ -258,34 +303,67 @@
   * Returns the first child of this node.
   * @return LzDataNodeMixin: The first child of this node
   */
-function getFirstChild (){
+public function getFirstChild (){
     return this.childNodes[ 0 ];
 }
 /** @access private */
-function $lzc$getFirstChild_dependencies( who, self ){
-    return [ this , "childNodes" ];
+function $lzc$getFirstChild_dependencies( who, self ) :Array {
+    return [ this, "childNodes" ];
 }
 
 /**
   * Returns the last child of this node.
   * @return LzDataNodeMixin: The last child of this node
   */
-function getLastChild (){
+public function getLastChild (){
     return this.childNodes[ this.childNodes.length-1 ];
 }
 /** @access private */
-function $lzc$getLastChild_dependencies( who, self ){
-    return [ this , "childNodes" ];
+function $lzc$getLastChild_dependencies( who, self ) :Array {
+    return [ this, "childNodes" ];
 }
 
+/** @access private */
+function __LZgetCO (child /*:LzDataNodeMixin*/) :int {
+    var cn:Array = this.childNodes;
+    if (! this.__LZcoDirty) {
+        //this is the fast path
+        var i:int = child.__LZo;
+        if (cn[i] === child) {
+            return i;
+        }
+    } else {
+        for (var i:int = cn.length - 1; i >= 0; --i) {
+            if (cn[i] === child) {
+                return i;
+            }
+        }
+    }
+    return -1;
+}
 
 /**
+  * fast removing of a childnode without: 
+  * - notifying the event-system 
+  * - setting parentNode to null 
+  * - setting ownerDocument to null 
   * @access private
   */
-function __LZupdateCO (){
-    for ( var i = 0; i < this.childNodes.length; i++ ){
-        this.childNodes[ i ].__LZo = i;
+function __LZremoveChild (oldChild /*:LzDataNodeMixin*/ ) :void {
+    var off:int = this.__LZgetCO(oldChild);
+    if (off >= 0) {
+        this.childNodes.splice(off, 1);
     }
+}
+
+/**
+  * @access private
+  */
+function __LZupdateCO () :void {
+    var cn:Array = this.childNodes;
+    for ( var i:int = 0; i < cn.length; i++ ){
+        cn[ i ].__LZo = i;
+    }
     this.__LZcoDirty = false;
 }
 
@@ -294,14 +372,14 @@
   * Sets the attributes of this node to the given Object.
   * @param Object attrs: The object to use as the attrs for this node.
   */
-function setAttrs ( attrs ){
-    var a = {};
-    for ( var k in attrs ){ a[ k ] = attrs[ k ]; }
+public function setAttrs ( attrs:Object ) :void {
+    var a:Object = {};
+    for ( var k:String in attrs ){ a[ k ] = attrs[ k ]; }
 
     this.attributes = a;
     if (this.onattributes.ready) this.onattributes.sendEvent( a);
     if (this.ownerDocument) {
-        this.ownerDocument.handleDocumentChange( "attributes" , this , 1);
+        this.ownerDocument.handleDocumentChange( "attributes", this, 1);
     }
 }
 
@@ -310,32 +388,57 @@
   * @param [LzDataNodeMixin] children: An array of LzDataNodeMixins to be the new children
   * of this node
   */
-function setChildNodes ( children ){
+public function setChildNodes ( children:Array ) :void {
+    //TODO [20080702 anba] this breaks smoke-check!
+    //var cn = this.childNodes;
+    //if (cn && cn.length > 0) {
+    //    for (var i = 0; i < cn.length; ++i) {
+    //        cn.parentNode = null;
+    //        cn.setOwnerDocument( null );
+    //    }
+    //}
+    
     this.childNodes = children;
-    for ( var i = 0; i < children.length; i++ ){
-        var c = children[ i ];
-        if (c) {
-            c.setOwnerDocument( this.ownerDocument );
-            c.parentNode = this;
-            if (c.onparentNode) {
-                if (c.onparentNode.ready) c.onparentNode.sendEvent( this );
+    
+    if (children.length > 0) {
+        // special-case: we cannot call removeChild() if 'children' is the childNodes-Array
+        // of another LzDataElement, because removeChild() alters the childNodes-Array directly. Argh!
+        var notifyParent:Boolean = true;
+        var otherParent = children[0].parentNode;
+        if (otherParent != null && otherParent !== this && otherParent.childNodes === children) {
+            notifyParent = false;
+            otherParent.setChildNodes([]);
+        }
+        
+        for (var i:int = 0; i < children.length; i++) {
+            var c = children[ i ];
+            if (c) {
+                if (notifyParent && c.parentNode != null) {
+                    if (c.parentNode !== this) {
+                        c.parentNode.removeChild( c );
+                    }
+                }
+                
+                c.setOwnerDocument( this.ownerDocument );
+                c.parentNode = this;
+                if (c.onparentNode && c.onparentNode.ready) c.onparentNode.sendEvent( this );
+                c.__LZo = i;
             }
-            c.__LZo = i;
         }
     }
+    
     this.__LZcoDirty = false;
     if (this.onchildNodes) {
         if (this.onchildNodes.ready) this.onchildNodes.sendEvent( children );
     }
-    this.ownerDocument.handleDocumentChange( "childNodes" , this , 0);
+    this.ownerDocument.handleDocumentChange( "childNodes", this, 0);
 }
 
 /**
   * Sets the name of this node.
   * @param String name: The new name for this node
   */
-function setNodeName ( name ){
-    //Debug.write('setting node name from "',this.nodeName, '" to "', name, '"');
+public function setNodeName ( name:String ) :void {
     this.nodeName = name;
     //since this can affect xpaths, send onchildNodes event
     if (this.onnodeName.ready) this.onnodeName.sendEvent( name );
@@ -343,18 +446,17 @@
         if (this.parentNode.onchildNodes.ready) this.parentNode.onchildNodes.sendEvent( this );
         if (this.parentNode.onchildNode.ready) this.parentNode.onchildNode.sendEvent( this );
     }
-    this.ownerDocument.handleDocumentChange( "childNodeName" , 
-                                             this.parentNode , 0 );
-    this.ownerDocument.handleDocumentChange( "nodeName" , this, 1 );
+    this.ownerDocument.handleDocumentChange( "childNodeName", this.parentNode, 0 );
+    this.ownerDocument.handleDocumentChange( "nodeName", this, 1 );
 }
 
 /**
   * @access private
   */
 // dummyarg needed for calls from LzDatapointer.__LZprocessOperator
-function __LZgetText ( dummyarg = null ){
-    var s= "";
-    for ( var i = 0; i < this.childNodes.length; i++ ){
+function __LZgetText ( dummyarg:* = null ) :String {
+    var s:String = "";
+    for ( var i:int = 0; i < this.childNodes.length; i++ ){
         var c = this.childNodes[ i ]
         if ( c.nodeType == LzDataElement.TEXT_NODE ){
             s += c.data;
@@ -368,9 +470,9 @@
   * @param String name: The name of the node to look for.
   * @return [LzDataNodeMixin]: A list of childNodes which have the given name.
   */
-function getElementsByTagName (name) {
-    var r = [];
-    for ( var i = 0; i < this.childNodes.length; i++ ){
+public function getElementsByTagName (name:String) :Array {
+    var r:Array = [];
+    for ( var i:int = 0; i < this.childNodes.length; i++ ){
         if ( this.childNodes[i].nodeName == name ){
             r.push( this.childNodes[ i ] );
         }
@@ -428,18 +530,17 @@
 /**
   * @access private
   */
-var __LZlt = "<";
+const __LZlt :String = "<";
 /**
   * @access private
   */
-var __LZgt = ">";
+const __LZgt :String = ">";
 
 
 /**
-  * Returns this node as a string of xml.
-  * @return String: The string serialization of this node.
+  * @access private
   */
-function serialize (len=Infinity){
+override public function serialize (len:Number = Infinity) :String {
     return this.serializeInternal(len);
 }
 
@@ -447,18 +548,18 @@
   * Implementation of serialize with option to limit string length
   * @access private
   */
-function serializeInternal (len=Infinity) {
-    var s = this.__LZlt + this.nodeName;
+function serializeInternal (len:Number = Infinity) :String {
+    var s:String = this.__LZlt + this.nodeName;
 
     //Debug.info('k', this.attributes);
-    for ( var k in this.attributes ){
+    for ( var k:String in this.attributes ){
         s += " " + k + '="' + LzDataElement.__LZXMLescape( this.attributes[ k ] ) + '"';
         if (s.length > len) { break; }
     }
 
     if ( s.length <= len && this.childNodes && this.childNodes.length ){
         s += this.__LZgt;
-        for ( var i = 0; i < this.childNodes.length; i++ ){
+        for ( var i:int = 0; i < this.childNodes.length; i++ ){
             s += this.childNodes[ i ].serialize(len);
             if (s.length > len) { break; }
         }
@@ -477,7 +578,7 @@
   * For debugging.  Same as serialize, but will abbreviate at printLength.
   * @access private
   */
-function _dbg_name () {
+function _dbg_name () :String {
     return this.serializeInternal(Debug.printLength);
 }
 }
@@ -490,8 +591,8 @@
   * @param LzDataNodeMixin who: The node that changed.
   * @param Number type: private
   */
-function handleDocumentChange ( what , who , type, cobj=null ){
-    var o = { who:  who , what: what , type : type};
+public function handleDocumentChange ( what:String, who /*:LzDataNodeMixin*/, type:int, cobj:Object? = null ) :void {
+    var o:Object = {who: who, what: what, type: type};
     if (cobj) o.cobj = cobj;
     if ( this.__LZchangeQ ){
         this.__LZchangeQ.push ( o );
@@ -503,44 +604,41 @@
 /**
   * @access private
   */
-override function toString (){
-    //this.__LZlt = "&lt;";
-    //this.__LZgt = "&gt;";
-    var r = this.serialize();
-    //delete this.__LZlt;
-    //delete this.__LZgt;
+override function toString () :String {
+    var r:String = this.serialize();
     return r;
 }
 
 /**
+  * @dev-note: public for swf9, but still doc-private!
   * @access private
   */
-function __LZdoLock ( locker ){
+public function __LZdoLock ( locker:LzDatapath ) :void {
     if ( !this.__LZchangeQ ){
         this.__LZchangeQ = [];
         this.__LZlocker = locker;
     }
 }
 
-
 /**
+  * @dev-note: public for swf9, but still doc-private!
   * @access private
   */
-function __LZdoUnlock ( locker ){
+public function __LZdoUnlock ( locker:LzDatapath ) :void {
     
     if ( this.__LZlocker != locker ){
         return;
     }
 
-    var lzq = this.__LZchangeQ;
+    var lzq:Array = this.__LZchangeQ;
     this.__LZchangeQ = null;
 
     if (lzq != null) {
-        for ( var i = 0; i < lzq.length; i++ ){
-            var sendit = true;
-            var tc = lzq[ i ];
-            for ( var j = 0; j < i; j++ ){
-                var oc = lzq[ j ];
+        for ( var i:int = 0; i < lzq.length; i++ ){
+            var sendit:Boolean = true;
+            var tc:Object = lzq[ i ];
+            for ( var j:int = 0; j < i; j++ ){
+                var oc:Object = lzq[ j ];
                 if ( tc.who == oc.who &&
                      tc.what == oc.what &&
                      tc.type == oc.type ){
@@ -554,8 +652,6 @@
             }
         }
     }
-  
-
 }
 
 } // End of LzDataElementMixin
@@ -579,10 +675,10 @@
      * @param Object attributes: A optional dictionary of attributes for this node.
      * @param [LzDataNode] children: An optional array of children for this node
      */
-    function LzDataElement ( name , attributes = null, children = null) {
+    function LzDataElement ( name:String, attributes:Object? = null, children:Array? = null) {
         // N.B.: LzDataElement is not an LzNode so has a different
         // initialize signature.
-            super(attributes, children);
+            super();
             this.nodeName = name;
             this.nodeType = LzDataElement.ELEMENT_NODE;
             this.attributes = attributes;
@@ -596,13 +692,13 @@
 
 /**
   * Returns a list of empty nodes, each named 'name'.
-  * @param Number count: how many nodes to create.
+  * @param int count: how many nodes to create.
   * @param String name: the name for each node
   * @return Array: list of new nodes.
   */
-static function makeNodeList(count, name) {
-    var a = [];
-    for (var i=0; i < count; i++) {
+static function makeNodeList(count:int, name:String) :Array {
+    var a:Array = [];
+    for (var i:int = 0; i < count; i++) {
         a[i] = new LzDataElement(name, {}, null);
     }
     return a;
@@ -611,8 +707,8 @@
 /**
   * Get LzDataElement representation of primitive type, array, or object value.
   */
-static function valueToElement ( o ) {
-    var n = new LzDataElement("element", { }, LzDataElement.__LZv2E(o));
+static function valueToElement ( o:* ) :LzDataElement {
+    var n:LzDataElement = new LzDataElement("element", { }, LzDataElement.__LZv2E(o));
     return n; 
 }
 
@@ -621,32 +717,30 @@
   * @return array of LzDataElements
   * @access private
   */
-static function __LZv2E ( o ) {
+static function __LZv2E ( o:* ) :Array {
 
-    var type = typeof( o );
+    var type:String = typeof( o );
     type.toLowerCase();
 
-    var c = [];
+    var c:Array = [];
     if (type == "object") {
-        if ( o instanceof LzDataElement ||
-             o instanceof LzDataText ) {
+        if ( o is LzDataElement ||
+             o is LzDataText ) {
             c[0] = o;
-        } else if (o instanceof Date) {
-
+        } else if (o is Date) {
             type = "date";
             // FIXME: [2004-04-10 pkang] what should we do with dates?
-
-        } else if (o instanceof Array) {
+        } else if (o is Array) {
             type = "array";
-            var tag = (o.__LZtag != null ? o.__LZtag : 'item');
-            for (var i=0; i < o.length; i++) {
-                var tmpC = LzDataElement.__LZv2E( o[i] );
+            var tag:String = (o.__LZtag != null ? o.__LZtag : 'item');
+            for (var i:int = 0; i < o.length; i++) {
+                var tmpC:Array = LzDataElement.__LZv2E( o[i] );
                 c[i] = new LzDataElement(tag, null, tmpC ); 
             }
         } else {
             type = "struct";
-            var i = 0;
-            for (var k in o) {
+            var i:int = 0;
+            for (var k:String in o) {
                 // skip any properties that start with __LZ
                 if (k.indexOf('__LZ') == 0) continue;
                 c[i++] = new LzDataElement(k, null, LzDataElement.__LZv2E(o[k]));
@@ -662,49 +756,48 @@
 }
 
 
-
 /** constant for LZX DOM data element node type 
-  * @type Number
+  * @type int
   * @lzxdefault "1"
   * @keywords read-only
   */
-static  var ELEMENT_NODE = 1;
+static const ELEMENT_NODE :int = 1;
 /** constant for LZX DOM data text node type 
-  * @type Number
+  * @type int
   * @lzxdefault "3"
   * @keywords read-only
   */
-static  var TEXT_NODE = 3;
+static const TEXT_NODE :int = 3;
 /** constant for LZX DOM document root node type  
-  * @type Number
+  * @type int
   * @lzxdefault "9"
   * @keywords read-only
   */
-static  var DOCUMENT_NODE = 9;
+static const DOCUMENT_NODE :int = 9;
 
 /** this is similar to the escape routine in LzText, but that one's shorter
   * since flash it's just for escaping &gt;&lt;
   * @access private
   */
-static var __LZescapechars = 
+static const __LZescapechars :Object = 
 { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&apos;'};
 
 
 /**
   * @access private
   */
-static function __LZXMLescape ( t ){
+static function __LZXMLescape ( t:* ) :* {
     if ( typeof( t ) != "string" ) return t;
 
-    var olen = t.length;
-    var r = "";
-    for ( var i = 0; i < olen; i++ ){
+    var olen:int = t.length;
+    var r:String = "";
+    for ( var i:int = 0; i < olen; i++ ){
         //handle newlines
-        var code = t.charCodeAt( i );
+        var code:Number = t.charCodeAt( i );
         if ( code < 32 ){
-            r += "&#x" + lz.Utils.dectohex(code,0) + ";";
+            r += "&#x" + lz.Utils.dectohex(code, 0) + ";";
         } else {
-            var c = t.charAt( i );
+            var c:String = t.charAt( i );
             if ( LzDataElement.__LZescapechars[ c ] != null ){
                 r += LzDataElement.__LZescapechars[ c ];
             } else {
@@ -728,14 +821,18 @@
   * @return LzDataElement: An LzDataElement which is the top of the hierarchy
   * generated from the string
   */
-static function stringToLzData( str, trimwhitespace=false, nsprefix=false ) {
-    // [todo hqm 2006-06] if we had try-catch, I'd try to catch errors in parseXML
-    // and return null in that case. 
+static function stringToLzData( str:String, trimwhitespace:Boolean=false, nsprefix:Boolean=false ) :LzDataElement {
     if (str != null && str != "") {
-        //Debug.info("stringToLzData: parsing: ", typeof(str), str);
-        var nativexml = LzXMLParser.parseXML(str, trimwhitespace, nsprefix);
-        var lfcnode = LzXMLTranslator.copyXML(nativexml, trimwhitespace, nsprefix);
-        return lfcnode;
+        try {
+            var nativexml:* = LzXMLParser.parseXML(str, trimwhitespace, nsprefix);
+            var lfcnode:LzDataElement = LzXMLTranslator.copyXML(nativexml, trimwhitespace, nsprefix);
+            return lfcnode;
+        } catch (e) {
+            if ($debug) {
+                Debug.warn("Cannot parse xml-string '%s': %w", str, e);
+            }
+            return null;
+        }
     } else {
         return null;
     }
@@ -743,19 +840,19 @@
 
 /** @type Dictionary 
   * @keywords read-only */
-static var whitespaceChars = {' ': true, '\r': true, '\n': true, '\t': true};
+static const whitespaceChars :Object = {' ': true, '\r': true, '\n': true, '\t': true};
 
 
 /**
   * trim whitespace from start and end of string
   * @access private
   */
-static function trim( str ) {
-    var whitech = LzDataElement.whitespaceChars;
-    var len = str.length;
-    var sindex = 0;
-    var eindex = str.length -1;
-    var ch;
+static function trim( str:String ) :String {
+    var whitech:Object = LzDataElement.whitespaceChars;
+    var len:int = str.length;
+    var sindex:int = 0;
+    var eindex:int = len - 1;
+    var ch:String;
     while (sindex < len) {
         ch = str.charAt(sindex);
         if (whitech[ch] != true) break;
@@ -768,7 +865,7 @@
         eindex--;
     }
         
-    return str.slice(sindex,eindex+1);
+    return str.slice(sindex, eindex + 1);
 }
 
 

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataNode.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataNode.lzs	2008-07-08 17:50:16 UTC (rev 10257)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataNode.lzs	2008-07-08 18:14:22 UTC (rev 10258)
@@ -68,63 +68,75 @@
 mixin LzDataNodeMixin
 {
 /** @lzxtype event */
-var onownerDocument = LzDeclaredEvent;
+var onownerDocument :LzDeclaredEventClass = LzDeclaredEvent;
+/** @lzxtype event */
+var onDocumentChange :LzDeclaredEventClass = LzDeclaredEvent;
+/** @lzxtype event */
+var onparentNode :LzDeclaredEventClass = LzDeclaredEvent;
+/** @lzxtype event */
+var onchildNode :LzDeclaredEventClass = LzDeclaredEvent;
+/** @lzxtype event */
+var onchildNodes :LzDeclaredEventClass = LzDeclaredEvent;
+/** @lzxtype event */
+var onattributes :LzDeclaredEventClass = LzDeclaredEvent;
+/** @lzxtype event */
+var onnodeName :LzDeclaredEventClass = LzDeclaredEvent;
 
-
 /** The type of this node -- ELEMENT_NODE or TEXT_NODE
-  * @type Number
+  * @type int
   * @keywords abstract
   */
-var nodeType:*; // This is undefined. Set elsewhere
+var nodeType :int; // This is undefined. Set elsewhere
 
-var parentNode:* = null;
+var parentNode :* = null;
 
-var ownerDocument:*;
+var ownerDocument :LzDataElementMixin;
+
 /** @access private */
-var __LZo:* = -1;
+var __LZo :int = -1;
 /** @access private */
-var sel:Boolean = false;
+var sel :Boolean = false;
 
 /** An array of children of this node
   * @type LzDataNodeMixin
   */
-var childNodes:* = null;
+var childNodes :Array = null;
 
 /** @access private */
-var __LZcoDirty = true;
+var __LZcoDirty :Boolean = true;
 
 
 /**
-  * Returns the sibling before this one this node's parentNodes List of children
-  * @return LzDataNodeMixin: The node preceeding this one in this node's childNodes
-  */
-function getPreviousSibling (){
-    if (!this.parentNode) return null;
-    if ( this.parentNode.__LZcoDirty ) this.parentNode.__LZupdateCO();
-    return this.parentNode.childNodes[ this.__LZo - 1 ];
-}
-
-/**
  * Returns the parent of this node
  * @return LzDataNodeMixin: the parent of this node
  */
-function getParent () {
+public function getParent () {
   return this.parentNode;
 }
 
 /**
   * gets offset of node in parent's childNodes array
-  * @return number
+  * @return int
   */
-function getOffset (){
+public function getOffset () :int {
     if (!this.parentNode) return 0;
     if (this.parentNode.__LZcoDirty) this.parentNode.__LZupdateCO();
 
     return this.__LZo;
 }
 
+/**
+  * Returns the sibling before this one this node's parentNodes List of children
+  * @return LzDataNodeMixin: The node preceeding this one in this node's childNodes
+  */
+public function getPreviousSibling (){
+    if (!this.parentNode) return null;
+    if ( this.parentNode.__LZcoDirty ) this.parentNode.__LZupdateCO();
+    return this.parentNode.childNodes[ this.__LZo - 1 ];
+}
+
 /** @access private */
-function $lzc$getPreviousSibling_dependencies( who, self ){
+function $lzc$getPreviousSibling_dependencies( who, self ) :Array {
     return [ this.parentNode , "childNodes" , this , "parentNode" ];
 }
 
@@ -132,14 +144,14 @@
   * Returns the sibling after this one this node's parentNodes List of children
   * @return LzDataNodeMixin: The node succeeding this one in this node's childNodes
   */
-function getNextSibling (){
+public function getNextSibling (){
     if (!this.parentNode) return null;
     if ( this.parentNode.__LZcoDirty ) this.parentNode.__LZupdateCO();
     return this.parentNode.childNodes[ this.__LZo + 1 ];
 }
 
 /** @access private */
-function $lzc$getNextSibling_dependencies( who, self ){
+function $lzc$getNextSibling_dependencies( who, self ) :Array {
     return [ this.parentNode , "childNodes" , this , "parentNode" ];
 }
 
@@ -149,7 +161,7 @@
   * Renamed from childOf to avoid conflict with LzNode.childOf.
   * childOf still exists because it is part of the public API.
   */
-function childOfNode ( el , allowself=false ) {
+function childOfNode ( el, allowself:Boolean = false ) :Boolean {
     var p = allowself ? this : this.parentNode
     while ( p ){
         if ( p == el ) return true;
@@ -169,17 +181,16 @@
   return this.childOfNode (el, allowself);
 }
 
-
 /**
   * Sets the LzDataNodeMixin which is the ownerDocument for this node.
   * @param LzDataNodeMixin ownerDoc: The LzDataNodeMixin to act as the ownerDocument for
   * this node.
   */
-function setOwnerDocument ( ownerDoc ){
+public function setOwnerDocument ( ownerDoc ){
     this.ownerDocument = ownerDoc;
     if (this.childNodes) {
-        for ( var i = 0; i < this.childNodes.length; i++ ){
-            this.childNodes[ i ] .setOwnerDocument( ownerDoc );
+        for ( var i:int = 0; i < this.childNodes.length; i++ ){
+            this.childNodes[ i ].setOwnerDocument( ownerDoc );
         }
     }
 
@@ -189,16 +200,34 @@
 }
 
 /**
+  * Returns a copy of this node.
+  * @param Boolean deep: If true, the children of this node will be part of the
+  * new node
+  * @return LzDataNodeMixin: A copy of this node.
+  */
+public function cloneNode ( deep:Boolean = false ) :LzDataNodeMixin {
+    /* not implemented here */
+}
+
+/**
+  * Returns this node as a string of xml.
+  * @return String: The string serialization of this node.
+  */
+public function serialize (len:Number = Infinity) :String {
+    /* not implemented here */
+}
+
+/**
   * @access private
   */
-function __LZlockFromUpdate ( locker ){
+function __LZlockFromUpdate ( locker:LzDatapath ){
     this.ownerDocument.__LZdoLock( locker );
 }
 
 /**
   * @access private
   */
-function __LZunlockFromUpdate ( locker ){
+function __LZunlockFromUpdate ( locker:LzDatapath ){
     this.ownerDocument.__LZdoUnlock( locker );
 }
 
@@ -206,8 +235,6 @@
 lz.DataNodeMixin = LzDataNodeMixin;  // publish
 
 
-// Only static methods and variables remain here
-
 /**
  * @topic LFC
  * @subtopic Data
@@ -220,37 +247,35 @@
  * @deprecated Use <code>LzDataElement.ELEMENT_NODE</code> instead. The methods and constants in this class are deprecated
  *
  */
-class LzDataNode extends  LzEventable {
+class LzDataNode extends LzEventable {
 
-    
 /**
   * @access private
   */
-    function LzDataNode ( attributes = null, children = null) {
+    function LzDataNode () {
         super();
     }
 
-
 /** @deprecated Use <code>LzDataElement.ELEMENT_NODE</code> instead
-  * @type Number
+  * @type int
   * @lzxdefault "1"
   * @keywords read-only
   */
-static var ELEMENT_NODE = 1;
+static const ELEMENT_NODE :int = 1;
 
 /** @deprecated Use <code>LzDataElement.TEXT_NODE</code> instead
-  * @type Number
+  * @type int
   * @lzxdefault "3"
   * @keywords read-only
   */
-static var TEXT_NODE = 3;
+static const TEXT_NODE :int = 3;
 
 /** @deprecated Use <code>LzDataElement.DOCUMENT_NODE</code> instead
-  * @type Number
+  * @type int
   * @lzxdefault "9"
   * @keywords read-only
   */
-static var DOCUMENT_NODE = 9;
+static const DOCUMENT_NODE :int = 9;
 
 
 /**
@@ -265,7 +290,7 @@
   * generated from the string
   * @deprecated Use <code>LzDataElement.stringToLzData</code> 
   */
-static function stringToLzData( str, trimwhitespace=false, nsprefix=false ) {
+static function stringToLzData( str:String, trimwhitespace:Boolean = false, nsprefix:Boolean = false ) :LzDataElement {
     if ( $debug ){
       Debug.info("%s.%w is deprecated.  Use `LzDataElement.stringToLzData` instead.",
                  this, arguments.callee);
@@ -274,14 +299,14 @@
 
 }
 
-  /**
-   * Needed because LzDataElementMixin wants to override this, and it is
-   * mixed in to both this and LzNode which defines toString, so _we_
-   * have to define it too.
-   * @access private
-   */
-  function toString ()
-    { return "LzDataNode";}
+/**
+ * Needed because LzDataElementMixin wants to override this, and it is
+ * mixed in to both this and LzNode which defines toString, so _we_
+ * have to define it too.
+ * @access private
+ */
+function toString () :String { 
+    return "LzDataNode";
+}
 
-
 } // End of LzDataNode

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataText.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataText.lzs	2008-07-08 17:50:16 UTC (rev 10257)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataText.lzs	2008-07-08 18:14:22 UTC (rev 10258)
@@ -13,8 +13,6 @@
   *
   * @shortdesc Represents a text node in a set of data.
   * @see lzdatanodemixin, lzdataelement, datapointer
-  * @fixme [2006-07-26] (LPP-2412) The Instance reference is required for lzpix
-  *                                to run.
   */
 class LzDataText extends LzDataNode with LzDataNodeMixin {
 
@@ -22,28 +20,15 @@
  * This object represents a text node in a set of data.
  * @param String text: The text that this node holds.
  */
-function LzDataText ( text ){
+function LzDataText ( text:String ){
     super();
     this.nodeType = LzDataElement.TEXT_NODE;
     this.data = text;
 }
 
 /** @lzxtype event */
-var onDocumentChange = LzDeclaredEvent;
-/** @lzxtype event */
-var onparentNode = LzDeclaredEvent;
-/** @lzxtype event */
-var onchildNode = LzDeclaredEvent;
-/** @lzxtype event */
-var onchildNodes = LzDeclaredEvent;
-/** @lzxtype event */
-var onattributes = LzDeclaredEvent;
-/** @lzxtype event */
-var onnodeName = LzDeclaredEvent;
+var ondata :LzDeclaredEventClass = LzDeclaredEvent;
 
-/** @lzxtype event */
-var ondata = LzDeclaredEvent;
-
 /** This property is of type String, can raise a DOMException object on setting
   * and can raise a DOMException object on retrieval. */
 //var nodeType = LzDataElement.TEXT_NODE;
@@ -53,40 +38,38 @@
  * "#text".
   * @type String
   */
-var nodeName        = '#text';
+var nodeName :String = '#text';
 
 /** The data held by this node.
   * @type String */
-var data = "";
+var data :String = "";
+
 /** @access private */
-function $lzc$set_data(v) { this.setData(v); }
+function $lzc$set_data(v:String) :void { this.setData(v); }
 
 /** @type Number
   * @keywords read-only 
   */
-var length = 0;
+var length :Number = 0;
 
 /**
   * Sets the string that this node holds.
   * @param String newdata: The new string for this node.
   */
-function setData ( newdata ) {
+public function setData ( newdata:String ) {
     this.data = newdata;
     if (this.ondata && this.ondata.ready) {
         this.ondata.sendEvent( newdata );
     }
     if (this.ownerDocument) {
-        this.ownerDocument.handleDocumentChange( "data" , this , 1 );
+        this.ownerDocument.handleDocumentChange( "data", this, 1 );
     }
 }
 
 /**
-  * Returns a copy of this node.
-  * @param ignore: This parameter is necessary because LzDataElementMixin
-  *                defines cloneNode() with an argument.
   * @access private
   */
-function cloneNode (ignore=null){
+override public function cloneNode ( deep:Boolean = false ) :LzDataNodeMixin {
     var n = new LzDataText(this.data);
     return n;
 }
@@ -94,14 +77,14 @@
 /**
   * @access private
   */
-function serialize (len=null){
+override public function serialize (len:Number = Infinity) :String {
     return LzDataElement.__LZXMLescape( this.data );
 }
 
 /**
   * @access private
   */
-override function toString (){
+override function toString () :String {
     //return this.serialize();
     return this.data;
 }



More information about the Laszlo-checkins mailing list