summaryrefslogtreecommitdiff
path: root/content/handlers/javascript/duktape/Element.bnd
diff options
context:
space:
mode:
Diffstat (limited to 'content/handlers/javascript/duktape/Element.bnd')
-rw-r--r--content/handlers/javascript/duktape/Element.bnd188
1 files changed, 188 insertions, 0 deletions
diff --git a/content/handlers/javascript/duktape/Element.bnd b/content/handlers/javascript/duktape/Element.bnd
index 33fc0863e..ff0686fd9 100644
--- a/content/handlers/javascript/duktape/Element.bnd
+++ b/content/handlers/javascript/duktape/Element.bnd
@@ -11,6 +11,7 @@
class Element {
prologue %{
#include <utils/corestrings.h>
+#include <dom/bindings/hubbub/parser.h>
%};
};
@@ -283,6 +284,9 @@ method Element::getAttribute()
const char *s = duk_safe_to_lstring(ctx, 0, &slen);
exc = dom_string_create((const uint8_t *)s, slen, &attr_name);
duk_pop(ctx);
+ if (exc != DOM_NO_ERR) {
+ return 0;
+ }
exc = dom_element_get_attribute(priv->parent.node,
attr_name, &attr_value);
@@ -336,6 +340,9 @@ method Element::hasAttribute()
const char *s = duk_safe_to_lstring(ctx, 0, &slen);
exc = dom_string_create((const uint8_t *)s, slen, &attr_name);
duk_pop(ctx);
+ if (exc != DOM_NO_ERR) {
+ return 0;
+ }
exc = dom_element_has_attribute(priv->parent.node,
attr_name, &res);
@@ -385,3 +392,184 @@ setter Element::className ()
return 0;
%}
+getter Element::classList ()
+%{
+ dom_exception exc;
+ dom_tokenlist *tokens;
+
+ duk_set_top(ctx, 0);
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, 0, MAGIC(classList));
+
+ if (duk_is_undefined(ctx, -1)) {
+ duk_pop(ctx);
+ exc = dom_tokenlist_create((dom_element *)priv->parent.node, corestring_dom_class, &tokens);
+ if (exc != DOM_NO_ERR) return 0; /* Coerced to undefined */
+
+ /* Create a settable tokenlist - While the IDL says this isn't settable, all browsers
+ * seem to make it settable, so we'll permit it too
+ */
+ duk_push_pointer(ctx, tokens);
+ if (dukky_create_object(ctx, PROTO_NAME(DOMSETTABLETOKENLIST), 1) != DUK_EXEC_SUCCESS) {
+ dom_tokenlist_unref(tokens);
+ NSLOG(dukky, DEBUG, "Unable to create DOMSettableTokenList object");
+ return 0; /* Coerced to undefined */
+ }
+ dom_tokenlist_unref(tokens);
+ duk_dup(ctx, -1);
+ duk_put_prop_string(ctx, 0, MAGIC(classList));
+ }
+
+ return 1;
+%}
+
+getter Element::innerHTML()
+%{
+ duk_push_lstring(ctx, "", 0);
+ return 1;
+%}
+
+setter Element::innerHTML()
+%{
+ duk_size_t size;
+ const char *s = duk_safe_to_lstring(ctx, 0, &size);
+ dom_hubbub_parser_params parse_params;
+ dom_hubbub_error error;
+ dom_hubbub_parser *parser = NULL;
+ struct dom_document *doc = NULL;
+ struct dom_document_fragment *fragment = NULL;
+ dom_exception exc;
+ struct dom_node *child = NULL, *html = NULL, *body = NULL;
+ struct dom_nodelist *bodies = NULL;
+
+ exc = dom_node_get_owner_document(priv->parent.node, &doc);
+ if (exc != DOM_NO_ERR) goto out;
+
+ parse_params.enc = "UTF-8";
+ parse_params.fix_enc = true;
+ parse_params.enable_script = false;
+ parse_params.msg = NULL;
+ parse_params.script = NULL;
+ parse_params.ctx = NULL;
+ parse_params.daf = NULL;
+
+ error = dom_hubbub_fragment_parser_create(&parse_params,
+ doc,
+ &parser,
+ &fragment);
+ if (error != DOM_HUBBUB_OK) {
+ NSLOG(netsurf, ERROR, "Unable to create fragment parser!");
+ goto out;
+ }
+
+ error = dom_hubbub_parser_parse_chunk(parser, (const uint8_t*)s, size);
+ if (error != DOM_HUBBUB_OK) {
+ NSLOG(netsurf, ERROR, "Unable to parse HTML chunk");
+ goto out;
+ }
+ error = dom_hubbub_parser_completed(parser);
+ if (error != DOM_HUBBUB_OK) {
+ NSLOG(netsurf, ERROR, "Unable to complete parser");
+ goto out;
+ }
+
+ /* Parse is finished, transfer contents of fragment into node */
+
+ /* 1. empty this node */
+ exc = dom_node_get_first_child(priv->parent.node, &child);
+ if (exc != DOM_NO_ERR) goto out;
+ while (child != NULL) {
+ struct dom_node *cref;
+ exc = dom_node_remove_child(priv->parent.node, child, &cref);
+ if (exc != DOM_NO_ERR) goto out;
+ dom_node_unref(child);
+ child = NULL;
+ dom_node_unref(cref);
+ exc = dom_node_get_first_child(priv->parent.node, &child);
+ if (exc != DOM_NO_ERR) goto out;
+ }
+
+ /* 2. the first child in the fragment will be an HTML element
+ * because that's how hubbub works, walk through that to the body
+ * element hubbub will have created, we want to migrate that element's
+ * children into ourself.
+ */
+ exc = dom_node_get_first_child(fragment, &html);
+ if (exc != DOM_NO_ERR) goto out;
+
+ /* We can then ask that HTML element to give us its body */
+ exc = dom_element_get_elements_by_tag_name(html, corestring_dom_BODY, &bodies);
+ if (exc != DOM_NO_ERR) goto out;
+
+ /* And now we can get the body which will be the zeroth body */
+ exc = dom_nodelist_item(bodies, 0, &body);
+ if (exc != DOM_NO_ERR) goto out;
+
+ /* 3. Migrate the children */
+ exc = dom_node_get_first_child(body, &child);
+ if (exc != DOM_NO_ERR) goto out;
+ while (child != NULL) {
+ struct dom_node *cref;
+ exc = dom_node_remove_child(body, child, &cref);
+ if (exc != DOM_NO_ERR) goto out;
+ dom_node_unref(cref);
+ exc = dom_node_append_child(priv->parent.node, child, &cref);
+ if (exc != DOM_NO_ERR) goto out;
+ dom_node_unref(cref);
+ dom_node_unref(child);
+ child = NULL;
+ exc = dom_node_get_first_child(body, &child);
+ if (exc != DOM_NO_ERR) goto out;
+ }
+out:
+ if (parser != NULL) {
+ dom_hubbub_parser_destroy(parser);
+ }
+ if (doc != NULL) {
+ dom_node_unref(doc);
+ }
+ if (fragment != NULL) {
+ dom_node_unref(fragment);
+ }
+ if (child != NULL) {
+ dom_node_unref(child);
+ }
+ if (html != NULL) {
+ dom_node_unref(html);
+ }
+ if (bodies != NULL) {
+ dom_nodelist_unref(bodies);
+ }
+ if (body != NULL) {
+ dom_node_unref(body);
+ }
+ return 0;
+%}
+
+getter Element::attributes()
+%{
+ dom_exception exc;
+ dom_namednodemap *nmap = NULL;
+ duk_set_top(ctx, 0);
+ duk_push_this(ctx);
+ duk_get_prop_string(ctx, 0, MAGIC(attributes));
+ if (duk_is_undefined(ctx, -1)) {
+ duk_pop(ctx);
+ exc = dom_node_get_attributes(priv->parent.node, &nmap);
+ if (exc != DOM_NO_ERR) return 0;
+ dukky_push_generics(ctx, "makeNodeMapProxy");
+ duk_push_pointer(ctx, nmap);
+ if (dukky_create_object(ctx, PROTO_NAME(NAMEDNODEMAP), 1) != DUK_EXEC_SUCCESS) {
+ dom_namednodemap_unref(nmap);
+ return 0;
+ }
+ dom_namednodemap_unref(nmap);
+ if (dukky_pcall(ctx, 1, false) != 0) {
+ NSLOG(dukky, DEBUG, "Unable to construct nodelist?");
+ return 0; /* coerced to undefined */
+ }
+ duk_dup(ctx, -1);
+ duk_put_prop_string(ctx, 0, MAGIC(attributes));
+ }
+ return 1;
+%}