summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2015-07-19 16:50:46 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2015-07-19 16:50:46 +0100
commit72a78ba9f5e2098480b922ab5cb5117ecdb05b36 (patch)
tree5a105118a75d8d896d78a000f336fb3c212edc7a
parent8ec9e559e00f7c2288fa724591208e710690eff5 (diff)
downloadnetsurf-72a78ba9f5e2098480b922ab5cb5117ecdb05b36.tar.gz
netsurf-72a78ba9f5e2098480b922ab5cb5117ecdb05b36.tar.bz2
Getting further
-rw-r--r--javascript/Makefile2
-rw-r--r--javascript/dukky.c2
-rw-r--r--javascript/duktape/document.c90
-rw-r--r--javascript/duktape/element.c172
-rw-r--r--javascript/duktape/html_collection.c48
-rw-r--r--javascript/duktape/node.c21
-rw-r--r--javascript/duktape/node_list.c84
-rw-r--r--javascript/duktape/private.h10
-rw-r--r--javascript/duktape/prototypes.h2
-rw-r--r--test/js/dom-element-firstElementChild.html4
-rw-r--r--utils/corestrings.c3
-rw-r--r--utils/corestrings.h1
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 */