From 387a2836f17f6158dd8fed066e211411b1661aec Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Wed, 15 Sep 2021 16:22:36 +0200 Subject: [PATCH] [ecmascript] domimplementation --- src/ecmascript/spidermonkey/Makefile | 3 +- src/ecmascript/spidermonkey/document.c | 55 +++++++++ src/ecmascript/spidermonkey/document.h | 2 + src/ecmascript/spidermonkey/implementation.c | 123 +++++++++++++++++++ src/ecmascript/spidermonkey/implementation.h | 11 ++ src/ecmascript/spidermonkey/meson.build | 2 +- 6 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 src/ecmascript/spidermonkey/implementation.c create mode 100644 src/ecmascript/spidermonkey/implementation.h diff --git a/src/ecmascript/spidermonkey/Makefile b/src/ecmascript/spidermonkey/Makefile index 6ed866ad..a003f6b6 100644 --- a/src/ecmascript/spidermonkey/Makefile +++ b/src/ecmascript/spidermonkey/Makefile @@ -2,6 +2,7 @@ top_builddir=../../.. include $(top_builddir)/Makefile.config INCLUDES += $(SPIDERMONKEY_CFLAGS) -OBJS = console.o document.o element.o form.o heartbeat.o location.o localstorage.o localstorage-db.o navigator.o screen.o unibar.o window.o +OBJS = console.o document.o element.o form.o heartbeat.o implementation.o location.o \ + localstorage.o localstorage-db.o navigator.o screen.o unibar.o window.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/spidermonkey/document.c b/src/ecmascript/spidermonkey/document.c index 375a7bd0..f360db23 100644 --- a/src/ecmascript/spidermonkey/document.c +++ b/src/ecmascript/spidermonkey/document.c @@ -25,6 +25,7 @@ #include "document/view.h" #include "ecmascript/ecmascript.h" #include "ecmascript/spidermonkey/form.h" +#include "ecmascript/spidermonkey/implementation.h" #include "ecmascript/spidermonkey/location.h" #include "ecmascript/spidermonkey/document.h" #include "ecmascript/spidermonkey/element.h" @@ -686,6 +687,37 @@ document_get_property_images(JSContext *ctx, unsigned int argc, JS::Value *vp) return true; } +static bool +document_get_property_implementation(JSContext *ctx, unsigned int argc, JS::Value *vp) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::CallArgs args = CallArgsFromVp(argc, vp); + + JS::Realm *comp = js::GetContextRealm(ctx); + struct ecmascript_interpreter *interpreter = JS::GetRealmPrivate(comp); + struct document_view *doc_view = interpreter->vs->doc_view; + struct document *document = doc_view->document; + + if (!document->dom) { + document->dom = document_parse(document); + } + + if (!document->dom) { + args.rval().setNull(); + return true; + } + + JSObject *obj = getImplementation(ctx); + if (!obj) { + args.rval().setNull(); + } else { + args.rval().setObject(*obj); + } + return true; +} + static bool document_get_property_links(JSContext *ctx, unsigned int argc, JS::Value *vp) { @@ -1132,6 +1164,7 @@ JSPropertySpec document_props[] = { JS_PSG("forms", document_get_property_forms, JSPROP_ENUMERATE), JS_PSG("head", document_get_property_head, JSPROP_ENUMERATE), JS_PSG("images", document_get_property_images, JSPROP_ENUMERATE), + JS_PSG("implementation", document_get_property_implementation, JSPROP_ENUMERATE), JS_PSG("inputEncoding", document_get_property_charset, JSPROP_ENUMERATE), JS_PSG("links", document_get_property_links, JSPROP_ENUMERATE), JS_PSGS("location", document_get_property_location, document_set_property_location, JSPROP_ENUMERATE), @@ -2038,3 +2071,25 @@ getDoctype(JSContext *ctx, void *node) return el; } + +JSObject * +getDocument(JSContext *ctx, void *doc) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JSObject *el = JS_NewObject(ctx, &document_class); + + if (!el) { + return NULL; + } + + JS::RootedObject r_el(ctx, el); + + JS_DefineProperties(ctx, r_el, (JSPropertySpec *) document_props); + spidermonkey_DefineFunctions(ctx, el, document_funcs); + + JS_SetPrivate(el, doc); + + return el; +} diff --git a/src/ecmascript/spidermonkey/document.h b/src/ecmascript/spidermonkey/document.h index 6f3c5032..3d031c43 100644 --- a/src/ecmascript/spidermonkey/document.h +++ b/src/ecmascript/spidermonkey/document.h @@ -9,4 +9,6 @@ extern const spidermonkeyFunctionSpec document_funcs[]; extern JSPropertySpec document_props[]; void *document_parse(struct document *document); +JSObject *getDocument(JSContext *ctx, void *doc); + #endif diff --git a/src/ecmascript/spidermonkey/implementation.c b/src/ecmascript/spidermonkey/implementation.c new file mode 100644 index 00000000..9b53e174 --- /dev/null +++ b/src/ecmascript/spidermonkey/implementation.c @@ -0,0 +1,123 @@ +/* The SpiderMonkey domimplementation object. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "elinks.h" + +#include "ecmascript/ecmascript.h" +#include "ecmascript/spidermonkey/document.h" +#include "ecmascript/spidermonkey/implementation.h" +#include "ecmascript/spidermonkey/util.h" +#include + +#include +#include + +static JSClassOps implementation_ops = { + nullptr, // addProperty + nullptr, // deleteProperty + nullptr, // enumerate + nullptr, // newEnumerate + nullptr, // resolve + nullptr, // mayResolve + nullptr, // finalize + nullptr, // call + nullptr, // hasInstance + nullptr, // construct + JS_GlobalObjectTraceHook +}; + +static JSClass implementation_class = { + "implementation", + JSCLASS_HAS_PRIVATE, + &implementation_ops +}; + +static bool +implementation_createHTMLDocument(JSContext *ctx, unsigned int argc, JS::Value *rval) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::Value val; + JS::RootedObject parent_doc(ctx); /* instance of @document_class */ + JS::CallArgs args = JS::CallArgsFromVp(argc, rval); + JS::RootedObject hobj(ctx, &args.thisv().toObject()); + + JS::Realm *comp = js::GetContextRealm(ctx); + + if (!comp || argc != 1) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + struct ecmascript_interpreter *interpreter = JS::GetRealmPrivate(comp); + + if (!JS_InstanceOf(ctx, hobj, &implementation_class, &args)) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + char *title = jsval_to_string(ctx, args[0]); + + if (title) { + struct string str; + init_string(&str); + + add_to_string(&str, ""); + add_to_string(&str, title); + add_to_string(&str, ""); + + // Parse HTML and create a DOM tree + xmlDoc* doc = htmlReadDoc((xmlChar*)str.source, NULL, "utf-8", + HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); + // Encapsulate raw libxml document in a libxml++ wrapper + xmlpp::Document *docu = new xmlpp::Document(doc); + done_string(&str); + mem_free(title); + + JSObject *obj = getDocument(ctx, docu); + + if (obj) { + args.rval().setObject(*obj); + return true; + } + } + + args.rval().setNull(); + return true; +} + +static const spidermonkeyFunctionSpec implementation_funcs[] = { + { "createHTMLDocument", implementation_createHTMLDocument, 1 }, + { NULL } +}; + + +JSObject * +getImplementation(JSContext *ctx) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JSObject *el = JS_NewObject(ctx, &implementation_class); + + if (!el) { + return NULL; + } + + JS::RootedObject r_el(ctx, el); + spidermonkey_DefineFunctions(ctx, el, implementation_funcs); + + return el; +} diff --git a/src/ecmascript/spidermonkey/implementation.h b/src/ecmascript/spidermonkey/implementation.h new file mode 100644 index 00000000..ba189845 --- /dev/null +++ b/src/ecmascript/spidermonkey/implementation.h @@ -0,0 +1,11 @@ +#ifndef EL__ECMASCRIPT_SPIDERMONKEY_IMPLEMENTATION_H +#define EL__ECMASCRIPT_SPIDERMONKEY_IMPLEMENTATION_H + +#include "ecmascript/spidermonkey/util.h" + +JSObject *getImplementation(JSContext *ctx); + +#endif + + + diff --git a/src/ecmascript/spidermonkey/meson.build b/src/ecmascript/spidermonkey/meson.build index 14435122..151130f6 100644 --- a/src/ecmascript/spidermonkey/meson.build +++ b/src/ecmascript/spidermonkey/meson.build @@ -1,3 +1,3 @@ #INCLUDES += $(SPIDERMONKEY_CFLAGS) -srcs += files('console.c', 'document.c', 'element.c', 'form.c', 'heartbeat.c', 'location.c', 'localstorage.c', 'localstorage-db.c', 'navigator.c', 'screen.c', 'unibar.c', 'window.c') +srcs += files('console.c', 'document.c', 'element.c', 'form.c', 'heartbeat.c', 'implementation.c', 'location.c', 'localstorage.c', 'localstorage-db.c', 'navigator.c', 'screen.c', 'unibar.c', 'window.c')