diff --git a/src/ecmascript/quickjs/Makefile b/src/ecmascript/quickjs/Makefile index c6e9c95c..121da800 100644 --- a/src/ecmascript/quickjs/Makefile +++ b/src/ecmascript/quickjs/Makefile @@ -2,6 +2,6 @@ top_builddir=../../.. include $(top_builddir)/Makefile.config OBJS = attr.o attributes.o collection.o console.o css.o customevent.o document.o domrect.o element.o event.o form.o forms.o heartbeat.o history.o implementation.o input.o \ - keyboard.o localstorage.o location.o mapa.o message.o navigator.o nodelist.o screen.o style.o unibar.o url.o urlsearchparams.o window.o xhr.o + keyboard.o localstorage.o location.o mapa.o message.o navigator.o nodelist.o nodelist2.o screen.o style.o unibar.o url.o urlsearchparams.o window.o xhr.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/quickjs/document.c b/src/ecmascript/quickjs/document.c index 7a3df4eb..6816f396 100644 --- a/src/ecmascript/quickjs/document.c +++ b/src/ecmascript/quickjs/document.c @@ -34,6 +34,7 @@ #include "ecmascript/quickjs/document.h" #include "ecmascript/quickjs/element.h" #include "ecmascript/quickjs/nodelist.h" +#include "ecmascript/quickjs/nodelist2.h" #include "ecmascript/quickjs/window.h" #include "session/session.h" #include "viewer/text/vs.h" @@ -1700,21 +1701,22 @@ js_document_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JS JS_FreeCString(ctx, selector); return JS_NULL; } - walk_tree_query_append((dom_node *)element, doc_root, selector, 0); - dom_node_unref(doc_root); - JS_FreeCString(ctx, selector); + LIST_OF(struct selector_node) *result_list = (LIST_OF(struct selector_node) *)mem_calloc(1, sizeof(*result_list)); - dom_nodelist *nodes = NULL; - exc = dom_node_get_child_nodes(element, &nodes); - dom_node_unref(element); - - if (exc != DOM_NO_ERR || !nodes) { + if (!result_list) { dom_node_unref(doc); + dom_node_unref(doc_root); + JS_FreeCString(ctx, selector); return JS_NULL; } + init_list(*result_list); + + walk_tree_query_append((dom_node *)element, doc_root, selector, 0, result_list); + dom_node_unref(doc_root); + JS_FreeCString(ctx, selector); dom_node_unref(doc); - return getNodeList(ctx, nodes); + return getNodeList2(ctx, result_list); } #if 0 diff --git a/src/ecmascript/quickjs/element.c b/src/ecmascript/quickjs/element.c index 284cdcad..e97b5ea2 100644 --- a/src/ecmascript/quickjs/element.c +++ b/src/ecmascript/quickjs/element.c @@ -35,6 +35,7 @@ #include "ecmascript/quickjs/heartbeat.h" #include "ecmascript/quickjs/keyboard.h" #include "ecmascript/quickjs/nodelist.h" +#include "ecmascript/quickjs/nodelist2.h" #include "ecmascript/quickjs/style.h" #include "ecmascript/quickjs/window.h" #include "session/session.h" @@ -3406,20 +3407,19 @@ js_element_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JSV dom_node_unref(el); return JS_NULL; } - walk_tree_query_append((dom_node *)element, el, selector, 0); - JS_FreeCString(ctx, selector); + LIST_OF(struct selector_node) *result_list = (LIST_OF(struct selector_node) *)mem_calloc(1, sizeof(*result_list)); - dom_nodelist *nodes = NULL; - exc = dom_node_get_child_nodes(element, &nodes); - dom_node_unref(element); - - if (exc != DOM_NO_ERR || !nodes) { + if (!result_list) { + JS_FreeCString(ctx, selector); dom_node_unref(el); return JS_NULL; } + init_list(*result_list); + walk_tree_query_append((dom_node *)element, el, selector, 0, result_list); + JS_FreeCString(ctx, selector); dom_node_unref(el); - return getNodeList(ctx, nodes); + return getNodeList2(ctx, result_list); } static JSValue diff --git a/src/ecmascript/quickjs/meson.build b/src/ecmascript/quickjs/meson.build index 17af9913..7738d4ab 100644 --- a/src/ecmascript/quickjs/meson.build +++ b/src/ecmascript/quickjs/meson.build @@ -1,3 +1,3 @@ srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'css.c', 'customevent.c', 'document.c', 'domrect.c', 'element.c', 'event.c', 'form.c', 'forms.c', 'heartbeat.c', 'history.c', 'implementation.c', 'input.c', 'keyboard.c', 'localstorage.c', 'location.c', -'mapa.c', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'style.c', 'unibar.c', 'url.c', 'urlsearchparams.c', 'window.c', 'xhr.c') +'mapa.c', 'message.c', 'navigator.c', 'nodelist.c', 'nodelist2.c', 'screen.c', 'style.c', 'unibar.c', 'url.c', 'urlsearchparams.c', 'window.c', 'xhr.c') diff --git a/src/ecmascript/quickjs/nodelist2.c b/src/ecmascript/quickjs/nodelist2.c new file mode 100644 index 00000000..16ac83e7 --- /dev/null +++ b/src/ecmascript/quickjs/nodelist2.c @@ -0,0 +1,180 @@ +/* The Quickjs nodeList2 object implementation. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "elinks.h" + +#include "ecmascript/libdom/dom.h" + +#include "bfu/dialog.h" +#include "cache/cache.h" +#include "cookies/cookies.h" +#include "dialogs/menu.h" +#include "dialogs/status.h" +#include "document/html/frames.h" +#include "document/document.h" +#include "document/forms.h" +#include "document/view.h" +#include "ecmascript/ecmascript.h" +#include "ecmascript/ecmascript-c.h" +#include "ecmascript/quickjs/mapa.h" +#include "ecmascript/quickjs.h" +#include "ecmascript/quickjs/element.h" +#include "ecmascript/quickjs/nodelist2.h" +#include "ecmascript/quickjs/window.h" +#include "intl/libintl.h" +#include "main/select.h" +#include "osdep/newwin.h" +#include "osdep/sysname.h" +#include "protocol/http/http.h" +#include "protocol/uri.h" +#include "session/history.h" +#include "session/location.h" +#include "session/session.h" +#include "session/task.h" +#include "terminal/tab.h" +#include "terminal/terminal.h" +#include "util/conv.h" +#include "util/lists.h" +#include "util/memory.h" +#include "util/string.h" +#include "viewer/text/draw.h" +#include "viewer/text/form.h" +#include "viewer/text/link.h" +#include "viewer/text/vs.h" + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +static JSClassID js_nodelist2_class_id; + +void *map_nodelist2; +void *map_rev_nodelist2; + +static void * +js_nodeList2_GetOpaque(JSValueConst this_val) +{ + REF_JS(this_val); + + return attr_find_in_map_rev(map_rev_nodelist2, this_val); +} + +static void +js_nodeList2_SetOpaque(JSValueConst this_val, void *node) +{ + REF_JS(this_val); + + if (!node) { + attr_erase_from_map_rev(map_rev_nodelist2, this_val); + } else { + attr_save_in_map_rev(map_rev_nodelist2, this_val, node); + } +} + +static JSValue +js_nodeList2_get_property_length(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + LIST_OF(struct selector_node) *sni = (LIST_OF(struct selector_node) *)(js_nodeList2_GetOpaque(this_val)); + uint32_t size = list_size(sni); + + return JS_NewInt32(ctx, size); +} + +static JSValue +js_nodeList2_item(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + if (argc != 1) { + return JS_UNDEFINED; + } + int index; + JS_ToInt32(ctx, &index, argv[0]); + LIST_OF(struct selector_node) *sni = (LIST_OF(struct selector_node) *)(js_nodeList2_GetOpaque(this_val)); + int counter = 0; + struct selector_node *sn = NULL; + + foreach (sn, *sni) { + if (counter == index) { + break; + } + counter++; + } + + if (!sn || !sn->node) { + return JS_NULL; + } + JSValue ret = getElement(ctx, sn->node); + + return ret; +} + +static JSValue +js_nodeList2_toString(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + return JS_NewString(ctx, "[nodeList2 object]"); +} + +static const JSCFunctionListEntry js_nodeList2_proto_funcs[] = { +// JS_CGETSET_DEF("length", js_nodeList_get_property_length, NULL), + JS_CFUNC_DEF("item", 1, js_nodeList2_item), + JS_CFUNC_DEF("toString", 0, js_nodeList2_toString) +}; + +static JSClassDef js_nodelist2_class = { + "nodelist2", +}; + +JSValue +getNodeList2(JSContext *ctx, void *nodes) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JSValue proto; + + /* nodelist class */ + JS_NewClassID(&js_nodelist2_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_nodelist2_class_id, &js_nodelist2_class); + proto = JS_NewArray(ctx); + REF_JS(proto); + + JS_SetPropertyFunctionList(ctx, proto, js_nodeList2_proto_funcs, countof(js_nodeList2_proto_funcs)); + JS_SetClassProto(ctx, js_nodelist2_class_id, proto); + + attr_save_in_map(map_nodelist2, nodes, proto); + js_nodeList2_SetOpaque(proto, nodes); + + LIST_OF(struct selector_node) *sni = (LIST_OF(struct selector_node) *)nodes; + + struct selector_node *sn = NULL; + int i = 0; + + foreach (sn, *sni) { + JSValue obj = getElement(ctx, sn->node); + REF_JS(obj); + + JS_SetPropertyUint32(ctx, proto, i, JS_DupValue(ctx, obj)); + JS_FreeValue(ctx, obj); + i++; + } + JSValue rr = JS_DupValue(ctx, proto); + RETURN_JS(rr); +} diff --git a/src/ecmascript/quickjs/nodelist2.h b/src/ecmascript/quickjs/nodelist2.h new file mode 100644 index 00000000..7d618e9b --- /dev/null +++ b/src/ecmascript/quickjs/nodelist2.h @@ -0,0 +1,16 @@ +#ifndef EL__ECMASCRIPT_QUICKJS_NODELIST2_H +#define EL__ECMASCRIPT_QUICKJS_NODELIST2_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +JSValue getNodeList2(JSContext *ctx, void *nodes); + +#ifdef __cplusplus +} +#endif + +#endif