[Top][All Lists]
[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);
- [Gnash-commit] gnash ChangeLog server/asobj/xmlnode.cpp server...,
Sandro Santilli <=