gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ChangeLog server/asobj/xmlnode.cpp server...


From: Sandro Santilli
Subject: [Gnash-commit] gnash ChangeLog server/asobj/xmlnode.cpp server...
Date: Tue, 10 Apr 2007 10:46:19 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Sandro Santilli <strk>  07/04/10 10:46:19

Modified files:
        .              : ChangeLog 
        server/asobj   : xmlnode.cpp xmlnode.h 
        testsuite/actionscript.all: XML.as 

Log message:
                * server/asobj/xmlnode.{h,cpp}: fix appendChild to properly
                  move the node; implement insertBefore and removeNode; fix
                  cloneNode to respect not copy childs if not deep; implement
                  parentNode gettersetter.
                * testsuite/actionscript.all/XML.as: add tests for insertBefore,
                  appendNode, cloneNode, removeNode and parentNode.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2821&r2=1.2822
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlnode.cpp?cvsroot=gnash&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xmlnode.h?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/XML.as?cvsroot=gnash&r1=1.26&r2=1.27

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2821
retrieving revision 1.2822
diff -u -b -r1.2821 -r1.2822
--- ChangeLog   10 Apr 2007 09:14:47 -0000      1.2821
+++ ChangeLog   10 Apr 2007 10:46:19 -0000      1.2822
@@ -1,5 +1,11 @@
 2007-04-10 Sandro Santilli <address@hidden>
 
+       * server/asobj/xmlnode.{h,cpp}: fix appendChild to properly
+         move the node; implement insertBefore and removeNode; fix
+         cloneNode to respect not copy childs if not deep; implement
+         parentNode gettersetter.
+       * testsuite/actionscript.all/XML.as: add tests for insertBefore,
+         appendNode, cloneNode, removeNode and parentNode.
        * macros/ffmpeg.m4: fix --with-ffmpeg-incl to look for
          avcodec.h under the 'ffmpeg' subdir (this is assumed
          to exist in Gnash source code).

Index: server/asobj/xmlnode.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/xmlnode.cpp,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- server/asobj/xmlnode.cpp    7 Apr 2007 15:27:16 -0000       1.27
+++ server/asobj/xmlnode.cpp    10 Apr 2007 10:46:19 -0000      1.28
@@ -14,7 +14,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: xmlnode.cpp,v 1.27 2007/04/07 15:27:16 strk Exp $ */
+/* $Id: xmlnode.cpp,v 1.28 2007/04/10 10:46:19 strk Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -63,6 +63,7 @@
 static as_value xmlnode_nextsibling(const fn_call& fn);
 static as_value xmlnode_previoussibling(const fn_call& fn);
 static as_value xmlnode_childNodes(const fn_call& fn);
+static as_value xmlnode_parentNode(const fn_call& fn);
 as_object* getXMLNodeInterface();
 
 static LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
@@ -97,16 +98,13 @@
 XMLNode::XMLNode(const XMLNode& tpl, bool deep)
     :
     as_object(getXMLNodeInterface()),
-    _parent(tpl._parent),
+    _parent(0), // _parent is never implicitly copied
     _name(tpl._name),
     _value(tpl._value),
     _type(tpl._type)
 {
-    if ( ! deep )
-    {
-            _children = tpl._children;
-    }
-    else // deep copy
+    // only clone childs if in deep mode
+    if ( deep ) 
     {
         const ChildList& from=tpl._children;
         for (ChildList::const_iterator it=from.begin(), itEnd=from.end();
@@ -160,10 +158,13 @@
 void
 XMLNode::appendChild(boost::intrusive_ptr<XMLNode> node)
 {
-    if (node)
-       {
+    assert (node);
+
+    boost::intrusive_ptr<XMLNode> oldparent = node->getParent();
                node->setParent(this);
                _children.push_back(node);
+    if ( oldparent ) {
+        oldparent->_children.remove(node);
     }
 
 //    log_msg("%s: partially unimplemented\n", __PRETTY_FUNCTION__);
@@ -180,24 +181,45 @@
     return newnode;
 }
 
-/// \brief insert a node before a node
-///
-/// Method; inserts a new child node into the XML object's child
-/// list, before the beforeNode node. If the beforeNode parameter is
-/// undefined or null, the node is added using the appendChild()
-/// method. If beforeNode is not a child of my_xml, the insertion
-/// fails.
 void
-XMLNode::insertBefore(XMLNode * /* newnode */, XMLNode * /* node */)
+XMLNode::insertBefore(boost::intrusive_ptr<XMLNode> newnode, 
boost::intrusive_ptr<XMLNode> pos)
 {
+    // find iterator for positional parameter
     log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
+
+    ChildList::iterator it = find(_children.begin(), _children.end(), pos);
+    if ( it == _children.end() )
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror("XMLNode.insertBefore(): positional parameter is not a 
child of this node");
+        );
+        return;
+    }
+
+    _children.insert(it, newnode);
+    boost::intrusive_ptr<XMLNode> oldparent = newnode->getParent();
+    newnode->setParent(this);
+    if ( oldparent )
+    {
+        oldparent->_children.remove(newnode);
+    }
 }
