diff --git a/src/ecmascript/ecmascript.h b/src/ecmascript/ecmascript.h index d22ab7061..0d4f4cdbb 100644 --- a/src/ecmascript/ecmascript.h +++ b/src/ecmascript/ecmascript.h @@ -40,6 +40,7 @@ extern "C" { #endif +struct document; struct document_view; struct form_state; struct form_view; diff --git a/src/ecmascript/libdom/Makefile b/src/ecmascript/libdom/Makefile index 5918ea73e..a59fbafbd 100644 --- a/src/ecmascript/libdom/Makefile +++ b/src/ecmascript/libdom/Makefile @@ -2,6 +2,8 @@ top_builddir=../../.. include $(top_builddir)/Makefile.config INCLUDES += $(LIBDOM_CFLAGS) +SUBDIRS-$(CONFIG_QUICKJS) += quickjs + OBJS = parse.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/libdom/meson.build b/src/ecmascript/libdom/meson.build index 0c505c48c..643d77ecd 100644 --- a/src/ecmascript/libdom/meson.build +++ b/src/ecmascript/libdom/meson.build @@ -1,2 +1,6 @@ +if conf_data.get('CONFIG_QUICKJS') + subdir('quickjs') +endif + srcs += files('parse.c') diff --git a/src/ecmascript/libdom/quickjs/Makefile b/src/ecmascript/libdom/quickjs/Makefile new file mode 100644 index 000000000..a773e8225 --- /dev/null +++ b/src/ecmascript/libdom/quickjs/Makefile @@ -0,0 +1,6 @@ +top_builddir=../../../.. +include $(top_builddir)/Makefile.config + +OBJS = attr.o mapa.obj + +include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/libdom/quickjs/attr.c b/src/ecmascript/libdom/quickjs/attr.c new file mode 100644 index 000000000..2b609ddfb --- /dev/null +++ b/src/ecmascript/libdom/quickjs/attr.c @@ -0,0 +1,165 @@ +/* The QuickJS attr object implementation. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef CONFIG_LIBDOM +#include +#include +#endif + +#include "elinks.h" + +#include "ecmascript/ecmascript.h" +#include "ecmascript/libdom/quickjs/mapa.h" +#include "ecmascript/quickjs.h" + +#define countof(x) (sizeof(x) / sizeof((x)[0])) + +static JSClassID js_attr_class_id; + +static JSValue +js_attr_get_property_name(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + + REF_JS(this_val); + + struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); + struct view_state *vs = interpreter->vs; + dom_string *name = NULL; + dom_exception err; + JSValue r; + + if (!vs) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return JS_EXCEPTION; + } + + dom_attr *attr = (dom_attr *)(JS_GetOpaque(this_val, js_attr_class_id)); + + if (!attr) { + return JS_NULL; + } + + err = dom_attr_get_name(attr, &name); + if (err != DOM_NO_ERR || name == NULL) { + return JS_NULL; + } + + r = JS_NewStringLen(ctx, dom_string_data(name), dom_string_length(name)); + dom_string_unref(name); + + RETURN_JS(r); +} + +static JSValue +js_attr_get_property_value(JSContext *ctx, JSValueConst this_val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(this_val); + struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); + struct view_state *vs = interpreter->vs; + dom_string *value = NULL; + dom_exception err; + JSValue r; + + if (!vs) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return JS_EXCEPTION; + } + + dom_attr *attr = (dom_attr *)(JS_GetOpaque(this_val, js_attr_class_id)); + + if (!attr) { + return JS_NULL; + } + err = dom_attr_get_value(attr, &value); + + if (err != DOM_NO_ERR || value == NULL) { + return JS_NULL; + } + r = JS_NewStringLen(ctx, dom_string_data(value), dom_string_length(value)); + dom_string_unref(value); + + RETURN_JS(r); +} + +static JSValue +js_attr_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, "[attr object]"); +} + +static const JSCFunctionListEntry js_attr_proto_funcs[] = { + JS_CGETSET_DEF("name", js_attr_get_property_name, NULL), + JS_CGETSET_DEF("value", js_attr_get_property_value, NULL), + JS_CFUNC_DEF("toString", 0, js_attr_toString) +}; + +static void *map_attrs; + +static +void js_attr_finalizer(JSRuntime *rt, JSValue val) +{ + REF_JS(val); + void *node = JS_GetOpaque(val, js_attr_class_id); + + attr_erase_from_map(map_attrs, node); +} + +static JSClassDef js_attr_class = { + "attr", + js_attr_finalizer +}; + +JSValue +getAttr(JSContext *ctx, void *node) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JSValue second = JS_NULL; + static int initialized; + /* create the element class */ + if (!initialized) { + JS_NewClassID(&js_attr_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_attr_class_id, &js_attr_class); + map_attrs = attr_create_new_attrs_map(); + initialized = 1; + } + second = attr_find_in_map(map_attrs, node); + + if (!JS_IsNull(second)) { + JSValue r = JS_DupValue(ctx, second); + + RETURN_JS(r); + } + + JSValue attr_obj = JS_NewObjectClass(ctx, js_attr_class_id); + + JS_SetPropertyFunctionList(ctx, attr_obj, js_attr_proto_funcs, countof(js_attr_proto_funcs)); + JS_SetClassProto(ctx, js_attr_class_id, attr_obj); + JS_SetOpaque(attr_obj, node); + + attr_save_in_map(map_attrs, node, attr_obj); + + JSValue rr = JS_DupValue(ctx, attr_obj); + + RETURN_JS(rr); +} diff --git a/src/ecmascript/libdom/quickjs/mapa.cpp b/src/ecmascript/libdom/quickjs/mapa.cpp new file mode 100644 index 000000000..9124fbc31 --- /dev/null +++ b/src/ecmascript/libdom/quickjs/mapa.cpp @@ -0,0 +1,54 @@ +/* map temporary file */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "ecmascript/libdom/quickjs/mapa.h" + +void +attr_save_in_map(void *m, void *node, JSValueConst value) +{ + std::map *mapa = static_cast *>(m); + (*mapa)[node] = value; +} + +void * +attr_create_new_attrs_map(void) +{ + std::map *mapa = new std::map; + + return (void *)mapa; +} + +void +attr_clear_map(void *m) +{ + std::map *mapa = static_cast *>(m); + mapa->clear(); +} + +JSValue +attr_find_in_map(void *m, void *node) +{ + std::map *mapa = static_cast *>(m); + + if (!mapa) { + return JS_NULL; + } + auto value = (*mapa).find(node); + + if (value == (*mapa).end()) { + return JS_NULL; + } + return value->second; +} + +void +attr_erase_from_map(void *m, void *node) +{ + std::map *mapa = static_cast *>(m); + mapa->erase(node); +} diff --git a/src/ecmascript/libdom/quickjs/mapa.h b/src/ecmascript/libdom/quickjs/mapa.h new file mode 100644 index 000000000..75b76728b --- /dev/null +++ b/src/ecmascript/libdom/quickjs/mapa.h @@ -0,0 +1,20 @@ +#ifndef EL__DOCUMENT_ECMASCRIPT_LIBDOM_QUICKJS_MAPA_H +#define EL__DOCUMENT_ECMASCRIPT_LIBDOM_QUICKJS_MAPA_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void attr_save_in_map(void *m, void *node, JSValueConst value); +void *attr_create_new_attrs_map(void); +void attr_clear_map(void *m); +JSValue attr_find_in_map(void *m, void *node); +void attr_erase_from_map(void *m, void *node); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/ecmascript/libdom/quickjs/meson.build b/src/ecmascript/libdom/quickjs/meson.build new file mode 100644 index 000000000..f07679aa7 --- /dev/null +++ b/src/ecmascript/libdom/quickjs/meson.build @@ -0,0 +1 @@ +srcs += files('attr.c', 'mapa.cpp') diff --git a/src/ecmascript/quickjs.h b/src/ecmascript/quickjs.h index 1286e08ff..4e1240b8a 100644 --- a/src/ecmascript/quickjs.h +++ b/src/ecmascript/quickjs.h @@ -45,7 +45,7 @@ int quickjs_eval_boolback(struct ecmascript_interpreter *interpreter, struct str void quickjs_call_function(struct ecmascript_interpreter *interpreter, JSValueConst fun, struct string *ret); -#ifndef JS_NAN_BOXING +#if !defined(JS_NAN_BOXING) && defined(__cplusplus) inline int operator<(JSValueConst a, JSValueConst b) { return JS_VALUE_GET_PTR(a) < JS_VALUE_GET_PTR(b); diff --git a/src/ecmascript/quickjs/attr.cpp b/src/ecmascript/quickjs/attr.cpp index 4656326e1..286df97d1 100644 --- a/src/ecmascript/quickjs/attr.cpp +++ b/src/ecmascript/quickjs/attr.cpp @@ -54,6 +54,8 @@ #define countof(x) (sizeof(x) / sizeof((x)[0])) +#ifndef CONFIG_LIBDOM + static JSClassID js_attr_class_id; static JSValue @@ -184,3 +186,4 @@ getAttr(JSContext *ctx, void *node) RETURN_JS(rr); } +#endif diff --git a/src/ecmascript/quickjs/attr.h b/src/ecmascript/quickjs/attr.h index e35fdffbf..7758ea8b9 100644 --- a/src/ecmascript/quickjs/attr.h +++ b/src/ecmascript/quickjs/attr.h @@ -3,6 +3,14 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + JSValue getAttr(JSContext *ctx, void *node); +#ifdef __cplusplus +} +#endif + #endif