diff --git a/src/ecmascript/mujs/Makefile b/src/ecmascript/mujs/Makefile index 11b91004..87f911c3 100644 --- a/src/ecmascript/mujs/Makefile +++ b/src/ecmascript/mujs/Makefile @@ -1,7 +1,7 @@ top_builddir=../../.. include $(top_builddir)/Makefile.config -OBJS = attr.o attributes.o collection.o console.o css.o customevent.o dataset.o document.o domparser.o domrect.o element.o event.o form.o forms.o history.o implementation.o input.o \ +OBJS = attr.o attributes.o collection.o collection2.o console.o css.o customevent.o dataset.o document.o domparser.o domrect.o element.o event.o form.o forms.o history.o implementation.o input.o \ keyboard.o localstorage.o location.o mapa.o message.o navigator.o nodelist.o nodelist2.o screen.o style.o tokenlist.o unibar.o url.o window.o xhr.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/mujs/collection.h b/src/ecmascript/mujs/collection.h index 2ff97f0f..8eea1876 100644 --- a/src/ecmascript/mujs/collection.h +++ b/src/ecmascript/mujs/collection.h @@ -8,6 +8,7 @@ extern "C" { #endif void mjs_push_collection(js_State *J, void *node); +void mjs_push_collection2(js_State *J, void *node); #ifdef __cplusplus } diff --git a/src/ecmascript/mujs/collection2.c b/src/ecmascript/mujs/collection2.c new file mode 100644 index 00000000..167609c5 --- /dev/null +++ b/src/ecmascript/mujs/collection2.c @@ -0,0 +1,262 @@ +/* The MuJS html collection2 object implementation. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifdef CONFIG_LIBDOM +#include +#include +#endif + +#include "elinks.h" + +#include "document/libdom/corestrings.h" +#include "ecmascript/ecmascript-c.h" +#include "ecmascript/ecmascript.h" +#include "ecmascript/mujs/mapa.h" +#include "ecmascript/mujs.h" +#include "ecmascript/mujs/collection.h" +#include "ecmascript/mujs/element.h" + +static void +mjs_htmlCollection2_get_property_length(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + struct el_dom_html_collection *ns = (struct el_dom_html_collection *)(js_touserdata(J, 0, "collection2")); + uint32_t size; + + if (!ns) { + js_pushnumber(J, 0); + return; + } + if (dom_html_collection_get_length(ns, &size) != DOM_NO_ERR) { + js_pushnumber(J, 0); + return; + } + js_pushnumber(J, size); +} + +static void +mjs_push_htmlCollection2_item2(js_State *J, int idx) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + struct el_dom_html_collection *ns = (struct el_dom_html_collection *)(js_touserdata(J, 0, "collection2")); + dom_node *node; + dom_exception err; + + if (!ns) { + js_pushundefined(J); + return; + } + err = dom_html_collection_item(ns, idx, &node); + + if (err != DOM_NO_ERR) { + js_pushundefined(J); + return; + } + mjs_push_element(J, node); + dom_node_unref(node); +} + +static void +mjs_htmlCollection2_item(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + int index = js_toint32(J, 1); + + mjs_push_htmlCollection2_item2(J, index); +} + +static void +mjs_push_htmlCollection2_namedItem2(js_State *J, const char *str) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + struct el_dom_html_collection *ns = (struct el_dom_html_collection *)(js_touserdata(J, 0, "collection2")); + dom_exception err; + dom_string *name; + uint32_t size, i; + + if (!ns) { + js_pushundefined(J); + return; + } + + if (dom_html_collection_get_length(ns, &size) != DOM_NO_ERR) { + js_pushundefined(J); + return; + } + + err = dom_string_create((const uint8_t*)str, strlen(str), &name); + + if (err != DOM_NO_ERR) { + js_pushundefined(J); + return; + } + + for (i = 0; i < size; i++) { + dom_node *element = NULL; + dom_string *val = NULL; + + err = dom_html_collection_item(ns, i, &element); + + if (err != DOM_NO_ERR || !element) { + continue; + } + + err = dom_element_get_attribute(element, corestring_dom_id, &val); + + if (err == DOM_NO_ERR && val) { + if (dom_string_caseless_isequal(name, val)) { + mjs_push_element(J, element); + dom_string_unref(val); + dom_string_unref(name); + dom_node_unref(element); + + return; + } + dom_string_unref(val); + } + + err = dom_element_get_attribute(element, corestring_dom_name, &val); + + if (err == DOM_NO_ERR && val) { + if (dom_string_caseless_isequal(name, val)) { + mjs_push_element(J, element); + dom_string_unref(val); + dom_string_unref(name); + dom_node_unref(element); + + return; + } + dom_string_unref(val); + } + dom_node_unref(element); + } + dom_string_unref(name); + js_pushundefined(J); +} + +static void +mjs_htmlCollection2_namedItem(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + const char *str = js_tostring(J, 1); + + mjs_push_htmlCollection2_namedItem2(J, str); +} + +static void +mjs_htmlCollection2_set_items(js_State *J, void *node) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + int counter = 0; + uint32_t size, i; + struct el_dom_html_collection *ns = (struct el_dom_html_collection *)node; + dom_exception err; + + if (!ns) { + return; + } + dom_html_collection_ref(ns); + + if (dom_html_collection_get_length(ns, &size) != DOM_NO_ERR) { + dom_html_collection_unref(ns); + return; + } + + for (i = 0; i < size; i++) { + dom_node *element = NULL; + dom_string *name = NULL; + err = dom_html_collection_item(ns, i, &element); + + if (err != DOM_NO_ERR || !element) { + continue; + } + mjs_push_element(J, element); + dom_node_unref(element); + js_setindex(J, -2, counter); + err = dom_element_get_attribute(element, corestring_dom_id, &name); + + if (err != DOM_NO_ERR || !name) { + err = dom_element_get_attribute(element, corestring_dom_name, &name); + } + + if (err == DOM_NO_ERR && name) { + if (!dom_string_caseless_lwc_isequal(name, corestring_lwc_item) && !dom_string_caseless_lwc_isequal(name, corestring_lwc_nameditem)) { + if (js_try(J)) { + js_pop(J, 1); + goto next; + } + mjs_push_element(J, element); + dom_node_unref(element); + js_setproperty(J, -2, dom_string_data(name)); + js_endtry(J); + } + } +next: + counter++; + if (name) { + dom_string_unref(name); + } + } + dom_html_collection_unref(ns); +} + +static void +mjs_htmlCollection2_toString(js_State *J) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + js_pushstring(J, "[htmlCollection2 object]"); +} + +static void +mjs_htmlCollection2_finalizer(js_State *J, void *node) +{ + struct el_dom_html_collection *ns = (struct el_dom_html_collection *)node; + + if (ns) { + //attr_erase_from_map_str(map_collections, ns); + if (ns->refcnt > 0) { + free_el_dom_collection(ns->ctx); + ns->ctx = NULL; + dom_html_collection_unref(ns); + } + } +} + +void +mjs_push_collection2(js_State *J, void *node) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + js_newarray(J); + { + js_newuserdata(J, "collection2", node, mjs_htmlCollection2_finalizer); + addmethod(J, "item", mjs_htmlCollection2_item, 1); + addmethod(J, "namedItem", mjs_htmlCollection2_namedItem, 1); + addmethod(J, "toString", mjs_htmlCollection2_toString, 0); + addproperty(J, "length", mjs_htmlCollection2_get_property_length, NULL); + mjs_htmlCollection2_set_items(J, node); + } + //attr_save_in_map(map_collections, node, node); +} diff --git a/src/ecmascript/mujs/document.c b/src/ecmascript/mujs/document.c index d9842fb4..e2a61c10 100644 --- a/src/ecmascript/mujs/document.c +++ b/src/ecmascript/mujs/document.c @@ -1236,13 +1236,13 @@ mjs_document_getElementsByClassName(js_State *J) return; } const char *classes = js_tostring(J, 1); - dom_html_collection *col = get_elements_by_class_name(doc, (dom_node *)doc, classes); + struct el_dom_html_collection *col = get_elements_by_class_name(doc, (dom_node *)doc, classes); if (!col) { js_pushnull(J); return; } - mjs_push_collection(J, col); + mjs_push_collection2(J, col); } #if 0 diff --git a/src/ecmascript/mujs/meson.build b/src/ecmascript/mujs/meson.build index 627a88dc..681367bf 100644 --- a/src/ecmascript/mujs/meson.build +++ b/src/ecmascript/mujs/meson.build @@ -1,3 +1,3 @@ -srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'css.c', 'customevent.c', 'dataset.c', 'document.c', 'domparser.c', 'domrect.c', +srcs += files('attr.c', 'attributes.c', 'collection.c', 'collection2.c', 'console.c', 'css.c', 'customevent.c', 'dataset.c', 'document.c', 'domparser.c', 'domrect.c', 'element.c', 'event.c', 'form.c', 'forms.c', 'history.c', 'implementation.c', 'input.c', 'keyboard.c', 'localstorage.c', 'location.c', 'mapa.c', 'message.c', 'navigator.c', 'nodelist.c', 'nodelist2.c', 'screen.c', 'style.c', 'tokenlist.c', 'unibar.c', 'url.c', 'window.c', 'xhr.c')