+
 /// \brief removes the specified XML object from its parent. Also
 /// deletes all descendants of the node.
 void
 XMLNode::removeNode()
 {
-    log_msg("%s: unimplemented \n", __PRETTY_FUNCTION__);
+    assert(get_ref_count() > 1);
+    boost::intrusive_ptr<XMLNode> oldparent = getParent();
+    if ( oldparent )
+    {
+        oldparent->_children.remove(this);
+    }
+    _children.clear();
+    _attributes.clear();
+    _parent = NULL;
+    assert(get_ref_count() > 0);
 }
 
 XMLNode *
@@ -377,7 +399,8 @@
     gettersetter = new builtin_function(&xmlnode_previoussibling, NULL);
     o.init_property("previousSibling", *gettersetter, *gettersetter);
 
-    o.init_member("parentNode",  as_value().set_null());
+    gettersetter = new builtin_function(&xmlnode_parentNode, NULL);
+    o.init_property("parentNode",  *gettersetter, *gettersetter);
 
 }
 
@@ -460,6 +483,40 @@
     GNASH_REPORT_FUNCTION;
     boost::intrusive_ptr<XMLNode> ptr = ensureType<XMLNode>(fn.this_ptr);
     
+       if ( fn.nargs < 2 )
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+        std::stringstream ss; fn.dump_args(ss);
+               log_aserror("XMLNode.insertBefore(%s) needs at least two 
argument", ss.str().c_str());
+               );
+               return as_value();
+       }
+
+       boost::intrusive_ptr<XMLNode> newnode = 
boost::dynamic_pointer_cast<XMLNode>(fn.arg(0).to_object());
+       if ( ! newnode )
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+        std::stringstream ss; fn.dump_args(ss);
+               log_aserror("First argument to XMLNode.insertBefore(%s) is not 
an XMLNode",
+                ss.str().c_str());
+               );
+               return as_value();
+       }
+
+       boost::intrusive_ptr<XMLNode> pos = 
boost::dynamic_pointer_cast<XMLNode>(fn.arg(1).to_object());
+       if ( ! pos )
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+        std::stringstream ss; fn.dump_args(ss);
+               log_aserror("Second argument to XMLNode.insertBefore(%s) is not 
an XMLNode",
+                ss.str().c_str());
+               );
+               return as_value();
+       }
+
+    ptr->insertBefore(newnode, pos);
+    return as_value();
+    
 //    return as_value(ptr->obj.getAllocated());
 //    ptr->obj.insertBefore();
     log_msg("%s:unimplemented \n", __PRETTY_FUNCTION__);
@@ -472,7 +529,6 @@
     GNASH_REPORT_FUNCTION;
     boost::intrusive_ptr<XMLNode> ptr = ensureType<XMLNode>(fn.this_ptr);
     
-//    return as_value(ptr->obj.getAllocated());
     ptr->removeNode();
     return as_value();
 }
@@ -693,6 +749,30 @@
     return rv;
 }
 
