From 1c51410fd3cbc049fe0dfe2b2f75dda1d3f55f78 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Mon, 1 Aug 2022 21:31:07 +0200 Subject: [PATCH] [mujs] Stubs for mujs --- config2.h.in | 3 + meson.build | 11 +- meson_options.txt | 1 + src/ecmascript/ecmascript.cpp | 46 +++-- src/ecmascript/meson.build | 5 + src/ecmascript/mujs.cpp | 307 ++++++++++++++++++++++++++++++++ src/ecmascript/mujs.h | 45 +++++ src/ecmascript/mujs/meson.build | 0 src/main/module.cpp | 2 +- 9 files changed, 407 insertions(+), 13 deletions(-) create mode 100644 src/ecmascript/mujs.cpp create mode 100644 src/ecmascript/mujs.h create mode 100644 src/ecmascript/mujs/meson.build diff --git a/config2.h.in b/config2.h.in index 540d5d79..c2c0eb6a 100644 --- a/config2.h.in +++ b/config2.h.in @@ -158,6 +158,9 @@ /* Define if you want: Mouse handling support */ #mesondefine CONFIG_MOUSE +/* Define if you want: mujs support */ +#mesondefine CONFIG_MUJS + /* Define to 1 if translation of program messages to the user's native language is requested. */ #mesondefine CONFIG_NLS diff --git a/meson.build b/meson.build index 4ea3731c..9d894f7b 100644 --- a/meson.build +++ b/meson.build @@ -94,8 +94,10 @@ conf_data.set('CONFIG_LIBEVENT', get_option('libevent')) conf_data.set('CONFIG_X', get_option('x')) conf_data.set('CONFIG_XML', get_option('xml')) conf_data.set('CONFIG_QUICKJS', get_option('quickjs')) +conf_data.set('CONFIG_MUJS', get_option('mujs')) -if conf_data.get('CONFIG_SCRIPTING_SPIDERMONKEY') or conf_data.get('CONFIG_ECMASCRIPT_SMJS') or conf_data.get('CONFIG_QUICKJS') + +if conf_data.get('CONFIG_SCRIPTING_SPIDERMONKEY') or conf_data.get('CONFIG_ECMASCRIPT_SMJS') or conf_data.get('CONFIG_QUICKJS') or conf_data.get('CONFIG_MUJS') conf_data.set('CONFIG_ECMASCRIPT', true) else conf_data.set('CONFIG_ECMASCRIPT', false) @@ -376,7 +378,7 @@ if conf_data.get('CONFIG_ECMASCRIPT_SMJS') or conf_data.get('CONFIG_SCRIPTING_SP deps += mozjsdeps endif -if conf_data.get('CONFIG_ECMASCRIPT_SMJS') or conf_data.get('CONFIG_QUICKJS') +if conf_data.get('CONFIG_ECMASCRIPT_SMJS') or conf_data.get('CONFIG_QUICKJS') or conf_data.get('CONFIG_MUJS') sqlite3deps = dependency('sqlite3', static: st) deps += sqlite3deps conf_data.set('CONFIG_XML', true) @@ -469,6 +471,11 @@ if conf_data.get('CONFIG_QUICKJS') deps += dep_atomic endif +if conf_data.get('CONFIG_MUJS') + mujsdeps = dependency('mujs', static: st) + deps += mujsdeps +endif + if not conf_data.get('CONFIG_OS_DOS') and compiler.has_header('sys/un.h') conf_data.set('CONFIG_INTERLINK', true) conf_data.set('HAVE_SYS_UN_H', 1) diff --git a/meson_options.txt b/meson_options.txt index d8b45c99..4599a078 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -70,3 +70,4 @@ option('reproducible', type: 'boolean', value: false, description: 'reproducible option('source-date-epoch', type: 'string', value: '', description: 'source date epoch for reproducible builds') option('dgi', type: 'boolean', value: false, description: 'DOS Gateway Interface support') +option('mujs', type: 'boolean', value: false, description: 'use mujs library') diff --git a/src/ecmascript/ecmascript.cpp b/src/ecmascript/ecmascript.cpp index 22d0dbd2..e083c2b1 100644 --- a/src/ecmascript/ecmascript.cpp +++ b/src/ecmascript/ecmascript.cpp @@ -18,11 +18,15 @@ #include "document/xml/renderer.h" #include "document/xml/renderer2.h" #include "ecmascript/ecmascript.h" +#ifdef CONFIG_MUJS +#include "ecmascript/mujs.h" +#else #ifdef CONFIG_QUICKJS #include "ecmascript/quickjs.h" #else #include "ecmascript/spidermonkey.h" #endif +#endif #include "ecmascript/timer.h" #include "intl/libintl.h" #include "main/module.h" @@ -234,7 +238,9 @@ ecmascript_get_interpreter(struct view_state *vs) init_list(interpreter->onload_snippets); /* The following backend call reads interpreter->vs. */ if ( -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS + !mujs_get_interpreter(interpreter) +#elif defined(CONFIG_QUICKJS) !quickjs_get_interpreter(interpreter) #else !spidermonkey_get_interpreter(interpreter) @@ -259,7 +265,9 @@ ecmascript_put_interpreter(struct ecmascript_interpreter *interpreter) /* If the assertion fails, it is better to leak the * interpreter than to corrupt memory. */ if_assert_failed return; -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS + mujs_put_interpreter(interpreter); +#elif defined(CONFIG_QUICKJS) quickjs_put_interpreter(interpreter); #else spidermonkey_put_interpreter(interpreter); @@ -332,7 +340,9 @@ ecmascript_eval(struct ecmascript_interpreter *interpreter, return; assert(interpreter); interpreter->backend_nesting++; -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS + mujs_eval(interpreter, code, ret); +#elif defined(CONFIG_QUICKJS) quickjs_eval(interpreter, code, ret); #else spidermonkey_eval(interpreter, code, ret); @@ -340,7 +350,11 @@ ecmascript_eval(struct ecmascript_interpreter *interpreter, interpreter->backend_nesting--; } -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS +static void +ecmascript_call_function(struct ecmascript_interpreter *interpreter, + void *fun, struct string *ret) +#elif defined(CONFIG_QUICKJS) static void ecmascript_call_function(struct ecmascript_interpreter *interpreter, JSValueConst fun, struct string *ret) @@ -354,7 +368,9 @@ ecmascript_call_function(struct ecmascript_interpreter *interpreter, return; assert(interpreter); interpreter->backend_nesting++; -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS + ; +#elif defined(CONFIG_QUICKJS) quickjs_call_function(interpreter, fun, ret); #else spidermonkey_call_function(interpreter, fun, ret); @@ -372,7 +388,9 @@ ecmascript_eval_stringback(struct ecmascript_interpreter *interpreter, return NULL; assert(interpreter); interpreter->backend_nesting++; -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS + result = mujs_eval_stringback(interpreter, code); +#elif defined(CONFIG_QUICKJS) result = quickjs_eval_stringback(interpreter, code); #else result = spidermonkey_eval_stringback(interpreter, code); @@ -394,7 +412,9 @@ ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter, return -1; assert(interpreter); interpreter->backend_nesting++; -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS + result = mujs_eval_boolback(interpreter, code); +#elif defined(CONFIG_QUICKJS) result = quickjs_eval_boolback(interpreter, code); #else result = spidermonkey_eval_boolback(interpreter, code); @@ -409,7 +429,8 @@ ecmascript_eval_boolback(struct ecmascript_interpreter *interpreter, void ecmascript_detach_form_view(struct form_view *fv) { -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS +#elif defined(CONFIG_QUICKJS) quickjs_detach_form_view(fv); #else spidermonkey_detach_form_view(fv); @@ -418,7 +439,8 @@ ecmascript_detach_form_view(struct form_view *fv) void ecmascript_detach_form_state(struct form_state *fs) { -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS +#elif defined(CONFIG_QUICKJS) quickjs_detach_form_state(fs); #else spidermonkey_detach_form_state(fs); @@ -427,7 +449,8 @@ void ecmascript_detach_form_state(struct form_state *fs) void ecmascript_moved_form_state(struct form_state *fs) { -#ifdef CONFIG_QUICKJS +#ifdef CONFIG_MUJS +#elif defined(CONFIG_QUICKJS) quickjs_moved_form_state(fs); #else spidermonkey_moved_form_state(fs); @@ -681,6 +704,9 @@ static struct module *ecmascript_modules[] = { #ifdef CONFIG_ECMASCRIPT_SMJS &spidermonkey_module, #endif +#ifdef CONFIG_MUJS + &mujs_module, +#endif #ifdef CONFIG_QUICKJS &quickjs_module, #endif diff --git a/src/ecmascript/meson.build b/src/ecmascript/meson.build index df915778..99b2a3b2 100644 --- a/src/ecmascript/meson.build +++ b/src/ecmascript/meson.build @@ -16,6 +16,11 @@ if CONFIG_ANY_SPIDERMONKEY srcs += files('spidermonkey-shared.cpp') endif +if conf_data.get('CONFIG_MUJS') + subdir('mujs') + srcs += files('css2xpath.cpp', 'ecmascript.cpp', 'localstorage-db.cpp', 'mujs.cpp') +endif + if conf_data.get('CONFIG_QUICKJS') subdir('quickjs') srcs += files('css2xpath.cpp', 'ecmascript.cpp', 'localstorage-db.cpp', 'quickjs.cpp') diff --git a/src/ecmascript/mujs.cpp b/src/ecmascript/mujs.cpp new file mode 100644 index 00000000..1dff44bd --- /dev/null +++ b/src/ecmascript/mujs.cpp @@ -0,0 +1,307 @@ +/* The mujs ECMAScript backend. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "elinks.h" + +#include "bfu/dialog.h" +#include "cache/cache.h" +#include "config/options.h" +#include "cookies/cookies.h" +#include "dialogs/menu.h" +#include "dialogs/status.h" +#include "document/html/frames.h" +#include "document/xml/renderer.h" +#include "document/xml/renderer2.h" +#include "document/document.h" +#include "document/forms.h" +#include "document/renderer.h" +#include "document/view.h" +#include "ecmascript/ecmascript.h" +#include "ecmascript/mujs.h" +#include "intl/libintl.h" +#include "main/select.h" +#include "osdep/newwin.h" +#include "osdep/sysname.h" +#include "protocol/http/http.h" +#include "protocol/uri.h" +#include "session/history.h" +#include "session/location.h" +#include "session/session.h" +#include "session/task.h" +#include "terminal/tab.h" +#include "terminal/terminal.h" +#include "util/conv.h" +#include "util/string.h" +#include "viewer/text/draw.h" +#include "viewer/text/form.h" +#include "viewer/text/link.h" +#include "viewer/text/view.h" +#include "viewer/text/vs.h" + +#include + +/*** Global methods */ + + +static void +mujs_init(struct module *xxx) +{ + //js_module_init_ok = spidermonkey_runtime_addref(); +} + +static void +mujs_done(struct module *xxx) +{ +// if (js_module_init_ok) +// spidermonkey_runtime_release(); +} + +void * +mujs_get_interpreter(struct ecmascript_interpreter *interpreter) +{ + return nullptr; +#if 0 + + JSContext *ctx; +// JSObject *console_obj, *document_obj, /* *forms_obj,*/ *history_obj, *location_obj, +// *statusbar_obj, *menubar_obj, *navigator_obj, *localstorage_obj, *screen_obj; + + assert(interpreter); +// if (!js_module_init_ok) return NULL; + + JSRuntime *rt = JS_NewRuntime(); + if (!rt) { + return nullptr; + } + + JS_SetMemoryLimit(rt, 64 * 1024 * 1024); + JS_SetGCThreshold(rt, 16 * 1024 * 1024); + + ctx = JS_NewContext(rt); + + if (!ctx) { + JS_FreeRuntime(rt); + return nullptr; + } + + interpreter->backend_data = ctx; + JS_SetContextOpaque(ctx, interpreter); + +// JS::SetWarningReporter(ctx, error_reporter); + + JS_SetInterruptHandler(rt, js_heartbeat_callback, interpreter); +// JS::RealmOptions options; + +// JS::RootedObject window_obj(ctx, JS_NewGlobalObject(ctx, &window_class, NULL, JS::FireOnNewGlobalHook, options)); + + js_window_init(ctx); + js_screen_init(ctx); + js_unibar_init(ctx); + js_navigator_init(ctx); + js_history_init(ctx); + js_console_init(ctx); + js_localstorage_init(ctx); + js_element_init(ctx); + + interpreter->document_obj = js_document_init(ctx); + interpreter->location_obj = js_location_init(ctx); + + return ctx; +#endif +} + +void +mujs_put_interpreter(struct ecmascript_interpreter *interpreter) +{ +#if 0 + JSContext *ctx; + + assert(interpreter); + + ctx = (JSContext *)interpreter->backend_data; + JS_FreeContext(ctx); + interpreter->backend_data = nullptr; + interpreter->ac = nullptr; + interpreter->ac2 = nullptr; +#endif +} + +#if 0 +static void +error_reporter(struct ecmascript_interpreter *interpreter, JSContext *ctx) +{ + struct session *ses = interpreter->vs->doc_view->session; + struct terminal *term; + struct string msg; + struct string f; + + assert(interpreter && interpreter->vs && interpreter->vs->doc_view + && ses && ses->tab); + if_assert_failed return; + + term = ses->tab->term; + +#ifdef CONFIG_LEDS + set_led_value(ses->status.ecmascript_led, 'J'); +#endif + + if (!get_opt_bool("ecmascript.error_reporting", ses)) { + return; + } + + if (init_string(&f)) { + js_dump_error(ctx, &f); + + if (!init_string(&msg)) { + done_string(&f); + return; + } else { + add_to_string(&msg, + _("A script embedded in the current document raised the following:\n", term)); + add_string_to_string(&msg, &f); + done_string(&f); + info_box(term, MSGBOX_FREE_TEXT, N_("JavaScript Error"), ALIGN_CENTER, msg.source); + } + } +} +#endif + +void +mujs_eval(struct ecmascript_interpreter *interpreter, + struct string *code, struct string *ret) +{ +#if 0 + JSContext *ctx; + + assert(interpreter); +// if (!js_module_init_ok) { +// return; +// } + ctx = (JSContext *)interpreter->backend_data; + interpreter->heartbeat = add_heartbeat(interpreter); + interpreter->ret = ret; + JSValue r = JS_Eval(ctx, code->source, code->length, "", 0); + done_heartbeat(interpreter->heartbeat); + + if (JS_IsException(r)) { + error_reporter(interpreter, ctx); + } +#endif +} + +void +mujs_call_function(struct ecmascript_interpreter *interpreter, + void *fun, struct string *ret) +{ +#if 0 + JSContext *ctx; + + assert(interpreter); +// if (!js_module_init_ok) { +// return; +// } + ctx = (JSContext *)interpreter->backend_data; + + interpreter->heartbeat = add_heartbeat(interpreter); + interpreter->ret = ret; + JSValue r = JS_Call(ctx, fun, JS_GetGlobalObject(ctx), 0, nullptr); + done_heartbeat(interpreter->heartbeat); + + if (JS_IsException(r)) { + error_reporter(interpreter, ctx); + } +#endif +} + +char * +mujs_eval_stringback(struct ecmascript_interpreter *interpreter, + struct string *code) +{ + return nullptr; +#if 0 + JSContext *ctx; + + assert(interpreter); +// if (!js_module_init_ok) { +// return; +// } + ctx = (JSContext *)interpreter->backend_data; + interpreter->heartbeat = add_heartbeat(interpreter); + interpreter->ret = nullptr; + JSValue r = JS_Eval(ctx, code->source, code->length, "", 0); + done_heartbeat(interpreter->heartbeat); + + if (JS_IsNull(r)) { + return nullptr; + } + + if (JS_IsException(r)) { + error_reporter(interpreter, ctx); + } + + const char *str; + char *string; + size_t len; + str = JS_ToCStringLen(ctx, &len, r); + + if (!str) { + return nullptr; + } + string = stracpy(str); + JS_FreeCString(ctx, str); + + return string; +#endif +} + +int +mujs_eval_boolback(struct ecmascript_interpreter *interpreter, + struct string *code) +{ + return -1; +#if 0 + + JSContext *ctx; + + assert(interpreter); +// if (!js_module_init_ok) { +// return; +// } + ctx = (JSContext *)interpreter->backend_data; + interpreter->heartbeat = add_heartbeat(interpreter); + interpreter->ret = nullptr; + JSValue r = JS_Eval(ctx, code->source, code->length, "", 0); + done_heartbeat(interpreter->heartbeat); + + if (JS_IsNull(r)) { + return -1; + } + + if (JS_IsUndefined(r)) { + return -1; + } + + int ret = -1; + + JS_ToInt32(ctx, &ret, r); + + return ret; +#endif +} + +struct module mujs_module = struct_module( + /* name: */ N_("mujs"), + /* options: */ NULL, + /* events: */ NULL, + /* submodules: */ NULL, + /* data: */ NULL, + /* init: */ mujs_init, + /* done: */ mujs_done +); diff --git a/src/ecmascript/mujs.h b/src/ecmascript/mujs.h new file mode 100644 index 00000000..8a3407c1 --- /dev/null +++ b/src/ecmascript/mujs.h @@ -0,0 +1,45 @@ +#ifndef EL__ECMASCRIPT_MUJS_H +#define EL__ECMASCRIPT_MUJS_H + +#include + +#ifdef ECMASCRIPT_DEBUG + +#if 0 + +#define RETURN_JS(obj) \ + fprintf(stderr, "%s:%d obj=%p\n", __FILE__, __LINE__, JS_VALUE_GET_PTR(obj)); \ + if (JS_VALUE_HAS_REF_COUNT(obj)) { \ + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(obj); \ + fprintf(stderr, "ref_count=%d\n", p->ref_count); \ + } \ + return obj + +#else + +#define RETURN_JS(obj) return obj + +#endif + +#endif + +struct ecmascript_interpreter; +struct form_view; +struct form_state; +struct string; + +void *mujs_get_interpreter(struct ecmascript_interpreter *interpreter); +void mujs_put_interpreter(struct ecmascript_interpreter *interpreter); + +//void mujs_detach_form_view(struct form_view *fv); +//void mujs_detach_form_state(struct form_state *fs); +//void mujs_moved_form_state(struct form_state *fs); + +void mujs_eval(struct ecmascript_interpreter *interpreter, struct string *code, struct string *ret); +char *mujs_eval_stringback(struct ecmascript_interpreter *interpreter, struct string *code); +int mujs_eval_boolback(struct ecmascript_interpreter *interpreter, struct string *code); + +//void mujs_call_function(struct ecmascript_interpreter *interpreter, JSValueConst fun, struct string *ret); + +extern struct module mujs_module; +#endif diff --git a/src/ecmascript/mujs/meson.build b/src/ecmascript/mujs/meson.build new file mode 100644 index 00000000..e69de29b diff --git a/src/main/module.cpp b/src/main/module.cpp index 796e0a30..b74febde 100644 --- a/src/main/module.cpp +++ b/src/main/module.cpp @@ -66,7 +66,7 @@ struct module *builtin_modules[] = { #ifdef CONFIG_COOKIES &cookies_module, #endif -#if defined(CONFIG_ECMASCRIPT_SMJS) || defined(CONFIG_QUICKJS) +#if defined(CONFIG_ECMASCRIPT_SMJS) || defined(CONFIG_MUJS) || defined(CONFIG_QUICKJS) &ecmascript_module, #endif #ifdef CONFIG_FORMHIST