From 86affcf076adf1e06c1a2d256c3154da4e32d8e7 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sun, 16 Jun 2024 19:41:15 +0200 Subject: [PATCH] [quickjs] DOMRect --- src/ecmascript/quickjs/Makefile | 2 +- src/ecmascript/quickjs/domrect.c | 396 ++++++++++++++++++++++++ src/ecmascript/quickjs/domrect.h | 17 + src/ecmascript/quickjs/element.c | 15 + src/ecmascript/quickjs/meson.build | 2 +- src/ecmascript/spidermonkey/domrect.cpp | 16 +- src/ecmascript/spidermonkey/element.cpp | 6 +- 7 files changed, 441 insertions(+), 13 deletions(-) create mode 100644 src/ecmascript/quickjs/domrect.c create mode 100644 src/ecmascript/quickjs/domrect.h diff --git a/src/ecmascript/quickjs/Makefile b/src/ecmascript/quickjs/Makefile index 6729fe893..c6e9c95c6 100644 --- a/src/ecmascript/quickjs/Makefile +++ b/src/ecmascript/quickjs/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 document.o element.o event.o form.o forms.o heartbeat.o history.o implementation.o input.o \ +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 include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/quickjs/domrect.c b/src/ecmascript/quickjs/domrect.c new file mode 100644 index 000000000..d7317c7d3 --- /dev/null +++ b/src/ecmascript/quickjs/domrect.c @@ -0,0 +1,396 @@ +/* The QuickJS DOMRect implementation. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "elinks.h" + +#include "ecmascript/ecmascript.h" +#include "ecmascript/libdom/dom.h" +#include "ecmascript/quickjs.h" +#include "ecmascript/quickjs/element.h" +#include "ecmascript/quickjs/event.h" +#include "intl/charsets.h" +#include "terminal/event.h" + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +JSClassID js_domRect_class_id; + +struct eljs_domrect { + double x; + double y; + double width; + double height; + double top; + double right; + double bottom; + double left; +}; + +static JSValue js_domRect_get_property_bottom(JSContext *ctx, JSValueConst this_val); +static JSValue js_domRect_get_property_height(JSContext *ctx, JSValueConst this_val); +static JSValue js_domRect_get_property_left(JSContext *ctx, JSValueConst this_val); +static JSValue js_domRect_get_property_right(JSContext *ctx, JSValueConst this_val); +static JSValue js_domRect_get_property_top(JSContext *ctx, JSValueConst this_val); +static JSValue js_domRect_get_property_width(JSContext *ctx, JSValueConst this_val); +static JSValue js_domRect_get_property_x(JSContext *ctx, JSValueConst this_val); +static JSValue js_domRect_get_property_y(JSContext *ctx, JSValueConst this_val); + +static JSValue js_domRect_set_property_bottom(JSContext *ctx, JSValueConst this_val, JSValue val); +static JSValue js_domRect_set_property_height(JSContext *ctx, JSValueConst this_val, JSValue val); +static JSValue js_domRect_set_property_left(JSContext *ctx, JSValueConst this_val, JSValue val); +static JSValue js_domRect_set_property_right(JSContext *ctx, JSValueConst this_val, JSValue val); +static JSValue js_domRect_set_property_top(JSContext *ctx, JSValueConst this_val, JSValue val); +static JSValue js_domRect_set_property_width(JSContext *ctx, JSValueConst this_val, JSValue val); +static JSValue js_domRect_set_property_x(JSContext *ctx, JSValueConst this_val, JSValue val); +static JSValue js_domRect_set_property_y(JSContext *ctx, JSValueConst this_val, JSValue val); + +static +void js_domRect_finalizer(JSRuntime *rt, JSValue val) +{ + REF_JS(val); + + struct eljs_domrect *d = (struct eljs_domrect *)JS_GetOpaque(val, js_domRect_class_id); + + if (d) { + mem_free(d); + } +} + +static JSClassDef js_domRect_class = { + "DOMRect", + js_domRect_finalizer +}; + +static const JSCFunctionListEntry js_domRect_proto_funcs[] = { + JS_CGETSET_DEF("bottom", js_domRect_get_property_bottom, js_domRect_set_property_bottom), + JS_CGETSET_DEF("height", js_domRect_get_property_height, js_domRect_set_property_height), + JS_CGETSET_DEF("left", js_domRect_get_property_left, js_domRect_set_property_left), + JS_CGETSET_DEF("right", js_domRect_get_property_right, js_domRect_set_property_right), + JS_CGETSET_DEF("top", js_domRect_get_property_top, js_domRect_set_property_top), + JS_CGETSET_DEF("width", js_domRect_get_property_width, js_domRect_set_property_width), + JS_CGETSET_DEF("x", js_domRect_get_property_x, js_domRect_set_property_x), + JS_CGETSET_DEF("y", js_domRect_get_property_y, js_domRect_set_property_y), +}; + +static JSValue +js_domRect_get_property_bottom(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JSValue r = JS_NewFloat64(ctx, d->bottom); + + RETURN_JS(r); +} + +static JSValue +js_domRect_get_property_height(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JSValue r = JS_NewFloat64(ctx, d->height); + + RETURN_JS(r); +} + +static JSValue +js_domRect_get_property_left(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JSValue r = JS_NewFloat64(ctx, d->left); + + RETURN_JS(r); +} + +static JSValue +js_domRect_get_property_right(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JSValue r = JS_NewFloat64(ctx, d->right); + + RETURN_JS(r); +} + +static JSValue +js_domRect_get_property_top(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JSValue r = JS_NewFloat64(ctx, d->top); + + RETURN_JS(r); +} + +static JSValue +js_domRect_get_property_width(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JSValue r = JS_NewFloat64(ctx, d->width); + + RETURN_JS(r); +} + +static JSValue +js_domRect_get_property_x(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JSValue r = JS_NewFloat64(ctx, d->x); + + RETURN_JS(r); +} + +static JSValue +js_domRect_get_property_y(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JSValue r = JS_NewFloat64(ctx, d->y); + + RETURN_JS(r); +} + +static JSValue +js_domRect_set_property_bottom(JSContext *ctx, JSValueConst this_val, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JS_ToFloat64(ctx, &d->bottom, val); + + return JS_UNDEFINED; +} + +static JSValue +js_domRect_set_property_height(JSContext *ctx, JSValueConst this_val, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JS_ToFloat64(ctx, &d->height, val); + + return JS_UNDEFINED; +} + +static JSValue +js_domRect_set_property_left(JSContext *ctx, JSValueConst this_val, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JS_ToFloat64(ctx, &d->left, val); + + return JS_UNDEFINED; +} + +static JSValue +js_domRect_set_property_right(JSContext *ctx, JSValueConst this_val, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JS_ToFloat64(ctx, &d->right, val); + + return JS_UNDEFINED; +} + +static JSValue +js_domRect_set_property_top(JSContext *ctx, JSValueConst this_val, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JS_ToFloat64(ctx, &d->top, val); + + return JS_UNDEFINED; +} + +static JSValue +js_domRect_set_property_width(JSContext *ctx, JSValueConst this_val, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JS_ToFloat64(ctx, &d->width, val); + + return JS_UNDEFINED; +} + +static JSValue +js_domRect_set_property_x(JSContext *ctx, JSValueConst this_val, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JS_ToFloat64(ctx, &d->x, val); + + return JS_UNDEFINED; +} + +static JSValue +js_domRect_set_property_y(JSContext *ctx, JSValueConst this_val, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + struct eljs_domrect *d = (struct eljs_domrect *)(JS_GetOpaque(this_val, js_domRect_class_id)); + + if (!d) { + return JS_NULL; + } + JS_ToFloat64(ctx, &d->y, val); + + return JS_UNDEFINED; +} + +JSValue +getDomRect(JSContext *ctx) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + struct eljs_domrect *d = mem_calloc(1, sizeof(*d)); + + JSValue proto, obj; + + /* Event class */ + JS_NewClassID(&js_domRect_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_domRect_class_id, &js_domRect_class); + proto = JS_NewObject(ctx); + REF_JS(proto); + + JS_SetPropertyFunctionList(ctx, proto, js_domRect_proto_funcs, countof(js_domRect_proto_funcs)); + JS_SetClassProto(ctx, js_domRect_class_id, proto); + +// JSValue obj = JS_NewObjectClass(ctx, js_domRect_class_id); +// REF_JS(obj); + + JS_SetOpaque(proto, d); + JSValue r = proto; + + RETURN_JS(r); +} diff --git a/src/ecmascript/quickjs/domrect.h b/src/ecmascript/quickjs/domrect.h new file mode 100644 index 000000000..935cb40fc --- /dev/null +++ b/src/ecmascript/quickjs/domrect.h @@ -0,0 +1,17 @@ +#ifndef EL__ECMASCRIPT_QUICKJS_DOMRECT_H +#define EL__ECMASCRIPT_QUICKJS_DOMRECT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +JSValue getDomRect(JSContext *ctx); +extern JSClassID js_domRect_class_id; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/ecmascript/quickjs/element.c b/src/ecmascript/quickjs/element.c index 1f47315c2..a4961241b 100644 --- a/src/ecmascript/quickjs/element.c +++ b/src/ecmascript/quickjs/element.c @@ -29,6 +29,7 @@ #include "ecmascript/quickjs/attr.h" #include "ecmascript/quickjs/attributes.h" #include "ecmascript/quickjs/collection.h" +#include "ecmascript/quickjs/domrect.h" #include "ecmascript/quickjs/element.h" #include "ecmascript/quickjs/event.h" #include "ecmascript/quickjs/heartbeat.h" @@ -2744,6 +2745,19 @@ js_element_getAttributeNode(JSContext *ctx, JSValueConst this_val, int argc, JSV return getAttr(ctx, attr); } +static JSValue +js_element_getBoundingClientRect(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + + JSValue rect = getDomRect(ctx); + + RETURN_JS(rect); +} + static JSValue js_element_getElementsByTagName(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -3357,6 +3371,7 @@ static const JSCFunctionListEntry js_element_proto_funcs[] = { JS_CFUNC_DEF("focus", 0, js_element_focus), JS_CFUNC_DEF("getAttribute", 1, js_element_getAttribute), JS_CFUNC_DEF("getAttributeNode",1, js_element_getAttributeNode), + JS_CFUNC_DEF("getBoundingClientRect", 0, js_element_getBoundingClientRect), JS_CFUNC_DEF("getElementsByTagName", 1, js_element_getElementsByTagName), JS_CFUNC_DEF("hasAttribute", 1, js_element_hasAttribute), JS_CFUNC_DEF("hasAttributes", 0, js_element_hasAttributes), diff --git a/src/ecmascript/quickjs/meson.build b/src/ecmascript/quickjs/meson.build index 3dc12df9f..17af9913c 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', 'element.c', 'event.c', 'form.c', 'forms.c', 'heartbeat.c', 'history.c', +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') diff --git a/src/ecmascript/spidermonkey/domrect.cpp b/src/ecmascript/spidermonkey/domrect.cpp index 3c4059405..8b38def90 100644 --- a/src/ecmascript/spidermonkey/domrect.cpp +++ b/src/ecmascript/spidermonkey/domrect.cpp @@ -55,14 +55,14 @@ static bool domRect_set_property_bottom(JSContext *ctx, unsigned int argc, JS::V static bool domRect_set_property_left(JSContext *ctx, unsigned int argc, JS::Value *vp); struct eljs_domrect { - float x; - float y; - float width; - float height; - float top; - float right; - float bottom; - float left; + double x; + double y; + double width; + double height; + double top; + double right; + double bottom; + double left; }; static void diff --git a/src/ecmascript/spidermonkey/element.cpp b/src/ecmascript/spidermonkey/element.cpp index f9f99d184..a24ef63f1 100644 --- a/src/ecmascript/spidermonkey/element.cpp +++ b/src/ecmascript/spidermonkey/element.cpp @@ -3741,7 +3741,7 @@ static bool element_dispatchEvent(JSContext *ctx, unsigned int argc, JS::Value * static bool element_focus(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_getAttribute(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_getAttributeNode(JSContext *ctx, unsigned int argc, JS::Value *rval); -static bool element_getBoundingRect(JSContext *ctx, unsigned int argc, JS::Value *rval); +static bool element_getBoundingClientRect(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_getElementsByTagName(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_hasAttribute(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_hasAttributes(JSContext *ctx, unsigned int argc, JS::Value *rval); @@ -3770,7 +3770,7 @@ const spidermonkeyFunctionSpec element_funcs[] = { { "focus", element_focus, 0 }, { "getAttribute", element_getAttribute, 1 }, { "getAttributeNode", element_getAttributeNode, 1 }, - { "getBoundingRect", element_getBoundingRect, 0 }, + { "getBoundingClientRect", element_getBoundingClientRect, 0 }, { "getElementsByTagName", element_getElementsByTagName, 1 }, { "hasAttribute", element_hasAttribute, 1 }, { "hasAttributes", element_hasAttributes, 0 }, @@ -4532,7 +4532,7 @@ element_getAttributeNode(JSContext *ctx, unsigned int argc, JS::Value *rval) } static bool -element_getBoundingRect(JSContext *ctx, unsigned int argc, JS::Value *rval) +element_getBoundingClientRect(JSContext *ctx, unsigned int argc, JS::Value *rval) { #ifdef ECMASCRIPT_DEBUG fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);