r3564 rjek - in /trunk/dom/test: list.c list.h
by netsurf@semichrome.net
Author: rjek
Date: Sat Sep 22 13:37:27 2007
New Revision: 3564
URL: http://source.netsurf-browser.org?rev=3564&view=rev
Log:
Use a typedef for the function pointers to comparison functions, add newline at end of file
Modified:
trunk/dom/test/list.c
trunk/dom/test/list.h
Modified: trunk/dom/test/list.c
URL: http://source.netsurf-browser.org/trunk/dom/test/list.c?rev=3564&r1=3563&...
==============================================================================
--- trunk/dom/test/list.c (original)
+++ trunk/dom/test/list.c Sat Sep 22 13:37:27 2007
@@ -58,8 +58,7 @@
list->size++;
}
-bool list_contains(struct list* list, void* data,
- int (*comparator)(const void* a, const void* b))
+bool list_contains(struct list* list, void* data, list_compare_func comparator)
{
struct list_elt* elt = list->head;
while (elt != NULL) {
@@ -72,7 +71,7 @@
}
bool list_contains_all(struct list* superList, struct list* subList,
- int (*comparator)(const void* a, const void* b))
+ list_compare_func comparator)
{
struct list_elt* elt = subList->head;
while (elt != NULL) {
@@ -83,3 +82,4 @@
}
return true;
}
+
Modified: trunk/dom/test/list.h
URL: http://source.netsurf-browser.org/trunk/dom/test/list.h?rev=3564&r1=3563&...
==============================================================================
--- trunk/dom/test/list.h (original)
+++ trunk/dom/test/list.h Sat Sep 22 13:37:27 2007
@@ -22,6 +22,8 @@
struct list* list_new(void);
void list_destroy(struct list* list);
+typedef int (*list_compare_func)(const void* a, const void* b);
+
/**
* Add data to the tail of the list.
*/
@@ -37,6 +39,6 @@
* Tests if superlist contains all elements in sublist. Order is not important.
*/
bool list_contains_all(struct list* superList, struct list* subList,
- int (*comparator)(const void* a, const void* b));
+ list_compare_func comparator);
#endif
15 years, 8 months
r3563 jmb - in /trunk/dom/test: list.c list.h
by netsurf@semichrome.net
Author: jmb
Date: Sat Sep 22 13:33:28 2007
New Revision: 3563
URL: http://source.netsurf-browser.org?rev=3563&view=rev
Log:
s/malloc.h/stdlib.h/ (malloc.h is non-standard, though common)
Sprinkle some assertions about so as to catch malloc failure at the earliest opportunity.
Pedantic line length and brace position changes.
Modified:
trunk/dom/test/list.c
trunk/dom/test/list.h
Modified: trunk/dom/test/list.c
URL: http://source.netsurf-browser.org/trunk/dom/test/list.c?rev=3563&r1=3562&...
==============================================================================
--- trunk/dom/test/list.c (original)
+++ trunk/dom/test/list.c Sat Sep 22 13:33:28 2007
@@ -5,21 +5,26 @@
* Copyright 2007 James Shaw <jshaw(a)netsurf-browser.org>
*/
-#include <malloc.h>
+#include <assert.h>
+
+#include <stdbool.h>
#include <stdio.h>
-#include <stdbool.h>
+#include <stdlib.h>
#include "list.h"
-struct list* list_new(void) {
+struct list* list_new(void)
+{
struct list* list = malloc(sizeof(struct list));
+ assert(list != NULL);
list->size = 0;
list->head = NULL;
list->tail = NULL;
return list;
}
-void list_destroy(struct list* list) {
+void list_destroy(struct list* list)
+{
struct list_elt* elt = list->head;
while (elt != NULL) {
struct list_elt* nextElt = elt->next;
@@ -29,8 +34,10 @@
free(list);
}
-void list_add(struct list* list, void* data) {
+void list_add(struct list* list, void* data)
+{
struct list_elt* elt = malloc(sizeof(struct list_elt));
+ assert(elt != NULL);
elt->data = data;
elt->next = NULL;
struct list_elt* tail = list->tail;
@@ -51,7 +58,9 @@
list->size++;
}
-bool list_contains(struct list* list, void* data, int (*comparator)(const void* a, const void* b)) {
+bool list_contains(struct list* list, void* data,
+ int (*comparator)(const void* a, const void* b))
+{
struct list_elt* elt = list->head;
while (elt != NULL) {
if (comparator(elt->data, data) == 0) {
@@ -62,7 +71,9 @@
return false;
}
-bool list_contains_all(struct list* superList, struct list* subList, int (*comparator)(const void* a, const void* b)) {
+bool list_contains_all(struct list* superList, struct list* subList,
+ int (*comparator)(const void* a, const void* b))
+{
struct list_elt* elt = subList->head;
while (elt != NULL) {
if (!list_contains(superList, elt->data, comparator)) {
Modified: trunk/dom/test/list.h
URL: http://source.netsurf-browser.org/trunk/dom/test/list.h?rev=3563&r1=3562&...
==============================================================================
--- trunk/dom/test/list.h (original)
+++ trunk/dom/test/list.h Sat Sep 22 13:33:28 2007
@@ -30,11 +30,13 @@
/**
* Tests if data is equal to any element in the list.
*/
-bool list_contains(struct list* list, void* data, int (*comparator)(const void* a, const void* b));
+bool list_contains(struct list* list, void* data,
+ int (*comparator)(const void* a, const void* b));
/**
* Tests if superlist contains all elements in sublist. Order is not important.
*/
-bool list_contains_all(struct list* superList, struct list* subList, int (*comparator)(const void* a, const void* b));
+bool list_contains_all(struct list* superList, struct list* subList,
+ int (*comparator)(const void* a, const void* b));
#endif
15 years, 8 months
r3562 jshaw - /trunk/dom/test/list.c
by netsurf@semichrome.net
Author: jshaw
Date: Sat Sep 22 13:31:06 2007
New Revision: 3562
URL: http://source.netsurf-browser.org?rev=3562&view=rev
Log:
Change to C-style comments
Modified:
trunk/dom/test/list.c
Modified: trunk/dom/test/list.c
URL: http://source.netsurf-browser.org/trunk/dom/test/list.c?rev=3562&r1=3561&...
==============================================================================
--- trunk/dom/test/list.c (original)
+++ trunk/dom/test/list.c Sat Sep 22 13:31:06 2007
@@ -35,19 +35,19 @@
elt->next = NULL;
struct list_elt* tail = list->tail;
- // if tail was set, make its 'next' ptr point to elt
+ /* if tail was set, make its 'next' ptr point to elt */
if (tail != NULL) {
tail->next = elt;
}
- // make elt the new tail
+ /* make elt the new tail */
list->tail = elt;
if (list->head == NULL) {
list->head = elt;
}
- // inc the size of the list
+ /* inc the size of the list */
list->size++;
}
15 years, 8 months
r3561 jmb - /trunk/dom/src/core/string.c
by netsurf@semichrome.net
Author: jmb
Date: Sat Sep 22 13:20:59 2007
New Revision: 3561
URL: http://source.netsurf-browser.org?rev=3561&view=rev
Log:
Assume that NULL dom_string pointers imply the empty string.
Modified:
trunk/dom/src/core/string.c
Modified: trunk/dom/src/core/string.c
URL: http://source.netsurf-browser.org/trunk/dom/src/core/string.c?rev=3561&r1...
==============================================================================
--- trunk/dom/src/core/string.c (original)
+++ trunk/dom/src/core/string.c Sat Sep 22 13:20:59 2007
@@ -48,6 +48,14 @@
uint32_t refcnt; /**< Reference count */
};
+static struct dom_string empty_string = {
+ .type = DOM_STRING_CONST_PTR,
+ .data.ptr = NULL,
+ .len = 0,
+ .ctx.doc = NULL,
+ .refcnt = 1
+};
+
/**
* Claim a reference on a DOM string
*
@@ -267,6 +275,10 @@
dom_exception dom_string_get_data(struct dom_string *str,
const uint8_t **data, size_t *len)
{
+ /* Assume that a NULL str pointer indicates the empty string */
+ if (str == NULL)
+ str = &empty_string;
+
switch (str->type) {
case DOM_STRING_PTR:
*data = str->data.ptr;
@@ -294,6 +306,8 @@
* \param s1 The first string to compare
* \param s2 The second string to compare
* \return 0 if strings match, non-0 otherwise
+ *
+ * NULL and "" will match.
*/
int dom_string_cmp(struct dom_string *s1, struct dom_string *s2)
{
@@ -322,6 +336,8 @@
* \param s1 The first string to compare
* \param s2 The second string to compare
* \return 0 if strings match, non-0 otherwise
+ *
+ * NULL and "" will match.
*/
int dom_string_icmp(struct dom_string *s1, struct dom_string *s2)
{
@@ -343,3 +359,4 @@
return strncasecmp((const char *) d1, (const char *) d2, l1);
}
+
15 years, 8 months
r3560 jshaw - in /trunk/dom/test: list.c list.h
by netsurf@semichrome.net
Author: jshaw
Date: Sat Sep 22 13:18:28 2007
New Revision: 3560
URL: http://source.netsurf-browser.org?rev=3560&view=rev
Log:
Implement list_contains_all()
Modified:
trunk/dom/test/list.c
trunk/dom/test/list.h
Modified: trunk/dom/test/list.c
URL: http://source.netsurf-browser.org/trunk/dom/test/list.c?rev=3560&r1=3559&...
==============================================================================
--- trunk/dom/test/list.c (original)
+++ trunk/dom/test/list.c Sat Sep 22 13:18:28 2007
@@ -62,3 +62,13 @@
return false;
}
+bool list_contains_all(struct list* superList, struct list* subList, int (*comparator)(const void* a, const void* b)) {
+ struct list_elt* elt = subList->head;
+ while (elt != NULL) {
+ if (!list_contains(superList, elt->data, comparator)) {
+ return false;
+ }
+ elt = elt->next;
+ }
+ return true;
+}
Modified: trunk/dom/test/list.h
URL: http://source.netsurf-browser.org/trunk/dom/test/list.h?rev=3560&r1=3559&...
==============================================================================
--- trunk/dom/test/list.h (original)
+++ trunk/dom/test/list.h Sat Sep 22 13:18:28 2007
@@ -32,4 +32,9 @@
*/
bool list_contains(struct list* list, void* data, int (*comparator)(const void* a, const void* b));
+/**
+ * Tests if superlist contains all elements in sublist. Order is not important.
+ */
+bool list_contains_all(struct list* superList, struct list* subList, int (*comparator)(const void* a, const void* b));
+
#endif
15 years, 8 months
r3559 jshaw - in /trunk/dom/test: list.c list.h
by netsurf@semichrome.net
Author: jshaw
Date: Sat Sep 22 12:25:29 2007
New Revision: 3559
URL: http://source.netsurf-browser.org?rev=3559&view=rev
Log:
Initial revision of linked list implementation
Added:
trunk/dom/test/list.c
trunk/dom/test/list.h
Added: trunk/dom/test/list.c
URL: http://source.netsurf-browser.org/trunk/dom/test/list.c?rev=3559&view=auto
==============================================================================
--- trunk/dom/test/list.c (added)
+++ trunk/dom/test/list.c Sat Sep 22 12:25:29 2007
@@ -1,0 +1,64 @@
+/*
+ * This file is part of libdom test suite.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 James Shaw <jshaw(a)netsurf-browser.org>
+ */
+
+#include <malloc.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "list.h"
+
+struct list* list_new(void) {
+ struct list* list = malloc(sizeof(struct list));
+ list->size = 0;
+ list->head = NULL;
+ list->tail = NULL;
+ return list;
+}
+
+void list_destroy(struct list* list) {
+ struct list_elt* elt = list->head;
+ while (elt != NULL) {
+ struct list_elt* nextElt = elt->next;
+ free(elt);
+ elt = nextElt;
+ }
+ free(list);
+}
+
+void list_add(struct list* list, void* data) {
+ struct list_elt* elt = malloc(sizeof(struct list_elt));
+ elt->data = data;
+ elt->next = NULL;
+ struct list_elt* tail = list->tail;
+
+ // if tail was set, make its 'next' ptr point to elt
+ if (tail != NULL) {
+ tail->next = elt;
+ }
+
+ // make elt the new tail
+ list->tail = elt;
+
+ if (list->head == NULL) {
+ list->head = elt;
+ }
+
+ // inc the size of the list
+ list->size++;
+}
+
+bool list_contains(struct list* list, void* data, int (*comparator)(const void* a, const void* b)) {
+ struct list_elt* elt = list->head;
+ while (elt != NULL) {
+ if (comparator(elt->data, data) == 0) {
+ return true;
+ }
+ elt = elt->next;
+ }
+ return false;
+}
+
Added: trunk/dom/test/list.h
URL: http://source.netsurf-browser.org/trunk/dom/test/list.h?rev=3559&view=auto
==============================================================================
--- trunk/dom/test/list.h (added)
+++ trunk/dom/test/list.h Sat Sep 22 12:25:29 2007
@@ -1,0 +1,35 @@
+/*
+ * This file is part of libdom test suite.
+ * Licensed under the MIT License,
+ * http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2007 James Shaw <jshaw(a)netsurf-browser.org>
+ */
+
+#ifndef list_h_
+#define list_h_
+
+struct list_elt {
+ void* data;
+ struct list_elt* next;
+};
+
+struct list {
+ unsigned int size;
+ struct list_elt* head;
+ struct list_elt* tail;
+};
+
+struct list* list_new(void);
+void list_destroy(struct list* list);
+
+/**
+ * Add data to the tail of the list.
+ */
+void list_add(struct list* list, void* data);
+
+/**
+ * Tests if data is equal to any element in the list.
+ */
+bool list_contains(struct list* list, void* data, int (*comparator)(const void* a, const void* b));
+
+#endif
15 years, 8 months
r3558 jmb - /trunk/dom/src/core/node.c
by netsurf@semichrome.net
Author: jmb
Date: Sat Sep 22 02:44:17 2007
New Revision: 3558
URL: http://source.netsurf-browser.org?rev=3558&view=rev
Log:
Implement dom_node_remove_node()
Make _dom_node_replace() handle DocumentFragments correctly.
Ensure _dom_node_detach_range() clears range's previous/next pointers.
Modified:
trunk/dom/src/core/node.c
Modified: trunk/dom/src/core/node.c
URL: http://source.netsurf-browser.org/trunk/dom/src/core/node.c?rev=3558&r1=3...
==============================================================================
--- trunk/dom/src/core/node.c (original)
+++ trunk/dom/src/core/node.c Sat Sep 22 02:44:17 2007
@@ -795,11 +795,28 @@
struct dom_node *old_child,
struct dom_node **result)
{
- UNUSED(node);
- UNUSED(old_child);
- UNUSED(result);
-
- return DOM_NOT_SUPPORTED_ERR;
+ /* We don't support removal of DocumentType or root Element nodes */
+ if (node->type == DOM_DOCUMENT_NODE &&
+ (old_child->type == DOM_DOCUMENT_TYPE_NODE ||
+ old_child->type == DOM_ELEMENT_NODE))
+ return DOM_NOT_SUPPORTED_ERR;
+
+ /* Ensure old_child is a child of node */
+ if (old_child->parent != node)
+ return DOM_NOT_FOUND_ERR;
+
+ /* Ensure node is writable */
+ if (_dom_node_readonly(node))
+ return DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+ /* Detach the node */
+ _dom_node_detach(old_child);
+
+ /* Sort out the return value */
+ dom_node_ref(old_child);
+ *result = old_child;
+
+ return DOM_NO_ERR;
}
/**
@@ -1554,6 +1571,9 @@
for (struct dom_node *n = first; n != last->next; n = n->next)
n->parent = NULL;
+
+ first->previous = NULL;
+ last->next = NULL;
}
/**
@@ -1569,19 +1589,34 @@
inline void _dom_node_replace(struct dom_node *old,
struct dom_node *replacement)
{
- replacement->previous = old->previous;
- replacement->next = old->next;
+ struct dom_node *first, *last;
+
+ if (replacement->type == DOM_DOCUMENT_FRAGMENT_NODE) {
+ first = replacement->first_child;
+ last = replacement->last_child;
+
+ replacement->first_child = replacement->last_child = NULL;
+ } else {
+ first = replacement;
+ last = replacement;
+ }
+
+ first->previous = old->previous;
+ last->next = old->next;
if (old->previous != NULL)
- old->previous->next = replacement;
+ old->previous->next = first;
else
- old->parent->first_child = replacement;
+ old->parent->first_child = first;
if (old->next != NULL)
- old->next->previous = replacement;
+ old->next->previous = last;
else
- old->parent->last_child = replacement;
-
- replacement->parent = old->parent;
-}
-
+ old->parent->last_child = last;
+
+ for (struct dom_node *n = first; n != last->next; n = n->next)
+ n->parent = old->parent;
+
+ old->previous = old->next = old->parent = NULL;
+}
+
15 years, 8 months
r3557 jmb - /trunk/dom/src/core/node.c
by netsurf@semichrome.net
Author: jmb
Date: Sat Sep 22 02:28:54 2007
New Revision: 3557
URL: http://source.netsurf-browser.org?rev=3557&view=rev
Log:
Implement dom_node_replace_child()
Modified:
trunk/dom/src/core/node.c
Modified: trunk/dom/src/core/node.c
URL: http://source.netsurf-browser.org/trunk/dom/src/core/node.c?rev=3557&r1=3...
==============================================================================
--- trunk/dom/src/core/node.c (original)
+++ trunk/dom/src/core/node.c Sat Sep 22 02:28:54 2007
@@ -39,6 +39,8 @@
struct dom_node *next);
static inline void _dom_node_detach_range(struct dom_node *first,
struct dom_node *last);
+static inline void _dom_node_replace(struct dom_node *old,
+ struct dom_node *replacement);
/**
* Destroy a DOM node
@@ -716,12 +718,59 @@
struct dom_node *new_child, struct dom_node *old_child,
struct dom_node **result)
{
- UNUSED(node);
- UNUSED(new_child);
- UNUSED(old_child);
- UNUSED(result);
-
- return DOM_NOT_SUPPORTED_ERR;
+ /* We don't support replacement of DocumentType or root Elements */
+ if (node->type == DOM_DOCUMENT_NODE &&
+ (new_child->type == DOM_DOCUMENT_TYPE_NODE ||
+ new_child->type == DOM_ELEMENT_NODE))
+ return DOM_NOT_SUPPORTED_ERR;
+
+ /* Ensure that new_child and node are owned by the same document */
+ if (new_child->owner != node->owner)
+ return DOM_WRONG_DOCUMENT_ERR;
+
+ /* Ensure node isn't read only */
+ if (_dom_node_readonly(node))
+ return DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+ /* Ensure that old_child is a child of node */
+ if (old_child->parent != node)
+ return DOM_NOT_FOUND_ERR;
+
+ /* Ensure that new_child is not an ancestor of node, nor node itself */
+ for (struct dom_node *n = node; n != NULL; n = n->parent) {
+ if (n == new_child)
+ return DOM_HIERARCHY_REQUEST_ERR;
+ }
+
+ /* Ensure that new_child is permitted as a child of node */
+ if (!_dom_node_permitted_child(node, new_child))
+ return DOM_HIERARCHY_REQUEST_ERR;
+
+ /* Attempting to replace a node with itself is a NOP */
+ if (new_child == old_child) {
+ dom_node_ref(old_child);
+ *result = old_child;
+
+ return DOM_NO_ERR;
+ }
+
+ /* If new_child is already in the tree and
+ * its parent isn't read only, remove it */
+ if (new_child->parent != NULL) {
+ if (_dom_node_readonly(new_child->parent))
+ return DOM_NO_MODIFICATION_ALLOWED_ERR;
+
+ _dom_node_detach(new_child);
+ }
+
+ /* Perform the replacement */
+ _dom_node_replace(old_child, new_child);
+
+ /* Sort out the return value */
+ dom_node_ref(old_child);
+ *result = old_child;
+
+ return DOM_NO_ERR;
}
/**
@@ -1507,3 +1556,32 @@
n->parent = NULL;
}
+/**
+ * Replace a node in the tree
+ *
+ * \param old Node to replace
+ * \param replacement Replacement node
+ *
+ * This is not implemented in terms of attach/detach in case
+ * we want to perform any special replacement-related behaviour
+ * at a later date.
+ */
+inline void _dom_node_replace(struct dom_node *old,
+ struct dom_node *replacement)
+{
+ replacement->previous = old->previous;
+ replacement->next = old->next;
+
+ if (old->previous != NULL)
+ old->previous->next = replacement;
+ else
+ old->parent->first_child = replacement;
+
+ if (old->next != NULL)
+ old->next->previous = replacement;
+ else
+ old->parent->last_child = replacement;
+
+ replacement->parent = old->parent;
+}
+
15 years, 8 months
r3556 jmb - /trunk/dom/src/core/node.c
by netsurf@semichrome.net
Author: jmb
Date: Sat Sep 22 02:13:17 2007
New Revision: 3556
URL: http://source.netsurf-browser.org?rev=3556&view=rev
Log:
If new_child is already in the tree ensure its parent is not read only
Modified:
trunk/dom/src/core/node.c
Modified: trunk/dom/src/core/node.c
URL: http://source.netsurf-browser.org/trunk/dom/src/core/node.c?rev=3556&r1=3...
==============================================================================
--- trunk/dom/src/core/node.c (original)
+++ trunk/dom/src/core/node.c Sat Sep 22 02:13:17 2007
@@ -638,9 +638,14 @@
return DOM_NO_ERR;
}
- /* If new_child is already in the tree, remove it */
- if (new_child->parent != NULL)
+ /* If new_child is already in the tree and
+ * its parent isn't read only, remove it */
+ if (new_child->parent != NULL) {
+ if (_dom_node_readonly(new_child->parent))
+ return DOM_NO_MODIFICATION_ALLOWED_ERR;
+
_dom_node_detach(new_child);
+ }
/* If new_child is a DocumentFragment, insert its children
* Otherwise, insert new_child */
15 years, 8 months
r3555 jmb - /trunk/dom/src/core/node.c
by netsurf@semichrome.net
Author: jmb
Date: Sat Sep 22 02:01:32 2007
New Revision: 3555
URL: http://source.netsurf-browser.org?rev=3555&view=rev
Log:
Fix misleading comments
Modified:
trunk/dom/src/core/node.c
Modified: trunk/dom/src/core/node.c
URL: http://source.netsurf-browser.org/trunk/dom/src/core/node.c?rev=3555&r1=3...
==============================================================================
--- trunk/dom/src/core/node.c (original)
+++ trunk/dom/src/core/node.c Sat Sep 22 02:01:32 2007
@@ -586,8 +586,9 @@
*
* Attempting to insert a node before itself is a NOP.
*
- * ::new_child's reference count will be increased. The caller should unref
- * it (as they should already have held a reference on the node)
+ * The returned node will have its reference count increased. It is
+ * the responsibility of the caller to unref the node once it has
+ * finished with it.
*/
dom_exception dom_node_insert_before(struct dom_node *node,
struct dom_node *new_child, struct dom_node *ref_child,
@@ -702,12 +703,9 @@
* ::new_child's children.
* If ::new_child is already in the tree, it is first removed.
*
- * ::new_child's reference count will be increased. The caller should unref
- * it (as they should already have held a reference on the node)
- *
- * ::old_child's reference count remains unmodified (::node's reference is
- * transferred to the caller). The caller should unref ::old_child once it
- * is finished with it.
+ * The returned node will have its reference count increased. It is
+ * the responsibility of the caller to unref the node once it has
+ * finished with it.
*/
dom_exception dom_node_replace_child(struct dom_node *node,
struct dom_node *new_child, struct dom_node *old_child,
@@ -735,9 +733,9 @@
* ::new_child is of type
* DocumentType or Element.
*
- * ::old_child's reference count remains unmodified (::node's reference is
- * transferred to the caller). The caller should unref ::old_child once it
- * is finished with it.
+ * The returned node will have its reference count increased. It is
+ * the responsibility of the caller to unref the node once it has
+ * finished with it.
*/
dom_exception dom_node_remove_child(struct dom_node *node,
struct dom_node *old_child,
@@ -772,8 +770,9 @@
* If ::new_child is a DocumentFragment, all of its children are inserted.
* If ::new_child is already in the tree, it is first removed.
*
- * ::new_child's reference count will be increased. The caller should unref
- * it (as they should already have held a reference on the node)
+ * The returned node will have its reference count increased. It is
+ * the responsibility of the caller to unref the node once it has
+ * finished with it.
*/
dom_exception dom_node_append_child(struct dom_node *node,
struct dom_node *new_child,
15 years, 8 months