summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorBo Yang <struggleyb.nku@gmail.com>2009-08-13 09:33:24 +0000
committerBo Yang <struggleyb.nku@gmail.com>2009-08-13 09:33:24 +0000
commit13fadb12fb400818e0ccb4c38b3bfce70ccfdad2 (patch)
tree19c55b39d97567a37b88b49aaaac13b21b9f24ee /src/core
parentbf6bc398bd40e39a016725550f5b8446a01ee2d1 (diff)
downloadlibdom-13fadb12fb400818e0ccb4c38b3bfce70ccfdad2.tar.gz
libdom-13fadb12fb400818e0ccb4c38b3bfce70ccfdad2.tar.bz2
Merge the Events module (branches/struggleyb/libdom-events) back to trunk. :)
svn path=/trunk/dom/; revision=9236
Diffstat (limited to 'src/core')
-rw-r--r--src/core/characterdata.c58
-rw-r--r--src/core/document.c21
-rw-r--r--src/core/document.h11
-rw-r--r--src/core/element.c222
-rw-r--r--src/core/implementation.c3
-rw-r--r--src/core/node.c85
-rw-r--r--src/core/node.h5
-rw-r--r--src/core/string.c26
-rw-r--r--src/core/string.h10
9 files changed, 396 insertions, 45 deletions
diff --git a/src/core/characterdata.c b/src/core/characterdata.c
index f5b4094..6bb542d 100644
--- a/src/core/characterdata.c
+++ b/src/core/characterdata.c
@@ -10,11 +10,13 @@
#include <dom/core/characterdata.h>
#include <dom/core/string.h>
+#include <dom/events/events.h>
#include "core/characterdata.h"
#include "core/document.h"
#include "core/node.h"
#include "utils/utils.h"
+#include "events/mutation_event.h"
/* The virtual functions for dom_characterdata, we make this vtable
* public to each child class */
@@ -128,6 +130,15 @@ dom_exception _dom_characterdata_set_data(struct dom_characterdata *cdata,
return DOM_NO_MODIFICATION_ALLOWED_ERR;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ dom_exception err;
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
+ data, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
@@ -135,7 +146,8 @@ dom_exception _dom_characterdata_set_data(struct dom_characterdata *cdata,
dom_string_ref(data);
c->value = data;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
/**
@@ -223,13 +235,22 @@ dom_exception _dom_characterdata_append_data(struct dom_characterdata *cdata,
return err;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
+ temp, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
c->value = temp;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
/**
@@ -270,13 +291,22 @@ dom_exception _dom_characterdata_insert_data(struct dom_characterdata *cdata,
return err;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
+ temp, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
c->value = temp;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
/**
@@ -319,13 +349,22 @@ dom_exception _dom_characterdata_delete_data(struct dom_characterdata *cdata,
return err;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value,
+ temp, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
c->value = temp;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
/**
@@ -370,13 +409,22 @@ dom_exception _dom_characterdata_replace_data(struct dom_characterdata *cdata,
return err;
}
+ /* Dispatch a DOMCharacterDataModified event */
+ struct dom_document *doc = dom_node_get_owner(cdata);
+ bool success = true;
+ err = _dom_dispatch_characterdata_modified_event(doc, c, c->value, temp,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
if (c->value != NULL) {
dom_string_unref(c->value);
}
c->value = temp;
- return DOM_NO_ERR;
+ success = true;
+ return _dom_dispatch_subtree_modified_event(doc, c->parent, &success);
}
diff --git a/src/core/document.c b/src/core/document.c
index 6bd0045..b15eef3 100644
--- a/src/core/document.c
+++ b/src/core/document.c
@@ -76,6 +76,7 @@ static dom_exception dom_document_dup_node(dom_document *doc,
* \param pw Pointer to client-specific private data
* \param doc Pointer to location to receive created document
* \param ctx The intern string context of this document
+ * \param daf The default action fetcher
* \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion.
*
* ::impl will have its reference count increased.
@@ -84,6 +85,7 @@ static dom_exception dom_document_dup_node(dom_document *doc,
*/
dom_exception dom_document_create(struct dom_implementation *impl,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc)
{
struct dom_document *d;
@@ -103,7 +105,7 @@ dom_exception dom_document_create(struct dom_implementation *impl,
* reaches zero. Documents own themselves (this simplifies the
* rest of the code, as it doesn't need to special case Documents)
*/
- err = _dom_document_initialise(d, impl, alloc, pw, ctx);
+ err = _dom_document_initialise(d, impl, alloc, pw, ctx, daf);
if (err != DOM_NO_ERR) {
/* Clean up document */
alloc(d, 0, pw);
@@ -118,7 +120,8 @@ dom_exception dom_document_create(struct dom_implementation *impl,
/* Initialise the document */
dom_exception _dom_document_initialise(struct dom_document *doc,
struct dom_implementation *impl, dom_alloc alloc, void *pw,
- struct lwc_context_s *ctx)
+ struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf)
{
assert(ctx != NULL);
assert(alloc != NULL);
@@ -150,7 +153,8 @@ dom_exception _dom_document_initialise(struct dom_document *doc,
doc->id_name = NULL;
- return err;
+ /* We should not pass a NULL when all things hook up */
+ return _dom_document_event_internal_initialise(doc, &doc->dei, daf);
}
@@ -185,6 +189,8 @@ bool _dom_document_finalise(struct dom_document *doc)
if (doc->id_name != NULL)
lwc_context_string_unref(doc->context, doc->id_name);
lwc_context_unref(doc->context);
+
+ _dom_document_event_internal_finalise(doc, &doc->dei);
return true;
}
@@ -1302,7 +1308,7 @@ dom_exception _dom_document_create_string(struct dom_document *doc,
return dom_string_create(doc->alloc, doc->pw, data, len, result);
}
-/*
+/**
* Create a lwc_string
*
* \param doc The document object
@@ -1324,6 +1330,13 @@ dom_exception _dom_document_create_lwcstring(struct dom_document *doc,
return _dom_exception_from_lwc_error(lerr);
}
+/* Unref a lwc_string created by this document */
+void _dom_document_unref_lwcstring(struct dom_document *doc,
+ struct lwc_string_s *str)
+{
+ lwc_context_string_unref(doc->context, str);
+}
+
/* Simple accessor for lwc_context of this document */
struct lwc_context_s *_dom_document_get_intern_context(
struct dom_document *doc)
diff --git a/src/core/document.h b/src/core/document.h
index 145eddf..ea961a2 100644
--- a/src/core/document.h
+++ b/src/core/document.h
@@ -21,6 +21,8 @@
#include "utils/resource_mgr.h"
#include "utils/list.h"
+#include "events/document_event.h"
+
struct dom_document;
struct dom_namednodemap;
struct dom_node;
@@ -61,12 +63,16 @@ struct dom_document {
/**< The deletion pending list */
struct lwc_string_s *id_name; /**< The ID attribute's name */
+
+ dom_document_event_internal dei;
+ /**< The DocumentEVent interface */
};
/* Initialise the document */
dom_exception _dom_document_initialise(struct dom_document *doc,
struct dom_implementation *impl, dom_alloc alloc, void *pw,
- struct lwc_context_s *ctx);
+ struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf);
/* Finalise the document */
bool _dom_document_finalise(struct dom_document *doc);
@@ -77,6 +83,9 @@ dom_exception _dom_document_create_string(struct dom_document *doc,
/* Create a lwc_string from C string */
dom_exception _dom_document_create_lwcstring(struct dom_document *doc,
const uint8_t *data, size_t len, struct lwc_string_s **result);
+/* Unref a lwc_string of this document */
+void _dom_document_unref_lwcstring(struct dom_document *doc,
+ struct lwc_string_s *str);
/* Create a dom_string from a lwc_string */
dom_exception _dom_document_create_string_from_lwcstring(
struct dom_document *doc, struct lwc_string_s *str,
diff --git a/src/core/element.c b/src/core/element.c
index 54bb9d1..7609b94 100644
--- a/src/core/element.c
+++ b/src/core/element.c
@@ -16,6 +16,7 @@
#include <dom/core/node.h>
#include <dom/core/string.h>
#include <dom/core/document.h>
+#include <dom/events/events.h>
#include "core/attr.h"
#include "core/document.h"
@@ -26,6 +27,7 @@
#include "utils/namespace.h"
#include "utils/utils.h"
#include "utils/hashtable.h"
+#include "events/mutation_event.h"
/* The three numbers are just random ones, maybe we should change it after some
* more consideration */
@@ -67,8 +69,6 @@ static dom_exception _dom_element_has_attr(struct dom_element *element,
static dom_exception _dom_element_set_id_attr(struct dom_element *element,
struct dom_hash_table *hs, struct dom_string *name, bool is_id);
-static unsigned int _dom_element_hash_lwcstring(void *key);
-
/* The operation set for namednodemap */
static dom_exception attributes_get_length(void *priv,
@@ -114,6 +114,7 @@ static void *_value(void *value, void *value_pw, dom_alloc alloc,
static void *_nsattributes(void *value, void *value_pw, dom_alloc alloc,
void *pw, bool clone);
+
/*----------------------------------------------------------------------*/
/* Constructors and Destructors */
@@ -183,14 +184,14 @@ dom_exception _dom_element_initialise(struct dom_element *el,
assert(doc != NULL);
err = _dom_document_create_hashtable(doc, CHAINS_ATTRIBUTES,
- _dom_element_hash_lwcstring, &el->attributes);
+ _dom_hash_hash_lwcstring, &el->attributes);
if (err != DOM_NO_ERR) {
_dom_document_alloc(doc, el, 0);
return err;
}
err = _dom_document_create_hashtable(doc, CHAINS_NAMESPACE,
- _dom_element_hash_lwcstring, &el->ns_attributes);
+ _dom_hash_hash_lwcstring, &el->ns_attributes);
if (err != DOM_NO_ERR) {
_dom_document_alloc(doc, el, 0);
_dom_document_alloc(doc, el->attributes, 0);
@@ -540,7 +541,7 @@ dom_exception _dom_element_set_attribute_ns(struct dom_element *element,
doc = dom_node_get_owner(element);
assert(doc != NULL);
err = _dom_document_create_hashtable(doc, CHAINS_NS_ATTRIBUTES,
- _dom_element_hash_lwcstring, &attrs);
+ _dom_hash_hash_lwcstring, &attrs);
if (err != DOM_NO_ERR)
return err;
@@ -686,7 +687,7 @@ dom_exception _dom_element_set_attribute_node_ns(struct dom_element *element,
doc = dom_node_get_owner(element);
assert(doc != NULL);
err = _dom_document_create_hashtable(doc, CHAINS_NS_ATTRIBUTES,
- _dom_element_hash_lwcstring, &attrs);
+ _dom_hash_hash_lwcstring, &attrs);
if (err != DOM_NO_ERR)
return err;
@@ -1218,7 +1219,7 @@ dom_exception _dom_element_get_attr(struct dom_element *element,
struct dom_string **value)
{
void *a;
- dom_exception err;
+ dom_exception err = DOM_NO_ERR;
lwc_string *str;
/* Looking for name */
@@ -1232,10 +1233,10 @@ dom_exception _dom_element_get_attr(struct dom_element *element,
if (a == NULL) {
*value = NULL;
} else {
- dom_attr_get_value(((struct dom_attr *) a), value);
+ err = dom_attr_get_value(((struct dom_attr *) a), value);
}
- return DOM_NO_ERR;
+ return err;
}
/**
@@ -1275,6 +1276,28 @@ dom_exception _dom_element_set_attr(struct dom_element *element,
/* Found an existing attribute, so replace its value */
dom_exception err;
+ /* Dispatch a DOMAttrModified event */
+ dom_string *old = NULL;
+ struct dom_document *doc = dom_node_get_owner(element);
+ bool success = true;
+ err = dom_attr_get_value(a, &old);
+ /* TODO: We did not support some node type such as entity
+ * reference, in that case, we should ignore the error to
+ * make sure the event model work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR)
+ return err;
+ err = _dom_dispatch_attr_modified_event(doc, e, old, value, a,
+ name, DOM_MUTATION_MODIFICATION, &success);
+ dom_string_unref(old);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) e, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
err = dom_attr_set_value((struct dom_attr *) a, value);
if (err != DOM_NO_ERR)
return err;
@@ -1294,6 +1317,26 @@ dom_exception _dom_element_set_attr(struct dom_element *element,
return err;
}
+ /* Dispatch a DOMAttrModified event */
+ struct dom_document *doc = dom_node_get_owner(element);
+ bool success = true;
+ err = _dom_dispatch_attr_modified_event(doc, e, NULL, value,
+ (dom_event_target *) attr, name,
+ DOM_MUTATION_ADDITION, &success);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(attr);
+ return err;
+ }
+
+ err = _dom_dispatch_node_change_event(doc,
+ (dom_event_target *) attr,
+ (dom_event_target *) element,
+ DOM_MUTATION_ADDITION, &success);
+ if (err != DOM_NO_ERR) {
+ dom_node_unref(attr);
+ return err;
+ }
+
added = _dom_hash_add(hs, str, attr, false);
if (added == false) {
/* If we failed at this step, there must be no memory */
@@ -1304,6 +1347,12 @@ dom_exception _dom_element_set_attr(struct dom_element *element,
dom_node_set_parent(attr, element);
dom_node_unref(attr);
dom_node_remove_pending(attr);
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) element, &success);
+ if (err != DOM_NO_ERR)
+ return err;
}
return DOM_NO_ERR;
@@ -1334,13 +1383,51 @@ dom_exception _dom_element_remove_attr(struct dom_element *element,
if (err != DOM_NO_ERR)
return err;
- a = (dom_node_internal *) _dom_hash_del(hs, str);
+ a = (dom_node_internal *) _dom_hash_get(hs, str);
/* Detach attr node from list */
if (a != NULL) {
+ /* Disptach DOMNodeRemoval event */
+ bool success = true;
+ struct dom_document *doc = dom_node_get_owner(element);
+ err = _dom_dispatch_node_change_event(doc,
+ (dom_event_target *) a,
+ (dom_event_target *) element,
+ DOM_MUTATION_REMOVAL, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ /* Delete the attribute node */
+ _dom_hash_del(hs, str);
+ /* Claim a reference for later event dispatch */
+ dom_node_ref(a);
+
/* And destroy attr */
dom_node_set_parent(a, NULL);
dom_node_try_destroy(a);
+
+ /* Dispatch a DOMAttrModified event */
+ success = true;
+ dom_string *old = NULL;
+ err = dom_attr_get_value(a, &old);
+ /* TODO: We did not support some node type such as entity
+ * reference, in that case, we should ignore the error to
+ * make sure the event model work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR)
+ return err;
+ err = _dom_dispatch_attr_modified_event(doc, e, old, NULL, a,
+ name, DOM_MUTATION_REMOVAL, &success);
+ dom_string_unref(old);
+ /* Release the reference */
+ dom_node_unref(a);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) e, &success);
+ if (err != DOM_NO_ERR)
+ return err;
}
/** \todo defaulted attribute handling */
@@ -1437,14 +1524,50 @@ dom_exception _dom_element_set_attr_node(struct dom_element *element,
if (err != DOM_NO_ERR)
return err;
- a = _dom_hash_del(hs, str);
+ a = _dom_hash_get(hs, str);
*result = NULL;
if (a != NULL) {
+ /* Disptach DOMNodeRemoval event */
+ bool success = true;
+ struct dom_document *doc = dom_node_get_owner(element);
+ err = _dom_dispatch_node_change_event(doc,
+ (dom_event_target *) a,
+ (dom_event_target *) element,
+ DOM_MUTATION_REMOVAL, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ _dom_hash_del(hs, str);
dom_node_ref(a);
*result = (dom_attr *) a;
dom_node_set_parent(a, NULL);
dom_node_mark_pending(a);
+
+ /* Dispatch a DOMAttrModified event */
+ dom_string *old = NULL;
+ success = true;
+ err = dom_attr_get_value(a, &old);
+ /* TODO: We did not support some node type such as entity
+ * reference, in that case, we should ignore the error to
+ * make sure the event model work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR) {
+ dom_node_unref(a);
+ return err;
+ }
+ err = _dom_dispatch_attr_modified_event(doc, e, old, NULL,
+ (dom_event_target *) a, name,
+ DOM_MUTATION_REMOVAL, &success);
+ dom_string_unref(old);
+ dom_node_unref(a);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) e, &success);
+ if (err != DOM_NO_ERR)
+ return err;
}
added = _dom_hash_add(hs, str, attr, false);
@@ -1455,10 +1578,39 @@ dom_exception _dom_element_set_attr_node(struct dom_element *element,
dom_node_set_parent(attr, element);
dom_node_remove_pending(attr);
+ /* Dispatch a DOMAttrModified event */
+ dom_string *new = NULL;
+ struct dom_document *doc = dom_node_get_owner(element);
+ bool success = true;
+ err = dom_attr_get_value(attr, &new);
+ /* TODO: We did not support some node type such as entity reference, in
+ * that case, we should ignore the error to make sure the event model
+ * work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR)
+ return err;
+ err = _dom_dispatch_attr_modified_event(doc, e, NULL, new,
+ (dom_event_target *) attr, name,
+ DOM_MUTATION_ADDITION, &success);
+ dom_string_unref(new);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ err = _dom_dispatch_node_change_event(doc, (dom_event_target *) attr,
+ (dom_event_target *) element, DOM_MUTATION_ADDITION,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
/* Cleanup */
if (name != NULL)
dom_string_unref(name);
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc,
+ (dom_event_target *) element, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
return DOM_NO_ERR;
}
@@ -1500,7 +1652,7 @@ dom_exception _dom_element_remove_attr_node(struct dom_element *element,
if (err != DOM_NO_ERR)
return err;
- a = _dom_hash_del(hs, str);
+ a = _dom_hash_get(hs, str);
/* Now, cleaup the dom_string and lwc_string */
dom_string_unref(name);
@@ -1512,16 +1664,53 @@ dom_exception _dom_element_remove_attr_node(struct dom_element *element,
return DOM_NOT_FOUND_ERR;
}
+ /* Dispatch a DOMNodeRemoved event */
+ bool success = true;
+ struct dom_document *doc = dom_node_get_owner(element);
+ err = _dom_dispatch_node_change_event(doc, (dom_event_target *) a,
+ (dom_event_target *) element, DOM_MUTATION_REMOVAL,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ /* Delete the attribute node */
+ _dom_hash_del(hs, str);
+ dom_node_ref(a);
+
+ /* Dispatch a DOMAttrModified event */
+ dom_string *old = NULL;
+ success = true;
+ err = dom_attr_get_value(a, &old);
+ /* TODO: We did not support some node type such as entity reference, in
+ * that case, we should ignore the error to make sure the event model
+ * work as excepted. */
+ if (err != DOM_NO_ERR && err != DOM_NOT_SUPPORTED_ERR) {
+ dom_node_unref(a);
+ return err;
+ }
+ err = _dom_dispatch_attr_modified_event(doc, e, old, NULL,
+ (dom_event_target *) a, name,
+ DOM_MUTATION_REMOVAL, &success);
+ dom_string_unref(old);
+ dom_node_unref(a);
+ if (err != DOM_NO_ERR)
+ return err;
+
/* When a Node is removed, it should be destroy. When its refcnt is not
* zero, it will be added to the document's deletion pending list.
* When a Node is removed, its parent should be NULL, but its owner
* should remain to be the document.
*/
- dom_node_ref(a);
*result = (dom_attr *) a;
dom_node_set_parent(a, NULL);
dom_node_mark_pending(a);
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(doc, (dom_event_target *) e,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
return DOM_NO_ERR;
}
@@ -1704,13 +1893,6 @@ dom_exception _dom_element_get_id(struct dom_element *ele, lwc_string **id)
}
-/* The hash function for attributes and id tables */
-unsigned int _dom_element_hash_lwcstring(void *key)
-{
- lwc_string *lstr = (lwc_string *) key;
-
- return lwc_string_hash_value(lstr);
-}
/*-------------- The dom_namednodemap functions -------------------------*/
diff --git a/src/core/implementation.c b/src/core/implementation.c
index e2b6763..30e1eb3 100644
--- a/src/core/implementation.c
+++ b/src/core/implementation.c
@@ -122,10 +122,11 @@ dom_exception dom_implementation_create_document(
struct dom_string *namespace, struct dom_string *qname,
struct dom_document_type *doctype,
dom_alloc alloc, void *pw, struct lwc_context_s *ctx,
+ dom_events_default_action_fetcher daf,
struct dom_document **doc)
{
return impl->create_document(impl, namespace, qname, doctype, alloc,
- pw, ctx, doc);
+ pw, ctx, daf, doc);
}
/**
diff --git a/src/core/node.c b/src/core/node.c
index 1c0b28f..1bdcade 100644
--- a/src/core/node.c
+++ b/src/core/node.c
@@ -17,6 +17,7 @@
#include <dom/core/nodelist.h>
#include <dom/core/implementation.h>
#include <dom/core/document_type.h>
+#include <dom/events/events.h>
#include "core/string.h"
#include "core/namednodemap.h"
@@ -33,15 +34,16 @@
#include "core/text.h"
#include "utils/utils.h"
#include "utils/resource_mgr.h"
+#include "events/mutation_event.h"
static bool _dom_node_permitted_child(const dom_node_internal *parent,
const dom_node_internal *child);
-static inline void _dom_node_attach(dom_node_internal *node,
+static inline dom_exception _dom_node_attach(dom_node_internal *node,
dom_node_internal *parent,
dom_node_internal *previous,
dom_node_internal *next);
static inline void _dom_node_detach(dom_node_internal *node);
-static inline void _dom_node_attach_range(dom_node_internal *first,
+static inline dom_exception _dom_node_attach_range(dom_node_internal *first,
dom_node_internal *last,
dom_node_internal *parent,
dom_node_internal *previous,
@@ -51,7 +53,6 @@ static inline void _dom_node_detach_range(dom_node_internal *first,
static inline void _dom_node_replace(dom_node_internal *old,
dom_node_internal *replacement);
-
static struct dom_node_vtable node_vtable = {
DOM_NODE_VTABLE
};
@@ -249,7 +250,7 @@ dom_exception _dom_node_initialise_generic(
dom_node_mark_pending(node);
}
- return DOM_NO_ERR;
+ return _dom_event_target_internal_initialise(doc, &node->eti);
}
/**
@@ -331,7 +332,14 @@ void _dom_node_finalise_generic(dom_node_internal *node, dom_alloc alloc,
if (node->name != NULL)
lwc_context_string_unref(ctx, node->name);
- /* Detach from the pending list, if we are in it */
+ /* If the node has no owner document, we need not to finalise its
+ * dom_event_target_internal structure.
+ */
+ if (node->owner != NULL)
+ _dom_event_target_internal_finalise(node->owner, &node->eti);
+
+ /* Detach from the pending list, if we are in it,
+ * this part of code should always be the end of this function. */
if (node->pending_list.prev != &node->pending_list) {
assert (node->pending_list.next != &node->pending_list);
list_del(&node->pending_list);
@@ -351,7 +359,8 @@ void _dom_node_finalise_generic(dom_node_internal *node, dom_alloc alloc,
*/
void _dom_node_ref(dom_node_internal *node)
{
- node->refcnt++;
+ if (node != NULL)
+ node->refcnt++;
}
@@ -816,6 +825,8 @@ dom_exception _dom_node_insert_before(dom_node_internal *node,
dom_node_internal *new_child, dom_node_internal *ref_child,
dom_node_internal **result)
{
+ dom_exception err;
+
/* Ensure that new_child and node are owned by the same document */
if ((new_child->type == DOM_DOCUMENT_TYPE_NODE &&
new_child->owner != NULL &&
@@ -874,24 +885,29 @@ dom_exception _dom_node_insert_before(dom_node_internal *node,
return DOM_HIERARCHY_REQUEST_ERR;
if (new_child->first_child != NULL) {
- _dom_node_attach_range(new_child->first_child,
+ err = _dom_node_attach_range(new_child->first_child,
new_child->last_child,
node,
ref_child == NULL ? node->last_child
: ref_child->previous,
ref_child == NULL ? NULL
: ref_child);
+ if (err != DOM_NO_ERR)
+ return err;
new_child->first_child = NULL;
new_child->last_child = NULL;
}
} else {
- _dom_node_attach(new_child,
+ err = _dom_node_attach(new_child,
node,
ref_child == NULL ? node->last_child
: ref_child->previous,
ref_child == NULL ? NULL
: ref_child);
+ if (err != DOM_NO_ERR)
+ return err;
+
}
/* DocumentType nodes are created outside the Document so,
@@ -1059,6 +1075,14 @@ dom_exception _dom_node_remove_child(dom_node_internal *node,
if (_dom_node_readonly(node))
return DOM_NO_MODIFICATION_ALLOWED_ERR;
+ /* Dispatch a DOMNodeRemoval event */
+ dom_exception err;
+ bool success = true;
+ err = _dom_dispatch_node_change_event(node->owner, old_child, node,
+ DOM_MUTATION_REMOVAL, &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
/* Detach the node */
_dom_node_detach(old_child);
@@ -1070,6 +1094,12 @@ dom_exception _dom_node_remove_child(dom_node_internal *node,
dom_node_try_destroy(old_child);
*result = old_child;
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(node->owner, node,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
return DOM_NO_ERR;
}
@@ -2048,7 +2078,8 @@ dom_exception _dom_node_copy(dom_node_internal *new, dom_node_internal *old)
* so it should be put in the pending list. */
dom_node_mark_pending(new);
- return DOM_NO_ERR;
+ /* Intialise the EventTarget interface */
+ return _dom_event_target_internal_initialise(new->owner, &new->eti);
}
@@ -2162,11 +2193,13 @@ bool _dom_node_readonly(const dom_node_internal *node)
* \param parent Node to attach ::node as child of
* \param previous Previous node in sibling list, or NULL if none
* \param next Next node in sibling list, or NULL if none
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
*/
-void _dom_node_attach(dom_node_internal *node, dom_node_internal *parent,
- dom_node_internal *previous, dom_node_internal *next)
+dom_exception _dom_node_attach(dom_node_internal *node,
+ dom_node_internal *parent, dom_node_internal *previous,
+ dom_node_internal *next)
{
- _dom_node_attach_range(node, node, parent, previous, next);
+ return _dom_node_attach_range(node, node, parent, previous, next);
}
/**
@@ -2191,10 +2224,11 @@ void _dom_node_detach(dom_node_internal *node)
* \param parent Node to attach range to
* \param previous Previous node in sibling list, or NULL if none
* \param next Next node in sibling list, or NULL if none
+ * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
*
* The range is assumed to be a linked list of sibling nodes.
*/
-void _dom_node_attach_range(dom_node_internal *first,
+dom_exception _dom_node_attach_range(dom_node_internal *first,
dom_node_internal *last,
dom_node_internal *parent,
dom_node_internal *previous,
@@ -2213,9 +2247,24 @@ void _dom_node_attach_range(dom_node_internal *first,
else
parent->last_child = last;
+ dom_exception err;
+ bool success = true;
for (dom_node_internal *n = first; n != last->next; n = n->next) {
n->parent = parent;
+ /* Dispatch a DOMNodeInserted event */
+ err = _dom_dispatch_node_change_event(parent->owner, n, parent,
+ DOM_MUTATION_ADDITION, &success);
+ if (err != DOM_NO_ERR)
+ return err;
}
+
+ success = true;
+ err = _dom_dispatch_subtree_modified_event(parent->owner, parent,
+ &success);
+ if (err != DOM_NO_ERR)
+ return err;
+
+ return DOM_NO_ERR;
}
/**
@@ -2239,10 +2288,20 @@ void _dom_node_detach_range(dom_node_internal *first,
else
last->parent->last_child = first->previous;
+ bool success = true;
+ dom_node_internal *parent = first->parent;
for (dom_node_internal *n = first; n != last->next; n = n->next) {
+ /* Dispatch a DOMNodeRemoval event */
+ _dom_dispatch_node_change_event(n->owner, n, n->parent,
+ DOM_MUTATION_REMOVAL, &success);
+
n->parent = NULL;
}
+ success = true;
+ _dom_dispatch_subtree_modified_event(parent->owner, parent,
+ &success);
+
first->previous = NULL;
last->next = NULL;
}
diff --git a/src/core/node.h b/src/core/node.h
index 68776da..c1a4192 100644
--- a/src/core/node.h
+++ b/src/core/node.h
@@ -15,6 +15,9 @@
#include <dom/core/node.h>
#include <dom/functypes.h>
+#include "events/event_target.h"
+#include "events/mutation_event.h"
+
#include "utils/list.h"
/**
@@ -76,6 +79,8 @@ struct dom_node_internal {
uint32_t refcnt; /**< Reference count */
struct list_entry pending_list; /**< The document delete pending list */
+
+ dom_event_target_internal eti; /**< The EventTarget interface */
};
dom_node_internal * _dom_node_create(struct dom_document *doc);
diff --git a/src/core/string.c b/src/core/string.c
index 081e03d..7442c66 100644
--- a/src/core/string.c
+++ b/src/core/string.c
@@ -56,7 +56,8 @@ static struct dom_string empty_string = {
*/
void dom_string_ref(struct dom_string *str)
{
- str->refcnt++;
+ if (str != NULL)
+ str->refcnt++;
}
/**
@@ -963,3 +964,26 @@ int _dom_lwc_string_compare_raw(struct lwc_string_s *s1,
return memcmp(rs1, rs2, len);
}
+/**
+ * Get the raw character data of the dom_string.
+ *
+ * \param str The dom_string object
+ * \return The C string pointer
+ *
+ * @note: This function is just provided for the convenience of accessing the
+ * raw C string character, no change on the result string is allowed.
+ */
+char *_dom_string_data(struct dom_string *str)
+{
+ return (char *) str->ptr;
+}
+
+/* Get the string length of this dom_string
+ *
+ * \param str The dom_string object
+ */
+size_t _dom_string_length(struct dom_string *str)
+{
+ return str->len;
+}
+
diff --git a/src/core/string.h b/src/core/string.h
index 8372688..46704d8 100644
--- a/src/core/string.h
+++ b/src/core/string.h
@@ -28,5 +28,15 @@ int _dom_lwc_string_compare_raw(struct lwc_string_s *s1,
/* Map the lwc_error to dom_exception */
dom_exception _dom_exception_from_lwc_error(lwc_error err);
+/**
+ * Get the raw character data of the dom_string.
+ * @note: This function is just provided for the convenience of accessing the
+ * raw C string character, no change on the result string is allowed.
+ */
+char *_dom_string_data(struct dom_string *str);
+
+/* Get the string length of this dom_string */
+size_t _dom_string_length(struct dom_string *str);
+
#endif