+// Both a getter and a (do-nothing) setter for parentNode
+static as_value
+xmlnode_parentNode(const fn_call& fn)
+{
+    //GNASH_REPORT_FUNCTION;
+    as_value rv;
+    rv.set_null();
+
+    if ( fn.nargs != 0 )
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror("Tried to set read-only property XMLNode.parentNode");
+        );
+        return rv;
+    }
+
+    boost::intrusive_ptr<XMLNode> ptr = ensureType<XMLNode>(fn.this_ptr);
+    XMLNode *node = ptr->getParent();
+    if (node) {
+       rv = node;
+    }
+    return rv;
+}
+
 // Both a getter and a (do-nothing) setter for childNodes
 static as_value
 xmlnode_childNodes(const fn_call& fn)

Index: server/asobj/xmlnode.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/xmlnode.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- server/asobj/xmlnode.h      7 Apr 2007 15:27:16 -0000       1.11
+++ server/asobj/xmlnode.h      10 Apr 2007 10:46:19 -0000      1.12
@@ -28,9 +28,6 @@
 #include "tu_config.h"
 
 //#define DEBUG_MEMORY_ALLOCATION 1
-#include <vector>
-#include <string>
-#include <sstream>
 
 #include "action.h"
 #include "impl.h"
@@ -45,6 +42,11 @@
 #include <libxml/parser.h>
 #include <libxml/xmlreader.h>
 
