From f562a8ed99d4e4d874a4681a2c33927ab238f86b Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Mon, 3 Apr 2023 18:32:11 +0200 Subject: [PATCH] [quickjs] libdom implementation.c --- src/ecmascript/ecmascript.cpp | 5 + src/ecmascript/ecmascript.h | 1 + src/ecmascript/libdom/parse.c | 31 ++-- src/ecmascript/libdom/quickjs/Makefile | 3 +- .../libdom/quickjs/implementation.c | 154 ++++++++++++++++++ src/ecmascript/libdom/quickjs/meson.build | 3 +- src/ecmascript/quickjs/implementation.cpp | 3 + 7 files changed, 186 insertions(+), 14 deletions(-) create mode 100644 src/ecmascript/libdom/quickjs/implementation.c diff --git a/src/ecmascript/ecmascript.cpp b/src/ecmascript/ecmascript.cpp index 1507950a..af16a86b 100644 --- a/src/ecmascript/ecmascript.cpp +++ b/src/ecmascript/ecmascript.cpp @@ -843,6 +843,11 @@ free_document(void *doc) } #ifndef CONFIG_LIBDOM +void *document_parse_text(char *text, size_t length) +{ + return NULL; +} + void * document_parse(struct document *document) { diff --git a/src/ecmascript/ecmascript.h b/src/ecmascript/ecmascript.h index 0d4f4cdb..dd82bcc2 100644 --- a/src/ecmascript/ecmascript.h +++ b/src/ecmascript/ecmascript.h @@ -196,6 +196,7 @@ void check_for_rerender(struct ecmascript_interpreter *interpreter, const char* void toggle_ecmascript(struct session *ses); void *document_parse(struct document *document); +void *document_parse_text(char *text, size_t length); void free_document(void *doc); void location_goto(struct document_view *doc_view, char *url); void location_goto_const(struct document_view *doc_view, const char *url); diff --git a/src/ecmascript/libdom/parse.c b/src/ecmascript/libdom/parse.c index 49ac7bd2..ec0ea8ea 100644 --- a/src/ecmascript/libdom/parse.c +++ b/src/ecmascript/libdom/parse.c @@ -18,23 +18,13 @@ #include "document/document.h" void * -document_parse(struct document *document) +document_parse_text(char *data, size_t length) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - struct cache_entry *cached = document->cached; - struct fragment *f = get_cache_fragment(cached); - const char *encoding; dom_hubbub_parser *parser = NULL; dom_hubbub_error error; dom_hubbub_parser_params params; dom_document *doc; - if (!f || !f->length) { - return NULL; - } - params.enc = NULL; params.fix_enc = true; params.enable_script = false; @@ -51,7 +41,7 @@ document_parse(struct document *document) } /* Parse */ - error = dom_hubbub_parser_parse_chunk(parser, f->data, f->length); + error = dom_hubbub_parser_parse_chunk(parser, (const uint8_t *)data, length); if (error != DOM_HUBBUB_OK) { dom_hubbub_parser_destroy(parser); fprintf(stderr, "Parsing errors occur\n"); @@ -71,3 +61,20 @@ document_parse(struct document *document) return doc; } + + +void * +document_parse(struct document *document) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + struct cache_entry *cached = document->cached; + struct fragment *f = get_cache_fragment(cached); + + if (!f || !f->length) { + return NULL; + } + + return document_parse_text(f->data, f->length); +} diff --git a/src/ecmascript/libdom/quickjs/Makefile b/src/ecmascript/libdom/quickjs/Makefile index 97c13b84..7d9046d7 100644 --- a/src/ecmascript/libdom/quickjs/Makefile +++ b/src/ecmascript/libdom/quickjs/Makefile @@ -1,6 +1,7 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.config -OBJS = attr.o attributes.o collection.o console.o document.o element.o form.o forms.o heartbeat.o history.o input.o keyboard.o localstorage.o location.o mapa.obj message.o navigator.o nodelist.o screen.o unibar.o window.o xhr.o +OBJS = attr.o attributes.o collection.o console.o document.o element.o form.o forms.o heartbeat.o history.o implementation.o input.o \ + keyboard.o localstorage.o location.o mapa.obj message.o navigator.o nodelist.o screen.o unibar.o window.o xhr.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/libdom/quickjs/implementation.c b/src/ecmascript/libdom/quickjs/implementation.c new file mode 100644 index 00000000..70e8ffb4 --- /dev/null +++ b/src/ecmascript/libdom/quickjs/implementation.c @@ -0,0 +1,154 @@ +/* The QuickJS domimplementation object. */ + +#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/quickjs.h" +#include "ecmascript/quickjs/document.h" +#include "ecmascript/quickjs/implementation.h" +#include "util/conv.h" + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +static JSClassID js_implementation_class_id; + +static JSValue +js_implementation_createHTMLDocument(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) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return JS_UNDEFINED; + } + size_t len; + const char *title = JS_ToCStringLen(ctx, &len, argv[0]); + + if (!title) { + return JS_EXCEPTION; + } + struct string str; + + if (!init_string(&str)) { + JS_FreeCString(ctx, title); + + return JS_NULL; + } + add_to_string(&str, "\n"); + add_html_to_string(&str, title, len); + add_to_string(&str, ""); + + void *docu = document_parse_text(str.source, str.length); + done_string(&str); + JS_FreeCString(ctx, title); + + return getDocument(ctx, docu); +} + +static JSValue +js_implementation_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, "[implementation object]"); +} + +static const JSCFunctionListEntry js_implementation_proto_funcs[] = { + JS_CFUNC_DEF("createHTMLDocument", 1, js_implementation_createHTMLDocument), + JS_CFUNC_DEF("toString", 0, js_implementation_toString) +}; + +static JSClassDef js_implementation_class = { + "implementation", +}; + +static JSValue +js_implementation_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) +{ + REF_JS(new_target); + + JSValue obj = JS_UNDEFINED; + JSValue proto; + /* using new_target to get the prototype is necessary when the + class is extended. */ + proto = JS_GetPropertyStr(ctx, new_target, "prototype"); + REF_JS(proto); + + if (JS_IsException(proto)) { + goto fail; + } + obj = JS_NewObjectProtoClass(ctx, proto, js_implementation_class_id); + JS_FreeValue(ctx, proto); + + if (JS_IsException(obj)) { + goto fail; + } + RETURN_JS(obj); + +fail: + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; +} + +int +js_implementation_init(JSContext *ctx, JSValue global_obj) +{ + REF_JS(global_obj); + + JSValue implementation_proto, implementation_class; + + /* create the implementation class */ + JS_NewClassID(&js_implementation_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_implementation_class_id, &js_implementation_class); + + implementation_proto = JS_NewObject(ctx); + REF_JS(implementation_proto); + + JS_SetPropertyFunctionList(ctx, implementation_proto, js_implementation_proto_funcs, countof(js_implementation_proto_funcs)); + + implementation_class = JS_NewCFunction2(ctx, js_implementation_ctor, "implementation", 0, JS_CFUNC_constructor, 0); + REF_JS(implementation_class); + + /* set proto.constructor and ctor.prototype */ + JS_SetConstructor(ctx, implementation_class, implementation_proto); + JS_SetClassProto(ctx, js_implementation_class_id, implementation_proto); + + JS_SetPropertyStr(ctx, global_obj, "implementation", JS_DupValue(ctx, implementation_proto)); + return 0; +} + +JSValue +getImplementation(JSContext *ctx) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JSValue implementation_obj = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, implementation_obj, js_implementation_proto_funcs, countof(js_implementation_proto_funcs)); +// implementation_class = JS_NewCFunction2(ctx, js_implementation_ctor, "implementation", 0, JS_CFUNC_constructor, 0); +// JS_SetConstructor(ctx, implementation_class, implementation_obj); + JS_SetClassProto(ctx, js_implementation_class_id, implementation_obj); + + RETURN_JS(implementation_obj); +} diff --git a/src/ecmascript/libdom/quickjs/meson.build b/src/ecmascript/libdom/quickjs/meson.build index ebc23627..31c0c1f7 100644 --- a/src/ecmascript/libdom/quickjs/meson.build +++ b/src/ecmascript/libdom/quickjs/meson.build @@ -1,2 +1,3 @@ -srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'document.c', 'element.c', 'form.c', 'forms.c', 'heartbeat.c', 'history.c', 'input.c', 'keyboard.c', 'localstorage.c', 'location.c', +srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'document.c', 'element.c', 'form.c', 'forms.c', 'heartbeat.c', 'history.c', +'implementation.c', 'input.c', 'keyboard.c', 'localstorage.c', 'location.c', 'mapa.cpp', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'unibar.c', 'window.c', 'xhr.c') diff --git a/src/ecmascript/quickjs/implementation.cpp b/src/ecmascript/quickjs/implementation.cpp index c67439cb..5bc3b8c9 100644 --- a/src/ecmascript/quickjs/implementation.cpp +++ b/src/ecmascript/quickjs/implementation.cpp @@ -19,6 +19,8 @@ #include #include +#ifndef CONFIG_LIBDOM + #define countof(x) (sizeof(x) / sizeof((x)[0])) static JSClassID js_implementation_class_id; @@ -154,3 +156,4 @@ getImplementation(JSContext *ctx) RETURN_JS(implementation_obj); } +#endif