From 188f63941c9af1bb896e979daddba4627aac0de9 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Mon, 11 Sep 2023 15:48:18 +0200 Subject: [PATCH] [spidermonkey] element.focus() --- src/document/document.cpp | 19 ++++++ src/document/document.h | 4 ++ .../libdom/spidermonkey/element.cpp | 67 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/src/document/document.cpp b/src/document/document.cpp index 8ae7fdaf..c20f2955 100644 --- a/src/document/document.cpp +++ b/src/document/document.cpp @@ -60,6 +60,7 @@ #include "document/html/renderer.h" #include "document/options.h" #include "document/refresh.h" +#include "document/renderer.h" #ifdef CONFIG_ECMASCRIPT #include "ecmascript/ecmascript.h" @@ -621,6 +622,24 @@ done_documents(struct module *module) free_table_cache(); } +#ifdef CONFIG_ECMASCRIPT +int +get_link_number_by_offset(struct document *document, int offset) +{ + int link; + + if (!document->links_sorted) sort_links(document); + + for (link = 0; link < document->nlinks; link++) { + if (document->links[link].element_offset == offset) { + return link; + } + } + + return -1; +} +#endif + struct module document_module = struct_module( /* Because this module is listed in main_modules rather than * in builtin_modules, its name does not appear in the user diff --git a/src/document/document.h b/src/document/document.h index 893f6a49..b76122dd 100644 --- a/src/document/document.h +++ b/src/document/document.h @@ -349,6 +349,10 @@ int get_format_cache_refresh_count(void); void shrink_format_cache(int); +#ifdef CONFIG_ECMASCRIPT +int get_link_number_by_offset(struct document *document, int offset); +#endif + extern struct module document_module; /** @todo FIXME: support for entities and all Unicode characters. diff --git a/src/ecmascript/libdom/spidermonkey/element.cpp b/src/ecmascript/libdom/spidermonkey/element.cpp index 8f1fc1b1..ce746852 100644 --- a/src/ecmascript/libdom/spidermonkey/element.cpp +++ b/src/ecmascript/libdom/spidermonkey/element.cpp @@ -24,6 +24,7 @@ #include "document/document.h" #include "document/forms.h" #include "document/libdom/corestrings.h" +#include "document/libdom/mapa.h" #include "document/view.h" #include "ecmascript/ecmascript.h" #include "ecmascript/spidermonkey/attr.h" @@ -2708,6 +2709,7 @@ static bool element_appendChild(JSContext *ctx, unsigned int argc, JS::Value *rv static bool element_cloneNode(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_closest(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_contains(JSContext *ctx, unsigned int argc, JS::Value *rval); +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_getElementsByTagName(JSContext *ctx, unsigned int argc, JS::Value *rval); @@ -2732,6 +2734,7 @@ const spidermonkeyFunctionSpec element_funcs[] = { { "cloneNode", element_cloneNode, 1 }, { "closest", element_closest, 1 }, { "contains", element_contains, 1 }, + { "focus", element_focus, 0 }, { "getAttribute", element_getAttribute, 1 }, { "getAttributeNode", element_getAttributeNode, 1 }, { "getElementsByTagName", element_getElementsByTagName, 1 }, @@ -3176,6 +3179,70 @@ element_contains(JSContext *ctx, unsigned int argc, JS::Value *rval) return true; } +static bool +element_focus(JSContext *ctx, unsigned int argc, JS::Value *rval) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::Realm *comp = js::GetContextRealm(ctx); + + if (!comp) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + JS::CallArgs args = CallArgsFromVp(argc, rval); + JS::RootedObject hobj(ctx, &args.thisv().toObject()); + + if (!JS_InstanceOf(ctx, hobj, &element_class, NULL)) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + args.rval().setUndefined(); + struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp); + struct view_state *vs = interpreter->vs; + + if (!vs) { + return true; + } + + struct document_view *doc_view = vs->doc_view; + + if (!doc_view) { + return true; + } + + struct document *doc = doc_view->document; + + if (!doc) { + return true; + } + dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot(hobj, 0); + + if (!el) { + return true; + } + int offset = find_offset(doc->element_map_rev, el); + + if (offset < 0) { + return true; + } + + int linknum = get_link_number_by_offset(doc, offset); + + if (linknum < 0) { + return true; + } + jump_to_link_number(doc_view->session, doc_view, linknum); + + return true; +} + static bool element_getAttribute(JSContext *ctx, unsigned int argc, JS::Value *rval) {