+#include <list>
+#include <vector>
+#include <string>
+#include <sstream>
+
 namespace gnash {  
  
 /// XMLNode  ActionScript class
@@ -135,7 +137,8 @@
     boost::intrusive_ptr<XMLNode> firstChild();
     boost::intrusive_ptr<XMLNode> lastChild();
     
-    typedef std::vector< boost::intrusive_ptr<XMLNode> > ChildList;
+    // Use a list for quick erasing
+    typedef std::list< boost::intrusive_ptr<XMLNode> > ChildList;
 
     typedef std::vector< XMLAttr > AttribList;
 
@@ -143,13 +146,6 @@
 
     AttribList& attributes() { return _attributes; }
     
-    boost::intrusive_ptr<XMLNode> operator [] (int x)
-    {
-        log_msg("%s: get element %d", __PRETTY_FUNCTION__, x);
-        
-        return _children[x];
-    }
-    
     XMLNode& operator = (XMLNode &node) {
         gnash::log_msg("%s: \n", __PRETTY_FUNCTION__);
         if (this == &node) return *this;
@@ -208,18 +204,35 @@
     /// undefined or null, the node is added using the appendChild()
     /// method. If beforeNode is not a child of my_xml, the insertion
     /// fails.
-    void insertBefore(XMLNode *newnode, XMLNode *node);
+    ///
+    /// @param newnoe
+    ///     The node to insert, moving from its current tree
+    ///
+    /// @param beforeWhich
+    ///     The node before which to insert the new one.
+    ///     Must be a child of this XMLNode or the operation will fail.
+    ///
+    void insertBefore(boost::intrusive_ptr<XMLNode> newnode, 
boost::intrusive_ptr<XMLNode> pos);
 
     /// Removes the specified XML object from its parent.
     //
     /// Also deletes all descendants of the node.
+    /// Make sure to keep an intrusive_ptr against
+    /// this instance during operation or the ref-counting
+    /// management might destroy it.
+    ///
     void removeNode();
 
     void toString(std::ostream& str) const;
 
     void  change_stack_frame(int frame, gnash::as_object *xml, 
gnash::as_environment *env);
 
+    // We might turn this back to a dumb pointer, as long
+    // as we'll make sure in the XMLNode destructor and
+    // any child cleaning interface to set child parent
+    // to NULL
     boost::intrusive_ptr<XMLNode> _parent;
+
     ChildList          _children;
     AttribList      _attributes;
 

Index: testsuite/actionscript.all/XML.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/actionscript.all/XML.as,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -b -r1.26 -r1.27
--- testsuite/actionscript.all/XML.as   8 Apr 2007 08:06:58 -0000       1.26
+++ testsuite/actionscript.all/XML.as   10 Apr 2007 10:46:19 -0000      1.27
@@ -20,7 +20,7 @@
 // compile this test case with Ming makeswf, and then
 // execute it like this gnash -1 -r 0 -v out.swf
 
-rcsid="$Id: XML.as,v 1.26 2007/04/08 08:06:58 strk Exp $";
+rcsid="$Id: XML.as,v 1.27 2007/04/10 10:46:19 strk Exp $";
 
 #include "dejagnu.as"
 #include "utils.as"
@@ -69,6 +69,7 @@
 check(XMLNode.prototype.hasOwnProperty("toString") );
 check(XMLNode.prototype.hasOwnProperty("cloneNode") );
 check(XMLNode.prototype.hasOwnProperty("attributes") );
+check(XMLNode.prototype.hasOwnProperty("parentNode") );
 check(! XMLNode.prototype.hasOwnProperty("length") );
 check(! XMLNode.prototype.hasOwnProperty("createElement") );
 check(! XMLNode.prototype.hasOwnProperty("addRequestHeader") );
@@ -91,7 +92,12 @@
 check(! XMLNode.hasOwnProperty("cloneNode") );
 #endif
 
+check(XML.prototype instanceof XMLNode);
+
 var tmp = new XML();
+check(tmp instanceof XML);
+check(tmp instanceof XMLNode);
+
 check_equals(typeof(tmp.length), 'undefined');
 check(! tmp.hasOwnProperty("length"));
 
@@ -242,9 +248,20 @@
 tmp.checkParsed = function ()
 {
        note("tmp.checkParsed called");
+
+       // Since we didn't *load* the XML, but we
+       // just *parsed* it, expect getBytesLoaded 
+       // and getBytesTotal to return undefined
+       check_equals(this.getBytesLoaded(), undefined);
+       check_equals(this.getBytesTotal(), undefined);
+
        check(this.hasChildNodes());
+       check_equals(typeof(this.nodeName), 'null');
+       check_equals(typeof(this.nodeValue), 'null');
        check(this.childNodes instanceof Array);
        check_equals(this.firstChild, this.lastChild);
+       check(this.firstChild instanceof XMLNode);
+       check_equals(typeof(this.length), 'undefined');
        check_equals(typeof(this.childNodes.length), 'number');
        check_equals(this.childNodes.length, 1);
        check_equals(this.childNodes[0], this.firstChild);
@@ -383,38 +400,98 @@
 tmp.checkParsed(); // onLoad won't be called
 //note("Parsed XML: "+tmp.toString());
 check_equals(tmp.toString(), xml_in);
-check(XML.prototype instanceof XMLNode);
-check(tmp instanceof XML);
-check(tmp instanceof XMLNode);
-check(tmp.firstChild instanceof XMLNode);
-check_equals(typeof(tmp.nodeName), 'null');
-check_equals(typeof(tmp.nodeValue), 'null');
-check_equals(typeof(tmp.length), 'undefined');
-check_equals(tmp.firstChild.nodeName, "TOPNODE");
-check_equals(typeof(tmp.firstChild.length), 'undefined');
 
-if (tmp.hasChildNodes() == true) {
-    pass("XML::hasChildNodes() works");
-} else {
-    fail("XML::hasChildNodes() doesn't work");
-}
-// note(tmp.getBytesLoaded());
-// note(tmp.getBytesTotal());
+//------------------------------------------------
+// Test XML editing
+//------------------------------------------------
+xml1 = new XML("<X1T><X1C1></X1C1><X1C2></X1C2></X1T>");
+xml2 = new XML("<X2T><X2C1></X2C1><X2C2></X2C2></X2T>");
+check_equals(xml1.childNodes.length, 1);
+check_equals(xml1.firstChild.childNodes.length, 2);
+check_equals(xml2.childNodes.length, 1);
+check_equals(xml2.firstChild.childNodes.length, 2);
+
+// Now move X1C1 to X2T
+movingchild = xml2.firstChild.lastChild;
+
+check_equals(movingchild.parentNode, xml2.firstChild);
+check(movingchild.parentNode != xml1.firstChild);
+xml1.firstChild.appendChild(movingchild);
+check_equals(movingchild.parentNode, xml1.firstChild);
+check(movingchild.parentNode != xml2.firstChild);
+
+check_equals(xml1.firstChild.childNodes.length, 3);
+check_equals(xml1.firstChild.childNodes[0].nodeName, "X1C1");
+check_equals(xml1.firstChild.childNodes[1].nodeName, "X1C2");
+check_equals(xml1.firstChild.childNodes[2].nodeName, "X2C2");
+
+check_equals(xml2.firstChild.childNodes.length, 1); // firstChild has been 
moved
+check_equals(xml2.firstChild.childNodes[0].nodeName, "X2C1");
+
+// Now insert X2C1 from xml2 before X1C2 in xml1
+xml1.firstChild.insertBefore(
+       xml2.firstChild.lastChild, // what to insert
+       xml1.firstChild.childNodes[1] // before what to insert it
+);
+check_equals(xml1.firstChild.childNodes.length, 4);
+check_equals(xml1.firstChild.childNodes[0].nodeName, "X1C1");
+check_equals(xml1.firstChild.childNodes[1].nodeName, "X2C1");
+check_equals(xml1.firstChild.childNodes[2].nodeName, "X1C2");
+check_equals(xml1.firstChild.childNodes[3].nodeName, "X2C2");
+
+// XMLNode.removeNode
+check_equals(xml2.firstChild.childNodes.length, 0); // lastChild has been moved
+xml2.firstChild.removeNode();
+check_equals(xml2.childNodes.length, 0); // it's only child has been dropped
+
+x1c1_node = xml1.firstChild.childNodes[0];
+x2c1_node = xml1.firstChild.childNodes[1];
+check_equals(x1c1_node.nodeName, "X1C1");
+check_equals(x1c1_node.nextSibling, x2c1_node);
+check_equals(x2c1_node.nodeName, "X2C1");
+check_equals(x2c1_node.previousSibling, x1c1_node);
+xml1.firstChild.removeNode(); // removeNode removes all childrens !!
+check_equals(xml1.childNodes.length, 0);
+// so these become orphaned (no parent)
+check_equals(x1c1_node.nodeName, "X1C1");
+check_equals(x1c1_node.nextSibling(), null);
+check_equals(x2c1_node.nodeName, "X2C1");
+check_equals(x2c1_node.previousSibling(), null);
+
+xml1.appendChild(x1c1_node);
+xml1.appendChild(x2c1_node);
+check_equals(x1c1_node.nextSibling, x2c1_node);
+check_equals(x2c1_node.previousSibling, x1c1_node);
+
+check_equals(xml1.childNodes.length, 2);
+x1c1_node.appendChild(x2c1_node);
+check_equals(xml1.childNodes.length, 1);
+check_equals(xml1.firstChild.lastChild.nodeName, 'X2C1');
+
+src_node = xml1.firstChild;
+cln_node = src_node.cloneNode(); // ! deep
+deepcln_node = src_node.cloneNode(true); // deep
+
+check_equals(src_node.childNodes.length, 1);
+check_equals(cln_node.childNodes.length, 0); // non-deep clone doesn't clone 
childs !
+check_equals(deepcln_node.childNodes.length, 1);
+
+check_equals(src_node.firstChild.nodeName, 'X2C1');
+check_equals(deepcln_node.firstChild.nodeName, 'X2C1');
+src_node.firstChild.nodeName = 'X2C1_modified';
+check_equals(src_node.firstChild.nodeName, 'X2C1_modified');
+check_equals(deepcln_node.firstChild.nodeName, 'X2C1');
+
+check_equals(deepcln_node.parentNode, null);
+deepcln_node.parentNode = src_node;
+check_equals(deepcln_node.parentNode, null);
+
+
+
+//------------------------------------------------
+// Other tests..
+//------------------------------------------------
 
-// Since we didn't *load* the XML, but we
-// just *parsed* it, expect getBytesLoaded 
-// and getBytesTotal to return undefined
-check_equals(tmp.getBytesLoaded(), undefined);
-check_equals(tmp.getBytesTotal(), undefined);
-
-if (tmp.getBytesLoaded() == tmp.getBytesTotal()) {
-    pass("bytes count are the same");
-} else {
-    fail("bytes counts are not the same");
-}
-
-
-check(XML);
 myXML = new XML();
 check(myXML != undefined);
 check(myXML.createElement);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]