diff options
Diffstat (limited to 'content/handlers/javascript/duktape/Element.bnd')
-rw-r--r-- | content/handlers/javascript/duktape/Element.bnd | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/content/handlers/javascript/duktape/Element.bnd b/content/handlers/javascript/duktape/Element.bnd index f7e33545f..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> %}; }; @@ -204,10 +205,18 @@ method Element::getElementsByTagName () tagname, &nlist); dom_string_unref(tagname); if (exc != DOM_NO_ERR) return 0; + + dukky_push_generics(ctx, "makeListProxy"); + duk_push_pointer(ctx, nlist); dukky_create_object(ctx, PROTO_NAME(NODELIST), 1); dom_nodelist_unref(nlist); + if (dukky_pcall(ctx, 1, false) != 0) { + NSLOG(dukky, DEBUG, "Unable to construct nodelist?"); + return 0; /* coerced to undefined */ + } + return 1; %} @@ -275,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); @@ -328,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); @@ -377,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; +%} |