diff --git a/src/ecmascript/libdom/quickjs/Makefile b/src/ecmascript/libdom/quickjs/Makefile index e4815d2f0..feca0665e 100644 --- a/src/ecmascript/libdom/quickjs/Makefile +++ b/src/ecmascript/libdom/quickjs/Makefile @@ -1,6 +1,6 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.config -OBJS = attr.o attributes.o collection.o console.o heartbeat.o history.o keyboard.o localstorage.o mapa.obj navigator.o screen.o unibar.o +OBJS = attr.o attributes.o collection.o console.o heartbeat.o history.o keyboard.o localstorage.o mapa.obj navigator.o nodelist.o screen.o unibar.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/libdom/quickjs/mapa.cpp b/src/ecmascript/libdom/quickjs/mapa.cpp index 38d78c5e2..d1d699e84 100644 --- a/src/ecmascript/libdom/quickjs/mapa.cpp +++ b/src/ecmascript/libdom/quickjs/mapa.cpp @@ -56,6 +56,22 @@ attr_create_new_collections_map_rev(void) return (void *)mapa; } +void * +attr_create_new_nodelist_map(void) +{ + std::map *mapa = new std::map; + + return (void *)mapa; +} + +void * +attr_create_new_nodelist_map_rev(void) +{ + std::map *mapa = new std::map; + + return (void *)mapa; +} + void attr_clear_map(void *m) { diff --git a/src/ecmascript/libdom/quickjs/mapa.h b/src/ecmascript/libdom/quickjs/mapa.h index d5598d3d3..fb2bc1c81 100644 --- a/src/ecmascript/libdom/quickjs/mapa.h +++ b/src/ecmascript/libdom/quickjs/mapa.h @@ -13,6 +13,8 @@ void *attr_create_new_attributes_map(void); void *attr_create_new_attributes_map_rev(void); void *attr_create_new_collections_map(void); void *attr_create_new_collections_map_rev(void); +void *attr_create_new_nodelist_map(void); +void *attr_create_new_nodelist_map_rev(void); void attr_clear_map(void *m); JSValue attr_find_in_map(void *m, void *node); diff --git a/src/ecmascript/libdom/quickjs/meson.build b/src/ecmascript/libdom/quickjs/meson.build index 7cf31322e..0aa5bbe72 100644 --- a/src/ecmascript/libdom/quickjs/meson.build +++ b/src/ecmascript/libdom/quickjs/meson.build @@ -1 +1 @@ -srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'heartbeat.c', 'history.c', 'keyboard.c', 'localstorage.c', 'mapa.cpp', 'navigator.c', 'screen.c', 'unibar.c') +srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'heartbeat.c', 'history.c', 'keyboard.c', 'localstorage.c', 'mapa.cpp', 'navigator.c', 'nodelist.c', 'screen.c', 'unibar.c') diff --git a/src/ecmascript/libdom/quickjs/nodelist.c b/src/ecmascript/libdom/quickjs/nodelist.c new file mode 100644 index 000000000..8e44f0e2b --- /dev/null +++ b/src/ecmascript/libdom/quickjs/nodelist.c @@ -0,0 +1,184 @@ +/* The QuickJS nodeList object implementation. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#ifdef CONFIG_LIBDOM +#include +#include +#endif + +#include "elinks.h" + +#include "ecmascript/ecmascript.h" +#include "ecmascript/libdom/quickjs/mapa.h" +#include "ecmascript/quickjs.h" +#include "ecmascript/quickjs/element.h" +#include "ecmascript/quickjs/nodelist.h" + + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +void *map_nodelist; +void *map_rev_nodelist; + +//static std::map map_nodelist; +//static std::map map_rev_nodelist; + +static void * +js_nodeList_GetOpaque(JSValueConst this_val) +{ + REF_JS(this_val); + + return attr_find_in_map_rev(map_rev_nodelist, this_val); +} + +static void +js_nodeList_SetOpaque(JSValueConst this_val, void *node) +{ + REF_JS(this_val); + + if (!node) { + attr_erase_from_map_rev(map_rev_nodelist, this_val); + } else { + attr_save_in_map_rev(map_rev_nodelist, this_val, node); + } +} + +static JSValue +js_nodeList_item2(JSContext *ctx, JSValueConst this_val, int idx) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + dom_nodelist *nl = (dom_nodelist *)(js_nodeList_GetOpaque(this_val)); + dom_node *element = NULL; + dom_exception err; + JSValue ret; + + if (!nl) { + return JS_UNDEFINED; + } + err = dom_nodelist_item(nl, idx, (void *)&element); + + if (err != DOM_NO_ERR || !element) { + return JS_UNDEFINED; + } + ret = getElement(ctx, element); + dom_node_unref(element); + + return ret; +} + +static JSValue +js_nodeList_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]); + + return js_nodeList_item2(ctx, this_val, index); +} + +static void +js_nodeList_set_items(JSContext *ctx, JSValue this_val, void *node) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + dom_nodelist *nl = (dom_nodelist *)(node); + dom_exception err; + uint32_t length, i; + + if (!nl) { + return; + } + err = dom_nodelist_get_length(nl, &length); + + if (err != DOM_NO_ERR) { + return; + } + + for (i = 0; i < length; i++) { + dom_node *element = NULL; + err = dom_nodelist_item(nl, i, &element); + JSValue obj; + + if (err != DOM_NO_ERR || !element) { + continue; + } + + obj = getElement(ctx, element); + REF_JS(obj); + + JS_SetPropertyUint32(ctx, this_val, i, JS_DupValue(ctx, obj)); + JS_FreeValue(ctx, obj); + dom_node_unref(element); + } +} + +static JSValue +js_nodeList_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, "[nodeList object]"); +} + +static const JSCFunctionListEntry js_nodeList_proto_funcs[] = { +// JS_CGETSET_DEF("length", js_nodeList_get_property_length, nullptr), + JS_CFUNC_DEF("item", 1, js_nodeList_item), + JS_CFUNC_DEF("toString", 0, js_nodeList_toString) +}; + +JSValue +getNodeList(JSContext *ctx, void *node) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + static int initialized; + JSValue second, nodeList_obj; + + if (!initialized) { + map_nodelist = attr_create_new_nodelist_map(); + map_rev_nodelist = attr_create_new_nodelist_map_rev(); + initialized = 1; + } + second = attr_find_in_map(map_nodelist, node); + + if (!JS_IsNull(second)) { + JSValue r = JS_DupValue(ctx, second); + + RETURN_JS(r); + } + nodeList_obj = JS_NewArray(ctx); + JS_SetPropertyFunctionList(ctx, nodeList_obj, js_nodeList_proto_funcs, countof(js_nodeList_proto_funcs)); + + attr_save_in_map(map_nodelist, node, nodeList_obj); + js_nodeList_SetOpaque(nodeList_obj, node); + js_nodeList_set_items(ctx, nodeList_obj, node); + JSValue rr = JS_DupValue(ctx, nodeList_obj); + + RETURN_JS(rr); +} diff --git a/src/ecmascript/quickjs/nodelist.cpp b/src/ecmascript/quickjs/nodelist.cpp index 2cb9aae42..a1c6cee4f 100644 --- a/src/ecmascript/quickjs/nodelist.cpp +++ b/src/ecmascript/quickjs/nodelist.cpp @@ -54,6 +54,8 @@ #include #include +#ifndef CONFIG_LIBDOM + #define countof(x) (sizeof(x) / sizeof((x)[0])) static std::map map_nodelist; @@ -233,3 +235,4 @@ getNodeList(JSContext *ctx, void *node) RETURN_JS(rr); } +#endif diff --git a/src/ecmascript/quickjs/nodelist.h b/src/ecmascript/quickjs/nodelist.h index 5a70fc8af..cba0c166f 100644 --- a/src/ecmascript/quickjs/nodelist.h +++ b/src/ecmascript/quickjs/nodelist.h @@ -3,6 +3,14 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + JSValue getNodeList(JSContext *ctx, void *node); +#ifdef __cplusplus +} +#endif + #endif