diff --git a/src/ecmascript/quickjs/Makefile b/src/ecmascript/quickjs/Makefile index 121da8005..09380ed61 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 nodelist2.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 tokenlist.o unibar.o url.o urlsearchparams.o window.o xhr.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/quickjs/element.c b/src/ecmascript/quickjs/element.c index 528fc8a16..98c3cc7db 100644 --- a/src/ecmascript/quickjs/element.c +++ b/src/ecmascript/quickjs/element.c @@ -37,6 +37,7 @@ #include "ecmascript/quickjs/nodelist.h" #include "ecmascript/quickjs/nodelist2.h" #include "ecmascript/quickjs/style.h" +#include "ecmascript/quickjs/tokenlist.h" #include "ecmascript/quickjs/window.h" #include "session/session.h" #include "terminal/event.h" @@ -339,6 +340,32 @@ js_element_get_property_childNodes(JSContext *ctx, JSValueConst this_val) RETURN_JS(rr); } +static JSValue +js_element_get_property_classList(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + JSValue r; + + dom_element *el = (dom_element *)(js_getopaque(this_val, js_element_class_id)); + + if (!el) { + return JS_NULL; + } + dom_node_ref(el); + dom_tokenlist *tl = NULL; + dom_exception exc = dom_tokenlist_create(el, corestring_dom_class, &tl); + dom_node_unref(el); + + if (exc != DOM_NO_ERR || !tl) { + return JS_NULL; + } + + return getTokenlist(ctx, tl); +} + static JSValue js_element_get_property_className(JSContext *ctx, JSValueConst this_val) { @@ -3589,6 +3616,7 @@ static const JSCFunctionListEntry js_element_proto_funcs[] = { JS_CGETSET_DEF("children", js_element_get_property_children, NULL), JS_CGETSET_DEF("childElementCount", js_element_get_property_childElementCount, NULL), JS_CGETSET_DEF("childNodes", js_element_get_property_childNodes, NULL), + JS_CGETSET_DEF("classList", js_element_get_property_classList, NULL), JS_CGETSET_DEF("className", js_element_get_property_className, js_element_set_property_className), // JS_CGETSET_DEF("clientHeight", js_element_get_property_clientHeight, NULL), // JS_CGETSET_DEF("clientLeft", js_element_get_property_clientLeft, NULL), diff --git a/src/ecmascript/quickjs/meson.build b/src/ecmascript/quickjs/meson.build index 7738d4ab9..169b259a5 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', 'nodelist2.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', 'tokenlist.c', 'unibar.c', 'url.c', 'urlsearchparams.c', 'window.c', 'xhr.c') diff --git a/src/ecmascript/quickjs/tokenlist.c b/src/ecmascript/quickjs/tokenlist.c new file mode 100644 index 000000000..dd25c08ec --- /dev/null +++ b/src/ecmascript/quickjs/tokenlist.c @@ -0,0 +1,243 @@ +/* The QuickJS dom tokenlist 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.h" +#include "ecmascript/quickjs/mapa.h" +#include "ecmascript/quickjs.h" +#include "ecmascript/quickjs/element.h" +#include "ecmascript/quickjs/tokenlist.h" + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +JSClassID js_tokenlist_class_id; + +static +void js_tokenlist_finalizer(JSRuntime *rt, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(val); + dom_tokenlist *tl = (dom_tokenlist *)(JS_GetOpaque(val, js_tokenlist_class_id)); + + if (tl) { + dom_tokenlist_unref(tl); + } +} + +static JSValue +js_tokenlist_add(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); + dom_tokenlist *tl = (dom_tokenlist *)(JS_GetOpaque(this_val, js_tokenlist_class_id)); + + if (!tl || argc < 1) { + return JS_UNDEFINED; + } + size_t size; + const char *klass = JS_ToCStringLen(ctx, &size, argv[0]); + + if (!klass) { + return JS_UNDEFINED; + } + dom_string *kl = NULL; + dom_exception exc = dom_string_create(klass, size, &kl); + JS_FreeCString(ctx, klass); + + if (exc != DOM_NO_ERR || !kl) { + return JS_UNDEFINED; + } + exc = dom_tokenlist_add(tl, kl); + dom_string_unref(kl); + + if (exc == DOM_NO_ERR) { + interpreter->changed = true; + } + + return JS_UNDEFINED; +} + +static JSValue +js_tokenlist_contains(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + dom_tokenlist *tl = (dom_tokenlist *)(JS_GetOpaque(this_val, js_tokenlist_class_id)); + + if (!tl || argc < 1) { + return JS_UNDEFINED; + } + size_t size; + const char *klass = JS_ToCStringLen(ctx, &size, argv[0]); + + if (!klass) { + return JS_UNDEFINED; + } + dom_string *kl = NULL; + dom_exception exc = dom_string_create(klass, size, &kl); + JS_FreeCString(ctx, klass); + + if (exc != DOM_NO_ERR || !kl) { + return JS_UNDEFINED; + } + bool res = false; + exc = dom_tokenlist_contains(tl, kl, &res); + dom_string_unref(kl); + + if (exc == DOM_NO_ERR) { + return JS_NewBool(ctx, res); + } + + return JS_UNDEFINED; +} + +static JSValue +js_tokenlist_remove(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); + dom_tokenlist *tl = (dom_tokenlist *)(JS_GetOpaque(this_val, js_tokenlist_class_id)); + + if (!tl || argc < 1) { + return JS_UNDEFINED; + } + size_t size; + const char *klass = JS_ToCStringLen(ctx, &size, argv[0]); + + if (!klass) { + return JS_UNDEFINED; + } + + dom_string *kl = NULL; + dom_exception exc = dom_string_create(klass, size, &kl); + JS_FreeCString(ctx, klass); + + if (exc != DOM_NO_ERR || !kl) { + return JS_UNDEFINED; + } + exc = dom_tokenlist_remove(tl, kl); + dom_string_unref(kl); + + if (exc == DOM_NO_ERR) { + interpreter->changed = true; + } + + return JS_UNDEFINED; +} + +static JSValue +js_tokenlist_toggle(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); + dom_tokenlist *tl = (dom_tokenlist *)(JS_GetOpaque(this_val, js_tokenlist_class_id)); + + if (!tl || argc < 1) { + return JS_UNDEFINED; + } + size_t size; + const char *klass = JS_ToCStringLen(ctx, &size, argv[0]); + + if (!klass) { + return JS_UNDEFINED; + } + dom_string *kl = NULL; + dom_exception exc = dom_string_create(klass, size, &kl); + JS_FreeCString(ctx, klass); + + if (exc != DOM_NO_ERR || !kl) { + return JS_UNDEFINED; + } + bool res = false; + exc = dom_tokenlist_contains(tl, kl, &res); + + if (exc == DOM_NO_ERR) { + if (res) { + exc = dom_tokenlist_remove(tl, kl); + } else { + exc = dom_tokenlist_add(tl, kl); + } + if (exc == DOM_NO_ERR) { + interpreter->changed = true; + } + } + dom_string_unref(kl); + + return JS_UNDEFINED; +} + +static JSValue +js_tokenlist_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, "[tokenlist object]"); +} + +static const JSCFunctionListEntry js_tokenlist_proto_funcs[] = { + JS_CFUNC_DEF("add", 1, js_tokenlist_add), + JS_CFUNC_DEF("contains", 1, js_tokenlist_contains), + JS_CFUNC_DEF("remove", 1, js_tokenlist_remove), + JS_CFUNC_DEF("toggle", 1, js_tokenlist_toggle), + JS_CFUNC_DEF("toString", 0, js_tokenlist_toString) +}; + +static JSClassDef js_tokenlist_class = { + "tokenlist", + .finalizer = js_tokenlist_finalizer +}; + +JSValue +getTokenlist(JSContext *ctx, void *node) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + /* nodelist class */ + static int initialized; + + if (!initialized) { + JS_NewClassID(&js_tokenlist_class_id); + //JS_NewClass(JS_GetRuntime(ctx), js_tokenlist_class_id, &js_tokenlist_class); + initialized = 1; + } + JSValue proto = JS_NewObjectClass(ctx, js_tokenlist_class_id); + REF_JS(proto); + + JS_SetPropertyFunctionList(ctx, proto, js_tokenlist_proto_funcs, countof(js_tokenlist_proto_funcs)); + JS_SetClassProto(ctx, js_tokenlist_class_id, proto); + JS_SetOpaque(proto, node); + JSValue rr = JS_DupValue(ctx, proto); + + RETURN_JS(rr); +} diff --git a/src/ecmascript/quickjs/tokenlist.h b/src/ecmascript/quickjs/tokenlist.h new file mode 100644 index 000000000..40952a0b1 --- /dev/null +++ b/src/ecmascript/quickjs/tokenlist.h @@ -0,0 +1,16 @@ +#ifndef EL__ECMASCRIPT_QUICKJS_TOKENLIST_H +#define EL__ECMASCRIPT_QUICKJS_TOKENLIST_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +JSValue getTokenlist(JSContext *ctx, void *node); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/ecmascript/spidermonkey/tokenlist.cpp b/src/ecmascript/spidermonkey/tokenlist.cpp index 8bb598ab8..3ae46006f 100644 --- a/src/ecmascript/spidermonkey/tokenlist.cpp +++ b/src/ecmascript/spidermonkey/tokenlist.cpp @@ -142,7 +142,7 @@ tokenlist_add(JSContext *ctx, unsigned int argc, JS::Value *vp) exc = dom_tokenlist_add(tl, kl); dom_string_unref(kl); - if (exc != DOM_NO_ERR) { + if (exc == DOM_NO_ERR) { interpreter->changed = true; } args.rval().setUndefined(); @@ -242,7 +242,7 @@ tokenlist_remove(JSContext *ctx, unsigned int argc, JS::Value *vp) exc = dom_tokenlist_remove(tl, kl); dom_string_unref(kl); - if (exc != DOM_NO_ERR) { + if (exc == DOM_NO_ERR) { interpreter->changed = true; } args.rval().setUndefined();