diff options
-rw-r--r-- | javascript/Makefile | 2 | ||||
-rw-r--r-- | javascript/dukky.c | 2 | ||||
-rw-r--r-- | javascript/duktape/document.c | 90 | ||||
-rw-r--r-- | javascript/duktape/element.c | 172 | ||||
-rw-r--r-- | javascript/duktape/html_collection.c | 48 | ||||
-rw-r--r-- | javascript/duktape/node.c | 21 | ||||
-rw-r--r-- | javascript/duktape/node_list.c | 84 | ||||
-rw-r--r-- | javascript/duktape/private.h | 10 | ||||
-rw-r--r-- | javascript/duktape/prototypes.h | 2 | ||||
-rw-r--r-- | test/js/dom-element-firstElementChild.html | 4 | ||||
-rw-r--r-- | utils/corestrings.c | 3 | ||||
-rw-r--r-- | utils/corestrings.h | 1 |
12 files changed, 434 insertions, 5 deletions
diff --git a/javascript/Makefile b/javascript/Makefile index 80bba8489..7c7006dc2 100644 --- a/javascript/Makefile +++ b/javascript/Makefile @@ -63,7 +63,7 @@ ifeq ($(NETSURF_USE_DUKTAPE),YES) S_DUKKY := event_target.c window.c node.c document.c \ element.c html_element.c html_unknown_element.c \ - character_data.c text.c comment.c + character_data.c text.c comment.c html_collection.c node_list.c S_JAVASCRIPT += dukky.c duktape.c content.c fetcher.c $(addprefix duktape/,$(S_DUKKY)) diff --git a/javascript/dukky.c b/javascript/dukky.c index 9fd208ff5..6536fa784 100644 --- a/javascript/dukky.c +++ b/javascript/dukky.c @@ -342,6 +342,8 @@ jscontext *js_newcontext(int timeout, jscallback *cb, void *cbctx) DUKKY_NEW_PROTOTYPE(element, "Element"); DUKKY_NEW_PROTOTYPE(html_element, "HTMLElement"); DUKKY_NEW_PROTOTYPE(html_unknown_element, "HTMLUnknownElement"); + DUKKY_NEW_PROTOTYPE(html_collection, "HTMLCollection"); + DUKKY_NEW_PROTOTYPE(node_list, "NodeList"); return ret; } diff --git a/javascript/duktape/document.c b/javascript/duktape/document.c index b4f8cefbe..76fec7501 100644 --- a/javascript/duktape/document.c +++ b/javascript/duktape/document.c @@ -44,7 +44,8 @@ static DUKKY_FUNC(document, write) DUKKY_GET_METHOD_PRIVATE(document); struct html_content *htmlc; duk_size_t text_len; - const char *text = duk_get_lstring(ctx, 0, &text_len); + const char *text = duk_safe_to_lstring(ctx, 0, &text_len); + LOG("Writing %*s", (int)text_len, text); dom_exception err; err = dom_node_get_user_data(priv->parent.node, corestring_dom___ns_key_html_content_data, @@ -114,6 +115,35 @@ static DUKKY_FUNC(document, createElement) return 1; } +static DUKKY_GETTER(document, head) +{ + DUKKY_GET_METHOD_PRIVATE(document); + struct dom_nodelist *nodes; + struct dom_node *retnode; + dom_exception err; + err = dom_document_get_elements_by_tag_name(priv->parent.node, + corestring_dom_HEAD, + &nodes); + if (err != DOM_NO_ERR) return 0; /* coerced to undefined */ + + err = dom_nodelist_item(nodes, 0, &retnode); + + if (err != DOM_NO_ERR) { + dom_nodelist_unref(nodes); + return 0; /* coerced to undefined */ + } + + dom_nodelist_unref(nodes); + + if (retnode == NULL) return 0; /* coerced to undefined */ + + dukky_push_node(ctx, retnode); + + dom_node_unref(retnode); + + return 1; +} + static DUKKY_GETTER(document, body) { DUKKY_GET_METHOD_PRIVATE(document); @@ -143,13 +173,71 @@ static DUKKY_GETTER(document, body) return 1; } +static DUKKY_FUNC(document, getElementById) +{ + DUKKY_GET_METHOD_PRIVATE(document); + dom_string *elementId_dom; + dom_element *element; + dom_exception exc; + duk_size_t text_len; + const char *text = duk_safe_to_lstring(ctx, 0, &text_len); + + exc = dom_string_create((uint8_t*)text, text_len, &elementId_dom); + if (exc != DOM_NO_ERR) { + return 0; + } + + exc = dom_document_get_element_by_id(((node_private_t *)priv)->node, + elementId_dom, &element); + dom_string_unref(elementId_dom); + if (exc != DOM_NO_ERR) { + return 0; + } + + if (element != NULL) { + dukky_push_node(ctx, (dom_node *)element); + return 1; + } + + return 0; +} + +static DUKKY_FUNC(document, getElementsByTagName) +{ + DUKKY_GET_METHOD_PRIVATE(document); + dom_nodelist *nodes; + dom_exception err; + duk_size_t text_len; + const char *text = duk_safe_to_lstring(ctx, 0, &text_len); + dom_string *tag; + + err = dom_string_create((uint8_t*)text, text_len, &tag); + + if (err != DOM_NO_ERR) return 0; /* coerced to undefined */ + + err = dom_document_get_elements_by_tag_name(((node_private_t *)priv)->node, + tag, &nodes); + dom_string_unref(tag); + if (err != DOM_NO_ERR) return 0; /* coerced to undefined */ + + if (nodes == NULL) return 0; /* coerced to undefined */ + + duk_push_pointer(ctx, nodes); + dukky_create_object(ctx, PROTO_NAME(node_list), 1); + dom_nodelist_unref(nodes); + return 1; +} + DUKKY_FUNC(document, __proto) { /* Populate document's prototypical functionality */ DUKKY_ADD_METHOD(document, write, 1); DUKKY_ADD_METHOD(document, createTextNode, 1); DUKKY_ADD_METHOD(document, createElement, 1); + DUKKY_ADD_METHOD(document, getElementById, 1); + DUKKY_ADD_METHOD(document, getElementsByTagName, 1); DUKKY_POPULATE_READONLY_PROPERTY(document, body); + DUKKY_POPULATE_READONLY_PROPERTY(document, head); /* Set this prototype's prototype (left-parent)*/ DUKKY_GET_PROTOTYPE(node); duk_set_prototype(ctx, 0); diff --git a/javascript/duktape/element.c b/javascript/duktape/element.c index f495d8621..23c76278a 100644 --- a/javascript/duktape/element.c +++ b/javascript/duktape/element.c @@ -36,10 +36,180 @@ static DUKKY_FUNC(element, __destructor) return 0; } +static DUKKY_GETTER(element, firstElementChild) +{ + DUKKY_GET_METHOD_PRIVATE(element); + dom_node *element; + dom_exception exc; + dom_node_type node_type; + dom_node *next_node; + + exc = dom_node_get_first_child(((node_private_t*)priv)->node, &element); + if (exc != DOM_NO_ERR) { + return 0; + } + + while (element != NULL) { + exc = dom_node_get_node_type(element, &node_type); + if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { + /* found it */ + dukky_push_node(ctx, (dom_node *)element); + dom_node_unref(element); + return 1; + } + + exc = dom_node_get_next_sibling(element, &next_node); + dom_node_unref(element); + if (exc == DOM_NO_ERR) { + element = next_node; + } else { + element = NULL; + } + } + return 0; +} + +static DUKKY_GETTER(element, lastElementChild) +{ + DUKKY_GET_METHOD_PRIVATE(element); + dom_node *element; + dom_exception exc; + dom_node_type node_type; + dom_node *next_node; + + exc = dom_node_get_last_child(((node_private_t*)priv)->node, &element); + if (exc != DOM_NO_ERR) { + return 0; + } + + while (element != NULL) { + exc = dom_node_get_node_type(element, &node_type); + if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { + /* found it */ + dukky_push_node(ctx, (dom_node *)element); + dom_node_unref(element); + return 1; + } + + exc = dom_node_get_previous_sibling(element, &next_node); + dom_node_unref(element); + if (exc == DOM_NO_ERR) { + element = next_node; + } else { + element = NULL; + } + } + return 0; +} + +static DUKKY_GETTER(element, previousElementSibling) +{ + DUKKY_GET_METHOD_PRIVATE(element); + dom_node *element; + dom_exception exc; + dom_node_type node_type; + dom_node *sib_node; + + exc = dom_node_get_previous_sibling(((node_private_t *)priv)->node, &element); + if (exc != DOM_NO_ERR) { + return 0; + } + + while (element != NULL) { + exc = dom_node_get_node_type(element, &node_type); + if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { + /* found it */ + dukky_push_node(ctx, (dom_node *)element); + dom_node_unref(element); + return 1; + } + + exc = dom_node_get_previous_sibling(element, &sib_node); + dom_node_unref(element); + if (exc == DOM_NO_ERR) { + element = sib_node; + } else { + element = NULL; + } + } + return 0; +} + +static DUKKY_GETTER(element, nextElementSibling) +{ + DUKKY_GET_METHOD_PRIVATE(element); + dom_node *element; + dom_exception exc; + dom_node_type node_type; + dom_node *sib_node; + + exc = dom_node_get_next_sibling(((node_private_t *)priv)->node, &element); + if (exc != DOM_NO_ERR) { + return 0; + } + + while (element != NULL) { + exc = dom_node_get_node_type(element, &node_type); + if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { + /* found it */ + dukky_push_node(ctx, (dom_node *)element); + dom_node_unref(element); + return 1; + } + + exc = dom_node_get_next_sibling(element, &sib_node); + dom_node_unref(element); + if (exc == DOM_NO_ERR) { + element = sib_node; + } else { + element = NULL; + } + } + return 0; +} + +static DUKKY_GETTER(element, childElementCount) +{ + LOG("MOO"); + DUKKY_GET_METHOD_PRIVATE(element); + dom_node *element; + dom_exception exc; + dom_node_type node_type; + dom_node *next_node; + duk_uint_t jsret = 0; + + exc = dom_node_get_first_child(((node_private_t *)priv)->node, &element); + if (exc != DOM_NO_ERR) { + return 0; + } + + while (element != NULL) { + exc = dom_node_get_node_type(element, &node_type); + if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) { + jsret += 1; + } + + exc = dom_node_get_next_sibling(element, &next_node); + dom_node_unref(element); + if (exc == DOM_NO_ERR) { + element = next_node; + } else { + element = NULL; + } + } + LOG("I found %u of them", jsret); + duk_push_uint(ctx, jsret); + return 1; +} + DUKKY_FUNC(element, __proto) { /* Populate element's prototypical functionality */ - + DUKKY_POPULATE_READONLY_PROPERTY(element, firstElementChild); + DUKKY_POPULATE_READONLY_PROPERTY(element, lastElementChild); + DUKKY_POPULATE_READONLY_PROPERTY(element, nextElementSibling); + DUKKY_POPULATE_READONLY_PROPERTY(element, previousElementSibling); + DUKKY_POPULATE_READONLY_PROPERTY(element, childElementCount); /* Set this prototype's prototype (left-parent)*/ DUKKY_GET_PROTOTYPE(node); duk_set_prototype(ctx, 0); diff --git a/javascript/duktape/html_collection.c b/javascript/duktape/html_collection.c new file mode 100644 index 000000000..835398a0e --- /dev/null +++ b/javascript/duktape/html_collection.c @@ -0,0 +1,48 @@ +/* DO NOT USE, DODGY EXAMPLE FOR VINCE */ + +#include "utils/log.h" + +#include <dom/dom.h> + +#include "javascript/dukky.h" + +DUKKY_FUNC_INIT(html_collection, struct dom_html_collection *coll) +{ + LOG("Initialise %p (priv=%p)", duk_get_heapptr(ctx, 0), priv); + priv->coll = coll; + dom_html_collection_ref(coll); +} + +DUKKY_FUNC_FINI(html_collection) +{ + /* do any html_collection finalisation here, priv ptr exists */ + LOG("Finalise %p", duk_get_heapptr(ctx, 0)); + dom_html_collection_unref(priv->coll); +} + +static DUKKY_FUNC(html_collection, __constructor) +{ + DUKKY_CREATE_PRIVATE(html_collection); + DUKKY_FUNC_T(html_collection, __init)(ctx, priv, + duk_get_pointer(ctx, 1)); + return 1; +} + +static DUKKY_FUNC(html_collection, __destructor) +{ + DUKKY_SAFE_GET_PRIVATE(html_collection, 0); + DUKKY_FUNC_T(html_collection, __fini)(ctx, priv); + free(priv); + return 0; +} + +DUKKY_FUNC(html_collection, __proto) +{ + /* Populate html_collection's prototypical functionality */ + + /* Set this prototype's prototype (left-parent)*/ + /* And the initialiser/finalizer */ + DUKKY_SET_DESTRUCTOR(0, html_collection); + DUKKY_SET_CONSTRUCTOR(0, html_collection, 0); + return 1; /* The proto object */ +} diff --git a/javascript/duktape/node.c b/javascript/duktape/node.c index d632a2414..2d7b1cf29 100644 --- a/javascript/duktape/node.c +++ b/javascript/duktape/node.c @@ -56,10 +56,31 @@ static DUKKY_FUNC(node, appendChild) return 0; } +static DUKKY_GETTER(node, textContent) +{ + DUKKY_GET_METHOD_PRIVATE(node); + dom_exception exc; + dom_string *content; + + exc = dom_node_get_text_content(priv->node, &content); + if (exc != DOM_NO_ERR) { + return 0; + } + + if (content != NULL) { + duk_push_lstring(ctx, dom_string_data(content), dom_string_length(content)); + dom_string_unref(content); + return 1; + } + + return 0; +} + DUKKY_FUNC(node, __proto) { /* Populate node's prototypical functionality */ DUKKY_ADD_METHOD(node, appendChild, 1); + DUKKY_POPULATE_READONLY_PROPERTY(node, textContent); /* Set this prototype's prototype (left-parent)*/ DUKKY_GET_PROTOTYPE(event_target); duk_set_prototype(ctx, 0); diff --git a/javascript/duktape/node_list.c b/javascript/duktape/node_list.c new file mode 100644 index 000000000..c127c2468 --- /dev/null +++ b/javascript/duktape/node_list.c @@ -0,0 +1,84 @@ +/* DO NOT USE, DODGY EXAMPLE FOR VINCE */ + +#include "utils/log.h" + +#include <dom/dom.h> + +#include "javascript/dukky.h" + +DUKKY_FUNC_INIT(node_list, struct dom_nodelist *nodes) +{ + LOG("Initialise %p (priv=%p)", duk_get_heapptr(ctx, 0), priv); + priv->nodes = nodes; + dom_nodelist_ref(nodes); +} + +DUKKY_FUNC_FINI(node_list) +{ + /* do any node_list finalisation here, priv ptr exists */ + LOG("Finalise %p", duk_get_heapptr(ctx, 0)); + dom_nodelist_unref(priv->nodes); +} + +static DUKKY_FUNC(node_list, __constructor) +{ + DUKKY_CREATE_PRIVATE(node_list); + DUKKY_FUNC_T(node_list, __init)(ctx, priv, duk_get_pointer(ctx, 1)); + duk_pop(ctx); + return 1; +} + +static DUKKY_FUNC(node_list, __destructor) +{ + DUKKY_SAFE_GET_PRIVATE(node_list, 0); + DUKKY_FUNC_T(node_list, __fini)(ctx, priv); + free(priv); + return 0; +} + +static DUKKY_GETTER(node_list, length) +{ + DUKKY_GET_METHOD_PRIVATE(node_list); + dom_exception err; + unsigned long len; + + err = dom_nodelist_get_length(priv->nodes, &len); + + if (err != DOM_NO_ERR) return 0; /* coerced to undefined */ + + duk_push_uint(ctx, (duk_uint_t)len); + return 1; +} + +static DUKKY_FUNC(node_list, item) +{ + DUKKY_GET_METHOD_PRIVATE(node_list); + unsigned long i = duk_to_uint(ctx, 0); + dom_exception err; + dom_node *node; + + LOG("Looking up %u in %p", i, priv->nodes); + + err = dom_nodelist_item(priv->nodes, i, &node); + + if (err != DOM_NO_ERR) return 0; /* coerced to undefied */ + + dukky_push_node(ctx, node); + dom_node_unref(node); + + return 1; +} + +/** TODO: ARRAY-LIKE behaviour missing */ + +DUKKY_FUNC(node_list, __proto) +{ + /* Populate node_list's prototypical functionality */ + DUKKY_POPULATE_READONLY_PROPERTY(node_list, length); + DUKKY_ADD_METHOD(node_list, item, 1); + /* Set this prototype's prototype (left-parent)*/ + /* And the initialiser/finalizer */ + DUKKY_SET_DESTRUCTOR(0, node_list); + DUKKY_SET_CONSTRUCTOR(0, node_list, 1); + return 1; /* The proto object */ +} diff --git a/javascript/duktape/private.h b/javascript/duktape/private.h index 6dd3086fd..42c207987 100644 --- a/javascript/duktape/private.h +++ b/javascript/duktape/private.h @@ -9,7 +9,9 @@ struct dom_document; struct dom_html_element; struct dom_node_character_data; struct dom_node_text; +struct dom_node_list; struct dom_node_comment; +struct dom_html_collection; typedef struct { } event_target_private_t; @@ -53,4 +55,12 @@ typedef struct { node_private_t parent; } document_private_t; +typedef struct { + struct dom_html_collection *coll; +} html_collection_private_t; + +typedef struct { + struct dom_nodelist *nodes; +} node_list_private_t; + #endif diff --git a/javascript/duktape/prototypes.h b/javascript/duktape/prototypes.h index aa1813e2f..1f25424ac 100644 --- a/javascript/duktape/prototypes.h +++ b/javascript/duktape/prototypes.h @@ -11,6 +11,8 @@ DUKKY_DECLARE_INTERFACE(document, struct dom_document *); DUKKY_DECLARE_INTERFACE(element, struct dom_element *); DUKKY_DECLARE_INTERFACE(html_element, struct dom_html_element *); DUKKY_DECLARE_INTERFACE(html_unknown_element, struct dom_html_element *); +DUKKY_DECLARE_INTERFACE(html_collection, struct dom_html_collection *); +DUKKY_DECLARE_INTERFACE(node_list, struct dom_nodelist *); #endif diff --git a/test/js/dom-element-firstElementChild.html b/test/js/dom-element-firstElementChild.html index 2d7762d00..e3ff9bb59 100644 --- a/test/js/dom-element-firstElementChild.html +++ b/test/js/dom-element-firstElementChild.html @@ -1,10 +1,10 @@ <html> <head> -<title>DOM firstElementChild reference</title> +<title>DOM firstElementChild reference (title)</title> <link rel="stylesheet" type="text/css" href="tst.css"> </head> <body> -<h1>DOM firstElementChild reference</h1> +<h1>DOM firstElementChild reference (body)</h1> <p><b>head.firstElementChild:</b> <script>document.write(document.head.firstElementChild.textContent);</script></p> <p><b>body.firstElementChild:</b> <script>document.write(document.body.firstElementChild.textContent);</script></p> </body> diff --git a/utils/corestrings.c b/utils/corestrings.c index 1d20362a3..1a016a2ac 100644 --- a/utils/corestrings.c +++ b/utils/corestrings.c @@ -261,6 +261,7 @@ dom_string *corestring_dom_INPUT; dom_string *corestring_dom_SELECT; dom_string *corestring_dom_TEXTAREA; dom_string *corestring_dom_BODY; +dom_string *corestring_dom_HEAD; dom_string *corestring_dom_html_namespace; dom_string *corestring_dom_button; dom_string *corestring_dom_image; @@ -534,6 +535,7 @@ void corestrings_fini(void) CSS_DOM_STRING_UNREF(SELECT); CSS_DOM_STRING_UNREF(TEXTAREA); CSS_DOM_STRING_UNREF(BODY); + CSS_DOM_STRING_UNREF(HEAD); /* DOM namespaces, not really CSS */ CSS_DOM_STRING_UNREF(html_namespace); /* DOM input types, not really CSS */ @@ -854,6 +856,7 @@ nserror corestrings_init(void) CSS_DOM_STRING_INTERN(SELECT); CSS_DOM_STRING_INTERN(TEXTAREA); CSS_DOM_STRING_INTERN(BODY); + CSS_DOM_STRING_INTERN(HEAD); /* DOM input types, not really CSS */ CSS_DOM_STRING_INTERN(button); CSS_DOM_STRING_INTERN(image); diff --git a/utils/corestrings.h b/utils/corestrings.h index 415dece26..e4523542b 100644 --- a/utils/corestrings.h +++ b/utils/corestrings.h @@ -273,6 +273,7 @@ extern struct dom_string *corestring_dom_INPUT; extern struct dom_string *corestring_dom_SELECT; extern struct dom_string *corestring_dom_TEXTAREA; extern struct dom_string *corestring_dom_BODY; +extern struct dom_string *corestring_dom_HEAD; /* DOM namespaces */ extern struct dom_string *corestring_dom_html_namespace; /* DOM input node types */ |